summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAsutosh Das <asutoshd@codeaurora.org>2013-10-01 16:03:16 +0530
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-31 15:25:54 -0700
commit0c758bb6b206df527df06eb2e2fb2a784b063148 (patch)
tree20bfe3e68ac49662f2e65ff2c595fb630bf1d236 /drivers
parent3f3e47cfbb93f0a1f1e996e7c1e932b9ef1eea8e (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.c14
-rw-r--r--drivers/mmc/core/mmc.c29
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) {
/*