Message ID | 1634263236-6111-1-git-send-email-haibo.chen@nxp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] mmc: sdhci-esdhc-imx: clear the buffer_read_ready to reset standard tuning circuit | expand |
On Fri, 15 Oct 2021 at 04:25, <haibo.chen@nxp.com> wrote: > > From: Haibo Chen <haibo.chen@nxp.com> > > To reset standard tuning circuit completely, after clear ESDHC_MIX_CTRL_EXE_TUNE, > also need to clear bit buffer_read_ready, this operation will finally clear the > USDHC IP internal logic flag execute_tuning_with_clr_buf, make sure the following > normal data transfer will not be impacted by standard tuning logic used before. > > Find this issue when do quick SD card insert/remove stress test. During standard > tuning prodedure, if remove SD card, USDHC standard tuning logic can't clear the > internal flag execute_tuning_with_clr_buf. Next time when insert SD card, all > data related commands can't get any data related interrupts, include data transfer > complete interrupt, data timeout interrupt, data CRC interrupt, data end bit interrupt. > Always trigger software timeout issue. Even reset the USDHC through bits in register > SYS_CTRL (0x2C, bit28 reset tuning, bit26 reset data, bit 25 reset command, bit 24 > reset all) can't recover this. From the user's point of view, USDHC stuck, SD can't > be recognized any more. > > Fixes: d9370424c948 ("mmc: sdhci-esdhc-imx: reset tuning circuit when power on mmc card") > Signed-off-by: Haibo Chen <haibo.chen@nxp.com> > Acked-by: Adrian Hunter <adrian.hunter@intel.com> Applied for fixes and by adding stable tag, thanks! Kind regards Uffe > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index f18d169bc8ff..e658f0174242 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -1187,6 +1187,7 @@ static void esdhc_reset_tuning(struct sdhci_host *host) > struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); > u32 ctrl; > + int ret; > > /* Reset the tuning circuit */ > if (esdhc_is_usdhc(imx_data)) { > @@ -1199,7 +1200,22 @@ static void esdhc_reset_tuning(struct sdhci_host *host) > } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { > ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); > ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; > + ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE; > writel(ctrl, host->ioaddr + SDHCI_AUTO_CMD_STATUS); > + /* Make sure ESDHC_MIX_CTRL_EXE_TUNE cleared */ > + ret = readl_poll_timeout(host->ioaddr + SDHCI_AUTO_CMD_STATUS, > + ctrl, !(ctrl & ESDHC_MIX_CTRL_EXE_TUNE), 1, 50); > + if (ret == -ETIMEDOUT) > + dev_warn(mmc_dev(host->mmc), > + "Warning! clear execute tuning bit failed\n"); > + /* > + * SDHCI_INT_DATA_AVAIL is W1C bit, set this bit will clear the > + * usdhc IP internal logic flag execute_tuning_with_clr_buf, which > + * will finally make sure the normal data transfer logic correct. > + */ > + ctrl = readl(host->ioaddr + SDHCI_INT_STATUS); > + ctrl |= SDHCI_INT_DATA_AVAIL; > + writel(ctrl, host->ioaddr + SDHCI_INT_STATUS); > } > } > } > -- > 2.17.1 >
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index f18d169bc8ff..e658f0174242 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1187,6 +1187,7 @@ static void esdhc_reset_tuning(struct sdhci_host *host) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); u32 ctrl; + int ret; /* Reset the tuning circuit */ if (esdhc_is_usdhc(imx_data)) { @@ -1199,7 +1200,22 @@ static void esdhc_reset_tuning(struct sdhci_host *host) } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; + ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE; writel(ctrl, host->ioaddr + SDHCI_AUTO_CMD_STATUS); + /* Make sure ESDHC_MIX_CTRL_EXE_TUNE cleared */ + ret = readl_poll_timeout(host->ioaddr + SDHCI_AUTO_CMD_STATUS, + ctrl, !(ctrl & ESDHC_MIX_CTRL_EXE_TUNE), 1, 50); + if (ret == -ETIMEDOUT) + dev_warn(mmc_dev(host->mmc), + "Warning! clear execute tuning bit failed\n"); + /* + * SDHCI_INT_DATA_AVAIL is W1C bit, set this bit will clear the + * usdhc IP internal logic flag execute_tuning_with_clr_buf, which + * will finally make sure the normal data transfer logic correct. + */ + ctrl = readl(host->ioaddr + SDHCI_INT_STATUS); + ctrl |= SDHCI_INT_DATA_AVAIL; + writel(ctrl, host->ioaddr + SDHCI_INT_STATUS); } } }