summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2013-02-01 17:14:33 +0530
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-31 15:25:44 -0700
commitfec8ffcb2b32902a07fb298453f254bebdc503d0 (patch)
treef4841ce02a55a00c09e9ef045363691f5763258f
parent0b0df0844f6429385cfb35d8a3237cc7d7eae24b (diff)
mmc: core: run clock scaling only in valid card state
Clock scaling requires the tuning and if the tuning command is sent to the card in invalid state, tuning procedure will fail. With urgent request mechanism implemented, there is a chance that clock scaling invoked when card is not in a proper state to receive the tuning command. This change checks the card state (by sending the status command) before invoking the clock scaling request. Change-Id: Icb71a8e74a9afdc70380a5901cd3d28931959e9c Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-rw-r--r--drivers/mmc/core/core.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 843edbed3ac9..2e94974d4d14 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2767,6 +2767,30 @@ out:
return;
}
+static bool mmc_is_vaild_state_for_clk_scaling(struct mmc_host *host)
+{
+ struct mmc_card *card = host->card;
+ u32 status;
+ bool ret = false;
+
+ if (!card)
+ goto out;
+
+ if (mmc_send_status(card, &status)) {
+ pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
+ goto out;
+ }
+
+ switch (R1_CURRENT_STATE(status)) {
+ case R1_STATE_TRAN:
+ ret = true;
+ break;
+ default:
+ break;
+ }
+out:
+ return ret;
+}
/**
* mmc_clk_scaling() - clock scaling decision algorithm
@@ -2839,6 +2863,10 @@ static void mmc_clk_scaling(struct mmc_host *host, bool from_wq)
if (!from_wq)
cancel_delayed_work_sync(
&host->clk_scaling.work);
+
+ if (!mmc_is_vaild_state_for_clk_scaling(host))
+ goto bypass_scaling;
+
err = host->bus_ops->change_bus_speed(host, &freq);
if (!err)
host->clk_scaling.curr_freq = freq;
@@ -2860,6 +2888,7 @@ static void mmc_clk_scaling(struct mmc_host *host, bool from_wq)
}
mmc_reset_clk_scale_stats(host);
+bypass_scaling:
host->clk_scaling.in_progress = false;
out:
return;