MLK-16499-1 mmc: Add support for HS400
authorYe Li <ye.li@nxp.com>
Wed, 20 Sep 2017 09:22:40 +0000 (04:22 -0500)
committerJason Liu <jason.hui.liu@nxp.com>
Thu, 2 Nov 2017 18:37:18 +0000 (02:37 +0800)
The HS400 ES (Enhanced Strobe) has been added. This patch addes support
for HS400 for eMMC 5.0 devices. It needs tuning at HS200 to synchronize
command response.

Signed-off-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
drivers/mmc/mmc.c
include/mmc.h

index f659751..a0c804e 100644 (file)
@@ -779,6 +779,12 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
        case MMC_HS_200:
                  speed_bits = EXT_CSD_TIMING_HS200;
                  break;
+       case MMC_HS_400:
+                 speed_bits = EXT_CSD_TIMING_HS400;
+                 break;
+       case MMC_HS_400_ES:
+                 speed_bits = EXT_CSD_TIMING_HS400;
+                 break;
        case MMC_LEGACY:
                  speed_bits = EXT_CSD_TIMING_LEGACY;
                  break;
@@ -1658,6 +1664,11 @@ static const struct mode_width_tuning mmc_modes_by_pref[] = {
                .mode = MMC_HS_400_ES,
                .widths = MMC_MODE_8BIT,
        },
+       {
+               .mode = MMC_HS_400,
+               .widths = MMC_MODE_8BIT,
+               .tuning = MMC_SEND_TUNING_BLOCK_HS200
+       },
        {
                .mode = MMC_HS_200,
                .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
@@ -1737,6 +1748,45 @@ static int mmc_select_hs400es(struct mmc *mmc)
        return 0;
 }
 
+static int mmc_select_hs400(struct mmc *mmc)
+{
+       int err;
+
+       /* Set timing to HS200 for tuning */
+       err = mmc_set_card_speed(mmc, MMC_HS_200);
+       if (err)
+               return err;
+
+       /* configure the bus mode (host) */
+       mmc_select_mode(mmc, MMC_HS_200);
+       mmc_set_clock(mmc, mmc->tran_speed, false);
+
+       /* execute tuning if needed */
+       err = mmc_execute_tuning(mmc, MMC_SEND_TUNING_BLOCK_HS200);
+       if (err) {
+               debug("tuning failed\n");
+               return err;
+       }
+
+       /* Set back to HS */
+       mmc_set_card_speed(mmc, MMC_HS);
+       mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
+
+       err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+               EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR);
+       if (err)
+               return err;
+
+       err = mmc_set_card_speed(mmc, MMC_HS_400);
+       if (err)
+               return err;
+
+       mmc_select_mode(mmc, MMC_HS_400);
+       mmc_set_clock(mmc, mmc->tran_speed, false);
+
+       return 0;
+}
+
 static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
 {
        int err;
@@ -1775,7 +1825,11 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
                                goto error;
                        mmc_set_bus_width(mmc, bus_width(ecbw->cap));
 
-                       if (mwt->mode == MMC_HS_400_ES) {
+                       if (mwt->mode == MMC_HS_400) {
+                               err = mmc_select_hs400(mmc);
+                               if (err)
+                                       goto error;
+                       } else if (mwt->mode == MMC_HS_400_ES) {
                                err = mmc_select_hs400es(mmc);
                                if (err)
                                        goto error;
index 7600519..18ae28b 100644 (file)
@@ -248,7 +248,6 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
 #define EXT_CSD_CARD_TYPE_HS400_1_2V   (1<<7)
 #define EXT_CSD_CARD_TYPE_HS400                (EXT_CSD_CARD_TYPE_HS400_1_8V | \
                                         EXT_CSD_CARD_TYPE_HS400_1_2V)
-#define EXT_CSD_CARD_TYPE_HS400ES      (1<<8)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */