summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/rockchip/clk-mmc-phase.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index dc4c227732bd..b7b9f2e7d64b 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -170,18 +170,30 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
unsigned long event, void *data)
{
struct rockchip_mmc_clock *mmc_clock = to_rockchip_mmc_clock(nb);
+ struct clk_notifier_data *ndata = data;
/*
* rockchip_mmc_clk is mostly used by mmc controllers to sample
* the intput data, which expects the fixed phase after the tuning
* process. However if the clock rate is changed, the phase is stale
* and may break the data sampling. So here we try to restore the phase
- * for that case.
+ * for that case, except that
+ * (1) cached_phase is invaild since we inevitably cached it when the
+ * clock provider be reparented from orphan to its real parent in the
+ * first place. Otherwise we may mess up the initialization of MMC cards
+ * since we only set the default sample phase and drive phase later on.
+ * (2) the new coming rate is higher than the older one since mmc driver
+ * set the max-frequency to match the boards' ability but we can't go
+ * over the heads of that, otherwise the tests smoke out the issue.
*/
+ if (ndata->old_rate <= ndata->new_rate)
+ return NOTIFY_DONE;
+
if (event == PRE_RATE_CHANGE)
mmc_clock->cached_phase =
rockchip_mmc_get_phase(&mmc_clock->hw);
- else if (event == POST_RATE_CHANGE)
+ else if (mmc_clock->cached_phase != -EINVAL &&
+ event == POST_RATE_CHANGE)
rockchip_mmc_set_phase(&mmc_clock->hw, mmc_clock->cached_phase);
return NOTIFY_DONE;