mmc: sdhci-esdhc-imx: simplify the auto tuning logic
authorHaibo Chen <haibo.chen@nxp.com>
Fri, 23 Dec 2022 02:50:21 +0000 (10:50 +0800)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 23 Jan 2023 14:51:38 +0000 (15:51 +0100)
Clear auto tuning bit when reset tuning, and enable auto tuning
only after tuning done successfully for both standard tuning and
manual tuning.

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

index 9e73c34..db5b5a6 100644 (file)
@@ -430,9 +430,10 @@ static inline void esdhc_wait_for_card_clock_gate_off(struct sdhci_host *host)
 }
 
 /* Enable the auto tuning circuit to check the CMD line and BUS line */
-static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
+static inline void usdhc_auto_tuning_mode_sel_and_en(struct sdhci_host *host)
 {
        u32 buswidth, auto_tune_buswidth;
+       u32 reg;
 
        buswidth = USDHC_GET_BUSWIDTH(readl(host->ioaddr + SDHCI_HOST_CONTROL));
 
@@ -451,6 +452,10 @@ static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host)
        esdhc_clrset_le(host, ESDHC_VEND_SPEC2_AUTO_TUNE_MODE_MASK,
                        auto_tune_buswidth | ESDHC_VEND_SPEC2_AUTO_TUNE_CMD_EN,
                        ESDHC_VEND_SPEC2);
+
+       reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
+       reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
+       writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
 }
 
 static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
@@ -682,14 +687,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
                        } else {
                                v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
                                m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
-                               m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
                        }
 
                        if (val & SDHCI_CTRL_EXEC_TUNING) {
                                v |= ESDHC_MIX_CTRL_EXE_TUNE;
                                m |= ESDHC_MIX_CTRL_FBCLK_SEL;
-                               m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
-                               usdhc_auto_tuning_mode_sel(host);
                        } else {
                                v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
                        }
@@ -1023,13 +1025,15 @@ static void esdhc_reset_tuning(struct sdhci_host *host)
 
        /* Reset the tuning circuit */
        if (esdhc_is_usdhc(imx_data)) {
+               ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL);
+               ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
                if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
-                       ctrl = readl(host->ioaddr + ESDHC_MIX_CTRL);
                        ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
                        ctrl &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
                        writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
                        writel(0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
                } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
+                       writel(ctrl, host->ioaddr + ESDHC_MIX_CTRL);
                        ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS);
                        ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
                        ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE;
@@ -1055,6 +1059,7 @@ static void esdhc_reset_tuning(struct sdhci_host *host)
 static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
        struct sdhci_host *host = mmc_priv(mmc);
+       int err;
 
        /*
         * i.MX uSDHC internally already uses a fixed optimized timing for
@@ -1069,7 +1074,12 @@ static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
         * correct delay cell.
         */
        esdhc_reset_tuning(host);
-       return sdhci_execute_tuning(mmc, opcode);
+       err = sdhci_execute_tuning(mmc, opcode);
+       /* If tuning done, enable auto tuning */
+       if (!err && !host->tuning_err)
+               usdhc_auto_tuning_mode_sel_and_en(host);
+
+       return err;
 }
 
 static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
@@ -1103,11 +1113,8 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 {
        u32 reg;
 
-       usdhc_auto_tuning_mode_sel(host);
-
        reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
        reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
-       reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
        writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
 }