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 /drivers | |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/mmc.c | 56 |
1 files changed, 55 insertions, 1 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; |