mmc: test mmc bus width on startup
authorLei Wen <leiwen@marvell.com>
Mon, 3 Oct 2011 20:35:11 +0000 (20:35 +0000)
committerAndy Fleming <afleming@freescale.com>
Thu, 3 Nov 2011 07:14:59 +0000 (02:14 -0500)
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>
drivers/mmc/mmc.c

index ac26db1d5bb2849bd0f26d9d1b7fbe4e9ccd6d91..96facb76596fde849a20caa72c4c5df297c87184 100644 (file)
@@ -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) {