mmc: sdhci-of-esdhc: disable SD clock for clock value 0
authoryangbo lu <yangbo.lu@nxp.com>
Thu, 21 Sep 2017 08:43:31 +0000 (16:43 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Feb 2018 14:42:33 +0000 (15:42 +0100)
commit dd3f6983b4a468efca9e8caa0e2b4aa20946d801 upstream.

SD clock should be disabled for clock value 0. It's not
right to just return. This may cause failure of signal
voltage switching.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Cc: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mmc/host/sdhci-of-esdhc.c

index d96a057..1f42437 100644 (file)
@@ -458,6 +458,33 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
        return clock / 256 / 16;
 }
 
+static void esdhc_clock_enable(struct sdhci_host *host, bool enable)
+{
+       u32 val;
+       ktime_t timeout;
+
+       val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+
+       if (enable)
+               val |= ESDHC_CLOCK_SDCLKEN;
+       else
+               val &= ~ESDHC_CLOCK_SDCLKEN;
+
+       sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL);
+
+       /* Wait max 20 ms */
+       timeout = ktime_add_ms(ktime_get(), 20);
+       val = ESDHC_CLOCK_STABLE;
+       while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) {
+               if (ktime_after(ktime_get(), timeout)) {
+                       pr_err("%s: Internal clock never stabilised.\n",
+                               mmc_hostname(host->mmc));
+                       break;
+               }
+               udelay(10);
+       }
+}
+
 static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -469,8 +496,10 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 
        host->mmc->actual_clock = 0;
 
-       if (clock == 0)
+       if (clock == 0) {
+               esdhc_clock_enable(host, false);
                return;
+       }
 
        /* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */
        if (esdhc->vendor_ver < VENDOR_V_23)
@@ -558,33 +587,6 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
        sdhci_writel(host, ctrl, ESDHC_PROCTL);
 }
 
-static void esdhc_clock_enable(struct sdhci_host *host, bool enable)
-{
-       u32 val;
-       ktime_t timeout;
-
-       val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
-
-       if (enable)
-               val |= ESDHC_CLOCK_SDCLKEN;
-       else
-               val &= ~ESDHC_CLOCK_SDCLKEN;
-
-       sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL);
-
-       /* Wait max 20 ms */
-       timeout = ktime_add_ms(ktime_get(), 20);
-       val = ESDHC_CLOCK_STABLE;
-       while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) {
-               if (ktime_after(ktime_get(), timeout)) {
-                       pr_err("%s: Internal clock never stabilised.\n",
-                               mmc_hostname(host->mmc));
-                       break;
-               }
-               udelay(10);
-       }
-}
-
 static void esdhc_reset(struct sdhci_host *host, u8 mask)
 {
        sdhci_reset(host, mask);