blob: 45bcffb6b2060a7410336cb2e2dec44f47d52767 [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
Bo Shenda55c662014-07-31 14:39:32 +0800113 if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
114 writel(MMCI_BIT(HSMODE), &mci->cfg);
115
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200116 initialized = 1;
117}
118
119/* Return the CMDR with flags for a given command and data packet */
120static u32 mci_encode_cmd(
121 struct mmc_cmd *cmd, struct mmc_data *data, u32* error_flags)
122{
123 u32 cmdr = 0;
124
125 /* Default Flags for Errors */
126 *error_flags |= (MMCI_BIT(DTOE) | MMCI_BIT(RDIRE) | MMCI_BIT(RENDE) |
127 MMCI_BIT(RINDE) | MMCI_BIT(RTOE));
128
129 /* Default Flags for the Command */
130 cmdr |= MMCI_BIT(MAXLAT);
131
132 if (data) {
133 cmdr |= MMCI_BF(TRCMD, 1);
134 if (data->blocks > 1)
135 cmdr |= MMCI_BF(TRTYP, 1);
136 if (data->flags & MMC_DATA_READ)
137 cmdr |= MMCI_BIT(TRDIR);
138 }
139
140 if (cmd->resp_type & MMC_RSP_CRC)
141 *error_flags |= MMCI_BIT(RCRCE);
142 if (cmd->resp_type & MMC_RSP_136)
143 cmdr |= MMCI_BF(RSPTYP, 2);
144 else if (cmd->resp_type & MMC_RSP_BUSY)
145 cmdr |= MMCI_BF(RSPTYP, 3);
146 else if (cmd->resp_type & MMC_RSP_PRESENT)
147 cmdr |= MMCI_BF(RSPTYP, 1);
148
149 return cmdr | MMCI_BF(CMDNB, cmd->cmdidx);
150}
151
152/* Entered into function pointer in mci_send_cmd */
153static u32 mci_data_read(atmel_mci_t *mci, u32* data, u32 error_flags)
154{
155 u32 status;
156
157 do {
158 status = readl(&mci->sr);
159 if (status & (error_flags | MMCI_BIT(OVRE)))
160 goto io_fail;
161 } while (!(status & MMCI_BIT(RXRDY)));
162
163 if (status & MMCI_BIT(RXRDY)) {
164 *data = readl(&mci->rdr);
165 status = 0;
166 }
167io_fail:
168 return status;
169}
170
171/* Entered into function pointer in mci_send_cmd */
172static u32 mci_data_write(atmel_mci_t *mci, u32* data, u32 error_flags)
173{
174 u32 status;
175
176 do {
177 status = readl(&mci->sr);
178 if (status & (error_flags | MMCI_BIT(UNRE)))
179 goto io_fail;
180 } while (!(status & MMCI_BIT(TXRDY)));
181
182 if (status & MMCI_BIT(TXRDY)) {
183 writel(*data, &mci->tdr);
184 status = 0;
185 }
186io_fail:
187 return status;
188}
189
190/*
191 * Entered into mmc structure during driver init
192 *
193 * Sends a command out on the bus and deals with the block data.
194 * Takes the mmc pointer, a command pointer, and an optional data pointer.
195 */
196static int
197mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
198{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200199 atmel_mci_t *mci = mmc->priv;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200200 u32 cmdr;
201 u32 error_flags = 0;
202 u32 status;
203
204 if (!initialized) {
205 puts ("MCI not initialized!\n");
206 return COMM_ERR;
207 }
208
209 /* Figure out the transfer arguments */
210 cmdr = mci_encode_cmd(cmd, data, &error_flags);
211
Wu, Josh1db73772012-09-13 22:22:04 +0000212 /* For multi blocks read/write, set the block register */
213 if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK)
214 || (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK))
215 writel(data->blocks | MMCI_BF(BLKLEN, mmc->read_bl_len),
216 &mci->blkr);
217
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200218 /* Send the command */
219 writel(cmd->cmdarg, &mci->argr);
220 writel(cmdr, &mci->cmdr);
221
222#ifdef DEBUG
223 dump_cmd(cmdr, cmd->cmdarg, 0, "DEBUG");
224#endif
225
226 /* Wait for the command to complete */
227 while (!((status = readl(&mci->sr)) & MMCI_BIT(CMDRDY)));
228
Bo Shen93e32362013-04-26 00:27:07 +0000229 if ((status & error_flags) & MMCI_BIT(RTOE)) {
230 dump_cmd(cmdr, cmd->cmdarg, status, "Command Time Out");
231 return TIMEOUT;
232 } else if (status & error_flags) {
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200233 dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed");
234 return COMM_ERR;
235 }
236
237 /* Copy the response to the response buffer */
238 if (cmd->resp_type & MMC_RSP_136) {
239 cmd->response[0] = readl(&mci->rspr);
240 cmd->response[1] = readl(&mci->rspr1);
241 cmd->response[2] = readl(&mci->rspr2);
242 cmd->response[3] = readl(&mci->rspr3);
243 } else
244 cmd->response[0] = readl(&mci->rspr);
245
246 /* transfer all of the blocks */
247 if (data) {
248 u32 word_count, block_count;
249 u32* ioptr;
250 u32 sys_blocksize, dummy, i;
251 u32 (*mci_data_op)
252 (atmel_mci_t *mci, u32* data, u32 error_flags);
253
254 if (data->flags & MMC_DATA_READ) {
255 mci_data_op = mci_data_read;
256 sys_blocksize = mmc->read_bl_len;
257 ioptr = (u32*)data->dest;
258 } else {
259 mci_data_op = mci_data_write;
260 sys_blocksize = mmc->write_bl_len;
261 ioptr = (u32*)data->src;
262 }
263
264 status = 0;
265 for (block_count = 0;
266 block_count < data->blocks && !status;
267 block_count++) {
268 word_count = 0;
269 do {
270 status = mci_data_op(mci, ioptr, error_flags);
271 word_count++;
272 ioptr++;
273 } while (!status && word_count < (data->blocksize/4));
274#ifdef DEBUG
275 if (data->flags & MMC_DATA_READ)
276 {
Wu, Josh9902c7b2014-05-07 17:06:08 +0800277 u32 cnt = word_count * 4;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200278 printf("Read Data:\n");
Wu, Josh9902c7b2014-05-07 17:06:08 +0800279 print_buffer(0, data->dest + cnt * block_count,
280 1, cnt, 0);
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200281 }
282#endif
283#ifdef DEBUG
284 if (!status && word_count < (sys_blocksize / 4))
285 printf("filling rest of block...\n");
286#endif
287 /* fill the rest of a full block */
288 while (!status && word_count < (sys_blocksize / 4)) {
289 status = mci_data_op(mci, &dummy,
290 error_flags);
291 word_count++;
292 }
293 if (status) {
294 dump_cmd(cmdr, cmd->cmdarg, status,
295 "Data Transfer Failed");
296 return COMM_ERR;
297 }
298 }
299
300 /* Wait for Transfer End */
301 i = 0;
302 do {
303 status = readl(&mci->sr);
304
305 if (status & error_flags) {
306 dump_cmd(cmdr, cmd->cmdarg, status,
307 "DTIP Wait Failed");
308 return COMM_ERR;
309 }
310 i++;
311 } while ((status & MMCI_BIT(DTIP)) && i < 10000);
312 if (status & MMCI_BIT(DTIP)) {
313 dump_cmd(cmdr, cmd->cmdarg, status,
314 "XFER DTIP never unset, ignoring");
315 }
316 }
317
318 return 0;
319}
320
321/* Entered into mmc structure during driver init */
322static void mci_set_ios(struct mmc *mmc)
323{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200324 atmel_mci_t *mci = mmc->priv;
Bo Shenaac4b692013-04-26 00:27:06 +0000325 int bus_width = mmc->bus_width;
326 unsigned int version = atmel_mci_get_version(mci);
327 int busw;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200328
329 /* Set the clock speed */
330 mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
331
332 /*
333 * set the bus width and select slot for this interface
334 * there is no capability for multiple slots on the same interface yet
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200335 */
Bo Shenaac4b692013-04-26 00:27:06 +0000336 if ((version & 0xf00) >= 0x300) {
337 switch (bus_width) {
338 case 8:
339 busw = 3;
340 break;
341 case 4:
342 busw = 2;
343 break;
344 default:
345 busw = 0;
346 break;
347 }
348
349 writel(busw << 6 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
350 } else {
351 busw = (bus_width == 4) ? 1 : 0;
352
353 writel(busw << 7 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
354 }
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200355}
356
357/* Entered into mmc structure during driver init */
358static int mci_init(struct mmc *mmc)
359{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200360 atmel_mci_t *mci = mmc->priv;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200361
362 /* Initialize controller */
363 writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */
364 writel(MMCI_BIT(PWSDIS), &mci->cr); /* disable power save */
365 writel(MMCI_BIT(MCIEN), &mci->cr); /* enable mci */
Reinhard Meyer2aed9d12010-11-16 09:24:41 +0100366 writel(MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr); /* select port */
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200367
Wu, Josh9924ca62012-09-13 22:22:06 +0000368 /* This delay can be optimized, but stick with max value */
369 writel(0x7f, &mci->dtor);
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200370 /* Disable Interrupts */
371 writel(~0UL, &mci->idr);
372
373 /* Set default clocks and blocklen */
374 mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
375
376 return 0;
377}
378
Pantelis Antoniouab769f22014-02-26 19:28:45 +0200379static const struct mmc_ops atmel_mci_ops = {
380 .send_cmd = mci_send_cmd,
381 .set_ios = mci_set_ios,
382 .init = mci_init,
383};
384
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200385/*
386 * This is the only exported function
387 *
388 * Call it with the MCI register base address
389 */
390int atmel_mci_init(void *regs)
391{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200392 struct mmc *mmc;
393 struct mmc_config *cfg;
Bo Shenaac4b692013-04-26 00:27:06 +0000394 struct atmel_mci *mci;
395 unsigned int version;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200396
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200397 cfg = malloc(sizeof(*cfg));
398 if (cfg == NULL)
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200399 return -1;
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200400 memset(cfg, 0, sizeof(*cfg));
Bo Shenaac4b692013-04-26 00:27:06 +0000401
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200402 mci = (struct atmel_mci *)regs;
403
404 cfg->name = "mci";
405 cfg->ops = &atmel_mci_ops;
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200406
407 /* need to be able to pass these in on a board by board basis */
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200408 cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
Bo Shenaac4b692013-04-26 00:27:06 +0000409 version = atmel_mci_get_version(mci);
Bo Shenda55c662014-07-31 14:39:32 +0800410 if ((version & 0xf00) >= 0x300) {
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200411 cfg->host_caps = MMC_MODE_8BIT;
Bo Shenda55c662014-07-31 14:39:32 +0800412 cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz;
413 }
Bo Shenaac4b692013-04-26 00:27:06 +0000414
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200415 cfg->host_caps |= MMC_MODE_4BIT;
Bo Shenaac4b692013-04-26 00:27:06 +0000416
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200417 /*
418 * min and max frequencies determined by
419 * max and min of clock divider
420 */
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200421 cfg->f_min = get_mci_clk_rate() / (2*256);
422 cfg->f_max = get_mci_clk_rate() / (2*1);
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200423
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200424 cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
John Rigby8feafcc2011-04-18 05:50:08 +0000425
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200426 mmc = mmc_create(cfg, regs);
427
428 if (mmc == NULL) {
429 free(cfg);
430 return -1;
431 }
432 /* NOTE: possibly leaking the cfg structure */
Reinhard Meyer1592ef82010-08-13 10:31:06 +0200433
434 return 0;
435}