summaryrefslogtreecommitdiff
path: root/drivers/mmc/mmc.c
diff options
context:
space:
mode:
authorTerry Lv <r65388@freescale.com>2009-11-25 19:20:41 +0800
committerTerry Lv <r65388@freescale.com>2009-11-27 15:49:14 +0800
commit04e98be5c3950fbe18db6cb6533c0695f23a72d7 (patch)
treecb2f557baeadab795beacada29cfc84f57961e2f /drivers/mmc/mmc.c
parent078cdf97a1ec61134f0c924a209520dfd7f63c5f (diff)
downloadu-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>
Diffstat (limited to 'drivers/mmc/mmc.c')
-rw-r--r--drivers/mmc/mmc.c59
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);