mmc: fsl_esdhc_imx: optimize the timing setting
authorHaibo Chen <haibo.chen@nxp.com>
Tue, 3 Nov 2020 09:18:35 +0000 (17:18 +0800)
committerStefano Babic <sbabic@denx.de>
Sun, 6 Dec 2020 14:31:37 +0000 (15:31 +0100)
For imx usdhc/esdhc, once set the DDR_EN, enable the DDR mode, the
card clock will be divied by 2 automatically by the host. So need
to first config the DDR_EN correctly, then update the card clock.
This will make sure the actual card clock is as our expected.
IC also suggest config the DDR_EN firstly, then config the clock
divider.

For HS400/HS400ES mode, need to config the strobe dll, this need
to based on the correct target clock rate, so need to do this after
clock rate is update.

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
drivers/mmc/fsl_esdhc_imx.c

index 29592d1..e5409ad 100644 (file)
@@ -760,7 +760,6 @@ static int esdhc_set_timing(struct mmc *mmc)
        case MMC_HS_400_ES:
                mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN;
                esdhc_write32(&regs->mixctrl, mixctrl);
-               esdhc_set_strobe_dll(mmc);
                break;
        case MMC_HS:
        case MMC_HS_52:
@@ -933,6 +932,23 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
        int ret __maybe_unused;
        u32 clock;
 
+#ifdef MMC_SUPPORTS_TUNING
+       /*
+        * call esdhc_set_timing() before update the clock rate,
+        * This is because current we support DDR and SDR mode,
+        * Once the DDR_EN bit is set, the card clock will be
+        * divide by 2 automatically. So need to do this before
+        * setting clock rate.
+        */
+       if (priv->mode != mmc->selected_mode) {
+               ret = esdhc_set_timing(mmc);
+               if (ret) {
+                       printf("esdhc_set_timing error %d\n", ret);
+                       return ret;
+               }
+       }
+#endif
+
        /* Set the clock speed */
        clock = mmc->clock;
        if (clock < mmc->cfg->f_min)
@@ -957,13 +973,13 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 #endif
        }
 
-       if (priv->mode != mmc->selected_mode) {
-               ret = esdhc_set_timing(mmc);
-               if (ret) {
-                       printf("esdhc_set_timing error %d\n", ret);
-                       return ret;
-               }
-       }
+       /*
+        * For HS400/HS400ES mode, make sure set the strobe dll in the
+        * target clock rate. So call esdhc_set_strobe_dll() after the
+        * clock updated.
+        */
+       if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES)
+               esdhc_set_strobe_dll(mmc);
 
        if (priv->signal_voltage != mmc->signal_voltage) {
                ret = esdhc_set_voltage(mmc);