Message ID | 20221223025022.1893102-2-haibo.chen@nxp.com |
---|---|
State | New |
Headers | show |
Series | fix the sdio device DATA/CMD CRC and Timeout issue after tuning | expand |
On 23/12/22 04:50, haibo.chen@nxp.com wrote: > From: Haibo Chen <haibo.chen@nxp.com> > > 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> > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 25 ++++++++++++++++--------- > 1 file changed, 16 insertions(+), 9 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index 89ef0c80ac37..bf8d6f60a9ee 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -429,9 +429,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)); > > @@ -450,6 +451,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) > @@ -681,14 +686,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; > } > @@ -1022,13 +1024,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; > @@ -1054,6 +1058,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 > @@ -1068,7 +1073,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) > @@ -1102,11 +1112,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); > } >
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 89ef0c80ac37..bf8d6f60a9ee 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -429,9 +429,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)); @@ -450,6 +451,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) @@ -681,14 +686,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; } @@ -1022,13 +1024,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; @@ -1054,6 +1058,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 @@ -1068,7 +1073,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) @@ -1102,11 +1112,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); }