* [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 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 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 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 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 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
* 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
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).