]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mmc/bfin_sdh.c
Blackfin: add driver for on-chip MMC/SD controller
[karo-tx-uboot.git] / drivers / mmc / bfin_sdh.c
1 /*
2  * Driver for Blackfin on-chip SDH controller
3  *
4  * Copyright (c) 2008 Analog Devices Inc.
5  *
6  * Licensed under the GPL-2 or later.
7  */
8
9 #include <common.h>
10 #include <malloc.h>
11 #include <part.h>
12 #include <mmc.h>
13
14 #include <asm/io.h>
15 #include <asm/errno.h>
16 #include <asm/byteorder.h>
17 #include <asm/blackfin.h>
18 #include <asm/mach-common/bits/sdh.h>
19 #include <asm/mach-common/bits/dma.h>
20
21 #include "bfin_sdh.h"
22
23 /* SD_CLK frequency must be less than 400k in identification mode */
24 #ifndef CONFIG_SYS_MMC_CLK_ID
25 #define CONFIG_SYS_MMC_CLK_ID           200000
26 #endif
27 /* SD_CLK for normal working */
28 #ifndef CONFIG_SYS_MMC_CLK_OP
29 #define CONFIG_SYS_MMC_CLK_OP           25000000
30 #endif
31 /* support 3.2-3.3V and 3.3-3.4V */
32 #define CONFIG_SYS_MMC_OP_COND          0x00300000
33 #define MMC_DEFAULT_RCA         1
34
35 #if defined(__ADSPBF51x__)
36 # define bfin_read_SDH_PWR_CTL          bfin_read_RSI_PWR_CONTROL
37 # define bfin_write_SDH_PWR_CTL         bfin_write_RSI_PWR_CONTROL
38 # define bfin_read_SDH_CLK_CTL          bfin_read_RSI_CLK_CONTROL
39 # define bfin_write_SDH_CLK_CTL         bfin_write_RSI_CLK_CONTROL
40 # define bfin_write_SDH_ARGUMENT        bfin_write_RSI_ARGUMENT
41 # define bfin_write_SDH_COMMAND         bfin_write_RSI_COMMAND
42 # define bfin_read_SDH_RESPONSE0        bfin_read_RSI_RESPONSE0
43 # define bfin_read_SDH_RESPONSE1        bfin_read_RSI_RESPONSE1
44 # define bfin_read_SDH_RESPONSE2        bfin_read_RSI_RESPONSE2
45 # define bfin_read_SDH_RESPONSE3        bfin_read_RSI_RESPONSE3
46 # define bfin_write_SDH_DATA_TIMER      bfin_write_RSI_DATA_TIMER
47 # define bfin_write_SDH_DATA_LGTH       bfin_write_RSI_DATA_LGTH
48 # define bfin_read_SDH_DATA_CTL         bfin_read_RSI_DATA_CONTROL
49 # define bfin_write_SDH_DATA_CTL        bfin_write_RSI_DATA_CONTROL
50 # define bfin_read_SDH_STATUS           bfin_read_RSI_STATUS
51 # define bfin_write_SDH_STATUS_CLR      bfin_write_RSI_STATUSCL
52 # define bfin_read_SDH_CFG              bfin_read_RSI_CONFIG
53 # define bfin_write_SDH_CFG             bfin_write_RSI_CONFIG
54 # define bfin_write_DMA_START_ADDR      bfin_write_DMA4_START_ADDR
55 # define bfin_write_DMA_X_COUNT         bfin_write_DMA4_X_COUNT
56 # define bfin_write_DMA_X_MODIFY        bfin_write_DMA4_X_MODIFY
57 # define bfin_write_DMA_CONFIG          bfin_write_DMA4_CONFIG
58 #elif defined(__ADSPBF54x__)
59 # define bfin_write_DMA_START_ADDR      bfin_write_DMA22_START_ADDR
60 # define bfin_write_DMA_X_COUNT         bfin_write_DMA22_X_COUNT
61 # define bfin_write_DMA_X_MODIFY        bfin_write_DMA22_X_MODIFY
62 # define bfin_write_DMA_CONFIG          bfin_write_DMA22_CONFIG
63 #else
64 # error no support for this proc yet
65 #endif
66
67 static unsigned int mmc_rca;
68 static int mmc_card_is_sd;
69 static block_dev_desc_t mmc_blkdev;
70 struct mmc_cid cid;
71 static __u32 csd[4];
72
73 #define get_bits(resp, start, size)                                     \
74         ({                                                              \
75                 const int __size = size;                                \
76                 const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1;    \
77                 const int32_t __off = 3 - ((start) / 32);                       \
78                 const int32_t __shft = (start) & 31;                    \
79                 uint32_t __res;                                         \
80                                                                         \
81                 __res = resp[__off] >> __shft;                          \
82                 if (__size + __shft > 32)                               \
83                         __res |= resp[__off-1] << ((32 - __shft) % 32); \
84                 __res & __mask;                                         \
85         })
86
87
88 block_dev_desc_t *mmc_get_dev(int dev)
89 {
90         return &mmc_blkdev;
91 }
92
93 static void mci_set_clk(unsigned long clk)
94 {
95         unsigned long sys_clk;
96         unsigned long clk_div;
97         __u16 clk_ctl = 0;
98
99         /* setting SD_CLK */
100         sys_clk = get_sclk();
101         bfin_write_SDH_CLK_CTL(0);
102         if (sys_clk % (2 * clk) == 0)
103                 clk_div = sys_clk / (2 * clk) - 1;
104         else
105                 clk_div = sys_clk / (2 * clk);
106
107         if (clk_div > 0xff)
108                 clk_div = 0xff;
109         clk_ctl |= (clk_div & 0xff);
110         clk_ctl |= CLK_E;
111         bfin_write_SDH_CLK_CTL(clk_ctl);
112 }
113
114 static int
115 mmc_cmd(unsigned long cmd, unsigned long arg, void *resp, unsigned long flags)
116 {
117         unsigned int sdh_cmd;
118         unsigned int status;
119         int ret = 0;
120         sdh_cmd = 0;
121         unsigned long *response = resp;
122         sdh_cmd |= cmd;
123
124         if (flags & MMC_RSP_PRESENT)
125                 sdh_cmd |= CMD_RSP;
126
127         if (flags & MMC_RSP_136)
128                 sdh_cmd |= CMD_L_RSP;
129
130         bfin_write_SDH_ARGUMENT(arg);
131         bfin_write_SDH_COMMAND(sdh_cmd | CMD_E);
132
133         /* wait for a while */
134         do {
135                 udelay(1);
136                 status = bfin_read_SDH_STATUS();
137         } while (!(status & (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT |
138                 CMD_CRC_FAIL)));
139
140         if (flags & MMC_RSP_PRESENT) {
141                 response[0] = bfin_read_SDH_RESPONSE0();
142                 if (flags & MMC_RSP_136) {
143                         response[1] = bfin_read_SDH_RESPONSE1();
144                         response[2] = bfin_read_SDH_RESPONSE2();
145                         response[3] = bfin_read_SDH_RESPONSE3();
146                 }
147         }
148
149         if (status & CMD_TIME_OUT) {
150                 printf("CMD%d timeout\n", (int)cmd);
151                 ret |= -ETIMEDOUT;
152         } else if (status & CMD_CRC_FAIL && flags & MMC_RSP_CRC) {
153                 printf("CMD%d CRC failure\n", (int)cmd);
154                 ret |= -EILSEQ;
155         }
156         bfin_write_SDH_STATUS_CLR(CMD_SENT_STAT | CMD_RESP_END_STAT |
157                                 CMD_TIMEOUT_STAT | CMD_CRC_FAIL_STAT);
158         return ret;
159 }
160
161 static int
162 mmc_acmd(unsigned long cmd, unsigned long arg, void *resp, unsigned long flags)
163 {
164         unsigned long aresp[4];
165         int ret = 0;
166
167         ret = mmc_cmd(MMC_CMD_APP_CMD, 0, aresp,
168                       MMC_RSP_PRESENT);
169         if (ret)
170                 return ret;
171
172         if ((aresp[0] & (ILLEGAL_COMMAND | APP_CMD)) != APP_CMD)
173                 return -ENODEV;
174         ret = mmc_cmd(cmd, arg, resp, flags);
175         return ret;
176 }
177
178 static unsigned long
179 mmc_bread(int dev, unsigned long start, lbaint_t blkcnt, void *buffer)
180 {
181         int ret, i;
182         unsigned long resp[4];
183         unsigned long card_status;
184         __u8 *buf = buffer;
185         __u32 status;
186         __u16 data_ctl = 0;
187         __u16 dma_cfg = 0;
188
189         if (blkcnt == 0)
190                 return 0;
191         debug("mmc_bread: dev %d, start %d, blkcnt %d\n", dev, start, blkcnt);
192         /* Force to use 512-byte block,because a lot of code depends on this */
193         data_ctl |= 9 << 4;
194         data_ctl |= DTX_DIR;
195         bfin_write_SDH_DATA_CTL(data_ctl);
196         dma_cfg |= WDSIZE_32 | RESTART | WNR | DMAEN;
197
198         /* FIXME later */
199         bfin_write_SDH_DATA_TIMER(0xFFFFFFFF);
200         for (i = 0; i < blkcnt; ++i, ++start) {
201                 blackfin_dcache_flush_invalidate_range(buf + i * mmc_blkdev.blksz,
202                         buf + (i + 1) * mmc_blkdev.blksz);
203                 bfin_write_DMA_START_ADDR(buf + i * mmc_blkdev.blksz);
204                 bfin_write_DMA_X_COUNT(mmc_blkdev.blksz / 4);
205                 bfin_write_DMA_X_MODIFY(4);
206                 bfin_write_DMA_CONFIG(dma_cfg);
207                 bfin_write_SDH_DATA_LGTH(mmc_blkdev.blksz);
208                 /* Put the device into Transfer state */
209                 ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, MMC_RSP_R1);
210                 if (ret) {
211                         printf("MMC_CMD_SELECT_CARD failed\n");
212                         goto out;
213                 }
214                 /* Set block length */
215                 ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, MMC_RSP_R1);
216                 if (ret) {
217                         printf("MMC_CMD_SET_BLOCKLEN failed\n");
218                         goto out;
219                 }
220                 ret = mmc_cmd(MMC_CMD_READ_SINGLE_BLOCK,
221                               start * mmc_blkdev.blksz, resp,
222                               MMC_RSP_R1);
223                 if (ret) {
224                         printf("MMC_CMD_READ_SINGLE_BLOCK failed\n");
225                         goto out;
226                 }
227                 bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E);
228
229                 do {
230                         udelay(1);
231                         status = bfin_read_SDH_STATUS();
232                 } while (!(status & (DAT_BLK_END | DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN)));
233
234                 if (status & (DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN)) {
235                         bfin_write_SDH_STATUS_CLR(DAT_TIMEOUT_STAT | \
236                                 DAT_CRC_FAIL_STAT | RX_OVERRUN_STAT);
237                         goto read_error;
238                 } else {
239                         bfin_write_SDH_STATUS_CLR(DAT_BLK_END_STAT | DAT_END_STAT);
240                         mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, 0);
241                 }
242         }
243  out:
244
245         return i;
246
247  read_error:
248         mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, MMC_RSP_R1);
249         printf("mmc: bread failed, status = %08x, card status = %08lx\n",
250                status, card_status);
251         goto out;
252 }
253
254 static unsigned long
255 mmc_bwrite(int dev, unsigned long start, lbaint_t blkcnt, const void *buffer)
256 {
257         int ret, i = 0;
258         unsigned long resp[4];
259         unsigned long card_status;
260         const __u8 *buf = buffer;
261         __u32 status;
262         __u16 data_ctl = 0;
263         __u16 dma_cfg = 0;
264
265         if (blkcnt == 0)
266                 return 0;
267
268         debug("mmc_bwrite: dev %d, start %lx, blkcnt %lx\n",
269                  dev, start, blkcnt);
270         /* Force to use 512-byte block,because a lot of code depends on this */
271         data_ctl |= 9 << 4;
272         data_ctl &= ~DTX_DIR;
273         bfin_write_SDH_DATA_CTL(data_ctl);
274         dma_cfg |= WDSIZE_32 | RESTART | DMAEN;
275         /* FIXME later */
276         bfin_write_SDH_DATA_TIMER(0xFFFFFFFF);
277         for (i = 0; i < blkcnt; ++i, ++start) {
278                 bfin_write_DMA_START_ADDR(buf + i * mmc_blkdev.blksz);
279                 bfin_write_DMA_X_COUNT(mmc_blkdev.blksz / 4);
280                 bfin_write_DMA_X_MODIFY(4);
281                 bfin_write_DMA_CONFIG(dma_cfg);
282                 bfin_write_SDH_DATA_LGTH(mmc_blkdev.blksz);
283
284                 /* Put the device into Transfer state */
285                 ret = mmc_cmd(MMC_CMD_SELECT_CARD, mmc_rca << 16, resp, MMC_RSP_R1);
286                 if (ret) {
287                         printf("MMC_CMD_SELECT_CARD failed\n");
288                         goto out;
289                 }
290                 /* Set block length */
291                 ret = mmc_cmd(MMC_CMD_SET_BLOCKLEN, mmc_blkdev.blksz, resp, MMC_RSP_R1);
292                 if (ret) {
293                         printf("MMC_CMD_SET_BLOCKLEN failed\n");
294                         goto out;
295                 }
296                 ret = mmc_cmd(MMC_CMD_WRITE_BLOCK,
297                               start * mmc_blkdev.blksz, resp,
298                               MMC_RSP_R1);
299                 if (ret) {
300                         printf("MMC_CMD_WRITE_SINGLE_BLOCK failed\n");
301                         goto out;
302                 }
303                 bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E);
304
305                 do {
306                         udelay(1);
307                         status = bfin_read_SDH_STATUS();
308                 } while (!(status & (DAT_BLK_END | DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | TX_UNDERRUN)));
309
310                 if (status & (DAT_TIME_OUT | DAT_CRC_FAIL | TX_UNDERRUN)) {
311                         bfin_write_SDH_STATUS_CLR(DAT_TIMEOUT_STAT |
312                                 DAT_CRC_FAIL_STAT | TX_UNDERRUN_STAT);
313                         goto write_error;
314                 } else {
315                         bfin_write_SDH_STATUS_CLR(DAT_BLK_END_STAT | DAT_END_STAT);
316                         mmc_cmd(MMC_CMD_SELECT_CARD, 0, resp, 0);
317                 }
318         }
319  out:
320         return i;
321
322  write_error:
323         mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, MMC_RSP_R1);
324         printf("mmc: bwrite failed, status = %08x, card status = %08lx\n",
325                status, card_status);
326         goto out;
327 }
328
329 static void mmc_parse_cid(struct mmc_cid *cid, unsigned long *resp)
330 {
331         cid->mid = resp[0] >> 24;
332         cid->oid = (resp[0] >> 8) & 0xffff;
333         cid->pnm[0] = resp[0];
334         cid->pnm[1] = resp[1] >> 24;
335         cid->pnm[2] = resp[1] >> 16;
336         cid->pnm[3] = resp[1] >> 8;
337         cid->pnm[4] = resp[1];
338         cid->pnm[5] = resp[2] >> 24;
339         cid->pnm[6] = 0;
340         cid->prv = resp[2] >> 16;
341         cid->psn = (resp[2] << 16) | (resp[3] >> 16);
342         cid->mdt = resp[3] >> 8;
343 }
344
345 static void sd_parse_cid(struct mmc_cid *cid, unsigned long *resp)
346 {
347         cid->mid = resp[0] >> 24;
348         cid->oid = (resp[0] >> 8) & 0xffff;
349         cid->pnm[0] = resp[0];
350         cid->pnm[1] = resp[1] >> 24;
351         cid->pnm[2] = resp[1] >> 16;
352         cid->pnm[3] = resp[1] >> 8;
353         cid->pnm[4] = resp[1];
354         cid->pnm[5] = 0;
355         cid->pnm[6] = 0;
356         cid->prv = resp[2] >> 24;
357         cid->psn = (resp[2] << 8) | (resp[3] >> 24);
358         cid->mdt = (resp[3] >> 8) & 0x0fff;
359 }
360
361 static void mmc_dump_cid(const struct mmc_cid *cid)
362 {
363         printf("CID information:\n");
364         printf("Manufacturer ID:       %02X\n", cid->mid);
365         printf("OEM/Application ID:    %04X\n", cid->oid);
366         printf("Product name:          %s\n", cid->pnm);
367         printf("Product Revision:      %u.%u\n",
368                cid->prv >> 4, cid->prv & 0x0f);
369         printf("Product Serial Number: %lu\n", cid->psn);
370         printf("Manufacturing Date:    %02u/%02u\n",
371                cid->mdt >> 4, cid->mdt & 0x0f);
372 }
373
374 static void mmc_dump_csd(__u32 *csd)
375 {
376         printf("CSD information:\n");
377         printf("CSD structure version:   1.%u\n", get_bits(csd, 126, 2));
378         printf("Card command classes:    %03x\n", get_bits(csd, 84, 12));
379         printf("Max trans speed: %s\n", (get_bits(csd, 96, 8) == 0x32) ? "25MHz" : "50MHz");
380         printf("Read block length:       %d\n", 1 << get_bits(csd, 80, 4));
381         printf("Write block length:      %u\n", 1 << get_bits(csd, 22, 4));
382         printf("Card capacity:          %u bytes\n",
383                (get_bits(csd, 62, 12) + 1) * (1 << (get_bits(csd, 47, 3) + 2)) *
384                (1 << get_bits(csd, 80, 4)));
385         putc('\n');
386 }
387
388 static int mmc_idle_cards(void)
389 {
390         int ret = 0;
391
392         /* Reset all cards */
393         ret = mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, NULL, 0);
394         if (ret)
395                 return ret;
396         udelay(500);
397         return mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, NULL, 0);
398 }
399
400 static int sd_init_card(struct mmc_cid *cid, int verbose)
401 {
402         unsigned long resp[4];
403         int i, ret = 0;
404
405         mmc_idle_cards();
406         for (i = 0; i < 1000; ++i) {
407                 ret = mmc_acmd(SD_CMD_APP_SEND_OP_COND, CONFIG_SYS_MMC_OP_COND,
408                                resp, MMC_RSP_R3);
409                 if (ret || (resp[0] & 0x80000000))
410                         break;
411                 ret = -ETIMEDOUT;
412         }
413         if (ret)
414                 return ret;
415
416         ret = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, resp, MMC_RSP_R2);
417         if (ret)
418                 return ret;
419         sd_parse_cid(cid, resp);
420         if (verbose)
421                 mmc_dump_cid(cid);
422
423         /* Get RCA of the card that responded */
424         ret = mmc_cmd(SD_CMD_SEND_RELATIVE_ADDR, 0, resp, MMC_RSP_R6);
425         if (ret)
426                 return ret;
427
428         mmc_rca = (resp[0] >> 16) & 0xffff;
429         if (verbose)
430                 printf("SD Card detected (RCA %u)\n", mmc_rca);
431         mmc_card_is_sd = 1;
432         return 0;
433 }
434
435 static int mmc_init_card(struct mmc_cid *cid, int verbose)
436 {
437         unsigned long resp[4];
438         int i, ret = 0;
439
440         mmc_idle_cards();
441         for (i = 0; i < 1000; ++i) {
442                 ret = mmc_cmd(MMC_CMD_SEND_OP_COND, CONFIG_SYS_MMC_OP_COND, resp,
443                               MMC_RSP_R3);
444                 if (ret || (resp[0] & 0x80000000))
445                         break;
446                 ret = -ETIMEDOUT;
447         }
448         if (ret)
449                 return ret;
450
451         /* Get CID of all cards. FIXME: Support more than one card */
452         ret = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, resp, MMC_RSP_R2);
453         if (ret)
454                 return ret;
455         mmc_parse_cid(cid, resp);
456         if (verbose)
457                 mmc_dump_cid(cid);
458
459         /* Set Relative Address of the card that responded */
460         ret = mmc_cmd(MMC_CMD_SET_RELATIVE_ADDR, mmc_rca << 16, resp,
461                       MMC_RSP_R1);
462         return ret;
463 }
464
465 int mmc_init(int verbose)
466 {
467         __u16 pwr_ctl = 0;
468         int ret;
469         unsigned int max_blksz;
470         /* Initialize sdh controller */
471 #if defined(__ADSPBF54x__)
472         bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
473         bfin_write_PORTC_FER(bfin_read_PORTC_FER() | 0x3F00);
474         bfin_write_PORTC_MUX(bfin_read_PORTC_MUX() & ~0xFFF0000);
475 #elif defined(__ADSPBF51x__)
476         bfin_write_PORTG_FER(bfin_read_PORTG_FER() | 0x01F8);
477         bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() & ~0x3FC) | 0x154);
478 #else
479 # error no portmux for this proc yet
480 #endif
481         bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
482         /* Disable card detect pin */
483         bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | 0x60);
484         mci_set_clk(CONFIG_SYS_MMC_CLK_ID);
485         /* setting power control */
486         pwr_ctl |= ROD_CTL;
487         pwr_ctl |= PWR_ON;
488         bfin_write_SDH_PWR_CTL(pwr_ctl);
489         mmc_card_is_sd = 0;
490         ret = sd_init_card(&cid, verbose);
491         if (ret) {
492                 mmc_rca = MMC_DEFAULT_RCA;
493                 ret = mmc_init_card(&cid, verbose);
494         }
495         if (ret)
496                 return ret;
497         /* Get CSD from the card */
498         ret = mmc_cmd(MMC_CMD_SEND_CSD, mmc_rca << 16, csd, MMC_RSP_R2);
499         if (ret)
500                 return ret;
501         if (verbose)
502                 mmc_dump_csd(csd);
503         /* Initialize the blockdev structure */
504         mmc_blkdev.if_type = IF_TYPE_MMC;
505         mmc_blkdev.part_type = PART_TYPE_DOS;
506         mmc_blkdev.block_read = mmc_bread;
507         mmc_blkdev.block_write = mmc_bwrite;
508         sprintf(mmc_blkdev.vendor,
509                 "Man %02x%04x Snr %08lx",
510                 cid.mid, cid.oid, cid.psn);
511         strncpy(mmc_blkdev.product, cid.pnm,
512                 sizeof(mmc_blkdev.product));
513         sprintf(mmc_blkdev.revision, "%x %x",
514                 cid.prv >> 4, cid.prv & 0x0f);
515
516         max_blksz = 1 << get_bits(csd, 80, 4);
517         /*
518          * If we can't use 512 byte blocks, refuse to deal with the
519          * card. Tons of code elsewhere seems to depend on this.
520          */
521         if (max_blksz < 512 || (max_blksz > 512 && !get_bits(csd, 79, 1))) {
522                 printf("Card does not support 512 byte reads, aborting.\n");
523                 return -ENODEV;
524         }
525
526         mmc_blkdev.blksz = 512;
527         mmc_blkdev.lba = (get_bits(csd, 62, 12) + 1) * (1 << (get_bits(csd, 47, 3) + 2));
528         mci_set_clk(CONFIG_SYS_MMC_CLK_OP);
529         init_part(&mmc_blkdev);
530         return 0;
531 }
532
533 int mmc_read(ulong src, uchar *dst, int size)
534 {
535         return -ENOSYS;
536 }
537
538 int mmc_write(uchar *src, ulong dst, int size)
539 {
540         return -ENOSYS;
541 }
542
543 int mmc2info(ulong addr)
544 {
545         return 0;
546 }