RE: [PATCH v19 12/12] mmc: renesas_sdhi: Add HS400 enhanced strobe support for RZ/G3L
Biju Das <[email protected]> Fri, 10 Jul 2026 09:27:26 +0000
| Newsgroups | org.kernel.vger.linux-mmc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc |
|---|---|
| Message-ID | <TY3PR01MB11346F6F629176C46DEC3498D86FD2@TY3PR01MB11346.jpnprd01.prod.outlook.com> |
Hi All, > -----Original Message----- > From: Biju <[email protected]> > Sent: 09 July 2026 20:29 > Subject: [PATCH v19 12/12] mmc: renesas_sdhi: Add HS400 enhanced strobe support for RZ/G3L > > From: Biju Das <[email protected]> > > The RZ/G3L SoC supports HS400 enhanced strobe mode, which requires additional SCC register programming > beyond the standard HS400 path. > > Introduce a TMIO_MMC_HS400ES flag (bit 17) to identify controllers that support enhanced strobe. Add > renesas_sdhi_hs400_enhanced_strobe(), > which, when ios->enhanced_strobe is set, disables DTSEL in SCC_CKSEL, clears TAPEN in SCC_DTCNTL, > programs SCC_TMPPORT3, sets HWADJ2 to 0xFF, enables the HS400 interface mode bit in CTL_SDIF_MODE, sets > HS400EN2 in HS400MODE2, and sets both HS400EN and the new HS400MODE1_ENHANCED_STROBE bit (BIT(30)) in > TMPPORT2. On exit from enhanced strobe, only the enhanced strobe bit is cleared. Register this callback > as host->ops.hs400_enhanced_strobe for controllers carrying the TMIO_MMC_HS400ES flag. > > Update renesas_sdhi_reset_hs400_mode() to also mask off HS400MODE1_ENHANCED_STROBE from TMPPORT2 when > TMIO_MMC_HS400ES is set, ensuring a clean reset on mode exit. > > Enable the TMIO_MMC_HS400ES flag in of_data_rzg3l to finalize support. > > Signed-off-by: Biju Das <[email protected]> > --- > v18->v19: > * Updated commit description. > * HS400ES support is enabled based on of_data. > * Fixed the space in HS400ES comment block. > v18: > * New patch. > --- > drivers/mmc/host/renesas_sdhi_core.c | 49 +++++++++++++++++-- > drivers/mmc/host/renesas_sdhi_internal_dmac.c | 2 +- > include/linux/platform_data/tmio.h | 3 ++ > 3 files changed, 49 insertions(+), 5 deletions(-) > > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c > index ae6b7d8c5b98..894da06b0d2b 100644 > --- a/drivers/mmc/host/renesas_sdhi_core.c > +++ b/drivers/mmc/host/renesas_sdhi_core.c > @@ -308,7 +308,8 @@ static int renesas_sdhi_card_busy(struct mmc_host *mmc) > #define SH_MOBILE_SDHI_SCC_SMPCMP_CMD_REQUP BIT(24) > #define SH_MOBILE_SDHI_SCC_SMPCMP_CMD_ERR (BIT(8) | BIT(24)) > > -#define SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN BIT(31) > +#define SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN BIT(31) > +#define SH_MOBILE_SDHI_SCC_HS400MODE1_ENHANCED_STROBE BIT(30) > > /* Definitions for values the SH_MOBILE_SDHI_SCC_TMPPORT4 register */ > #define SH_MOBILE_SDHI_SCC_TMPPORT4_DLL_ACC_START BIT(0) > @@ -589,6 +590,8 @@ static void renesas_sdhi_adjust_hs400_mode_disable(struct tmio_mmc_host *host) > static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, > struct renesas_sdhi *priv) > { > + u32 val = ~(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN | > +host->pdata->osel_tmpout); > + > sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN & > sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); > > @@ -598,10 +601,11 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, > > sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos); > > + if (host->pdata->flags & TMIO_MMC_HS400ES) > + val &= ~SH_MOBILE_SDHI_SCC_HS400MODE1_ENHANCED_STROBE; > + > sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, > - ~(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN | > - host->pdata->osel_tmpout) & > - sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2)); > + val & sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2)); > > if (host->pdata->flags & TMIO_MMC_HS400MODE2) > sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HS400MODE2, 0x0); @@ -806,6 +810,41 @@ static int > renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) > return ret; > } > > +static void renesas_sdhi_hs400_enhanced_strobe(struct mmc_host *mmc, > + struct mmc_ios *ios) > +{ Looks it is false positive as mentioned by sashiko[1], I can enter and exit suspend to RAM without any issues. On this platform during STR all power supplies down except PMIC which puts the DDR into retention mode. [1] https://sashiko.dev/#/patchset/20260709192916.630794-1-biju.das.jz%40bp.renesas.com root@smarc-rzg3l:~# cat /sys/kernel/debug/mmc0/ios clock: 150000000 Hz actual clock: 150000000 Hz vdd: 21 (3.3 ~ 3.4 V) bus mode: 2 (push-pull) chip select: 0 (don't care) power mode: 2 (on) bus width: 3 (8 bits) timing spec: 10 (mmc HS400 enhanced strobe) signal voltage: 1 (1.80 V) driver type: 1 (driver type A) root@smarc-rzg3l:~# mount -t auto /dev/mmcblk0p2 /media/ [ 75.719668] EXT4-fs (mmcblk0p2): recovery complete [ 75.725806] EXT4-fs (mmcblk0p2): mounted filesystem 3a87d114-78ab-4be0-8fac-d055b25f4bd0 r/w with ordered data mode. Quota mode: none. root@smarc-rzg3l:~# echo TEST > /media/1.txt root@smarc-rzg3l:~# echo mem > /sys/power/state [ 105.965920] PM: suspend entry (deep) [ 105.980163] Filesystems sync: 0.009 seconds [ 105.992243] Freezing user space processes [ 106.001271] Freezing user space processes completed (elapsed 0.003 seconds) [ 106.008260] OOM killer disabled. [ 106.011496] Freezing remaining freezable tasks [ 106.017309] Freezing remaining freezable tasks completed (elapsed 0.001 seconds) [ 106.024713] printk: Suspending console(s) (use no_console_suspend to debug) NOTICE: BL2: v2.10.5(release):2.10.5/rzg3l_1.0.1_rc2 NOTICE: BL2: Built : 09:19:29, Jun 16 2026 INFO: BL2: Doing platform setup INFO: Configuring TrustZone Controller INFO: Total 3 regions set. INFO: Configuring TrustZone Controller INFO: Total 1 regions set. INFO: Configuring TrustZone Controller INFO: Total 1 regions set. INFO: Loading image id=39 at address 0x44428 INFO: Image id=39 loaded: 0x44428 - 0x45428 INFO: DDR: Retention Exit (Rev. 02.05) NOTICE: BL2: SYS_LSI_MODE: 0x12061 NOTICE: BL2: SYS_LSI_DEVID: 0x87d9447 INFO: BL2: Skip loading image id 3 INFO: BL2: Skip loading image id 5 NOTICE: BL2: Booting BL31 INFO: Entry point address = 0x44000000 INFO: SPSR = 0x3cd [ 106.061768] renesas-gbeth 11c30000.ethernet end0: Link is Down [ 106.065811] Disabling non-boot CPUs ... [ 106.068100] psci: CPU3 killed (polled 4 ms) [ 106.071161] psci: CPU2 killed (polled 4 ms) [ 106.075159] psci: CPU1 killed (polled 4 ms) [ 106.076800] Enabling non-boot CPUs ... [ 106.077070] Detected VIPT I-cache on CPU1 [ 106.077135] GICv3: CPU1: found redistributor 100 region 0:0x0000000012460000 [ 106.077182] CPU1: Booted secondary processor 0x0000000100 [0x412fd050] [ 106.078267] CPU1 is up [ 106.078429] Detected VIPT I-cache on CPU2 [ 106.078469] GICv3: CPU2: found redistributor 200 region 0:0x0000000012480000 [ 106.078502] CPU2: Booted secondary processor 0x0000000200 [0x412fd050] [ 106.079474] CPU2 is up [ 106.079661] Detected VIPT I-cache on CPU3 [ 106.079708] GICv3: CPU3: found redistributor 300 region 0:0x00000000124a0000 [ 106.079751] CPU3: Booted secondary processor 0x0000000300 [0x412fd050] [ 106.080888] CPU3 is up [ 106.095014] dwmac4: Master AXI performs fixed burst length [ 106.095061] renesas-gbeth 11c30000.ethernet end0: No Safety Features support found [ 106.095104] renesas-gbeth 11c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported [ 106.096191] renesas-gbeth 11c30000.ethernet end0: configuring for phy/rgmii-id link mode [ 106.111005] dwmac4: Master AXI performs fixed burst length [ 106.111035] renesas-gbeth 11c40000.ethernet end1: No Safety Features support found [ 106.111066] renesas-gbeth 11c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported [ 106.112144] renesas-gbeth 11c40000.ethernet end1: configuring for phy/rgmii-id link mode [ 106.283664] OOM killer enabled. [ 106.286800] Restarting tasks: Starting [ 106.292440] Restarting tasks: Done [ 106.296062] random: crng reseeded on system resumption [ 106.301515] PM: suspend exit [ 109.062679] renesas-gbeth 11c30000.ethernet end0: Link is Up - 1Gbps/Full - flow control rx/tx root@smarc-rzg3l:~# cat /media/1.txt TEST root@smarc-rzg3l:~# cat /sys/kernel/debug/mmc0/ios clock: 150000000 Hz actual clock: 150000000 Hz vdd: 21 (3.3 ~ 3.4 V) bus mode: 2 (push-pull) chip select: 0 (don't care) power mode: 2 (on) bus width: 3 (8 bits) timing spec: 10 (mmc HS400 enhanced strobe) signal voltage: 1 (1.80 V) driver type: 1 (driver type A) root@smarc-rzg3l:~# > + struct tmio_mmc_host *host = mmc_priv(mmc); > + struct renesas_sdhi *priv = host_to_priv(host); > + u32 val = sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2); > + > + if (!(host->pdata->flags & TMIO_MMC_HS400ES)) > + return; > + > + if (ios->enhanced_strobe) { > + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL, > + ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL & > + sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL)); OK, hardware manual mention this "When this bit is switched, stop the SD clock output from the SD/MMC host interface (set SCLKEN in SD_CLK_CTRL to 0)." So, I will disable CLK_CTL_SCLKEN before changing these registers. Cheers, Biju > + > + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL, > + ~SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN & > + sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL)); > + > + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT3, BIT(8) | BIT(9)); > + sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ2, 0xFF); > + sd_ctrl_write16(host, CTL_SDIF_MODE, SDIF_MODE_HS400 | > + sd_ctrl_read16(host, CTL_SDIF_MODE)); > + sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HS400MODE2, > + RZG3L_SDHI_SCC_HS400MODE2_HS400EN2); > + > + val |= SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN | > + SH_MOBILE_SDHI_SCC_HS400MODE1_ENHANCED_STROBE; > + } else { > + val &= ~SH_MOBILE_SDHI_SCC_HS400MODE1_ENHANCED_STROBE; > + } > + > + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, val); } > + > static bool renesas_sdhi_manual_correction(struct tmio_mmc_host *host, bool use_4tap) { > struct renesas_sdhi *priv = host_to_priv(host); @@ -1358,6 +1397,8 @@ int > renesas_sdhi_probe(struct platform_device *pdev, > host->ops.prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning; > host->ops.hs400_downgrade = renesas_sdhi_disable_scc; > host->ops.hs400_complete = renesas_sdhi_hs400_complete; > + if (host->pdata->flags & TMIO_MMC_HS400ES) > + host->ops.hs400_enhanced_strobe = > +renesas_sdhi_hs400_enhanced_strobe; > } > > sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask_all); diff --git > a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c > index 4000673ed7f8..ea993197aff2 100644 > --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c > +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c > @@ -175,7 +175,7 @@ static const struct renesas_sdhi_of_data of_data_rzg3l = { > TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2 | > TMIO_MMC_64BIT_DATA_PORT | TMIO_MMC_TUNING_DELAY | > TMIO_MMC_INTERNAL_DIVIDER | TMIO_MMC_HWADJ | > - TMIO_MMC_HS400MODE2, > + TMIO_MMC_HS400MODE2 | TMIO_MMC_HS400ES, > .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | > MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY, > .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT | MMC_CAP2_MERGE_CAPABLE, > diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h > index 8a5dc18d43da..75d32c8ee57a 100644 > --- a/include/linux/platform_data/tmio.h > +++ b/include/linux/platform_data/tmio.h > @@ -62,6 +62,9 @@ > /* Some controllers have HS400MODE2 */ > #define TMIO_MMC_HS400MODE2 BIT(16) > > +/* Some controllers have HS400ES */ > +#define TMIO_MMC_HS400ES BIT(17) > + > struct tmio_mmc_data { > void *chan_priv_tx; > void *chan_priv_rx; > -- > 2.43.0