Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
mmc: sdhci-of-esdhc: disable SD clock for clock value 0
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Adrian Hunter <[email protected]>
Signed-off-by: Ulf Hansson <[email protected]>
  • Loading branch information
yangbolu1991 authored and storulf committed Oct 30, 2017
1 parent cdaba73 commit dd3f698
Showing 1 changed file with 30 additions and 28 deletions.
58 changes: 30 additions & 28 deletions drivers/mmc/host/sdhci-of-esdhc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit dd3f698

Please sign in to comment.