* [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic @ 2025-05-21 2:55 ziniu.wang_1 2025-05-21 2:55 ` [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support ziniu.wang_1 ` (3 more replies) 0 siblings, 4 replies; 10+ messages in thread From: ziniu.wang_1 @ 2025-05-21 2:55 UTC (permalink / raw) To: haibo.chen, adrian.hunter, ulf.hansson, linux-mmc Cc: shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel From: Luke Wang <ziniu.wang_1@nxp.com> i.MX reference manual specifies that internal clock loopback should be used for SDR104/HS200/HS400 modes. Move ESDHC_MIX_CTRL_FBCLK_SEL configuration into the timing selection function to: 1. Explicitly set internal loopback path for SDR104/HS200/HS400 modes 2. Avoid redundant bit manipulation across multiple functions Preserve ESDHC_MIX_CTRL_FBCLK_SEL during system resume for SDIO devices with MMC_PM_KEEP_POWER and MMC_PM_WAKE_SDIO_IRQ flag, as the controller might lose register state during suspend while skipping card re-initialization. Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> --- drivers/mmc/host/sdhci-esdhc-imx.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 7611682f10c3..c448a53530a5 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -728,23 +728,17 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); - u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); - if (val & SDHCI_CTRL_TUNED_CLK) { + if (val & SDHCI_CTRL_TUNED_CLK) v |= ESDHC_MIX_CTRL_SMPCLK_SEL; - } else { + else v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; - m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; - } - if (val & SDHCI_CTRL_EXEC_TUNING) { + if (val & SDHCI_CTRL_EXEC_TUNING) v |= ESDHC_MIX_CTRL_EXE_TUNE; - m |= ESDHC_MIX_CTRL_FBCLK_SEL; - } else { + else v &= ~ESDHC_MIX_CTRL_EXE_TUNE; - } writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); - writel(m, host->ioaddr + ESDHC_MIX_CTRL); } return; case SDHCI_TRANSFER_MODE: @@ -1082,7 +1076,6 @@ static void esdhc_reset_tuning(struct sdhci_host *host) ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { 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) { @@ -1177,8 +1170,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) "warning! RESET_ALL never complete before sending tuning command\n"); reg = readl(host->ioaddr + ESDHC_MIX_CTRL); - reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | - ESDHC_MIX_CTRL_FBCLK_SEL; + reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL; writel(reg, host->ioaddr + ESDHC_MIX_CTRL); writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, val), host->ioaddr + ESDHC_TUNE_CTRL_STATUS); @@ -1432,6 +1424,15 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) break; } + if (timing == MMC_TIMING_UHS_SDR104 || + timing == MMC_TIMING_MMC_HS200 || + timing == MMC_TIMING_MMC_HS400) + m |= ESDHC_MIX_CTRL_FBCLK_SEL; + else + m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; + + writel(m, host->ioaddr + ESDHC_MIX_CTRL); + esdhc_change_pinstate(host, timing); } -- 2.34.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support 2025-05-21 2:55 [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic ziniu.wang_1 @ 2025-05-21 2:55 ` ziniu.wang_1 2025-05-21 16:20 ` Frank Li ` (2 more replies) 2025-05-21 16:09 ` [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic Frank Li ` (2 subsequent siblings) 3 siblings, 3 replies; 10+ messages in thread From: ziniu.wang_1 @ 2025-05-21 2:55 UTC (permalink / raw) To: haibo.chen, adrian.hunter, ulf.hansson, linux-mmc Cc: shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel From: Luke Wang <ziniu.wang_1@nxp.com> For legacy platforms without dummy pad: When clock <= 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 0 (external clock pad loopback) for better bus clock proximity. When clock > 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 1 (internal clock loopback) to avoid signal reflection noise at high frequency. For i.MX94/95 with dummy pad support: Keep ESDHC_MIX_CTRL_FBCLK_SEL at 0 for all speed mode. Hardware automatically substitutes clock pad loopback with dummy pad loopback when available, eliminating signal reflections while preserving better bus clock proximity. Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> --- drivers/mmc/host/sdhci-esdhc-imx.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index c448a53530a5..5f1c45b2bd5d 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -212,6 +212,9 @@ /* The IP does not have GPIO CD wake capabilities */ #define ESDHC_FLAG_SKIP_CD_WAKE BIT(18) +/* the controller has dummy pad for clock loopback */ +#define ESDHC_FLAG_DUMMY_PAD BIT(19) + #define ESDHC_AUTO_TUNING_WINDOW 3 enum wp_types { @@ -348,6 +351,15 @@ static struct esdhc_soc_data usdhc_imx8mm_data = { .quirks = SDHCI_QUIRK_NO_LED, }; +static struct esdhc_soc_data usdhc_imx95_data = { + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES + | ESDHC_FLAG_STATE_LOST_IN_LPMODE + | ESDHC_FLAG_DUMMY_PAD, + .quirks = SDHCI_QUIRK_NO_LED, +}; + struct pltfm_imx_data { u32 scratchpad; struct pinctrl *pinctrl; @@ -392,6 +404,8 @@ static const struct of_device_id imx_esdhc_dt_ids[] = { { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, }, { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, }, { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, }, + { .compatible = "fsl,imx94-usdhc", .data = &usdhc_imx95_data, }, + { .compatible = "fsl,imx95-usdhc", .data = &usdhc_imx95_data, }, { .compatible = "fsl,imxrt1050-usdhc", .data = &usdhc_imxrt1050_data, }, { .compatible = "nxp,s32g2-usdhc", .data = &usdhc_s32g2_data, }, { /* sentinel */ } @@ -1424,9 +1438,10 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) break; } - if (timing == MMC_TIMING_UHS_SDR104 || - timing == MMC_TIMING_MMC_HS200 || - timing == MMC_TIMING_MMC_HS400) + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD) && + (timing == MMC_TIMING_UHS_SDR104 || + timing == MMC_TIMING_MMC_HS200 || + timing == MMC_TIMING_MMC_HS400)) m |= ESDHC_MIX_CTRL_FBCLK_SEL; else m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; @@ -1678,7 +1693,9 @@ static void sdhc_esdhc_tuning_restore(struct sdhci_host *host) writel(reg, host->ioaddr + ESDHC_TUNING_CTRL); reg = readl(host->ioaddr + ESDHC_MIX_CTRL); - reg |= ESDHC_MIX_CTRL_SMPCLK_SEL | ESDHC_MIX_CTRL_FBCLK_SEL; + reg |= ESDHC_MIX_CTRL_SMPCLK_SEL; + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD)) + reg |= ESDHC_MIX_CTRL_FBCLK_SEL; writel(reg, host->ioaddr + ESDHC_MIX_CTRL); writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, -- 2.34.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support 2025-05-21 2:55 ` [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support ziniu.wang_1 @ 2025-05-21 16:20 ` Frank Li 2025-05-28 10:34 ` Adrian Hunter 2025-06-09 14:24 ` Ulf Hansson 2 siblings, 0 replies; 10+ messages in thread From: Frank Li @ 2025-05-21 16:20 UTC (permalink / raw) To: ziniu.wang_1 Cc: haibo.chen, adrian.hunter, ulf.hansson, linux-mmc, shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel On Wed, May 21, 2025 at 10:55:02AM +0800, ziniu.wang_1@nxp.com wrote: > From: Luke Wang <ziniu.wang_1@nxp.com> > > For legacy platforms without dummy pad: > When clock <= 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 0 (external clock > pad loopback) for better bus clock proximity. > When clock > 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 1 (internal clock > loopback) to avoid signal reflection noise at high frequency. > > For i.MX94/95 with dummy pad support: > Keep ESDHC_MIX_CTRL_FBCLK_SEL at 0 for all speed mode. Hardware > automatically substitutes clock pad loopback with dummy pad loopback > when available, eliminating signal reflections while preserving better > bus clock proximity. Add indents after : to better read For legacy platforms without dummy pad: When clock <= 100Mhz: Set ... For i.MX94/95 with dummy pad support: Set ESDHC_MIX_CTRL_FBCLK_SEL at 0 for all speed mode. .... > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index c448a53530a5..5f1c45b2bd5d 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -212,6 +212,9 @@ > /* The IP does not have GPIO CD wake capabilities */ > #define ESDHC_FLAG_SKIP_CD_WAKE BIT(18) > > +/* the controller has dummy pad for clock loopback */ > +#define ESDHC_FLAG_DUMMY_PAD BIT(19) > + > #define ESDHC_AUTO_TUNING_WINDOW 3 > > enum wp_types { > @@ -348,6 +351,15 @@ static struct esdhc_soc_data usdhc_imx8mm_data = { > .quirks = SDHCI_QUIRK_NO_LED, > }; > > +static struct esdhc_soc_data usdhc_imx95_data = { > + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING > + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 > + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES > + | ESDHC_FLAG_STATE_LOST_IN_LPMODE > + | ESDHC_FLAG_DUMMY_PAD, > + .quirks = SDHCI_QUIRK_NO_LED, > +}; > + > struct pltfm_imx_data { > u32 scratchpad; > struct pinctrl *pinctrl; > @@ -392,6 +404,8 @@ static const struct of_device_id imx_esdhc_dt_ids[] = { > { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, }, > { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, }, > { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, }, > + { .compatible = "fsl,imx94-usdhc", .data = &usdhc_imx95_data, }, > + { .compatible = "fsl,imx95-usdhc", .data = &usdhc_imx95_data, }, You'd better mention "fsl,imx94-usdhc" and "fsl,imx95-usdhc" already in binding doc after "---" to let maintainer known these already documented. Frank > { .compatible = "fsl,imxrt1050-usdhc", .data = &usdhc_imxrt1050_data, }, > { .compatible = "nxp,s32g2-usdhc", .data = &usdhc_s32g2_data, }, > { /* sentinel */ } > @@ -1424,9 +1438,10 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > break; > } > > - if (timing == MMC_TIMING_UHS_SDR104 || > - timing == MMC_TIMING_MMC_HS200 || > - timing == MMC_TIMING_MMC_HS400) > + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD) && > + (timing == MMC_TIMING_UHS_SDR104 || > + timing == MMC_TIMING_MMC_HS200 || > + timing == MMC_TIMING_MMC_HS400)) > m |= ESDHC_MIX_CTRL_FBCLK_SEL; > else > m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > @@ -1678,7 +1693,9 @@ static void sdhc_esdhc_tuning_restore(struct sdhci_host *host) > writel(reg, host->ioaddr + ESDHC_TUNING_CTRL); > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > - reg |= ESDHC_MIX_CTRL_SMPCLK_SEL | ESDHC_MIX_CTRL_FBCLK_SEL; > + reg |= ESDHC_MIX_CTRL_SMPCLK_SEL; > + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD)) > + reg |= ESDHC_MIX_CTRL_FBCLK_SEL; > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support 2025-05-21 2:55 ` [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support ziniu.wang_1 2025-05-21 16:20 ` Frank Li @ 2025-05-28 10:34 ` Adrian Hunter 2025-06-09 14:24 ` Ulf Hansson 2 siblings, 0 replies; 10+ messages in thread From: Adrian Hunter @ 2025-05-28 10:34 UTC (permalink / raw) To: ziniu.wang_1, haibo.chen, ulf.hansson, linux-mmc Cc: shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel On 21/05/2025 05:55, ziniu.wang_1@nxp.com wrote: > From: Luke Wang <ziniu.wang_1@nxp.com> > > For legacy platforms without dummy pad: > When clock <= 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 0 (external clock > pad loopback) for better bus clock proximity. > When clock > 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 1 (internal clock > loopback) to avoid signal reflection noise at high frequency. > > For i.MX94/95 with dummy pad support: > Keep ESDHC_MIX_CTRL_FBCLK_SEL at 0 for all speed mode. Hardware > automatically substitutes clock pad loopback with dummy pad loopback > when available, eliminating signal reflections while preserving better > bus clock proximity. > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index c448a53530a5..5f1c45b2bd5d 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -212,6 +212,9 @@ > /* The IP does not have GPIO CD wake capabilities */ > #define ESDHC_FLAG_SKIP_CD_WAKE BIT(18) > > +/* the controller has dummy pad for clock loopback */ > +#define ESDHC_FLAG_DUMMY_PAD BIT(19) > + > #define ESDHC_AUTO_TUNING_WINDOW 3 > > enum wp_types { > @@ -348,6 +351,15 @@ static struct esdhc_soc_data usdhc_imx8mm_data = { > .quirks = SDHCI_QUIRK_NO_LED, > }; > > +static struct esdhc_soc_data usdhc_imx95_data = { > + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING > + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 > + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES > + | ESDHC_FLAG_STATE_LOST_IN_LPMODE > + | ESDHC_FLAG_DUMMY_PAD, > + .quirks = SDHCI_QUIRK_NO_LED, > +}; > + > struct pltfm_imx_data { > u32 scratchpad; > struct pinctrl *pinctrl; > @@ -392,6 +404,8 @@ static const struct of_device_id imx_esdhc_dt_ids[] = { > { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, }, > { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, }, > { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, }, > + { .compatible = "fsl,imx94-usdhc", .data = &usdhc_imx95_data, }, > + { .compatible = "fsl,imx95-usdhc", .data = &usdhc_imx95_data, }, > { .compatible = "fsl,imxrt1050-usdhc", .data = &usdhc_imxrt1050_data, }, > { .compatible = "nxp,s32g2-usdhc", .data = &usdhc_s32g2_data, }, > { /* sentinel */ } > @@ -1424,9 +1438,10 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > break; > } > > - if (timing == MMC_TIMING_UHS_SDR104 || > - timing == MMC_TIMING_MMC_HS200 || > - timing == MMC_TIMING_MMC_HS400) > + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD) && > + (timing == MMC_TIMING_UHS_SDR104 || > + timing == MMC_TIMING_MMC_HS200 || > + timing == MMC_TIMING_MMC_HS400)) > m |= ESDHC_MIX_CTRL_FBCLK_SEL; > else > m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > @@ -1678,7 +1693,9 @@ static void sdhc_esdhc_tuning_restore(struct sdhci_host *host) > writel(reg, host->ioaddr + ESDHC_TUNING_CTRL); > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > - reg |= ESDHC_MIX_CTRL_SMPCLK_SEL | ESDHC_MIX_CTRL_FBCLK_SEL; > + reg |= ESDHC_MIX_CTRL_SMPCLK_SEL; > + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD)) > + reg |= ESDHC_MIX_CTRL_FBCLK_SEL; > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support 2025-05-21 2:55 ` [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support ziniu.wang_1 2025-05-21 16:20 ` Frank Li 2025-05-28 10:34 ` Adrian Hunter @ 2025-06-09 14:24 ` Ulf Hansson 2 siblings, 0 replies; 10+ messages in thread From: Ulf Hansson @ 2025-06-09 14:24 UTC (permalink / raw) To: ziniu.wang_1 Cc: haibo.chen, adrian.hunter, linux-mmc, shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel On Wed, 21 May 2025 at 04:53, <ziniu.wang_1@nxp.com> wrote: > > From: Luke Wang <ziniu.wang_1@nxp.com> > > For legacy platforms without dummy pad: > When clock <= 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 0 (external clock > pad loopback) for better bus clock proximity. > When clock > 100MHz: Set ESDHC_MIX_CTRL_FBCLK_SEL to 1 (internal clock > loopback) to avoid signal reflection noise at high frequency. > > For i.MX94/95 with dummy pad support: > Keep ESDHC_MIX_CTRL_FBCLK_SEL at 0 for all speed mode. Hardware > automatically substitutes clock pad loopback with dummy pad loopback > when available, eliminating signal reflections while preserving better > bus clock proximity. > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> Applied for next, thanks! Kind regards Uffe > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index c448a53530a5..5f1c45b2bd5d 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -212,6 +212,9 @@ > /* The IP does not have GPIO CD wake capabilities */ > #define ESDHC_FLAG_SKIP_CD_WAKE BIT(18) > > +/* the controller has dummy pad for clock loopback */ > +#define ESDHC_FLAG_DUMMY_PAD BIT(19) > + > #define ESDHC_AUTO_TUNING_WINDOW 3 > > enum wp_types { > @@ -348,6 +351,15 @@ static struct esdhc_soc_data usdhc_imx8mm_data = { > .quirks = SDHCI_QUIRK_NO_LED, > }; > > +static struct esdhc_soc_data usdhc_imx95_data = { > + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING > + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 > + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES > + | ESDHC_FLAG_STATE_LOST_IN_LPMODE > + | ESDHC_FLAG_DUMMY_PAD, > + .quirks = SDHCI_QUIRK_NO_LED, > +}; > + > struct pltfm_imx_data { > u32 scratchpad; > struct pinctrl *pinctrl; > @@ -392,6 +404,8 @@ static const struct of_device_id imx_esdhc_dt_ids[] = { > { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, }, > { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, }, > { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, }, > + { .compatible = "fsl,imx94-usdhc", .data = &usdhc_imx95_data, }, > + { .compatible = "fsl,imx95-usdhc", .data = &usdhc_imx95_data, }, > { .compatible = "fsl,imxrt1050-usdhc", .data = &usdhc_imxrt1050_data, }, > { .compatible = "nxp,s32g2-usdhc", .data = &usdhc_s32g2_data, }, > { /* sentinel */ } > @@ -1424,9 +1438,10 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > break; > } > > - if (timing == MMC_TIMING_UHS_SDR104 || > - timing == MMC_TIMING_MMC_HS200 || > - timing == MMC_TIMING_MMC_HS400) > + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD) && > + (timing == MMC_TIMING_UHS_SDR104 || > + timing == MMC_TIMING_MMC_HS200 || > + timing == MMC_TIMING_MMC_HS400)) > m |= ESDHC_MIX_CTRL_FBCLK_SEL; > else > m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > @@ -1678,7 +1693,9 @@ static void sdhc_esdhc_tuning_restore(struct sdhci_host *host) > writel(reg, host->ioaddr + ESDHC_TUNING_CTRL); > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > - reg |= ESDHC_MIX_CTRL_SMPCLK_SEL | ESDHC_MIX_CTRL_FBCLK_SEL; > + reg |= ESDHC_MIX_CTRL_SMPCLK_SEL; > + if (!(imx_data->socdata->flags & ESDHC_FLAG_DUMMY_PAD)) > + reg |= ESDHC_MIX_CTRL_FBCLK_SEL; > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic 2025-05-21 2:55 [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic ziniu.wang_1 2025-05-21 2:55 ` [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support ziniu.wang_1 @ 2025-05-21 16:09 ` Frank Li 2025-05-22 3:52 ` Bough Chen 2025-05-28 10:34 ` Adrian Hunter 2025-06-09 14:24 ` Ulf Hansson 3 siblings, 1 reply; 10+ messages in thread From: Frank Li @ 2025-05-21 16:09 UTC (permalink / raw) To: ziniu.wang_1 Cc: haibo.chen, adrian.hunter, ulf.hansson, linux-mmc, shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel On Wed, May 21, 2025 at 10:55:01AM +0800, ziniu.wang_1@nxp.com wrote: > From: Luke Wang <ziniu.wang_1@nxp.com> > > i.MX reference manual specifies that internal clock loopback should be > used for SDR104/HS200/HS400 modes. Move ESDHC_MIX_CTRL_FBCLK_SEL > configuration into the timing selection function to: > > 1. Explicitly set internal loopback path for SDR104/HS200/HS400 modes > 2. Avoid redundant bit manipulation across multiple functions > > Preserve ESDHC_MIX_CTRL_FBCLK_SEL during system resume for SDIO devices > with MMC_PM_KEEP_POWER and MMC_PM_WAKE_SDIO_IRQ flag, as the controller > might lose register state during suspend while skipping card > re-initialization. what's means? controller lost power during suspend, so u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL) to get reset value and miss set ~ESDHC_MIX_CTRL_FBCLK_SEL? Frank > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 27 ++++++++++++++------------- > 1 file changed, 14 insertions(+), 13 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index 7611682f10c3..c448a53530a5 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -728,23 +728,17 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) > writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); > if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { > u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); > - u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); > - if (val & SDHCI_CTRL_TUNED_CLK) { > + if (val & SDHCI_CTRL_TUNED_CLK) > v |= ESDHC_MIX_CTRL_SMPCLK_SEL; > - } else { > + else > v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; > - m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > - } > > - if (val & SDHCI_CTRL_EXEC_TUNING) { > + if (val & SDHCI_CTRL_EXEC_TUNING) > v |= ESDHC_MIX_CTRL_EXE_TUNE; > - m |= ESDHC_MIX_CTRL_FBCLK_SEL; > - } else { > + else > v &= ~ESDHC_MIX_CTRL_EXE_TUNE; > - } > > writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); > - writel(m, host->ioaddr + ESDHC_MIX_CTRL); > } > return; > case SDHCI_TRANSFER_MODE: > @@ -1082,7 +1076,6 @@ static void esdhc_reset_tuning(struct sdhci_host *host) > ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; > if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { > 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) { > @@ -1177,8 +1170,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) > "warning! RESET_ALL never complete before sending tuning command\n"); > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > - reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | > - ESDHC_MIX_CTRL_FBCLK_SEL; > + reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL; > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, val), > host->ioaddr + ESDHC_TUNE_CTRL_STATUS); > @@ -1432,6 +1424,15 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > break; > } > > + if (timing == MMC_TIMING_UHS_SDR104 || > + timing == MMC_TIMING_MMC_HS200 || > + timing == MMC_TIMING_MMC_HS400) > + m |= ESDHC_MIX_CTRL_FBCLK_SEL; > + else > + m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > + > + writel(m, host->ioaddr + ESDHC_MIX_CTRL); > + > esdhc_change_pinstate(host, timing); > } > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic 2025-05-21 16:09 ` [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic Frank Li @ 2025-05-22 3:52 ` Bough Chen 2025-05-22 3:59 ` Bough Chen 0 siblings, 1 reply; 10+ messages in thread From: Bough Chen @ 2025-05-22 3:52 UTC (permalink / raw) To: Frank Li, Luke Wang Cc: adrian.hunter@intel.com, ulf.hansson@linaro.org, linux-mmc@vger.kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, imx@lists.linux.dev, dl-S32, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Frank Li <frank.li@nxp.com> > Sent: 2025年5月22日 0:10 > To: Luke Wang <ziniu.wang_1@nxp.com> > Cc: Bough Chen <haibo.chen@nxp.com>; adrian.hunter@intel.com; > ulf.hansson@linaro.org; linux-mmc@vger.kernel.org; shawnguo@kernel.org; > s.hauer@pengutronix.de; kernel@pengutronix.de; festevam@gmail.com; > imx@lists.linux.dev; dl-S32 <S32@nxp.com>; > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback > selection logic > > On Wed, May 21, 2025 at 10:55:01AM +0800, ziniu.wang_1@nxp.com wrote: > > From: Luke Wang <ziniu.wang_1@nxp.com> > > > > i.MX reference manual specifies that internal clock loopback should be > > used for SDR104/HS200/HS400 modes. Move ESDHC_MIX_CTRL_FBCLK_SEL > > configuration into the timing selection function to: > > > > 1. Explicitly set internal loopback path for SDR104/HS200/HS400 modes > > 2. Avoid redundant bit manipulation across multiple functions > > > > Preserve ESDHC_MIX_CTRL_FBCLK_SEL during system resume for SDIO > > devices with MMC_PM_KEEP_POWER and MMC_PM_WAKE_SDIO_IRQ flag, > as the > > controller might lose register state during suspend while skipping > > card re-initialization. > > what's means? > > controller lost power during suspend, so > u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL) to get reset value and miss > > set ~ESDHC_MIX_CTRL_FBCLK_SEL? Miss set ESDHC_MIX_CTRL_FBCLK_SEL. Previous SDIO3.0 device with MMC_PM_KEEP_POWER will set ESDHC_MIX_CTRL_FBCLK_SEL, After system resume, need to re-config ESDHC_MIX_CTRL_FBCLK_SEL. But SDIO3.0 device with MMC_PM_KEEP_POWER will not re-initialization, but will call set_ios-> set_uhs_signaling(). Regards Haibo Chen > > Frank > > > > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> > > --- > > drivers/mmc/host/sdhci-esdhc-imx.c | 27 ++++++++++++++------------- > > 1 file changed, 14 insertions(+), 13 deletions(-) > > > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c > > b/drivers/mmc/host/sdhci-esdhc-imx.c > > index 7611682f10c3..c448a53530a5 100644 > > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > > @@ -728,23 +728,17 @@ static void esdhc_writew_le(struct sdhci_host > *host, u16 val, int reg) > > writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); > > if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { > > u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); > > - u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); > > - if (val & SDHCI_CTRL_TUNED_CLK) { > > + if (val & SDHCI_CTRL_TUNED_CLK) > > v |= ESDHC_MIX_CTRL_SMPCLK_SEL; > > - } else { > > + else > > v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; > > - m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > > - } > > > > - if (val & SDHCI_CTRL_EXEC_TUNING) { > > + if (val & SDHCI_CTRL_EXEC_TUNING) > > v |= ESDHC_MIX_CTRL_EXE_TUNE; > > - m |= ESDHC_MIX_CTRL_FBCLK_SEL; > > - } else { > > + else > > v &= ~ESDHC_MIX_CTRL_EXE_TUNE; > > - } > > > > writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); > > - writel(m, host->ioaddr + ESDHC_MIX_CTRL); > > } > > return; > > case SDHCI_TRANSFER_MODE: > > @@ -1082,7 +1076,6 @@ static void esdhc_reset_tuning(struct sdhci_host > *host) > > ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; > > if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { > > 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) > { @@ > > -1177,8 +1170,7 @@ static void esdhc_prepare_tuning(struct sdhci_host > *host, u32 val) > > "warning! RESET_ALL never complete before sending tuning > > command\n"); > > > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > > - reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | > > - ESDHC_MIX_CTRL_FBCLK_SEL; > > + reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL; > > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > > > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MAS > K, val), > > host->ioaddr + ESDHC_TUNE_CTRL_STATUS); @@ -1432,6 > +1424,15 > > @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned > timing) > > break; > > } > > > > + if (timing == MMC_TIMING_UHS_SDR104 || > > + timing == MMC_TIMING_MMC_HS200 || > > + timing == MMC_TIMING_MMC_HS400) > > + m |= ESDHC_MIX_CTRL_FBCLK_SEL; > > + else > > + m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > > + > > + writel(m, host->ioaddr + ESDHC_MIX_CTRL); > > + > > esdhc_change_pinstate(host, timing); } > > > > -- > > 2.34.1 > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic 2025-05-22 3:52 ` Bough Chen @ 2025-05-22 3:59 ` Bough Chen 0 siblings, 0 replies; 10+ messages in thread From: Bough Chen @ 2025-05-22 3:59 UTC (permalink / raw) To: Frank Li, Luke Wang Cc: adrian.hunter@intel.com, ulf.hansson@linaro.org, linux-mmc@vger.kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, imx@lists.linux.dev, dl-S32, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Bough Chen > Sent: 2025年5月22日 11:53 > To: Frank Li <frank.li@nxp.com>; Luke Wang <ziniu.wang_1@nxp.com> > Cc: adrian.hunter@intel.com; ulf.hansson@linaro.org; > linux-mmc@vger.kernel.org; shawnguo@kernel.org; s.hauer@pengutronix.de; > kernel@pengutronix.de; festevam@gmail.com; imx@lists.linux.dev; dl-S32 > <S32@nxp.com>; linux-arm-kernel@lists.infradead.org; > linux-kernel@vger.kernel.org > Subject: RE: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback > selection logic > > > -----Original Message----- > > From: Frank Li <frank.li@nxp.com> > > Sent: 2025年5月22日 0:10 > > To: Luke Wang <ziniu.wang_1@nxp.com> > > Cc: Bough Chen <haibo.chen@nxp.com>; adrian.hunter@intel.com; > > ulf.hansson@linaro.org; linux-mmc@vger.kernel.org; > > shawnguo@kernel.org; s.hauer@pengutronix.de; kernel@pengutronix.de; > > festevam@gmail.com; imx@lists.linux.dev; dl-S32 <S32@nxp.com>; > > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org > > Subject: Re: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback > > selection logic > > > > On Wed, May 21, 2025 at 10:55:01AM +0800, ziniu.wang_1@nxp.com wrote: > > > From: Luke Wang <ziniu.wang_1@nxp.com> > > > > > > i.MX reference manual specifies that internal clock loopback should > > > be used for SDR104/HS200/HS400 modes. Move > ESDHC_MIX_CTRL_FBCLK_SEL > > > configuration into the timing selection function to: > > > > > > 1. Explicitly set internal loopback path for SDR104/HS200/HS400 > > > modes 2. Avoid redundant bit manipulation across multiple functions > > > > > > Preserve ESDHC_MIX_CTRL_FBCLK_SEL during system resume for SDIO > > > devices with MMC_PM_KEEP_POWER and MMC_PM_WAKE_SDIO_IRQ flag, > > as the > > > controller might lose register state during suspend while skipping > > > card re-initialization. > > > > what's means? > > > > controller lost power during suspend, so > > u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL) to get reset value and > > miss > > > > set ~ESDHC_MIX_CTRL_FBCLK_SEL? > > Miss set ESDHC_MIX_CTRL_FBCLK_SEL. > > Previous SDIO3.0 device with MMC_PM_KEEP_POWER will set > ESDHC_MIX_CTRL_FBCLK_SEL, After system resume, need to re-config > ESDHC_MIX_CTRL_FBCLK_SEL. But SDIO3.0 device with > MMC_PM_KEEP_POWER will not re-initialization, but will call set_ios-> > set_uhs_signaling(). sdhc_esdhc_tuning_restore() will also set back the ESDHC_MIX_CTRL_FBCLK_SEL.. Regards Haibo Chen > > Regards > Haibo Chen > > > > Frank > > > > > > > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> > > > --- > > > drivers/mmc/host/sdhci-esdhc-imx.c | 27 ++++++++++++++------------- > > > 1 file changed, 14 insertions(+), 13 deletions(-) > > > > > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c > > > b/drivers/mmc/host/sdhci-esdhc-imx.c > > > index 7611682f10c3..c448a53530a5 100644 > > > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > > > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > > > @@ -728,23 +728,17 @@ static void esdhc_writew_le(struct sdhci_host > > *host, u16 val, int reg) > > > writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); > > > if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { > > > u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); > > > - u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); > > > - if (val & SDHCI_CTRL_TUNED_CLK) { > > > + if (val & SDHCI_CTRL_TUNED_CLK) > > > v |= ESDHC_MIX_CTRL_SMPCLK_SEL; > > > - } else { > > > + else > > > v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; > > > - m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > > > - } > > > > > > - if (val & SDHCI_CTRL_EXEC_TUNING) { > > > + if (val & SDHCI_CTRL_EXEC_TUNING) > > > v |= ESDHC_MIX_CTRL_EXE_TUNE; > > > - m |= ESDHC_MIX_CTRL_FBCLK_SEL; > > > - } else { > > > + else > > > v &= ~ESDHC_MIX_CTRL_EXE_TUNE; > > > - } > > > > > > writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); > > > - writel(m, host->ioaddr + ESDHC_MIX_CTRL); > > > } > > > return; > > > case SDHCI_TRANSFER_MODE: > > > @@ -1082,7 +1076,6 @@ static void esdhc_reset_tuning(struct > > > sdhci_host > > *host) > > > ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; > > > if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { > > > 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) > > { @@ > > > -1177,8 +1170,7 @@ static void esdhc_prepare_tuning(struct > > > sdhci_host > > *host, u32 val) > > > "warning! RESET_ALL never complete before sending tuning > > > command\n"); > > > > > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > > > - reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | > > > - ESDHC_MIX_CTRL_FBCLK_SEL; > > > + reg |= ESDHC_MIX_CTRL_EXE_TUNE | > ESDHC_MIX_CTRL_SMPCLK_SEL; > > > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > > > > > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MAS > > K, val), > > > host->ioaddr + ESDHC_TUNE_CTRL_STATUS); @@ -1432,6 > > +1424,15 > > > @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, > > > unsigned > > timing) > > > break; > > > } > > > > > > + if (timing == MMC_TIMING_UHS_SDR104 || > > > + timing == MMC_TIMING_MMC_HS200 || > > > + timing == MMC_TIMING_MMC_HS400) > > > + m |= ESDHC_MIX_CTRL_FBCLK_SEL; > > > + else > > > + m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > > > + > > > + writel(m, host->ioaddr + ESDHC_MIX_CTRL); > > > + > > > esdhc_change_pinstate(host, timing); } > > > > > > -- > > > 2.34.1 > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic 2025-05-21 2:55 [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic ziniu.wang_1 2025-05-21 2:55 ` [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support ziniu.wang_1 2025-05-21 16:09 ` [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic Frank Li @ 2025-05-28 10:34 ` Adrian Hunter 2025-06-09 14:24 ` Ulf Hansson 3 siblings, 0 replies; 10+ messages in thread From: Adrian Hunter @ 2025-05-28 10:34 UTC (permalink / raw) To: ziniu.wang_1, haibo.chen, ulf.hansson, linux-mmc Cc: shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel On 21/05/2025 05:55, ziniu.wang_1@nxp.com wrote: > From: Luke Wang <ziniu.wang_1@nxp.com> > > i.MX reference manual specifies that internal clock loopback should be > used for SDR104/HS200/HS400 modes. Move ESDHC_MIX_CTRL_FBCLK_SEL > configuration into the timing selection function to: > > 1. Explicitly set internal loopback path for SDR104/HS200/HS400 modes > 2. Avoid redundant bit manipulation across multiple functions > > Preserve ESDHC_MIX_CTRL_FBCLK_SEL during system resume for SDIO devices > with MMC_PM_KEEP_POWER and MMC_PM_WAKE_SDIO_IRQ flag, as the controller > might lose register state during suspend while skipping card > re-initialization. > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 27 ++++++++++++++------------- > 1 file changed, 14 insertions(+), 13 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index 7611682f10c3..c448a53530a5 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -728,23 +728,17 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) > writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); > if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { > u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); > - u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); > - if (val & SDHCI_CTRL_TUNED_CLK) { > + if (val & SDHCI_CTRL_TUNED_CLK) > v |= ESDHC_MIX_CTRL_SMPCLK_SEL; > - } else { > + else > v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; > - m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > - } > > - if (val & SDHCI_CTRL_EXEC_TUNING) { > + if (val & SDHCI_CTRL_EXEC_TUNING) > v |= ESDHC_MIX_CTRL_EXE_TUNE; > - m |= ESDHC_MIX_CTRL_FBCLK_SEL; > - } else { > + else > v &= ~ESDHC_MIX_CTRL_EXE_TUNE; > - } > > writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); > - writel(m, host->ioaddr + ESDHC_MIX_CTRL); > } > return; > case SDHCI_TRANSFER_MODE: > @@ -1082,7 +1076,6 @@ static void esdhc_reset_tuning(struct sdhci_host *host) > ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; > if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { > 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) { > @@ -1177,8 +1170,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) > "warning! RESET_ALL never complete before sending tuning command\n"); > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > - reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | > - ESDHC_MIX_CTRL_FBCLK_SEL; > + reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL; > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, val), > host->ioaddr + ESDHC_TUNE_CTRL_STATUS); > @@ -1432,6 +1424,15 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > break; > } > > + if (timing == MMC_TIMING_UHS_SDR104 || > + timing == MMC_TIMING_MMC_HS200 || > + timing == MMC_TIMING_MMC_HS400) > + m |= ESDHC_MIX_CTRL_FBCLK_SEL; > + else > + m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > + > + writel(m, host->ioaddr + ESDHC_MIX_CTRL); > + > esdhc_change_pinstate(host, timing); > } > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic 2025-05-21 2:55 [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic ziniu.wang_1 ` (2 preceding siblings ...) 2025-05-28 10:34 ` Adrian Hunter @ 2025-06-09 14:24 ` Ulf Hansson 3 siblings, 0 replies; 10+ messages in thread From: Ulf Hansson @ 2025-06-09 14:24 UTC (permalink / raw) To: ziniu.wang_1 Cc: haibo.chen, adrian.hunter, linux-mmc, shawnguo, s.hauer, kernel, festevam, imx, s32, linux-arm-kernel, linux-kernel On Wed, 21 May 2025 at 04:53, <ziniu.wang_1@nxp.com> wrote: > > From: Luke Wang <ziniu.wang_1@nxp.com> > > i.MX reference manual specifies that internal clock loopback should be > used for SDR104/HS200/HS400 modes. Move ESDHC_MIX_CTRL_FBCLK_SEL > configuration into the timing selection function to: > > 1. Explicitly set internal loopback path for SDR104/HS200/HS400 modes > 2. Avoid redundant bit manipulation across multiple functions > > Preserve ESDHC_MIX_CTRL_FBCLK_SEL during system resume for SDIO devices > with MMC_PM_KEEP_POWER and MMC_PM_WAKE_SDIO_IRQ flag, as the controller > might lose register state during suspend while skipping card > re-initialization. > > Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com> Applied for next, thanks! Kind regards Uffe > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 27 ++++++++++++++------------- > 1 file changed, 14 insertions(+), 13 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c > index 7611682f10c3..c448a53530a5 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -728,23 +728,17 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) > writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); > if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { > u32 v = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS); > - u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); > - if (val & SDHCI_CTRL_TUNED_CLK) { > + if (val & SDHCI_CTRL_TUNED_CLK) > v |= ESDHC_MIX_CTRL_SMPCLK_SEL; > - } else { > + else > v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; > - m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > - } > > - if (val & SDHCI_CTRL_EXEC_TUNING) { > + if (val & SDHCI_CTRL_EXEC_TUNING) > v |= ESDHC_MIX_CTRL_EXE_TUNE; > - m |= ESDHC_MIX_CTRL_FBCLK_SEL; > - } else { > + else > v &= ~ESDHC_MIX_CTRL_EXE_TUNE; > - } > > writel(v, host->ioaddr + SDHCI_AUTO_CMD_STATUS); > - writel(m, host->ioaddr + ESDHC_MIX_CTRL); > } > return; > case SDHCI_TRANSFER_MODE: > @@ -1082,7 +1076,6 @@ static void esdhc_reset_tuning(struct sdhci_host *host) > ctrl &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN; > if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { > 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) { > @@ -1177,8 +1170,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) > "warning! RESET_ALL never complete before sending tuning command\n"); > > reg = readl(host->ioaddr + ESDHC_MIX_CTRL); > - reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | > - ESDHC_MIX_CTRL_FBCLK_SEL; > + reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL; > writel(reg, host->ioaddr + ESDHC_MIX_CTRL); > writel(FIELD_PREP(ESDHC_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK, val), > host->ioaddr + ESDHC_TUNE_CTRL_STATUS); > @@ -1432,6 +1424,15 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing) > break; > } > > + if (timing == MMC_TIMING_UHS_SDR104 || > + timing == MMC_TIMING_MMC_HS200 || > + timing == MMC_TIMING_MMC_HS400) > + m |= ESDHC_MIX_CTRL_FBCLK_SEL; > + else > + m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; > + > + writel(m, host->ioaddr + ESDHC_MIX_CTRL); > + > esdhc_change_pinstate(host, timing); > } > > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-06-09 14:25 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-05-21 2:55 [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic ziniu.wang_1 2025-05-21 2:55 ` [PATCH 2/2] mmc: sdhci-esdhc-imx: optimize clock loopback selection with dummy pad support ziniu.wang_1 2025-05-21 16:20 ` Frank Li 2025-05-28 10:34 ` Adrian Hunter 2025-06-09 14:24 ` Ulf Hansson 2025-05-21 16:09 ` [PATCH 1/2] mmc: sdhci-esdhc-imx: refactor clock loopback selection logic Frank Li 2025-05-22 3:52 ` Bough Chen 2025-05-22 3:59 ` Bough Chen 2025-05-28 10:34 ` Adrian Hunter 2025-06-09 14:24 ` Ulf Hansson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).