diff options
author | Ye Li <ye.li@nxp.com> | 2017-09-20 04:22:40 -0500 |
---|---|---|
committer | Ye Li <ye.li@nxp.com> | 2017-09-21 20:39:31 -0500 |
commit | 0d224a38f12ee6d01c6aa09df7700645ba0c7eae (patch) | |
tree | 3eff8bbbb2bb99573a19433de43a5f0bb92b962f | |
parent | aa49bce19a5aa71a98756f30d9b5da130fdae496 (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.c | 56 | ||||
-rw-r--r-- | include/mmc.h | 1 |
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 */ |