]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
mmc: sdhci-esdhc-imx: reset async FIFO before sending manual tuning command
authorHaibo Chen <haibo.chen@nxp.com>
Wed, 9 Apr 2025 07:55:46 +0000 (15:55 +0800)
committerUlf Hansson <ulf.hansson@linaro.org>
Wed, 14 May 2025 14:59:17 +0000 (16:59 +0200)
During manual tuning, residual data in the async FIFO from previous
commands may impact with the tuning process. To ensure a clean state:

1. Set the RST_FIFO bit (SYS_CTRL[22]) to reset the async FIFO.
2. Poll the bit until self-cleared, confirming reset completion.

This hardening ensures the tuning command starts with a clean FIFO state,
improving the reliability of the manual tuning procedure.

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Link: https://lore.kernel.org/r/20250409075550.3413032-3-ziniu.wang_1@nxp.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci-esdhc-imx.c

index 067f485987a6af2bda2735b0a578c7348fe7d204..53c7b858b43c81639f1218fb46101faac19dad7a 100644 (file)
@@ -31,6 +31,7 @@
 #include "cqhci.h"
 
 #define ESDHC_SYS_CTRL_DTOCV_MASK      GENMASK(19, 16)
+#define ESDHC_SYS_CTRL_RST_FIFO                BIT(22)
 #define ESDHC_SYS_CTRL_IPP_RST_N       BIT(23)
 #define ESDHC_SYS_CTRL_RESET_TUNING    BIT(28)
 #define        ESDHC_CTRL_D3CD                 0x08
@@ -1154,7 +1155,7 @@ static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 
 static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
 {
-       u32 reg;
+       u32 reg, sys_ctrl;
        u8 sw_rst;
        int ret;
 
@@ -1178,6 +1179,16 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
        dev_dbg(mmc_dev(host->mmc),
                "tuning with delay 0x%x ESDHC_TUNE_CTRL_STATUS 0x%x\n",
                        val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS));
+
+       /* set RST_FIFO to reset the async FIFO, and wat it to self-clear */
+       sys_ctrl = readl(host->ioaddr + ESDHC_SYSTEM_CONTROL);
+       sys_ctrl |= ESDHC_SYS_CTRL_RST_FIFO;
+       writel(sys_ctrl, host->ioaddr + ESDHC_SYSTEM_CONTROL);
+       ret = readl_poll_timeout(host->ioaddr + ESDHC_SYSTEM_CONTROL, sys_ctrl,
+                                !(sys_ctrl & ESDHC_SYS_CTRL_RST_FIFO), 10, 100);
+       if (ret == -ETIMEDOUT)
+               dev_warn(mmc_dev(host->mmc),
+                        "warning! RST_FIFO not clear in 100us\n");
 }
 
 static void esdhc_post_tuning(struct sdhci_host *host)