diff options
author | Asutosh Das <asutoshd@codeaurora.org> | 2013-10-01 16:03:16 +0530 |
---|---|---|
committer | Subhash Jadavani <subhashj@codeaurora.org> | 2016-05-31 15:25:54 -0700 |
commit | 0c758bb6b206df527df06eb2e2fb2a784b063148 (patch) | |
tree | 20bfe3e68ac49662f2e65ff2c595fb630bf1d236 /drivers | |
parent | 3f3e47cfbb93f0a1f1e996e7c1e932b9ef1eea8e (diff) |
mmc: core: add clock-scaling support to HS400 cards
This patch adds clock scaling support to HS400 cards.
Scaling down to 52MHz from HS400 involves:
- switching the bus-speed mode to HS at 52MHz
Scaling up to HS400 would require all of the initialization
process upto HS400 mode selection.
Change-Id: I8196d6666bcc0ef327659253df53a17792fa51f7
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
Signed-off-by: Krishna Konda <kkonda@codeaurora.org>
[venkatg@codeaurora.org: fix mmc_select_hs args and MAX_DTRs
as used in 3.14 kernel]
Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
[subhashj@codeaurora.org: fixed merge conflicts]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/core/core.c | 14 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 29 |
2 files changed, 41 insertions, 2 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5970e3ced815..0b0f1821f5fb 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2689,13 +2689,19 @@ EXPORT_SYMBOL_GPL(mmc_reset_clk_scale_stats); unsigned long mmc_get_max_frequency(struct mmc_host *host) { unsigned long freq; + unsigned char timing; if (host->ops && host->ops->get_max_frequency) { freq = host->ops->get_max_frequency(host); goto out; } - switch (host->ios.timing) { + if (mmc_card_hs400(host->card)) + timing = MMC_TIMING_MMC_HS400; + else + timing = host->ios.timing; + + switch (timing) { case MMC_TIMING_UHS_SDR50: freq = UHS_SDR50_MAX_DTR; break; @@ -2708,6 +2714,9 @@ unsigned long mmc_get_max_frequency(struct mmc_host *host) case MMC_TIMING_UHS_DDR50: freq = UHS_DDR50_MAX_DTR; break; + case MMC_TIMING_MMC_HS400: + freq = MMC_HS200_MAX_DTR; + break; default: mmc_host_clk_hold(host); freq = host->ios.clock; @@ -2748,6 +2757,9 @@ static unsigned long mmc_get_min_frequency(struct mmc_host *host) case MMC_TIMING_MMC_HS200: freq = MMC_HIGH_52_MAX_DTR; break; + case MMC_TIMING_MMC_HS400: + freq = MMC_HIGH_52_MAX_DTR; + break; case MMC_TIMING_UHS_DDR50: freq = UHS_DDR50_MAX_DTR / 2; break; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index e5731432963d..200a9442508c 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -624,6 +624,7 @@ static int mmc_read_ext_csd(struct mmc_card *card) return err; } + memcpy(&card->cached_ext_csd, ext_csd, sizeof(card->ext_csd)); err = mmc_decode_ext_csd(card, ext_csd); kfree(ext_csd); return err; @@ -1299,6 +1300,26 @@ err: return err; } +int mmc_set_clock_bus_speed(struct mmc_card *card, unsigned long freq) +{ + int err; + + if (freq < MMC_HS200_MAX_DTR) { + /* + * Lower the clock and adjust the timing to be able + * to switch to HighSpeed mode + */ + mmc_set_timing(card->host, MMC_TIMING_LEGACY); + mmc_set_clock(card->host, MMC_HIGH_26_MAX_DTR); + + err = mmc_select_hs(card); + } else { + err = mmc_select_hs400(card); + } + + return err; +} + /** * mmc_change_bus_speed() - Change MMC card bus frequency at runtime * @host: pointer to mmc host structure @@ -1340,7 +1361,13 @@ static int mmc_change_bus_speed(struct mmc_host *host, unsigned long *freq) if (*freq < host->f_min) *freq = host->f_min; - mmc_set_clock(host, (unsigned int) (*freq)); + if (mmc_card_hs400(card)) { + err = mmc_set_clock_bus_speed(card, *freq); + if (err) + goto out; + } else { + mmc_set_clock(host, (unsigned int) (*freq)); + } if (mmc_card_hs200(card) && card->host->ops->execute_tuning) { /* |