blob: 21aedbaa3fe2e27e9f1e82a6c4ed3b0f66ad4550 [file] [log] [blame]
Andy Fleming272cc702008-10-30 16:41:01 -05001/*
2 * Copyright 2008, Freescale Semiconductor, Inc
3 * Andy Fleming
4 *
5 * Based vaguely on the Linux code
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <config.h>
27#include <common.h>
28#include <command.h>
29#include <mmc.h>
30#include <part.h>
31#include <malloc.h>
32#include <linux/list.h>
Rabin Vincent9b1f9422009-04-05 13:30:54 +053033#include <div64.h>
Andy Fleming272cc702008-10-30 16:41:01 -050034
Matt Waddelce0fbcd2011-02-24 16:35:23 +000035/* Set block count limit because of 16 bit register limit on some hardware*/
36#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
37#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
38#endif
39
Andy Fleming272cc702008-10-30 16:41:01 -050040static struct list_head mmc_devices;
41static int cur_dev_num = -1;
42
Stefano Babic11fdade2010-02-05 15:04:43 +010043int __board_mmc_getcd(u8 *cd, struct mmc *mmc) {
44 return -1;
45}
46
47int board_mmc_getcd(u8 *cd, struct mmc *mmc)__attribute__((weak,
48 alias("__board_mmc_getcd")));
49
Andy Fleming272cc702008-10-30 16:41:01 -050050int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
51{
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +000052#ifdef CONFIG_MMC_TRACE
53 int ret;
54 int i;
55 u8 *ptr;
56
57 printf("CMD_SEND:%d\n", cmd->cmdidx);
58 printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
59 printf("\t\tFLAG\t\t\t %d\n", cmd->flags);
60 ret = mmc->send_cmd(mmc, cmd, data);
61 switch (cmd->resp_type) {
62 case MMC_RSP_NONE:
63 printf("\t\tMMC_RSP_NONE\n");
64 break;
65 case MMC_RSP_R1:
66 printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08X \n",
67 cmd->response[0]);
68 break;
69 case MMC_RSP_R1b:
70 printf("\t\tMMC_RSP_R1b\t\t 0x%08X \n",
71 cmd->response[0]);
72 break;
73 case MMC_RSP_R2:
74 printf("\t\tMMC_RSP_R2\t\t 0x%08X \n",
75 cmd->response[0]);
76 printf("\t\t \t\t 0x%08X \n",
77 cmd->response[1]);
78 printf("\t\t \t\t 0x%08X \n",
79 cmd->response[2]);
80 printf("\t\t \t\t 0x%08X \n",
81 cmd->response[3]);
82 printf("\n");
83 printf("\t\t\t\t\tDUMPING DATA\n");
84 for (i = 0; i < 4; i++) {
85 int j;
86 printf("\t\t\t\t\t%03d - ", i*4);
87 ptr = &cmd->response[i];
88 ptr += 3;
89 for (j = 0; j < 4; j++)
90 printf("%02X ", *ptr--);
91 printf("\n");
92 }
93 break;
94 case MMC_RSP_R3:
95 printf("\t\tMMC_RSP_R3,4\t\t 0x%08X \n",
96 cmd->response[0]);
97 break;
98 default:
99 printf("\t\tERROR MMC rsp not supported\n");
100 break;
101 }
102 return ret;
103#else
Andy Fleming272cc702008-10-30 16:41:01 -0500104 return mmc->send_cmd(mmc, cmd, data);
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +0000105#endif
Andy Fleming272cc702008-10-30 16:41:01 -0500106}
107
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000108int mmc_send_status(struct mmc *mmc, int timeout)
109{
110 struct mmc_cmd cmd;
111 int err;
112#ifdef CONFIG_MMC_TRACE
113 int status;
114#endif
115
116 cmd.cmdidx = MMC_CMD_SEND_STATUS;
117 cmd.resp_type = MMC_RSP_R1;
118 cmd.cmdarg = 0;
119 cmd.flags = 0;
120
121 do {
122 err = mmc_send_cmd(mmc, &cmd, NULL);
123 if (err)
124 return err;
125 else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
126 break;
127
128 udelay(1000);
129
130 if (cmd.response[0] & MMC_STATUS_MASK) {
131 printf("Status Error: 0x%08X\n", cmd.response[0]);
132 return COMM_ERR;
133 }
134 } while (timeout--);
135
Raffaele Recalcati5db2fe32011-03-11 02:01:14 +0000136#ifdef CONFIG_MMC_TRACE
137 status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
138 printf("CURR STATE:%d\n", status);
139#endif
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000140 if (!timeout) {
141 printf("Timeout waiting card ready\n");
142 return TIMEOUT;
143 }
144
145 return 0;
146}
147
Andy Fleming272cc702008-10-30 16:41:01 -0500148int mmc_set_blocklen(struct mmc *mmc, int len)
149{
150 struct mmc_cmd cmd;
151
152 cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
153 cmd.resp_type = MMC_RSP_R1;
154 cmd.cmdarg = len;
155 cmd.flags = 0;
156
157 return mmc_send_cmd(mmc, &cmd, NULL);
158}
159
160struct mmc *find_mmc_device(int dev_num)
161{
162 struct mmc *m;
163 struct list_head *entry;
164
165 list_for_each(entry, &mmc_devices) {
166 m = list_entry(entry, struct mmc, link);
167
168 if (m->block_dev.dev == dev_num)
169 return m;
170 }
171
172 printf("MMC Device %d not found\n", dev_num);
173
174 return NULL;
175}
176
177static ulong
Lei Wen01581262010-10-14 13:38:11 +0800178mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
Andy Fleming272cc702008-10-30 16:41:01 -0500179{
180 struct mmc_cmd cmd;
181 struct mmc_data data;
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000182 int timeout = 1000;
Andy Fleming272cc702008-10-30 16:41:01 -0500183
Lei Wend2bf29e2010-09-13 22:07:27 +0800184 if ((start + blkcnt) > mmc->block_dev.lba) {
Steve Sakomandef412b2010-10-28 09:00:26 -0700185 printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
Lei Wend2bf29e2010-09-13 22:07:27 +0800186 start + blkcnt, mmc->block_dev.lba);
187 return 0;
188 }
Andy Fleming272cc702008-10-30 16:41:01 -0500189
190 if (blkcnt > 1)
191 cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
192 else
193 cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
194
195 if (mmc->high_capacity)
196 cmd.cmdarg = start;
197 else
Steve Sakomandef412b2010-10-28 09:00:26 -0700198 cmd.cmdarg = start * mmc->write_bl_len;
Andy Fleming272cc702008-10-30 16:41:01 -0500199
200 cmd.resp_type = MMC_RSP_R1;
201 cmd.flags = 0;
202
203 data.src = src;
204 data.blocks = blkcnt;
Steve Sakomandef412b2010-10-28 09:00:26 -0700205 data.blocksize = mmc->write_bl_len;
Andy Fleming272cc702008-10-30 16:41:01 -0500206 data.flags = MMC_DATA_WRITE;
207
Steve Sakomandef412b2010-10-28 09:00:26 -0700208 if (mmc_send_cmd(mmc, &cmd, &data)) {
209 printf("mmc write failed\n");
210 return 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500211 }
212
Thomas Choud52ebf12010-12-24 13:12:21 +0000213 /* SPI multiblock writes terminate using a special
214 * token, not a STOP_TRANSMISSION request.
215 */
216 if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
Andy Fleming272cc702008-10-30 16:41:01 -0500217 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
218 cmd.cmdarg = 0;
219 cmd.resp_type = MMC_RSP_R1b;
220 cmd.flags = 0;
Steve Sakomandef412b2010-10-28 09:00:26 -0700221 if (mmc_send_cmd(mmc, &cmd, NULL)) {
222 printf("mmc fail to send stop cmd\n");
223 return 0;
Lei Wen01581262010-10-14 13:38:11 +0800224 }
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000225
226 /* Waiting for the ready status */
227 mmc_send_status(mmc, timeout);
Andy Fleming272cc702008-10-30 16:41:01 -0500228 }
229
230 return blkcnt;
231}
232
Lei Wen01581262010-10-14 13:38:11 +0800233static ulong
234mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
235{
Lei Wen01581262010-10-14 13:38:11 +0800236 lbaint_t cur, blocks_todo = blkcnt;
237
Steve Sakomandef412b2010-10-28 09:00:26 -0700238 struct mmc *mmc = find_mmc_device(dev_num);
Lei Wen01581262010-10-14 13:38:11 +0800239 if (!mmc)
Steve Sakomandef412b2010-10-28 09:00:26 -0700240 return 0;
Lei Wen01581262010-10-14 13:38:11 +0800241
Steve Sakomandef412b2010-10-28 09:00:26 -0700242 if (mmc_set_blocklen(mmc, mmc->write_bl_len))
243 return 0;
Lei Wen01581262010-10-14 13:38:11 +0800244
245 do {
John Rigby8feafcc2011-04-18 05:50:08 +0000246 cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
Lei Wen01581262010-10-14 13:38:11 +0800247 if(mmc_write_blocks(mmc, start, cur, src) != cur)
Steve Sakomandef412b2010-10-28 09:00:26 -0700248 return 0;
Lei Wen01581262010-10-14 13:38:11 +0800249 blocks_todo -= cur;
250 start += cur;
251 src += cur * mmc->write_bl_len;
252 } while (blocks_todo > 0);
253
254 return blkcnt;
255}
256
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700257int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
Andy Fleming272cc702008-10-30 16:41:01 -0500258{
259 struct mmc_cmd cmd;
260 struct mmc_data data;
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000261 int timeout = 1000;
Andy Fleming272cc702008-10-30 16:41:01 -0500262
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700263 if (blkcnt > 1)
264 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
265 else
266 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
Andy Fleming272cc702008-10-30 16:41:01 -0500267
268 if (mmc->high_capacity)
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700269 cmd.cmdarg = start;
Andy Fleming272cc702008-10-30 16:41:01 -0500270 else
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700271 cmd.cmdarg = start * mmc->read_bl_len;
Andy Fleming272cc702008-10-30 16:41:01 -0500272
273 cmd.resp_type = MMC_RSP_R1;
274 cmd.flags = 0;
275
276 data.dest = dst;
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700277 data.blocks = blkcnt;
Andy Fleming272cc702008-10-30 16:41:01 -0500278 data.blocksize = mmc->read_bl_len;
279 data.flags = MMC_DATA_READ;
280
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700281 if (mmc_send_cmd(mmc, &cmd, &data))
282 return 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500283
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700284 if (blkcnt > 1) {
285 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
286 cmd.cmdarg = 0;
287 cmd.resp_type = MMC_RSP_R1b;
288 cmd.flags = 0;
289 if (mmc_send_cmd(mmc, &cmd, NULL)) {
290 printf("mmc fail to send stop cmd\n");
291 return 0;
292 }
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000293
294 /* Waiting for the ready status */
295 mmc_send_status(mmc, timeout);
Andy Fleming272cc702008-10-30 16:41:01 -0500296 }
297
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700298 return blkcnt;
Andy Fleming272cc702008-10-30 16:41:01 -0500299}
300
301static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
302{
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700303 lbaint_t cur, blocks_todo = blkcnt;
Andy Fleming272cc702008-10-30 16:41:01 -0500304
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700305 if (blkcnt == 0)
306 return 0;
307
308 struct mmc *mmc = find_mmc_device(dev_num);
Andy Fleming272cc702008-10-30 16:41:01 -0500309 if (!mmc)
310 return 0;
311
Lei Wend2bf29e2010-09-13 22:07:27 +0800312 if ((start + blkcnt) > mmc->block_dev.lba) {
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700313 printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
Lei Wend2bf29e2010-09-13 22:07:27 +0800314 start + blkcnt, mmc->block_dev.lba);
315 return 0;
316 }
Andy Fleming272cc702008-10-30 16:41:01 -0500317
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700318 if (mmc_set_blocklen(mmc, mmc->read_bl_len))
Andy Fleming272cc702008-10-30 16:41:01 -0500319 return 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500320
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700321 do {
John Rigby8feafcc2011-04-18 05:50:08 +0000322 cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
Alagu Sankar4a1a06b2010-10-25 07:23:56 -0700323 if(mmc_read_blocks(mmc, dst, start, cur) != cur)
324 return 0;
325 blocks_todo -= cur;
326 start += cur;
327 dst += cur * mmc->read_bl_len;
328 } while (blocks_todo > 0);
Andy Fleming272cc702008-10-30 16:41:01 -0500329
330 return blkcnt;
331}
332
333int mmc_go_idle(struct mmc* mmc)
334{
335 struct mmc_cmd cmd;
336 int err;
337
338 udelay(1000);
339
340 cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
341 cmd.cmdarg = 0;
342 cmd.resp_type = MMC_RSP_NONE;
343 cmd.flags = 0;
344
345 err = mmc_send_cmd(mmc, &cmd, NULL);
346
347 if (err)
348 return err;
349
350 udelay(2000);
351
352 return 0;
353}
354
355int
356sd_send_op_cond(struct mmc *mmc)
357{
358 int timeout = 1000;
359 int err;
360 struct mmc_cmd cmd;
361
362 do {
363 cmd.cmdidx = MMC_CMD_APP_CMD;
364 cmd.resp_type = MMC_RSP_R1;
365 cmd.cmdarg = 0;
366 cmd.flags = 0;
367
368 err = mmc_send_cmd(mmc, &cmd, NULL);
369
370 if (err)
371 return err;
372
373 cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
374 cmd.resp_type = MMC_RSP_R3;
Stefano Babic250de122010-01-20 18:20:39 +0100375
376 /*
377 * Most cards do not answer if some reserved bits
378 * in the ocr are set. However, Some controller
379 * can set bit 7 (reserved for low voltages), but
380 * how to manage low voltages SD card is not yet
381 * specified.
382 */
Thomas Choud52ebf12010-12-24 13:12:21 +0000383 cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
384 (mmc->voltages & 0xff8000);
Andy Fleming272cc702008-10-30 16:41:01 -0500385
386 if (mmc->version == SD_VERSION_2)
387 cmd.cmdarg |= OCR_HCS;
388
389 err = mmc_send_cmd(mmc, &cmd, NULL);
390
391 if (err)
392 return err;
393
394 udelay(1000);
395 } while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);
396
397 if (timeout <= 0)
398 return UNUSABLE_ERR;
399
400 if (mmc->version != SD_VERSION_2)
401 mmc->version = SD_VERSION_1_0;
402
Thomas Choud52ebf12010-12-24 13:12:21 +0000403 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
404 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
405 cmd.resp_type = MMC_RSP_R3;
406 cmd.cmdarg = 0;
407 cmd.flags = 0;
408
409 err = mmc_send_cmd(mmc, &cmd, NULL);
410
411 if (err)
412 return err;
413 }
414
Rabin Vincent998be3d2009-04-05 13:30:56 +0530415 mmc->ocr = cmd.response[0];
Andy Fleming272cc702008-10-30 16:41:01 -0500416
417 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
418 mmc->rca = 0;
419
420 return 0;
421}
422
423int mmc_send_op_cond(struct mmc *mmc)
424{
Raffaele Recalcati31cacba2011-03-11 02:01:13 +0000425 int timeout = 10000;
Andy Fleming272cc702008-10-30 16:41:01 -0500426 struct mmc_cmd cmd;
427 int err;
428
429 /* Some cards seem to need this */
430 mmc_go_idle(mmc);
431
Raffaele Recalcati31cacba2011-03-11 02:01:13 +0000432 /* Asking to the card its capabilities */
433 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
434 cmd.resp_type = MMC_RSP_R3;
435 cmd.cmdarg = 0;
436 cmd.flags = 0;
Wolfgang Denkcd6881b2011-05-19 22:21:41 +0200437
Raffaele Recalcati31cacba2011-03-11 02:01:13 +0000438 err = mmc_send_cmd(mmc, &cmd, NULL);
Wolfgang Denkcd6881b2011-05-19 22:21:41 +0200439
Raffaele Recalcati31cacba2011-03-11 02:01:13 +0000440 if (err)
441 return err;
Wolfgang Denkcd6881b2011-05-19 22:21:41 +0200442
Raffaele Recalcati31cacba2011-03-11 02:01:13 +0000443 udelay(1000);
Wolfgang Denkcd6881b2011-05-19 22:21:41 +0200444
Andy Fleming272cc702008-10-30 16:41:01 -0500445 do {
446 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
447 cmd.resp_type = MMC_RSP_R3;
Raffaele Recalcati31cacba2011-03-11 02:01:13 +0000448 cmd.cmdarg = (mmc_host_is_spi(mmc) ? 0 :
449 (mmc->voltages &
450 (cmd.response[0] & OCR_VOLTAGE_MASK)) |
451 (cmd.response[0] & OCR_ACCESS_MODE));
Andy Fleming272cc702008-10-30 16:41:01 -0500452 cmd.flags = 0;
453
454 err = mmc_send_cmd(mmc, &cmd, NULL);
455
456 if (err)
457 return err;
458
459 udelay(1000);
460 } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
461
462 if (timeout <= 0)
463 return UNUSABLE_ERR;
464
Thomas Choud52ebf12010-12-24 13:12:21 +0000465 if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
466 cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
467 cmd.resp_type = MMC_RSP_R3;
468 cmd.cmdarg = 0;
469 cmd.flags = 0;
470
471 err = mmc_send_cmd(mmc, &cmd, NULL);
472
473 if (err)
474 return err;
475 }
476
Andy Fleming272cc702008-10-30 16:41:01 -0500477 mmc->version = MMC_VERSION_UNKNOWN;
Rabin Vincent998be3d2009-04-05 13:30:56 +0530478 mmc->ocr = cmd.response[0];
Andy Fleming272cc702008-10-30 16:41:01 -0500479
480 mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
481 mmc->rca = 0;
482
483 return 0;
484}
485
486
487int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
488{
489 struct mmc_cmd cmd;
490 struct mmc_data data;
491 int err;
492
493 /* Get the Card Status Register */
494 cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
495 cmd.resp_type = MMC_RSP_R1;
496 cmd.cmdarg = 0;
497 cmd.flags = 0;
498
499 data.dest = ext_csd;
500 data.blocks = 1;
501 data.blocksize = 512;
502 data.flags = MMC_DATA_READ;
503
504 err = mmc_send_cmd(mmc, &cmd, &data);
505
506 return err;
507}
508
509
510int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
511{
512 struct mmc_cmd cmd;
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000513 int timeout = 1000;
514 int ret;
Andy Fleming272cc702008-10-30 16:41:01 -0500515
516 cmd.cmdidx = MMC_CMD_SWITCH;
517 cmd.resp_type = MMC_RSP_R1b;
518 cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000519 (index << 16) |
520 (value << 8);
Andy Fleming272cc702008-10-30 16:41:01 -0500521 cmd.flags = 0;
522
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000523 ret = mmc_send_cmd(mmc, &cmd, NULL);
524
525 /* Waiting for the ready status */
526 mmc_send_status(mmc, timeout);
527
528 return ret;
529
Andy Fleming272cc702008-10-30 16:41:01 -0500530}
531
532int mmc_change_freq(struct mmc *mmc)
533{
534 char ext_csd[512];
535 char cardtype;
536 int err;
537
538 mmc->card_caps = 0;
539
Thomas Choud52ebf12010-12-24 13:12:21 +0000540 if (mmc_host_is_spi(mmc))
541 return 0;
542
Andy Fleming272cc702008-10-30 16:41:01 -0500543 /* Only version 4 supports high-speed */
544 if (mmc->version < MMC_VERSION_4)
545 return 0;
546
547 mmc->card_caps |= MMC_MODE_4BIT;
548
549 err = mmc_send_ext_csd(mmc, ext_csd);
550
551 if (err)
552 return err;
553
Andy Fleming272cc702008-10-30 16:41:01 -0500554 cardtype = ext_csd[196] & 0xf;
555
556 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
557
558 if (err)
559 return err;
560
561 /* Now check to see that it worked */
562 err = mmc_send_ext_csd(mmc, ext_csd);
563
564 if (err)
565 return err;
566
567 /* No high-speed support */
568 if (!ext_csd[185])
569 return 0;
570
571 /* High Speed is set, there are two types: 52MHz and 26MHz */
572 if (cardtype & MMC_HS_52MHZ)
573 mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
574 else
575 mmc->card_caps |= MMC_MODE_HS;
576
577 return 0;
578}
579
Lei Wenbc897b12011-05-02 16:26:26 +0000580int mmc_switch_part(int dev_num, unsigned int part_num)
581{
582 struct mmc *mmc = find_mmc_device(dev_num);
583
584 if (!mmc)
585 return -1;
586
587 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
588 (mmc->part_config & ~PART_ACCESS_MASK)
589 | (part_num & PART_ACCESS_MASK));
590}
591
Andy Fleming272cc702008-10-30 16:41:01 -0500592int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
593{
594 struct mmc_cmd cmd;
595 struct mmc_data data;
596
597 /* Switch the frequency */
598 cmd.cmdidx = SD_CMD_SWITCH_FUNC;
599 cmd.resp_type = MMC_RSP_R1;
600 cmd.cmdarg = (mode << 31) | 0xffffff;
601 cmd.cmdarg &= ~(0xf << (group * 4));
602 cmd.cmdarg |= value << (group * 4);
603 cmd.flags = 0;
604
605 data.dest = (char *)resp;
606 data.blocksize = 64;
607 data.blocks = 1;
608 data.flags = MMC_DATA_READ;
609
610 return mmc_send_cmd(mmc, &cmd, &data);
611}
612
613
614int sd_change_freq(struct mmc *mmc)
615{
616 int err;
617 struct mmc_cmd cmd;
618 uint scr[2];
619 uint switch_status[16];
620 struct mmc_data data;
621 int timeout;
622
623 mmc->card_caps = 0;
624
Thomas Choud52ebf12010-12-24 13:12:21 +0000625 if (mmc_host_is_spi(mmc))
626 return 0;
627
Andy Fleming272cc702008-10-30 16:41:01 -0500628 /* Read the SCR to find out if this card supports higher speeds */
629 cmd.cmdidx = MMC_CMD_APP_CMD;
630 cmd.resp_type = MMC_RSP_R1;
631 cmd.cmdarg = mmc->rca << 16;
632 cmd.flags = 0;
633
634 err = mmc_send_cmd(mmc, &cmd, NULL);
635
636 if (err)
637 return err;
638
639 cmd.cmdidx = SD_CMD_APP_SEND_SCR;
640 cmd.resp_type = MMC_RSP_R1;
641 cmd.cmdarg = 0;
642 cmd.flags = 0;
643
644 timeout = 3;
645
646retry_scr:
647 data.dest = (char *)&scr;
648 data.blocksize = 8;
649 data.blocks = 1;
650 data.flags = MMC_DATA_READ;
651
652 err = mmc_send_cmd(mmc, &cmd, &data);
653
654 if (err) {
655 if (timeout--)
656 goto retry_scr;
657
658 return err;
659 }
660
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300661 mmc->scr[0] = __be32_to_cpu(scr[0]);
662 mmc->scr[1] = __be32_to_cpu(scr[1]);
Andy Fleming272cc702008-10-30 16:41:01 -0500663
664 switch ((mmc->scr[0] >> 24) & 0xf) {
665 case 0:
666 mmc->version = SD_VERSION_1_0;
667 break;
668 case 1:
669 mmc->version = SD_VERSION_1_10;
670 break;
671 case 2:
672 mmc->version = SD_VERSION_2;
673 break;
674 default:
675 mmc->version = SD_VERSION_1_0;
676 break;
677 }
678
Alagu Sankarb44c7082010-05-12 15:08:24 +0530679 if (mmc->scr[0] & SD_DATA_4BIT)
680 mmc->card_caps |= MMC_MODE_4BIT;
681
Andy Fleming272cc702008-10-30 16:41:01 -0500682 /* Version 1.0 doesn't support switching */
683 if (mmc->version == SD_VERSION_1_0)
684 return 0;
685
686 timeout = 4;
687 while (timeout--) {
688 err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
689 (u8 *)&switch_status);
690
691 if (err)
692 return err;
693
694 /* The high-speed function is busy. Try again */
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300695 if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
Andy Fleming272cc702008-10-30 16:41:01 -0500696 break;
697 }
698
Andy Fleming272cc702008-10-30 16:41:01 -0500699 /* If high-speed isn't supported, we return */
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300700 if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
Andy Fleming272cc702008-10-30 16:41:01 -0500701 return 0;
702
703 err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)&switch_status);
704
705 if (err)
706 return err;
707
Yauhen Kharuzhy4e3d89b2009-05-07 00:43:30 +0300708 if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
Andy Fleming272cc702008-10-30 16:41:01 -0500709 mmc->card_caps |= MMC_MODE_HS;
710
711 return 0;
712}
713
714/* frequency bases */
715/* divided by 10 to be nice to platforms without floating point */
Mike Frysinger5f837c22010-10-20 01:15:53 +0000716static const int fbase[] = {
Andy Fleming272cc702008-10-30 16:41:01 -0500717 10000,
718 100000,
719 1000000,
720 10000000,
721};
722
723/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
724 * to platforms without floating point.
725 */
Mike Frysinger5f837c22010-10-20 01:15:53 +0000726static const int multipliers[] = {
Andy Fleming272cc702008-10-30 16:41:01 -0500727 0, /* reserved */
728 10,
729 12,
730 13,
731 15,
732 20,
733 25,
734 30,
735 35,
736 40,
737 45,
738 50,
739 55,
740 60,
741 70,
742 80,
743};
744
745void mmc_set_ios(struct mmc *mmc)
746{
747 mmc->set_ios(mmc);
748}
749
750void mmc_set_clock(struct mmc *mmc, uint clock)
751{
752 if (clock > mmc->f_max)
753 clock = mmc->f_max;
754
755 if (clock < mmc->f_min)
756 clock = mmc->f_min;
757
758 mmc->clock = clock;
759
760 mmc_set_ios(mmc);
761}
762
763void mmc_set_bus_width(struct mmc *mmc, uint width)
764{
765 mmc->bus_width = width;
766
767 mmc_set_ios(mmc);
768}
769
770int mmc_startup(struct mmc *mmc)
771{
772 int err;
773 uint mult, freq;
774 u64 cmult, csize;
775 struct mmc_cmd cmd;
Sukumar Ghoraid23e2c02010-09-20 18:29:29 +0530776 char ext_csd[512];
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000777 int timeout = 1000;
Andy Fleming272cc702008-10-30 16:41:01 -0500778
Thomas Choud52ebf12010-12-24 13:12:21 +0000779#ifdef CONFIG_MMC_SPI_CRC_ON
780 if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
781 cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
782 cmd.resp_type = MMC_RSP_R1;
783 cmd.cmdarg = 1;
784 cmd.flags = 0;
785 err = mmc_send_cmd(mmc, &cmd, NULL);
786
787 if (err)
788 return err;
789 }
790#endif
791
Andy Fleming272cc702008-10-30 16:41:01 -0500792 /* Put the Card in Identify Mode */
Thomas Choud52ebf12010-12-24 13:12:21 +0000793 cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
794 MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
Andy Fleming272cc702008-10-30 16:41:01 -0500795 cmd.resp_type = MMC_RSP_R2;
796 cmd.cmdarg = 0;
797 cmd.flags = 0;
798
799 err = mmc_send_cmd(mmc, &cmd, NULL);
800
801 if (err)
802 return err;
803
804 memcpy(mmc->cid, cmd.response, 16);
805
806 /*
807 * For MMC cards, set the Relative Address.
808 * For SD cards, get the Relatvie Address.
809 * This also puts the cards into Standby State
810 */
Thomas Choud52ebf12010-12-24 13:12:21 +0000811 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
812 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
813 cmd.cmdarg = mmc->rca << 16;
814 cmd.resp_type = MMC_RSP_R6;
815 cmd.flags = 0;
Andy Fleming272cc702008-10-30 16:41:01 -0500816
Thomas Choud52ebf12010-12-24 13:12:21 +0000817 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Fleming272cc702008-10-30 16:41:01 -0500818
Thomas Choud52ebf12010-12-24 13:12:21 +0000819 if (err)
820 return err;
Andy Fleming272cc702008-10-30 16:41:01 -0500821
Thomas Choud52ebf12010-12-24 13:12:21 +0000822 if (IS_SD(mmc))
823 mmc->rca = (cmd.response[0] >> 16) & 0xffff;
824 }
Andy Fleming272cc702008-10-30 16:41:01 -0500825
826 /* Get the Card-Specific Data */
827 cmd.cmdidx = MMC_CMD_SEND_CSD;
828 cmd.resp_type = MMC_RSP_R2;
829 cmd.cmdarg = mmc->rca << 16;
830 cmd.flags = 0;
831
832 err = mmc_send_cmd(mmc, &cmd, NULL);
833
Raffaele Recalcati5d4fc8d2011-03-11 02:01:12 +0000834 /* Waiting for the ready status */
835 mmc_send_status(mmc, timeout);
836
Andy Fleming272cc702008-10-30 16:41:01 -0500837 if (err)
838 return err;
839
Rabin Vincent998be3d2009-04-05 13:30:56 +0530840 mmc->csd[0] = cmd.response[0];
841 mmc->csd[1] = cmd.response[1];
842 mmc->csd[2] = cmd.response[2];
843 mmc->csd[3] = cmd.response[3];
Andy Fleming272cc702008-10-30 16:41:01 -0500844
845 if (mmc->version == MMC_VERSION_UNKNOWN) {
Rabin Vincent0b453ff2009-04-05 13:30:55 +0530846 int version = (cmd.response[0] >> 26) & 0xf;
Andy Fleming272cc702008-10-30 16:41:01 -0500847
848 switch (version) {
849 case 0:
850 mmc->version = MMC_VERSION_1_2;
851 break;
852 case 1:
853 mmc->version = MMC_VERSION_1_4;
854 break;
855 case 2:
856 mmc->version = MMC_VERSION_2_2;
857 break;
858 case 3:
859 mmc->version = MMC_VERSION_3;
860 break;
861 case 4:
862 mmc->version = MMC_VERSION_4;
863 break;
864 default:
865 mmc->version = MMC_VERSION_1_2;
866 break;
867 }
868 }
869
870 /* divide frequency by 10, since the mults are 10x bigger */
Rabin Vincent0b453ff2009-04-05 13:30:55 +0530871 freq = fbase[(cmd.response[0] & 0x7)];
872 mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
Andy Fleming272cc702008-10-30 16:41:01 -0500873
874 mmc->tran_speed = freq * mult;
875
Rabin Vincent998be3d2009-04-05 13:30:56 +0530876 mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
Andy Fleming272cc702008-10-30 16:41:01 -0500877
878 if (IS_SD(mmc))
879 mmc->write_bl_len = mmc->read_bl_len;
880 else
Rabin Vincent998be3d2009-04-05 13:30:56 +0530881 mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
Andy Fleming272cc702008-10-30 16:41:01 -0500882
883 if (mmc->high_capacity) {
884 csize = (mmc->csd[1] & 0x3f) << 16
885 | (mmc->csd[2] & 0xffff0000) >> 16;
886 cmult = 8;
887 } else {
888 csize = (mmc->csd[1] & 0x3ff) << 2
889 | (mmc->csd[2] & 0xc0000000) >> 30;
890 cmult = (mmc->csd[2] & 0x00038000) >> 15;
891 }
892
893 mmc->capacity = (csize + 1) << (cmult + 2);
894 mmc->capacity *= mmc->read_bl_len;
895
896 if (mmc->read_bl_len > 512)
897 mmc->read_bl_len = 512;
898
899 if (mmc->write_bl_len > 512)
900 mmc->write_bl_len = 512;
901
902 /* Select the card, and put it into Transfer Mode */
Thomas Choud52ebf12010-12-24 13:12:21 +0000903 if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
904 cmd.cmdidx = MMC_CMD_SELECT_CARD;
905 cmd.resp_type = MMC_RSP_R1b;
906 cmd.cmdarg = mmc->rca << 16;
907 cmd.flags = 0;
908 err = mmc_send_cmd(mmc, &cmd, NULL);
Andy Fleming272cc702008-10-30 16:41:01 -0500909
Thomas Choud52ebf12010-12-24 13:12:21 +0000910 if (err)
911 return err;
912 }
Andy Fleming272cc702008-10-30 16:41:01 -0500913
Lei Wenbc897b12011-05-02 16:26:26 +0000914 mmc->part_config = MMCPART_NOAVAILABLE;
Sukumar Ghoraid23e2c02010-09-20 18:29:29 +0530915 if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
916 /* check ext_csd version and capacity */
917 err = mmc_send_ext_csd(mmc, ext_csd);
918 if (!err & (ext_csd[192] >= 2)) {
919 mmc->capacity = ext_csd[212] << 0 | ext_csd[213] << 8 |
920 ext_csd[214] << 16 | ext_csd[215] << 24;
921 mmc->capacity *= 512;
922 }
Lei Wenbc897b12011-05-02 16:26:26 +0000923
924 /* store the partition info of emmc */
925 if (ext_csd[160] & PART_SUPPORT)
926 mmc->part_config = ext_csd[179];
Sukumar Ghoraid23e2c02010-09-20 18:29:29 +0530927 }
928
Andy Fleming272cc702008-10-30 16:41:01 -0500929 if (IS_SD(mmc))
930 err = sd_change_freq(mmc);
931 else
932 err = mmc_change_freq(mmc);
933
934 if (err)
935 return err;
936
937 /* Restrict card's capabilities by what the host can do */
938 mmc->card_caps &= mmc->host_caps;
939
940 if (IS_SD(mmc)) {
941 if (mmc->card_caps & MMC_MODE_4BIT) {
942 cmd.cmdidx = MMC_CMD_APP_CMD;
943 cmd.resp_type = MMC_RSP_R1;
944 cmd.cmdarg = mmc->rca << 16;
945 cmd.flags = 0;
946
947 err = mmc_send_cmd(mmc, &cmd, NULL);
948 if (err)
949 return err;
950
951 cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
952 cmd.resp_type = MMC_RSP_R1;
953 cmd.cmdarg = 2;
954 cmd.flags = 0;
955 err = mmc_send_cmd(mmc, &cmd, NULL);
956 if (err)
957 return err;
958
959 mmc_set_bus_width(mmc, 4);
960 }
961
962 if (mmc->card_caps & MMC_MODE_HS)
963 mmc_set_clock(mmc, 50000000);
964 else
965 mmc_set_clock(mmc, 25000000);
966 } else {
967 if (mmc->card_caps & MMC_MODE_4BIT) {
968 /* Set the card to use 4 bit*/
969 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
970 EXT_CSD_BUS_WIDTH,
971 EXT_CSD_BUS_WIDTH_4);
972
973 if (err)
974 return err;
975
976 mmc_set_bus_width(mmc, 4);
977 } else if (mmc->card_caps & MMC_MODE_8BIT) {
978 /* Set the card to use 8 bit*/
979 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
980 EXT_CSD_BUS_WIDTH,
981 EXT_CSD_BUS_WIDTH_8);
982
983 if (err)
984 return err;
985
986 mmc_set_bus_width(mmc, 8);
987 }
988
989 if (mmc->card_caps & MMC_MODE_HS) {
990 if (mmc->card_caps & MMC_MODE_HS_52MHz)
991 mmc_set_clock(mmc, 52000000);
992 else
993 mmc_set_clock(mmc, 26000000);
994 } else
995 mmc_set_clock(mmc, 20000000);
996 }
997
998 /* fill in device description */
999 mmc->block_dev.lun = 0;
1000 mmc->block_dev.type = 0;
1001 mmc->block_dev.blksz = mmc->read_bl_len;
Rabin Vincent9b1f9422009-04-05 13:30:54 +05301002 mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
Rabin Vincent0b453ff2009-04-05 13:30:55 +05301003 sprintf(mmc->block_dev.vendor, "Man %06x Snr %08x", mmc->cid[0] >> 8,
1004 (mmc->cid[2] << 8) | (mmc->cid[3] >> 24));
1005 sprintf(mmc->block_dev.product, "%c%c%c%c%c", mmc->cid[0] & 0xff,
1006 (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
1007 (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
1008 sprintf(mmc->block_dev.revision, "%d.%d", mmc->cid[2] >> 28,
1009 (mmc->cid[2] >> 24) & 0xf);
Andy Fleming272cc702008-10-30 16:41:01 -05001010 init_part(&mmc->block_dev);
1011
1012 return 0;
1013}
1014
1015int mmc_send_if_cond(struct mmc *mmc)
1016{
1017 struct mmc_cmd cmd;
1018 int err;
1019
1020 cmd.cmdidx = SD_CMD_SEND_IF_COND;
1021 /* We set the bit if the host supports voltages between 2.7 and 3.6 V */
1022 cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
1023 cmd.resp_type = MMC_RSP_R7;
1024 cmd.flags = 0;
1025
1026 err = mmc_send_cmd(mmc, &cmd, NULL);
1027
1028 if (err)
1029 return err;
1030
Rabin Vincent998be3d2009-04-05 13:30:56 +05301031 if ((cmd.response[0] & 0xff) != 0xaa)
Andy Fleming272cc702008-10-30 16:41:01 -05001032 return UNUSABLE_ERR;
1033 else
1034 mmc->version = SD_VERSION_2;
1035
1036 return 0;
1037}
1038
1039int mmc_register(struct mmc *mmc)
1040{
1041 /* Setup the universal parts of the block interface just once */
1042 mmc->block_dev.if_type = IF_TYPE_MMC;
1043 mmc->block_dev.dev = cur_dev_num++;
1044 mmc->block_dev.removable = 1;
1045 mmc->block_dev.block_read = mmc_bread;
1046 mmc->block_dev.block_write = mmc_bwrite;
John Rigby8feafcc2011-04-18 05:50:08 +00001047 if (!mmc->b_max)
1048 mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
Andy Fleming272cc702008-10-30 16:41:01 -05001049
1050 INIT_LIST_HEAD (&mmc->link);
1051
1052 list_add_tail (&mmc->link, &mmc_devices);
1053
1054 return 0;
1055}
1056
1057block_dev_desc_t *mmc_get_dev(int dev)
1058{
1059 struct mmc *mmc = find_mmc_device(dev);
1060
Rabin Vincente85649c2009-04-05 13:30:53 +05301061 return mmc ? &mmc->block_dev : NULL;
Andy Fleming272cc702008-10-30 16:41:01 -05001062}
1063
1064int mmc_init(struct mmc *mmc)
1065{
1066 int err;
1067
Lei Wenbc897b12011-05-02 16:26:26 +00001068 if (mmc->has_init)
1069 return 0;
1070
Andy Fleming272cc702008-10-30 16:41:01 -05001071 err = mmc->init(mmc);
1072
1073 if (err)
1074 return err;
1075
Ilya Yanokb86b85e2009-06-29 17:53:16 +04001076 mmc_set_bus_width(mmc, 1);
1077 mmc_set_clock(mmc, 1);
1078
Andy Fleming272cc702008-10-30 16:41:01 -05001079 /* Reset the Card */
1080 err = mmc_go_idle(mmc);
1081
1082 if (err)
1083 return err;
1084
Lei Wenbc897b12011-05-02 16:26:26 +00001085 /* The internal partition reset to user partition(0) at every CMD0*/
1086 mmc->part_num = 0;
1087
Andy Fleming272cc702008-10-30 16:41:01 -05001088 /* Test for SD version 2 */
1089 err = mmc_send_if_cond(mmc);
1090
Andy Fleming272cc702008-10-30 16:41:01 -05001091 /* Now try to get the SD card's operating condition */
1092 err = sd_send_op_cond(mmc);
1093
1094 /* If the command timed out, we check for an MMC card */
1095 if (err == TIMEOUT) {
1096 err = mmc_send_op_cond(mmc);
1097
1098 if (err) {
1099 printf("Card did not respond to voltage select!\n");
1100 return UNUSABLE_ERR;
1101 }
1102 }
1103
Lei Wenbc897b12011-05-02 16:26:26 +00001104 err = mmc_startup(mmc);
1105 if (err)
1106 mmc->has_init = 0;
1107 else
1108 mmc->has_init = 1;
1109 return err;
Andy Fleming272cc702008-10-30 16:41:01 -05001110}
1111
1112/*
1113 * CPU and board-specific MMC initializations. Aliased function
1114 * signals caller to move on
1115 */
1116static int __def_mmc_init(bd_t *bis)
1117{
1118 return -1;
1119}
1120
Peter Tyserf9a109b2009-04-20 11:08:46 -05001121int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
1122int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
Andy Fleming272cc702008-10-30 16:41:01 -05001123
1124void print_mmc_devices(char separator)
1125{
1126 struct mmc *m;
1127 struct list_head *entry;
1128
1129 list_for_each(entry, &mmc_devices) {
1130 m = list_entry(entry, struct mmc, link);
1131
1132 printf("%s: %d", m->name, m->block_dev.dev);
1133
1134 if (entry->next != &mmc_devices)
1135 printf("%c ", separator);
1136 }
1137
1138 printf("\n");
1139}
1140
Lei Wenea6ebe22011-05-02 16:26:25 +00001141int get_mmc_num(void)
1142{
1143 return cur_dev_num;
1144}
1145
Andy Fleming272cc702008-10-30 16:41:01 -05001146int mmc_initialize(bd_t *bis)
1147{
1148 INIT_LIST_HEAD (&mmc_devices);
1149 cur_dev_num = 0;
1150
1151 if (board_mmc_init(bis) < 0)
1152 cpu_mmc_init(bis);
1153
1154 print_mmc_devices(',');
1155
1156 return 0;
1157}