The ESDHC_FLUSH_ASYNC_FIFO bit which is set to flush asynchronous FIFO should be polled until it's auto cleared by hardware. Signed-off-by: Yangbo Lu <yangbo.lu@xxxxxxx> --- Changes for v2: - None. Changes for v3: - Converted to use esdhc_flush_async_fifo() and usleep_range(). --- drivers/mmc/host/sdhci-of-esdhc.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 1d1953d..d4bcf95 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -560,6 +560,32 @@ static void esdhc_clock_enable(struct sdhci_host *host, bool enable) } } +static void esdhc_flush_async_fifo(struct sdhci_host *host) +{ + ktime_t timeout; + u32 val; + + val = sdhci_readl(host, ESDHC_DMA_SYSCTL); + val |= ESDHC_FLUSH_ASYNC_FIFO; + sdhci_writel(host, val, ESDHC_DMA_SYSCTL); + + /* Wait max 20 ms */ + timeout = ktime_add_ms(ktime_get(), 20); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + if (!(sdhci_readl(host, ESDHC_DMA_SYSCTL) & + ESDHC_FLUSH_ASYNC_FIFO)) + break; + if (timedout) { + pr_err("%s: flushing asynchronous FIFO timeout.\n", + mmc_hostname(host->mmc)); + break; + } + usleep_range(10, 20); + } +} + static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -652,9 +678,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL); esdhc_clock_enable(host, false); - temp = sdhci_readl(host, ESDHC_DMA_SYSCTL); - temp |= ESDHC_FLUSH_ASYNC_FIFO; - sdhci_writel(host, temp, ESDHC_DMA_SYSCTL); + esdhc_flush_async_fifo(host); } /* Wait max 20 ms */ @@ -814,10 +838,7 @@ static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable) u32 val; esdhc_clock_enable(host, false); - - val = sdhci_readl(host, ESDHC_DMA_SYSCTL); - val |= ESDHC_FLUSH_ASYNC_FIFO; - sdhci_writel(host, val, ESDHC_DMA_SYSCTL); + esdhc_flush_async_fifo(host); val = sdhci_readl(host, ESDHC_TBCTL); if (enable) -- 2.7.4