summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorLei Wen <leiwen@marvell.com>2011-10-03 20:35:11 +0000
committerAndy Fleming <afleming@freescale.com>2011-11-03 02:14:59 -0500
commit4137894e04dc5c435012344939080a723e8c58ac (patch)
tree6dbd459cbe50dfb60ccd9e8a1a2e66e442753498 /drivers/mmc
parent0560db18ecd5b6f15f8bc655868d7d2316eba261 (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/mmc')
-rw-r--r--drivers/mmc/mmc.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index ac26db1d5b..96facb7659 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) {