Re: [PATCH v4 2/7] mmc: sdhci-esdhc-imx: restore DLL override for DDR modes on resume
Adrian Hunter <[email protected]>
| Newsgroups | org.kernel.vger.linux-mmc,dev.linux.lists.imx,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Organization | Intel Finland Oy, Registered Address: c/o Alberga Business Park, 6 krs, Bertel Jungin Aukio 5, 02600 Espoo, Business Identity Code: 0357606 - 4, Domiciled in Helsinki |
| Message-ID | <[email protected]> |
On 03/07/2026 13:42, [email protected] wrote: > From: Luke Wang <[email protected]> > > sdhci_esdhc_imx_hwinit() unconditionally clears ESDHC_DLL_CTRL by > writing zero. For SDIO devices that keep power during system suspend > and operate in DDR mode, the card remains in DDR timing while the host > DLL override configuration is lost. > > Extract the DLL override setup from esdhc_set_uhs_signaling() into > a helper esdhc_set_dll_override(), and call it on the resume path > when the card kept power and is using a DDR timing mode. > > Fixes: 676a83855614 ("mmc: host: sdhci-esdhc-imx: refactor the system PM logic") > Reviewed-by: Frank Li <[email protected]> > Reviewed-by: Haibo Chen <[email protected]> > Signed-off-by: Luke Wang <[email protected]> Acked-by: Adrian Hunter <[email protected]> > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 39 +++++++++++++++++++++--------- > 1 file changed, 28 insertions(+), 11 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index 6526d65538de..7230d70e02ae 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -1349,6 +1349,23 @@ static int esdhc_change_pinstate(struct sdhci_host *host, > return pinctrl_select_state(imx_data->pinctrl, pinctrl); > } > > +static void esdhc_set_dll_override(struct sdhci_host *host) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); > + struct esdhc_platform_data *boarddata = &imx_data->boarddata; > + u32 v; > + > + if (!boarddata->delay_line) > + return; > + > + v = boarddata->delay_line << ESDHC_DLL_OVERRIDE_VAL_SHIFT | > + (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT); > + if (is_imx53_esdhc(imx_data)) > + v <<= 1; > + writel(v, host->ioaddr + ESDHC_DLL_CTRL); > +} > + > /* > * For HS400 eMMC, there is a data_strobe line. This signal is generated > * by the device and used for data output and CRC status response output > @@ -1404,7 +1421,6 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > u32 m; > struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); > - struct esdhc_platform_data *boarddata = &imx_data->boarddata; > > /* disable ddr mode and disable HS400 mode */ > m = readl(host->ioaddr + ESDHC_MIX_CTRL); > @@ -1425,15 +1441,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > m |= ESDHC_MIX_CTRL_DDREN; > writel(m, host->ioaddr + ESDHC_MIX_CTRL); > imx_data->is_ddr = 1; > - if (boarddata->delay_line) { > - u32 v; > - v = boarddata->delay_line << > - ESDHC_DLL_OVERRIDE_VAL_SHIFT | > - (1 << ESDHC_DLL_OVERRIDE_EN_SHIFT); > - if (is_imx53_esdhc(imx_data)) > - v <<= 1; > - writel(v, host->ioaddr + ESDHC_DLL_CTRL); > - } > + esdhc_set_dll_override(host); > break; > case MMC_TIMING_MMC_HS400: > m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN; > @@ -2123,9 +2131,18 @@ static int sdhci_esdhc_resume(struct device *dev) > * restore the saved tuning delay value for the device which keep > * power during system PM. > */ > - if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data)) > + if (mmc_card_keep_power(host->mmc) && esdhc_is_usdhc(imx_data)) { > sdhc_esdhc_tuning_restore(host); > > + /* > + * Restore DLL override for DDR modes. hwinit unconditionally > + * clears ESDHC_DLL_CTRL, but the card is still in DDR mode. > + */ > + if (host->timing == MMC_TIMING_UHS_DDR50 || > + host->timing == MMC_TIMING_MMC_DDR52) > + esdhc_set_dll_override(host); > + } > + > pm_runtime_put_autosuspend(dev); > > return ret;