diff options
author | Terry Lv <r65388@freescale.com> | 2009-11-25 19:20:41 +0800 |
---|---|---|
committer | Terry Lv <r65388@freescale.com> | 2009-11-27 15:49:14 +0800 |
commit | 04e98be5c3950fbe18db6cb6533c0695f23a72d7 (patch) | |
tree | cb2f557baeadab795beacada29cfc84f57961e2f | |
parent | 078cdf97a1ec61134f0c924a209520dfd7f63c5f (diff) | |
download | u-boot-imx-04e98be5c3950fbe18db6cb6533c0695f23a72d7.zip u-boot-imx-04e98be5c3950fbe18db6cb6533c0695f23a72d7.tar.gz u-boot-imx-04e98be5c3950fbe18db6cb6533c0695f23a72d7.tar.bz2 |
ENGR00118751: Some mmc card can't read and write from right offset.
Some mmc card can't read and write from right offset.
Driver see these card as high capacity and use sector mode for them.
This will lead to read and write corrupt.
Signed-off-by: Terry Lv <r65388@freescale.com>
-rw-r--r-- | drivers/mmc/mmc.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index f8510b2..f78b8a8 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -407,7 +407,7 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) int mmc_change_freq(struct mmc *mmc) { - char ext_csd[512]; + char *ext_csd; char cardtype; int err; @@ -419,30 +419,42 @@ int mmc_change_freq(struct mmc *mmc) mmc->card_caps |= MMC_MODE_4BIT; + ext_csd = (char *)malloc(512); + + if (!ext_csd) { + puts("Could not allocate buffer for MMC ext csd!\n"); + return -1; + } + err = mmc_send_ext_csd(mmc, ext_csd); if (err) - return err; + goto err_rtn; - if (ext_csd[212] || ext_csd[213] || ext_csd[214] || ext_csd[215]) +/* + if (ext_csd[EXT_CSD_SEC_CNT] || + ext_csd[EXT_CSD_SEC_CNT + 1] || + ext_csd[EXT_CSD_SEC_CNT + 2] || + ext_csd[EXT_CSD_SEC_CNT + 3]) mmc->high_capacity = 1; +*/ - cardtype = ext_csd[196] & 0xf; + cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf; err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); if (err) - return err; + goto err_rtn; /* Now check to see that it worked */ err = mmc_send_ext_csd(mmc, ext_csd); if (err) - return err; + goto err_rtn; /* No high-speed support */ - if (!ext_csd[185]) - return 0; + if (!ext_csd[EXT_CSD_HS_TIMING]) + goto no_err_rtn; /* High Speed is set, there are two types: 52MHz and 26MHz */ if (cardtype & MMC_HS_52MHZ) @@ -450,7 +462,13 @@ int mmc_change_freq(struct mmc *mmc) else mmc->card_caps |= MMC_MODE_HS; +no_err_rtn: + free(ext_csd); return 0; + +err_rtn: + free(ext_csd); + return err; } int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) @@ -720,14 +738,29 @@ int mmc_startup(struct mmc *mmc) else mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf); - if (mmc->high_capacity) { + if (IS_SD(mmc)) { + int csd_struct = (cmd.response[0] >> 30) & 0x3; + + switch (csd_struct) { + case 1: + csize = (mmc->csd[1] & 0x3f) << 16 + | (mmc->csd[2] & 0xffff0000) >> 16; + cmult = 8; + break; + case 0: + default: + if (0 != csd_struct) + printf("unrecognised CSD structure version %d\n", + csd_struct); + csize = (mmc->csd[1] & 0x3ff) << 2 + | (mmc->csd[2] & 0xc0000000) >> 30; + cmult = (mmc->csd[2] & 0x00038000) >> 15; + break; + } + } else { csize = (mmc->csd[1] & 0x3f) << 16 | (mmc->csd[2] & 0xffff0000) >> 16; cmult = 8; - } else { - csize = (mmc->csd[1] & 0x3ff) << 2 - | (mmc->csd[2] & 0xc0000000) >> 30; - cmult = (mmc->csd[2] & 0x00038000) >> 15; } mmc->capacity = (csize + 1) << (cmult + 2); |