summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2017-09-20 04:22:40 -0500
committerYe Li <ye.li@nxp.com>2017-09-21 20:39:31 -0500
commit0d224a38f12ee6d01c6aa09df7700645ba0c7eae (patch)
tree3eff8bbbb2bb99573a19433de43a5f0bb92b962f
parentaa49bce19a5aa71a98756f30d9b5da130fdae496 (diff)
MLK-16499-1 mmc: Add support for HS400
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>
-rw-r--r--drivers/mmc/mmc.c56
-rw-r--r--include/mmc.h1
2 files changed, 55 insertions, 2 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index f659751948..a0c804e4b5 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -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;
@@ -1659,6 +1665,11 @@ static const struct mode_width_tuning mmc_modes_by_pref[] = {
.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,
.tuning = MMC_SEND_TUNING_BLOCK_HS200
@@ -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;
diff --git a/include/mmc.h b/include/mmc.h
index 76005191e6..18ae28bed2 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -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 */