91d1f2ce6f7d860878169f0097edf2bc49769418
[oweals/openwrt.git] /
1 From 0f5cf5dcc3ca4f8e610ebe1e62e3d3546b9d09ca Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Mon, 16 Sep 2019 19:17:44 +0800
4 Subject: [PATCH] mmc: sdhci-of-esdhc: poll ESDHC_FLUSH_ASYNC_FIFO bit until
5  completion
6
7 The ESDHC_FLUSH_ASYNC_FIFO bit which is set to flush asynchronous FIFO
8 should be polled until it's auto cleared by hardware.
9
10 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
11 ---
12  drivers/mmc/host/sdhci-of-esdhc.c | 35 ++++++++++++++++++++++++++++-------
13  1 file changed, 28 insertions(+), 7 deletions(-)
14
15 --- a/drivers/mmc/host/sdhci-of-esdhc.c
16 +++ b/drivers/mmc/host/sdhci-of-esdhc.c
17 @@ -591,6 +591,32 @@ static void esdhc_clock_enable(struct sd
18         }
19  }
20  
21 +static void esdhc_flush_async_fifo(struct sdhci_host *host)
22 +{
23 +       ktime_t timeout;
24 +       u32 val;
25 +
26 +       val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
27 +       val |= ESDHC_FLUSH_ASYNC_FIFO;
28 +       sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
29 +
30 +       /* Wait max 20 ms */
31 +       timeout = ktime_add_ms(ktime_get(), 20);
32 +       while (1) {
33 +               bool timedout = ktime_after(ktime_get(), timeout);
34 +
35 +               if (!(sdhci_readl(host, ESDHC_DMA_SYSCTL) &
36 +                     ESDHC_FLUSH_ASYNC_FIFO))
37 +                       break;
38 +               if (timedout) {
39 +                       pr_err("%s: flushing asynchronous FIFO timeout.\n",
40 +                               mmc_hostname(host->mmc));
41 +                       break;
42 +               }
43 +               usleep_range(10, 20);
44 +       }
45 +}
46 +
47  static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
48  {
49         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
50 @@ -683,9 +709,7 @@ static void esdhc_of_set_clock(struct sd
51                 sdhci_writel(host, temp | ESDHC_HS400_WNDW_ADJUST, ESDHC_TBCTL);
52  
53                 esdhc_clock_enable(host, false);
54 -               temp = sdhci_readl(host, ESDHC_DMA_SYSCTL);
55 -               temp |= ESDHC_FLUSH_ASYNC_FIFO;
56 -               sdhci_writel(host, temp, ESDHC_DMA_SYSCTL);
57 +               esdhc_flush_async_fifo(host);
58         }
59  
60         /* Wait max 20 ms */
61 @@ -852,10 +876,7 @@ static void esdhc_tuning_block_enable(st
62         u32 val;
63  
64         esdhc_clock_enable(host, false);
65 -
66 -       val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
67 -       val |= ESDHC_FLUSH_ASYNC_FIFO;
68 -       sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
69 +       esdhc_flush_async_fifo(host);
70  
71         val = sdhci_readl(host, ESDHC_TBCTL);
72         if (enable)