diff options
author | Lei Wen <leiwen@marvell.com> | 2011-10-03 20:35:11 +0000 |
---|---|---|
committer | Andy Fleming <afleming@freescale.com> | 2011-11-03 02:14:59 -0500 |
commit | 4137894e04dc5c435012344939080a723e8c58ac (patch) | |
tree | 6dbd459cbe50dfb60ccd9e8a1a2e66e442753498 /drivers | |
parent | 0560db18ecd5b6f15f8bc655868d7d2316eba261 (diff) |
mmc: test mmc bus width on startup
For we don't know mmc bus width from reading registers, the only way
to check is to test.
Current compare offset is:
EXT_CSD_PARTITIONING_SUPPORT
EXT_CSD_ERASE_GROUP_DEF
EXT_CSD_REV
EXT_CSD_HC_ERASE_GRP_SIZE
EXT_CSD_SEC_CNT
Signed-off-by: Lei Wen <leiwen@marvell.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/mmc.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ac26db1d5bb..96facb76596 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -631,8 +631,6 @@ int mmc_change_freq(struct mmc *mmc) if (mmc->version < MMC_VERSION_4) return 0; - mmc->card_caps |= MMC_MODE_4BIT; - err = mmc_send_ext_csd(mmc, ext_csd); if (err) @@ -856,11 +854,12 @@ void mmc_set_bus_width(struct mmc *mmc, uint width) int mmc_startup(struct mmc *mmc) { - int err; + int err, width; uint mult, freq; u64 cmult, csize, capacity; struct mmc_cmd cmd; ALLOC_CACHE_ALIGN_BUFFER(char, ext_csd, 512); + ALLOC_CACHE_ALIGN_BUFFER(char, test_csd, 512); int timeout = 1000; #ifdef CONFIG_MMC_SPI_CRC_ON @@ -1080,26 +1079,35 @@ int mmc_startup(struct mmc *mmc) else mmc_set_clock(mmc, 25000000); } else { - if (mmc->card_caps & MMC_MODE_4BIT) { + for (width = EXT_CSD_BUS_WIDTH_8; width >= 0; width--) { /* Set the card to use 4 bit*/ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - EXT_CSD_BUS_WIDTH_4); + EXT_CSD_BUS_WIDTH, width); if (err) - return err; - - mmc_set_bus_width(mmc, 4); - } else if (mmc->card_caps & MMC_MODE_8BIT) { - /* Set the card to use 8 bit*/ - err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - EXT_CSD_BUS_WIDTH_8); + continue; - if (err) - return err; - - mmc_set_bus_width(mmc, 8); + if (!width) { + mmc_set_bus_width(mmc, 1); + break; + } else + mmc_set_bus_width(mmc, 4 * width); + + err = mmc_send_ext_csd(mmc, test_csd); + if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \ + == test_csd[EXT_CSD_PARTITIONING_SUPPORT] + && ext_csd[EXT_CSD_ERASE_GROUP_DEF] \ + == test_csd[EXT_CSD_ERASE_GROUP_DEF] \ + && ext_csd[EXT_CSD_REV] \ + == test_csd[EXT_CSD_REV] + && ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \ + == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] + && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \ + &test_csd[EXT_CSD_SEC_CNT], 4) == 0) { + + mmc->card_caps |= width; + break; + } } if (mmc->card_caps & MMC_MODE_HS) { |