diff mbox series

[2/3] mmc: sdhci-of-esdhc: poll ESDHC_FLUSH_ASYNC_FIFO bit until completion

Message ID 20190917044631.3161-3-yangbo.lu@nxp.com (mailing list archive)
State New, archived
Headers show
Series mmc: sdhci-of-esdhc: fix up erratum A-008171 workaround | expand

Commit Message

Yangbo Lu Sept. 17, 2019, 4:46 a.m. UTC
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@nxp.com>
---
 drivers/mmc/host/sdhci-of-esdhc.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
diff mbox series

Patch

diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 4dd43b1..a01d3a5 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -650,6 +650,21 @@  static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 		temp = sdhci_readl(host, ESDHC_DMA_SYSCTL);
 		temp |= ESDHC_FLUSH_ASYNC_FIFO;
 		sdhci_writel(host, temp, 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: tuning block polling FLUSH_ASYNC_FIFO timeout.\n",
+					mmc_hostname(host->mmc));
+				break;
+			}
+			udelay(10);
+		}
 	}
 
 	/* Wait max 20 ms */
@@ -806,6 +821,7 @@  static struct soc_device_attribute soc_fixup_tuning[] = {
 
 static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
 {
+	ktime_t timeout;
 	u32 val;
 
 	esdhc_clock_enable(host, false);
@@ -814,6 +830,22 @@  static void esdhc_tuning_block_enable(struct sdhci_host *host, bool enable)
 	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: tuning block polling FLUSH_ASYNC_FIFO timeout.\n",
+				mmc_hostname(host->mmc));
+			break;
+		}
+		udelay(10);
+	}
+
 	val = sdhci_readl(host, ESDHC_TBCTL);
 	if (enable)
 		val |= ESDHC_TB_EN;