blob: 8778a4d81283ceff7ca0ace5bc3f2d801976449b [file] [log] [blame]
Reinhard Meyer1592ef82010-08-13 10:31:06 +02001/*
2 * Copyright (C) 2010
3 * Rob Emanuele <rob@emanuele.us>
4 * Reinhard Meyer, EMK Elektronik <reinhard.meyer@emk-elektronik.de>
5 *
6 * Original Driver:
7 * Copyright (C) 2004-2006 Atmel Corporation
8 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02009 * SPDX-License-Identifier: GPL-2.0+
Reinhard Meyer1592ef82010-08-13 10:31:06 +020010 */
11
12#include <common.h>
13#include <mmc.h>
14#include <part.h>
15#include <malloc.h>
16#include <asm/io.h>
17#include <asm/errno.h>
18#include <asm/byteorder.h>
19#include <asm/arch/clk.h>
Reinhard Meyer329f0f52010-11-03 16:32:56 +010020#include <asm/arch/hardware.h>
Reinhard Meyer1592ef82010-08-13 10:31:06 +020021#include "atmel_mci.h"
22
23#ifndef CONFIG_SYS_MMC_CLK_OD
24# define CONFIG_SYS_MMC_CLK_OD 150000
25#endif
26
27#define MMC_DEFAULT_BLKLEN 512
28
29#if defined(CONFIG_ATMEL_MCI_PORTB)
30# define MCI_BUS 1
31#else
32# define MCI_BUS 0
33#endif
34
35static int initialized = 0;
36
Bo Shenaac4b692013-04-26 00:27:06 +000037/* Read Atmel MCI IP version */
38static unsigned int atmel_mci_get_version(struct atmel_mci *mci)
39{
40 return readl(&mci->version) & 0x00000fff;
41}
42
Reinhard Meyer1592ef82010-08-13 10:31:06 +020043/*
44 * Print command and status:
45 *
46 * - always when DEBUG is defined
47 * - on command errors
48 */
49static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
50{
51 printf("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n",
52 cmdr, cmdr&0x3F, arg, status, msg);
53}
54
55/* Setup for MCI Clock and Block Size */
56static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
57{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +020058 atmel_mci_t *mci = mmc->priv;
Reinhard Meyer1592ef82010-08-13 10:31:06 +020059 u32 bus_hz = get_mci_clk_rate();
60 u32 clkdiv = 255;
Bo Shencd60ebd42014-07-31 14:39:30 +080061 unsigned int version = atmel_mci_get_version(mci);
62 u32 clkodd = 0;
63 u32 mr;
Reinhard Meyer1592ef82010-08-13 10:31:06 +020064
65 debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
66 bus_hz, hz, blklen);
67 if (hz > 0) {
Bo Shencd60ebd42014-07-31 14:39:30 +080068 if (version >= 0x500) {
69 clkdiv = DIV_ROUND_UP(bus_hz, hz) - 2;
70 if (clkdiv > 511)
71 clkdiv = 511;
72
73 clkodd = clkdiv & 1;
74 clkdiv >>= 1;
75
76 printf("mci: setting clock %u Hz, block size %u\n",
77 bus_hz / (clkdiv * 2 + clkodd + 2), blklen);
78 } else {
79 /* find clkdiv yielding a rate <= than requested */
80 for (clkdiv = 0; clkdiv < 255; clkdiv++) {
81 if ((bus_hz / (clkdiv + 1) / 2) <= hz)
82 break;
83 }
84 printf("mci: setting clock %u Hz, block size %u\n",
85 (bus_hz / (clkdiv + 1)) / 2, blklen);
86
Reinhard Meyer1592ef82010-08-13 10:31:06 +020087 }
88 }
Reinhard Meyer1592ef82010-08-13 10:31:06 +020089
90 blklen &= 0xfffc;
Bo Shencd60ebd42014-07-31 14:39:30 +080091
92 mr = MMCI_BF(CLKDIV, clkdiv);
93
94 /* MCI IP version >= 0x200 has R/WPROOF */
95 if (version >= 0x200)
96 mr |= MMCI_BIT(RDPROOF) | MMCI_BIT(WRPROOF);
97
Wu, Josh1db73772012-09-13 22:22:04 +000098 /*
Bo Shencd60ebd42014-07-31 14:39:30 +080099 * MCI IP version >= 0x500 use bit 16 as clkodd.
100 * MCI IP version < 0x500 use upper 16 bits for blklen.
Wu, Josh1db73772012-09-13 22:22:04 +0000101 */
Bo Shencd60ebd42014-07-31 14:39:30 +0800102 if (version >= 0x500)
103 mr |= MMCI_BF(CLKODD, clkodd);
104 else
105 mr |= MMCI_BF(BLKLEN, blklen);
106
107 writel(mr, &mci->mr);
108
109 /* MCI IP version >= 0x200 has blkr */
110 if (version >= 0x200)
111 writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
112
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200113 initialized = 1;
114}
115
116/* Return the CMDR with flags for a given command and data packet */
117static u32 mci_encode_cmd(
118 struct mmc_cmd *cmd, struct mmc_data *data, u32* error_flags)
119{
120 u32 cmdr = 0;
121
122 /* Default Flags for Errors */
123 *error_flags |= (MMCI_BIT(DTOE) | MMCI_BIT(RDIRE) | MMCI_BIT(RENDE) |
124 MMCI_BIT(RINDE) | MMCI_BIT(RTOE));
125
126 /* Default Flags for the Command */
127 cmdr |= MMCI_BIT(MAXLAT);
128
129 if (data) {
130 cmdr |= MMCI_BF(TRCMD, 1);
131 if (data->blocks > 1)
132 cmdr |= MMCI_BF(TRTYP, 1);
133 if (data->flags & MMC_DATA_READ)
134 cmdr |= MMCI_BIT(TRDIR);
135 }
136
137 if (cmd->resp_type & MMC_RSP_CRC)
138 *error_flags |= MMCI_BIT(RCRCE);
139 if (cmd->resp_type & MMC_RSP_136)
140 cmdr |= MMCI_BF(RSPTYP, 2);
141 else if (cmd->resp_type & MMC_RSP_BUSY)
142 cmdr |= MMCI_BF(RSPTYP, 3);
143 else if (cmd->resp_type & MMC_RSP_PRESENT)
144 cmdr |= MMCI_BF(RSPTYP, 1);
145
146 return cmdr | MMCI_BF(CMDNB, cmd->cmdidx);
147}
148
149/* Entered into function pointer in mci_send_cmd */
150static u32 mci_data_read(atmel_mci_t *mci, u32* data, u32 error_flags)
151{
152 u32 status;
153
154 do {
155 status = readl(&mci->sr);
156 if (status & (error_flags | MMCI_BIT(OVRE)))
157 goto io_fail;
158 } while (!(status & MMCI_BIT(RXRDY)));
159
160 if (status & MMCI_BIT(RXRDY)) {
161 *data = readl(&mci->rdr);
162 status = 0;
163 }
164io_fail:
165 return status;
166}
167
168/* Entered into function pointer in mci_send_cmd */
169static u32 mci_data_write(atmel_mci_t *mci, u32* data, u32 error_flags)
170{
171 u32 status;
172
173 do {
174 status = readl(&mci->sr);
175 if (status & (error_flags | MMCI_BIT(UNRE)))
176 goto io_fail;
177 } while (!(status & MMCI_BIT(TXRDY)));
178
179 if (status & MMCI_BIT(TXRDY)) {
180 writel(*data, &mci->tdr);
181 status = 0;
182 }
183io_fail:
184 return status;
185}
186
187/*
188 * Entered into mmc structure during driver init
189 *
190 * Sends a command out on the bus and deals with the block data.
191 * Takes the mmc pointer, a command pointer, and an optional data pointer.
192 */
193static int
194mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
195{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200196 atmel_mci_t *mci = mmc->priv;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200197 u32 cmdr;
198 u32 error_flags = 0;
199 u32 status;
200
201 if (!initialized) {
202 puts ("MCI not initialized!\n");
203 return COMM_ERR;
204 }
205
206 /* Figure out the transfer arguments */
207 cmdr = mci_encode_cmd(cmd, data, &error_flags);
208
Wu, Josh1db73772012-09-13 22:22:04 +0000209 /* For multi blocks read/write, set the block register */
210 if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK)
211 || (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK))
212 writel(data->blocks | MMCI_BF(BLKLEN, mmc->read_bl_len),
213 &mci->blkr);
214
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200215 /* Send the command */
216 writel(cmd->cmdarg, &mci->argr);
217 writel(cmdr, &mci->cmdr);
218
219#ifdef DEBUG
220 dump_cmd(cmdr, cmd->cmdarg, 0, "DEBUG");
221#endif
222
223 /* Wait for the command to complete */
224 while (!((status = readl(&mci->sr)) & MMCI_BIT(CMDRDY)));
225
Bo Shen93e32362013-04-26 00:27:07 +0000226 if ((status & error_flags) & MMCI_BIT(RTOE)) {
227 dump_cmd(cmdr, cmd->cmdarg, status, "Command Time Out");
228 return TIMEOUT;
229 } else if (status & error_flags) {
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200230 dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed");
231 return COMM_ERR;
232 }
233
234 /* Copy the response to the response buffer */
235 if (cmd->resp_type & MMC_RSP_136) {
236 cmd->response[0] = readl(&mci->rspr);
237 cmd->response[1] = readl(&mci->rspr1);
238 cmd->response[2] = readl(&mci->rspr2);
239 cmd->response[3] = readl(&mci->rspr3);
240 } else
241 cmd->response[0] = readl(&mci->rspr);
242
243 /* transfer all of the blocks */
244 if (data) {
245 u32 word_count, block_count;
246 u32* ioptr;
247 u32 sys_blocksize, dummy, i;
248 u32 (*mci_data_op)
249 (atmel_mci_t *mci, u32* data, u32 error_flags);
250
251 if (data->flags & MMC_DATA_READ) {
252 mci_data_op = mci_data_read;
253 sys_blocksize = mmc->read_bl_len;
254 ioptr = (u32*)data->dest;
255 } else {
256 mci_data_op = mci_data_write;
257 sys_blocksize = mmc->write_bl_len;
258 ioptr = (u32*)data->src;
259 }
260
261 status = 0;
262 for (block_count = 0;
263 block_count < data->blocks && !status;
264 block_count++) {
265 word_count = 0;
266 do {
267 status = mci_data_op(mci, ioptr, error_flags);
268 word_count++;
269 ioptr++;
270 } while (!status && word_count < (data->blocksize/4));
271#ifdef DEBUG
272 if (data->flags & MMC_DATA_READ)
273 {
Wu, Josh9902c7b2014-05-07 17:06:08 +0800274 u32 cnt = word_count * 4;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200275 printf("Read Data:\n");
Wu, Josh9902c7b2014-05-07 17:06:08 +0800276 print_buffer(0, data->dest + cnt * block_count,
277 1, cnt, 0);
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200278 }
279#endif
280#ifdef DEBUG
281 if (!status && word_count < (sys_blocksize / 4))
282 printf("filling rest of block...\n");
283#endif
284 /* fill the rest of a full block */
285 while (!status && word_count < (sys_blocksize / 4)) {
286 status = mci_data_op(mci, &dummy,
287 error_flags);
288 word_count++;
289 }
290 if (status) {
291 dump_cmd(cmdr, cmd->cmdarg, status,
292 "Data Transfer Failed");
293 return COMM_ERR;
294 }
295 }
296
297 /* Wait for Transfer End */
298 i = 0;
299 do {
300 status = readl(&mci->sr);
301
302 if (status & error_flags) {
303 dump_cmd(cmdr, cmd->cmdarg, status,
304 "DTIP Wait Failed");
305 return COMM_ERR;
306 }
307 i++;
308 } while ((status & MMCI_BIT(DTIP)) && i < 10000);
309 if (status & MMCI_BIT(DTIP)) {
310 dump_cmd(cmdr, cmd->cmdarg, status,
311 "XFER DTIP never unset, ignoring");
312 }
313 }
314
315 return 0;
316}
317
318/* Entered into mmc structure during driver init */
319static void mci_set_ios(struct mmc *mmc)
320{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200321 atmel_mci_t *mci = mmc->priv;
Bo Shenaac4b692013-04-26 00:27:06 +0000322 int bus_width = mmc->bus_width;
323 unsigned int version = atmel_mci_get_version(mci);
324 int busw;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200325
326 /* Set the clock speed */
327 mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
328
329 /*
330 * set the bus width and select slot for this interface
331 * there is no capability for multiple slots on the same interface yet
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200332 */
Bo Shenaac4b692013-04-26 00:27:06 +0000333 if ((version & 0xf00) >= 0x300) {
334 switch (bus_width) {
335 case 8:
336 busw = 3;
337 break;
338 case 4:
339 busw = 2;
340 break;
341 default:
342 busw = 0;
343 break;
344 }
345
346 writel(busw << 6 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
347 } else {
348 busw = (bus_width == 4) ? 1 : 0;
349
350 writel(busw << 7 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
351 }
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200352}
353
354/* Entered into mmc structure during driver init */
355static int mci_init(struct mmc *mmc)
356{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200357 atmel_mci_t *mci = mmc->priv;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200358
359 /* Initialize controller */
360 writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */
361 writel(MMCI_BIT(PWSDIS), &mci->cr); /* disable power save */
362 writel(MMCI_BIT(MCIEN), &mci->cr); /* enable mci */
Reinhard Meyer2aed9d12010-11-16 09:24:41 +0100363 writel(MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr); /* select port */
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200364
Wu, Josh9924ca62012-09-13 22:22:06 +0000365 /* This delay can be optimized, but stick with max value */
366 writel(0x7f, &mci->dtor);
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200367 /* Disable Interrupts */
368 writel(~0UL, &mci->idr);
369
370 /* Set default clocks and blocklen */
371 mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
372
373 return 0;
374}
375
Pantelis Antoniouab769f22014-02-26 19:28:45 +0200376static const struct mmc_ops atmel_mci_ops = {
377 .send_cmd = mci_send_cmd,
378 .set_ios = mci_set_ios,
379 .init = mci_init,
380};
381
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200382/*
383 * This is the only exported function
384 *
385 * Call it with the MCI register base address
386 */
387int atmel_mci_init(void *regs)
388{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200389 struct mmc *mmc;
390 struct mmc_config *cfg;
Bo Shenaac4b692013-04-26 00:27:06 +0000391 struct atmel_mci *mci;
392 unsigned int version;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200393
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200394 cfg = malloc(sizeof(*cfg));
395 if (cfg == NULL)
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200396 return -1;
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200397 memset(cfg, 0, sizeof(*cfg));
Bo Shenaac4b692013-04-26 00:27:06 +0000398
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200399 mci = (struct atmel_mci *)regs;
400
401 cfg->name = "mci";
402 cfg->ops = &atmel_mci_ops;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200403
404 /* need to be able to pass these in on a board by board basis */
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200405 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
Bo Shenaac4b692013-04-26 00:27:06 +0000406 version = atmel_mci_get_version(mci);
407 if ((version & 0xf00) >= 0x300)
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200408 cfg->host_caps = MMC_MODE_8BIT;
Bo Shenaac4b692013-04-26 00:27:06 +0000409
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200410 cfg->host_caps |= MMC_MODE_4BIT;
Bo Shenaac4b692013-04-26 00:27:06 +0000411
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200412 /*
413 * min and max frequencies determined by
414 * max and min of clock divider
415 */
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200416 cfg->f_min = get_mci_clk_rate() / (2*256);
417 cfg->f_max = get_mci_clk_rate() / (2*1);
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200418
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200419 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
John Rigby8feafcc2011-04-18 05:50:08 +0000420
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200421 mmc = mmc_create(cfg, regs);
422
423 if (mmc == NULL) {
424 free(cfg);
425 return -1;
426 }
427 /* NOTE: possibly leaking the cfg structure */
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200428
429 return 0;
430}