From: Faiz Abbas faiz_abbas@ti.com
[ Upstream commit 5b0d62108b468b13410533c0ceea3821942bf592 ]
The TRM (SPRUIC2C - January 2017 - Revised May 2018 [1]) forbids assertion of data reset while tuning is happening. Implement a platform specific callback that takes care of this condition.
[1] http://www.ti.com/lit/pdf/spruic2 Section 25.5.1.2.4
Acked-by: Kishon Vijay Abraham I kishon@ti.com Signed-off-by: Faiz Abbas faiz_abbas@ti.com Acked-by: Adrian Hunter adrian.hunter@intel.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/mmc/host/sdhci-omap.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index d02f5cf..8a17257 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -115,6 +115,7 @@ struct sdhci_omap_host {
struct pinctrl *pinctrl; struct pinctrl_state **pinctrl_state; + bool is_tuning; };
static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host); @@ -326,6 +327,8 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) dcrc_was_enabled = true; }
+ omap_host->is_tuning = true; + while (phase_delay <= MAX_PHASE_DELAY) { sdhci_omap_set_dll(omap_host, phase_delay);
@@ -363,9 +366,12 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) phase_delay = max_window + 4 * (max_len >> 1); sdhci_omap_set_dll(omap_host, phase_delay);
+ omap_host->is_tuning = false; + goto ret;
tuning_error: + omap_host->is_tuning = false; dev_err(dev, "Tuning failed\n"); sdhci_omap_disable_tuning(omap_host);
@@ -695,6 +701,18 @@ static void sdhci_omap_set_uhs_signaling(struct sdhci_host *host, sdhci_omap_start_clock(omap_host); }
+void sdhci_omap_reset(struct sdhci_host *host, u8 mask) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); + + /* Don't reset data lines during tuning operation */ + if (omap_host->is_tuning) + mask &= ~SDHCI_RESET_DATA; + + sdhci_reset(host, mask); +} + static struct sdhci_ops sdhci_omap_ops = { .set_clock = sdhci_omap_set_clock, .set_power = sdhci_omap_set_power, @@ -703,7 +721,7 @@ static void sdhci_omap_set_uhs_signaling(struct sdhci_host *host, .get_min_clock = sdhci_omap_get_min_clock, .set_bus_width = sdhci_omap_set_bus_width, .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, - .reset = sdhci_reset, + .reset = sdhci_omap_reset, .set_uhs_signaling = sdhci_omap_set_uhs_signaling, };