2 * u-boot S3C2410 MMC/SD card driver
3 * (C) Copyright 2006 by OpenMoko, Inc.
4 * Author: Harald Welte <laforge@openmoko.org>
6 * based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c
7 * (C) 2005-2005 Thomas Kleffel
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 #include <asm/errno.h>
34 #if defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C)
37 #define pr_debug(fmt, args...) printf(fmt, ##args)
39 #define pr_debug(...) do { } while(0)
42 #define CONFIG_MMC_WIDE
44 static S3C2410_SDI
*sdi
;
46 static block_dev_desc_t mmc_dev
;
48 block_dev_desc_t
* mmc_get_dev(int dev
)
50 return ((block_dev_desc_t
*)&mmc_dev
);
54 * FIXME needs to read cid and csd info to determine block size
55 * and other parameters
57 static uchar mmc_buf
[MMC_BLOCK_SIZE
];
58 static mmc_csd_t mmc_csd
;
59 static int mmc_ready
= 0;
63 #define CMD_F_RESP 0x01
64 #define CMD_F_RESP_LONG 0x02
66 #define CMD_F_RESP_R7 CMD_F_RESP
68 static u_int32_t
*mmc_cmd(ushort cmd
, ulong arg
, ushort flags
)
70 static u_int32_t resp
[5];
73 u_int32_t csta_rdy_bit
= S3C2410_SDICMDSTAT_CMDSENT
;
75 memset(resp
, 0, sizeof(resp
));
77 debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd
, arg
, flags
);
79 sdi
->SDICSTA
= 0xffffffff;
80 sdi
->SDIDSTA
= 0xffffffff;
81 sdi
->SDIFSTA
= 0xffffffff;
85 ccon
= cmd
& S3C2410_SDICMDCON_INDEX
;
86 ccon
|= S3C2410_SDICMDCON_SENDERHOST
|S3C2410_SDICMDCON_CMDSTART
;
88 if (flags
& CMD_F_RESP
) {
89 ccon
|= S3C2410_SDICMDCON_WAITRSP
;
90 csta_rdy_bit
= S3C2410_SDICMDSTAT_RSPFIN
; /* 1 << 9 */
93 if (flags
& CMD_F_RESP_LONG
)
94 ccon
|= S3C2410_SDICMDCON_LONGRSP
;
100 if (csta
& csta_rdy_bit
)
102 if (csta
& S3C2410_SDICMDSTAT_CMDTIMEOUT
) {
103 printf("===============> MMC CMD Timeout\n");
104 sdi
->SDICSTA
|= S3C2410_SDICMDSTAT_CMDTIMEOUT
;
109 debug("final MMC CMD status 0x%x\n", csta
);
111 sdi
->SDICSTA
|= csta_rdy_bit
;
113 if (flags
& CMD_F_RESP
) {
114 resp
[0] = sdi
->SDIRSP0
;
115 resp
[1] = sdi
->SDIRSP1
;
116 resp
[2] = sdi
->SDIRSP2
;
117 resp
[3] = sdi
->SDIRSP3
;
123 #define FIFO_FILL(host) ((host->SDIFSTA & S3C2410_SDIFSTA_COUNTMASK) >> 2)
125 static int mmc_block_read(uchar
*dst
, ulong src
, ulong len
)
127 u_int32_t dcon
, fifo
;
128 u_int32_t
*dst_u32
= (u_int32_t
*)dst
;
134 debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong
)dst
, src
, len
);
137 resp
= mmc_cmd(MMC_CMD_SET_BLOCKLEN
, len
, CMD_F_RESP
);
140 //sdi->SDIPRE = 0xff;
143 dcon
= (len
>> 9) & S3C2410_SDIDCON_BLKNUM
;
144 dcon
|= S3C2410_SDIDCON_BLOCKMODE
;
145 dcon
|= S3C2410_SDIDCON_RXAFTERCMD
|S3C2410_SDIDCON_XFER_RXSTART
;
147 dcon
|= S3C2410_SDIDCON_WIDEBUS
;
148 #if defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
149 dcon
|= S3C2440_SDIDCON_DS_WORD
| S3C2440_SDIDCON_DATSTART
;
153 /* send read command */
154 resp
= mmc_cmd(MMC_CMD_READ_BLOCK
, (mmc_dev
.if_type
== IF_TYPE_SDHC
) ? (src
>> 9) : src
, CMD_F_RESP
);
157 u_int32_t sdidsta
= sdi
->SDIDSTA
;
158 fifo
= FIFO_FILL(sdi
);
159 if (sdidsta
& (S3C2410_SDIDSTA_FIFOFAIL
|
160 S3C2410_SDIDSTA_CRCFAIL
|
161 S3C2410_SDIDSTA_RXCRCFAIL
|
162 S3C2410_SDIDSTA_DATATIMEOUT
)) {
163 printf("mmc_block_read: err SDIDSTA=0x%08x\n", sdidsta
);
168 //debug("dst_u32 = 0x%08x\n", dst_u32);
169 *(dst_u32
++) = sdi
->SDIDAT
;
179 debug("waiting for SDIDSTA (currently 0x%08x\n", sdi
->SDIDSTA
);
180 while (!(sdi
->SDIDSTA
& (1 << 4))) {}
181 debug("done waiting for SDIDSTA (currently 0x%08x\n", sdi
->SDIDSTA
);
185 if (!(sdi
->SDIDSTA
& S3C2410_SDIDSTA_XFERFINISH
))
186 debug("mmc_block_read; transfer not finished!\n");
191 static int mmc_block_write(ulong dst
, uchar
*src
, int len
)
193 printf("MMC block write not yet supported on S3C2410!\n");
198 int mmc_read(ulong src
, uchar
*dst
, int size
)
200 ulong end
, part_start
, part_end
, part_len
, aligned_start
, aligned_end
;
201 ulong mmc_block_size
, mmc_block_address
;
207 printf("Please initialize the MMC first\n");
211 mmc_block_size
= MMC_BLOCK_SIZE
;
212 mmc_block_address
= ~(mmc_block_size
- 1);
216 part_start
= ~mmc_block_address
& src
;
217 part_end
= ~mmc_block_address
& end
;
218 aligned_start
= mmc_block_address
& src
;
219 aligned_end
= mmc_block_address
& end
;
221 /* all block aligned accesses */
222 debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
223 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
225 part_len
= mmc_block_size
- part_start
;
226 debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
227 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
228 if ((mmc_block_read(mmc_buf
, aligned_start
, mmc_block_size
)) < 0)
231 memcpy(dst
, mmc_buf
+part_start
, part_len
);
235 debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
236 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
237 for (; src
< aligned_end
; src
+= mmc_block_size
, dst
+= mmc_block_size
) {
238 debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
239 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
240 if ((mmc_block_read((uchar
*)(dst
), src
, mmc_block_size
)) < 0)
243 debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
244 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
245 if (part_end
&& src
< end
) {
246 debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
247 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
248 if ((mmc_block_read(mmc_buf
, aligned_end
, mmc_block_size
)) < 0)
251 memcpy(dst
, mmc_buf
, part_end
);
256 int mmc_write(uchar
*src
, ulong dst
, int size
)
258 ulong end
, part_start
, part_end
, part_len
, aligned_start
, aligned_end
;
259 ulong mmc_block_size
, mmc_block_address
;
265 printf("Please initialize the MMC first\n");
269 mmc_block_size
= MMC_BLOCK_SIZE
;
270 mmc_block_address
= ~(mmc_block_size
- 1);
274 part_start
= ~mmc_block_address
& dst
;
275 part_end
= ~mmc_block_address
& end
;
276 aligned_start
= mmc_block_address
& dst
;
277 aligned_end
= mmc_block_address
& end
;
279 /* all block aligned accesses */
280 debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
281 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
283 part_len
= mmc_block_size
- part_start
;
284 debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
285 (ulong
)src
, dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
286 if ((mmc_block_read(mmc_buf
, aligned_start
, mmc_block_size
)) < 0)
289 memcpy(mmc_buf
+part_start
, src
, part_len
);
290 if ((mmc_block_write(aligned_start
, mmc_buf
, mmc_block_size
)) < 0)
296 debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
297 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
298 for (; dst
< aligned_end
; src
+= mmc_block_size
, dst
+= mmc_block_size
) {
299 debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
300 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
301 if ((mmc_block_write(dst
, (uchar
*)src
, mmc_block_size
)) < 0)
305 debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
306 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
307 if (part_end
&& dst
< end
) {
308 debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
309 src
, (ulong
)dst
, end
, part_start
, part_end
, aligned_start
, aligned_end
);
310 if ((mmc_block_read(mmc_buf
, aligned_end
, mmc_block_size
)) < 0)
313 memcpy(mmc_buf
, src
, part_end
);
314 if ((mmc_block_write(aligned_end
, mmc_buf
, mmc_block_size
)) < 0)
321 ulong
mmc_bread(int dev_num
, ulong blknr
, ulong blkcnt
, void *dst
)
323 int mmc_block_size
= MMC_BLOCK_SIZE
;
324 ulong src
= blknr
* mmc_block_size
+ CFG_MMC_BASE
;
326 mmc_read(src
, dst
, blkcnt
*mmc_block_size
);
330 /* MMC_DEFAULT_RCA should probably be just 1, but this may break other code
331 that expects it to be shifted. */
332 static u_int16_t rca
= MMC_DEFAULT_RCA
>> 16;
334 static u_int32_t
mmc_size(const struct mmc_csd
*csd
)
336 u_int32_t block_len
, mult
, blocknr
;
338 block_len
= csd
->read_bl_len
<< 12;
339 mult
= csd
->c_size_mult1
<< 8;
340 blocknr
= (csd
->c_size
+1) * mult
;
342 return blocknr
* block_len
;
346 char pnm_0
; /* product name */
347 char oid_1
; /* OEM/application ID */
349 uint8_t mid
; /* manufacturer ID */
354 uint8_t psn_2
; /* product serial number */
356 uint8_t psn_0
; /* MSB */
357 uint8_t prv
; /* product revision */
358 uint8_t crc
; /* CRC7 checksum, b0 is unused and set to 1 */
359 uint8_t mdt_1
; /* manufacturing date, LSB, RRRRyyyy yyyymmmm */
360 uint8_t mdt_0
; /* MSB */
361 uint8_t psn_3
; /* LSB */
364 static void print_mmc_cid(mmc_cid_t
*cid
)
366 printf("MMC found. Card desciption is:\n");
367 printf("Manufacturer ID = %02x%02x%02x\n",
368 cid
->id
[0], cid
->id
[1], cid
->id
[2]);
369 printf("HW/FW Revision = %x %x\n",cid
->hwrev
, cid
->fwrev
);
370 cid
->hwrev
= cid
->fwrev
= 0; /* null terminate string */
371 printf("Product Name = %s\n",cid
->name
);
372 printf("Serial Number = %02x%02x%02x\n",
373 cid
->sn
[0], cid
->sn
[1], cid
->sn
[2]);
374 printf("Month = %d\n",cid
->month
);
375 printf("Year = %d\n",1997 + cid
->year
);
378 static void print_sd_cid(const struct sd_cid
*cid
)
380 printf("Manufacturer: 0x%02x, OEM \"%c%c\"\n",
381 cid
->mid
, cid
->oid_0
, cid
->oid_1
);
382 printf("Product name: \"%c%c%c%c%c\", revision %d.%d\n",
383 cid
->pnm_0
, cid
->pnm_1
, cid
->pnm_2
, cid
->pnm_3
, cid
->pnm_4
,
384 cid
->prv
>> 4, cid
->prv
& 15);
385 printf("Serial number: %u\n",
386 cid
->psn_0
<< 24 | cid
->psn_1
<< 16 | cid
->psn_2
<< 8 |
388 printf("Manufacturing date: %d/%d\n",
390 2000+((cid
->mdt_0
& 15) << 4)+((cid
->mdt_1
& 0xf0) >> 4));
391 printf("CRC: 0x%02x, b0 = %d\n",
392 cid
->crc
>> 1, cid
->crc
& 1);
395 int mmc_init(int verbose
)
397 int retries
, rc
= -ENODEV
;
400 S3C24X0_CLOCK_POWER
* const clk_power
= S3C24X0_GetBase_CLOCK_POWER();
401 block_dev_desc_t
*mmc_blkdev_p
= &mmc_dev
;
403 sdi
= S3C2410_GetBase_SDI();
405 debug("mmc_init(PCLK=%u)\n", get_PCLK());
407 clk_power
->CLKCON
|= (1 << 9);
410 #if defined(CONFIG_S3C2410)
411 /* S3C2410 has some bug that prevents reliable operation at higher speed */
412 //sdi->SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */
413 sdi
->SDIPRE
= 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */
414 sdi
->SDIDTIMER
= 0xffff;
415 #elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
416 sdi
->SDIPRE
= 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */
417 sdi
->SDIDTIMER
= 0x7fffff;
420 sdi
->SDICON
= S3C2410_SDICON_FIFORESET
|S3C2410_SDICON_CLOCKTYPE
;
421 udelay(125000); /* FIXME: 74 SDCLK cycles */
427 resp
= mmc_cmd(MMC_CMD_RESET
, 0, 0);
429 mmc_dev
.if_type
= IF_TYPE_UNKNOWN
;
431 puts("mmc: Probing for SDHC ...\n");
433 /* Send supported voltage range */
434 /* SD cards 1.x do not answer to CMD8 */
435 resp
= mmc_cmd(MMC_CMD_IF_COND
, ((1 << 8) | 0xAA), CMD_F_RESP_R7
);
438 * ARC: No answer let's try SD 1.x
441 puts("mmc: No answer to CMD8 trying SD\n");
442 mmc_blkdev_p
->if_type
= IF_TYPE_SD
;
445 * ARC: probably an SDHC card
447 mmc_blkdev_p
->if_type
= IF_TYPE_SDHC
;
449 puts("mmc: SD 2.0 or later card found\n");
451 /* Check if the card supports this voltage */
452 if (resp
[0] != ((1 << 8) | 0xAA)) {
453 pr_debug("mmc: Invalid voltage range\n");
459 * ARC: HC (30) bit set according to response to
463 pr_debug("mmc: Sending ACMD41 %s HC set\n",
464 ((mmc_blkdev_p
->if_type
==
465 IF_TYPE_SDHC
) ? "with" : "without"));
467 printf("trying to detect SD Card...\n");
470 resp
= mmc_cmd(55, 0x00000000, CMD_F_RESP
);
471 resp
= mmc_cmd(41, (mmc_blkdev_p
->if_type
== IF_TYPE_SDHC
)? (0x00300000 | (1<<30)) : 0x00300000, CMD_F_RESP
);
473 if (resp
[0] & (1 << 31)) {
480 * ARC: check for HC bit, if its not set
483 if (is_sd
&& (resp
[0] & 0xc0000000) == 0x80000000) {
484 mmc_dev
.if_type
= IF_TYPE_SD
;
487 if (retries
== 0 && !is_sd
) {
489 printf("failed to detect SD Card, trying MMC\n");
490 mmc_blkdev_p
->if_type
= IF_TYPE_MMC
;
491 resp
= mmc_cmd(MMC_CMD_SEND_OP_COND
, 0x00ffc000, CMD_F_RESP
);
492 while (retries
-- && resp
&& !(resp
[4] & 0x80)) {
493 debug("resp %x %x\n", resp
[0], resp
[1]);
495 resp
= mmc_cmd(1, 0x00ffff00, CMD_F_RESP
);
499 /* try to get card id */
500 resp
= mmc_cmd(MMC_CMD_ALL_SEND_CID
, 0, CMD_F_RESP
|CMD_F_RESP_LONG
);
503 /* TODO configure mmc driver depending on card
505 mmc_cid_t
*cid
= (mmc_cid_t
*)resp
;
509 sprintf((char *) mmc_dev
.vendor
,
510 "Man %02x%02x%02x Snr %02x%02x%02x",
511 cid
->id
[0], cid
->id
[1], cid
->id
[2],
512 cid
->sn
[0], cid
->sn
[1], cid
->sn
[2]);
513 sprintf((char *) mmc_dev
.product
,"%s",cid
->name
);
514 sprintf((char *) mmc_dev
.revision
,"%x %x",
515 cid
->hwrev
, cid
->fwrev
);
518 struct sd_cid
*cid
= (struct sd_cid
*) resp
;
522 sprintf((char *) mmc_dev
.vendor
,
523 "Man %02 OEM %c%c \"%c%c%c%c%c\"",
524 cid
->mid
, cid
->oid_0
, cid
->oid_1
,
525 cid
->pnm_0
, cid
->pnm_1
, cid
->pnm_2
, cid
->pnm_3
,
527 sprintf((char *) mmc_dev
.product
, "%d",
528 cid
->psn_0
<< 24 | cid
->psn_1
<< 16 |
529 cid
->psn_2
<< 8 | cid
->psn_3
);
530 sprintf((char *) mmc_dev
.revision
, "%d.%d",
531 cid
->prv
>> 4, cid
->prv
& 15);
534 /* fill in device description */
535 if (mmc_dev
.if_type
== IF_TYPE_UNKNOWN
)
536 mmc_dev
.if_type
= IF_TYPE_MMC
;
537 mmc_dev
.part_type
= PART_TYPE_DOS
;
541 /* FIXME fill in the correct size (is set to 32MByte) */
543 mmc_dev
.lba
= 0x10000;
544 mmc_dev
.removable
= 0;
545 mmc_dev
.block_read
= mmc_bread
;
547 /* MMC exists, get CSD too */
548 resp
= mmc_cmd(MMC_CMD_SET_RCA
, MMC_DEFAULT_RCA
, CMD_F_RESP
);
552 resp
= mmc_cmd(MMC_CMD_SEND_CSD
, rca
<<16, CMD_F_RESP
|CMD_F_RESP_LONG
);
554 mmc_csd_t
*csd
= (mmc_csd_t
*)resp
;
555 memcpy(&mmc_csd
, csd
, sizeof(csd
));
558 /* FIXME add verbose printout for csd */
559 printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n",
560 csd
->read_bl_len
, csd
->c_size_mult1
, csd
->c_size
);
561 printf("size = %u\n", mmc_size(csd
));
565 resp
= mmc_cmd(MMC_CMD_SELECT_CARD
, rca
<<16, CMD_F_RESP
);
568 printf("SD Card detected RCA: 0x%x type: %s\n",
569 rca
, ((mmc_dev
.if_type
== IF_TYPE_SDHC
) ? "SDHC" : ((mmc_dev
.if_type
== IF_TYPE_SD
) ? "SD" : "MMC")));
571 #ifdef CONFIG_MMC_WIDE
573 resp
= mmc_cmd(55, rca
<<16, CMD_F_RESP
);
574 resp
= mmc_cmd(6, 0x02, CMD_F_RESP
);
579 fat_register_device(&mmc_dev
,1); /* partitions start counting with 1 */
585 mmc_ident(block_dev_desc_t
*dev
)
593 /* FIXME hard codes to 32 MB device */
594 if (addr
>= CFG_MMC_BASE
&& addr
< CFG_MMC_BASE
+ 0x02000000)
600 #endif /* defined(CONFIG_MMC) && defined(CONFIG_MMC_S3C) */