From f0d1246ed7cb5a88522244c596d7ae7e6f161283 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 27 Jun 2007 13:34:26 +0200 Subject: atmel_mci: Use 512 byte blocksize if possible Instead of always using the largest blocksize the card supports, check if it can support smaller block sizes and use 512 bytes if possible. Most cards do support this, and other parts of u-boot seem to have trouble with block sizes different from 512 bytes. Also enable underrun/overrun protection. Signed-off-by: Haavard Skinnemoen Acked-by: Hans-Christian Egtvedt --- cpu/at32ap/atmel_mci.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'cpu/at32ap/atmel_mci.c') diff --git a/cpu/at32ap/atmel_mci.c b/cpu/at32ap/atmel_mci.c index 9f62c0f..bdca1c1 100644 --- a/cpu/at32ap/atmel_mci.c +++ b/cpu/at32ap/atmel_mci.c @@ -82,7 +82,9 @@ static void mci_set_mode(unsigned long hz, unsigned long blklen) blklen &= 0xfffc; mmci_writel(MR, (MMCI_BF(CLKDIV, clkdiv) - | MMCI_BF(BLKLEN, blklen))); + | MMCI_BF(BLKLEN, blklen) + | MMCI_BIT(RDPROOF) + | MMCI_BIT(WRPROOF))); } #define RESP_NO_CRC 1 @@ -225,7 +227,7 @@ mmc_bread(int dev, unsigned long start, lbaint_t blkcnt, *buffer++ = data; wordcount++; } - } while(wordcount < (512 / 4)); + } while(wordcount < (mmc_blkdev.blksz / 4)); pr_debug("mmc: read %u words, waiting for BLKE\n", wordcount); @@ -243,7 +245,7 @@ out: fail: mmc_cmd(MMC_CMD_SEND_STATUS, mmc_rca << 16, &card_status, R1 | NCR); - printf("mmc: bread failed, card status = ", card_status); + printf("mmc: bread failed, card status = %08x\n", card_status); goto out; } @@ -409,6 +411,7 @@ int mmc_init(int verbose) { struct mmc_cid cid; struct mmc_csd csd; + unsigned int max_blksz; int ret; /* Initialize controller */ @@ -444,7 +447,17 @@ int mmc_init(int verbose) sizeof(mmc_blkdev.product)); sprintf((char *)mmc_blkdev.revision, "%x %x", cid.prv >> 4, cid.prv & 0x0f); - mmc_blkdev.blksz = 1 << csd.read_bl_len; + + /* + * If we can't use 512 byte blocks, refuse to deal with the + * card. Tons of code elsewhere seems to depend on this. + */ + max_blksz = 1 << csd.read_bl_len; + if (max_blksz < 512 || (max_blksz > 512 && !csd.read_bl_partial)) { + printf("Card does not support 512 byte reads, aborting.\n"); + return -ENODEV; + } + mmc_blkdev.blksz = 512; mmc_blkdev.lba = (csd.c_size + 1) * (1 << (csd.c_size_mult + 2)); mci_set_mode(CFG_MMC_CLK_PP, mmc_blkdev.blksz); -- cgit v1.1 From a08458303e7f9db67f296980036d3292c35cb45c Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 29 Jun 2007 18:38:51 +0200 Subject: atmel_mci: Fix data timeout value Calculate the data timeout based on values from the CSD instead of just using a hardcoded DTOR value. This is a backport of a similar fix in BSP 2.0, with one additional fix: the DTOCYC value is rounded up instead of down. Signed-off-by: Haavard Skinnemoen --- cpu/at32ap/atmel_mci.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'cpu/at32ap/atmel_mci.c') diff --git a/cpu/at32ap/atmel_mci.c b/cpu/at32ap/atmel_mci.c index bdca1c1..cf48be1 100644 --- a/cpu/at32ap/atmel_mci.c +++ b/cpu/at32ap/atmel_mci.c @@ -56,6 +56,7 @@ #define MMC_DEFAULT_RCA 1 static unsigned int mmc_rca; +static int mmc_card_is_sd; static block_dev_desc_t mmc_blkdev; block_dev_desc_t *mmc_get_dev(int dev) @@ -373,6 +374,7 @@ static int sd_init_card(struct mmc_cid *cid, int verbose) mmc_rca = resp[0] >> 16; if (verbose) printf("SD Card detected (RCA %u)\n", mmc_rca); + mmc_card_is_sd = 1; return 0; } @@ -407,6 +409,59 @@ static int mmc_init_card(struct mmc_cid *cid, int verbose) return ret; } +static void mci_set_data_timeout(struct mmc_csd *csd) +{ + static const unsigned int dtomul_to_shift[] = { + 0, 4, 7, 8, 10, 12, 16, 20, + }; + static const unsigned int taac_exp[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, + }; + static const unsigned int taac_mant[] = { + 0, 10, 12, 13, 15, 60, 25, 30, + 35, 40, 45, 50, 55, 60, 70, 80, + }; + unsigned int timeout_ns, timeout_clks; + unsigned int e, m; + unsigned int dtocyc, dtomul; + unsigned int shift; + u32 dtor; + + e = csd->taac & 0x07; + m = (csd->taac >> 3) & 0x0f; + + timeout_ns = (taac_exp[e] * taac_mant[m] + 9) / 10; + timeout_clks = csd->nsac * 100; + + timeout_clks += (((timeout_ns + 9) / 10) + * ((CFG_MMC_CLK_PP + 99999) / 100000) + 9999) / 10000; + if (!mmc_card_is_sd) + timeout_clks *= 10; + else + timeout_clks *= 100; + + dtocyc = timeout_clks; + dtomul = 0; + while (dtocyc > 15 && dtomul < 8) { + dtomul++; + shift = dtomul_to_shift[dtomul]; + dtocyc = (timeout_clks + (1 << shift) - 1) >> shift; + } + + if (dtomul >= 8) { + dtomul = 7; + dtocyc = 15; + puts("Warning: Using maximum data timeout\n"); + } + + dtor = (MMCI_BF(DTOMUL, dtomul) + | MMCI_BF(DTOCYC, dtocyc)); + mmci_writel(DTOR, dtor); + + printf("mmc: Using %u cycles data timeout (DTOR=0x%x)\n", + dtocyc << shift, dtor); +} + int mmc_init(int verbose) { struct mmc_cid cid; @@ -421,6 +476,8 @@ int mmc_init(int verbose) mmci_writel(IDR, ~0UL); mci_set_mode(CFG_MMC_CLK_OD, MMC_DEFAULT_BLKLEN); + mmc_card_is_sd = 0; + ret = sd_init_card(&cid, verbose); if (ret) { mmc_rca = MMC_DEFAULT_RCA; @@ -436,6 +493,8 @@ int mmc_init(int verbose) if (verbose) mmc_dump_csd(&csd); + mci_set_data_timeout(&csd); + /* Initialize the blockdev structure */ mmc_blkdev.if_type = IF_TYPE_MMC; mmc_blkdev.part_type = PART_TYPE_DOS; -- cgit v1.1