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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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>
---
 drivers/mmc/host/sdhci-of-esdhc.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

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;
-- 
2.7.4




[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux