Linux Renesas SOC kernel development
 help / color / mirror / Atom feed
* [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support
@ 2026-08-20 17:16 Biju
  2026-08-20 17:16 ` [PATCH v24 01/15] dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC Biju
                   ` (16 more replies)
  0 siblings, 17 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Philipp Zabel, Magnus Damm
  Cc: Biju Das, Wolfram Sang, linux-mmc, devicetree, linux-kernel,
	linux-renesas-soc, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

Hi All,

The Renesas RZ/G3L SoC has:

Channel 0 supports SD and eMMC (including HS400/HS400ES).
Channel 1 supports SD and eMMC (except for HS400).
Channel 2 supports SD.

The SoC supports a maximum frequency of 150 MHz. The SD0 interface does
not support IOVS and PWEN in the SDHI register (no internal regulator),
unlike SD1 and SD2. It has an internal divider for all modes except HS400.
It also has a 2048-bit divider compared to 512 on others. Moreover
RZ/G3L supports HS400 enhanced strobe mode.

This patch series support all modes. Please see the test logs for
smarc-rzg3l[1]

This patch series tested on smarc-rz{v2l,g2l,g2lc,g2ul,g3s,g3l,g3e},
rz{v2h,t2h}-evk and hihope-rz{g2h,g2m,g2n} boards

v23->v24:
 * Added Add SDHI_SD_CLK_CTL_DIV1 macro for handling 1/1 option.
 * Updated commit description for patch#6.
 * Replaced GENMASK(7, 0) with CLK_CTL_DIV_MASK.
 * Replaced magic bits GENMASK(9, 8) and GENMASK(17, 16) with
   RZG3L_CLK_CTL_DIV9_DIV8 and RZG3L_CLK_CTL_DIV9_DIV8_SRC.
 * Simplified renesas_sdhi_set_tmpport().
 * Replaced GENMASK(15, 0) with RZG3L_SDHI_SCC_HS400MODE1_TMPOUT.
v22->v23:
 * Added write32hook function for hardware idle synchronization for
   CTL_SD_CARD_CLK_CTL writes.
 * Changed the data type of max_divider from unsigned int to signed int.
 * Assigned of_data->clk_div_mask in renesas_sdhi_probe().
 * Updated commit description for patch#7.
 * Updated tmio_mmc_reset() to handle 32 bit divider register in RZ/G3L.
v21->v22:
 * Added HS400 ES mode after fixing inode corruption when eMMC is
   mounted as rootfs.
 * Updated commit descriptions for patches #4, #5, #6, #7, #9, #12,
   and #13.
 * Added clk_div_mask to of_default_cfg and of_rcar_gen2_compatible.
 * Added a renesas_sdhi_set_hw_adjustment_delay() call to
   renesas_sdhi_init_tuning().
 * Added renesas_sdhi_is_internal_divider_enabled() and
   renesas_sdhi_clk_get_rate() to simplify the clock rate logic.
 * Added `clock &= ~GENMASK(9, 8)` to clear the divider mask bits in
   the register value.
 * Added a renesas_sdhi_set_tmpport() helper to set delay values.
 * Added a check in renesas_sdhi_is_internal_divider_enabled() to
   return disabled status when in HS400 mode.
 * renesas_sdhi_reset() now restores data strobe register values
   after reset.
v20->v21:
 * Dropped HS400 ES support due to file system corruption, will add this
   mode later after investigation.
 * Added support for make clock divider mask configurable
 * Added clk_div_mask to RZ/G2L of_data.
 * Added clk_div_mask to RZ/G3L of_data.
 * Restored actual_clk calculation in renesas_sdhi_set_clock().
 * Updated renesas_sdhi_set_clock() for RZ/G3L HS400 clock handling as
   it supports only single clk divider value and other values are
   prohibited.
 * Updated commit description for patch#12.
v19->v20:
 * Replaced the check mmd->clk_mask with mmc_data->clk_mask and moved
   the code after assignment of variable mmd, this ensures assigning
   the default values for non-DT platforms and DT platforms with no
   device data.
 * Replaced the check mmd->max_divider with mmc_data->max_divider and
   moved the code after assignment of variable mmd, this ensures
   assigning the default values for non-DT platforms and DT platforms with
   no device data.
 * Fixed the ordering of resets in suspend/resume paths.
 * Added bitfield.h header file.
 * Reworked on renesas_sdhi_set_clock() to handle the 11-bit divider
   case and the 32-bit register write.
 * Updated resume() with scoped PM runtime call.
 * SD_CLK_CTRL clk enable turned off before updating SCC_CKSEL_DTSEL
   register.
v18->v19:
 * Updated commit description for patch#1,#2,#6,#8,#11 and #12
 * Updated clock and reset description with AXI master and AXI slave
 * Added else condition for reset and reset-names.
 * Renamed aclk->aclkm and reordered the axi clocks similar to resets.
 * Retained the tag got binding patch as the changes are trivial.
 * Fixed the clk_mask for non-DT platforms.
 * Fixed max-divider setting for non-DT platforms.
 * Replaced the magic number '9' with ilog2 function in
   renesas_sdhi_clk_enable().
 * Dropped divider variable from struct renesas_sdhi.
 * Updated renesas_sdhi_clk_update() to return rate for HS400 mode
   and non HS400 mode(uses 1/2 internal divider).
 * Updated handling for clk divider.
 * Renamed TMIO_MMC_HWADJ2->TMIO_MMC_HWADJ to make it generic for
   hardware tuning delays
 * Dropped duplicate SH_MOBILE_SDHI_SCC_TMPPORT2 macro
 * Updated suspend/resume with scoped runtime calls in suspend.
 * Fixed extra space in HS400MODE2 comment block.
 * Updated the comment HS400mode2->HS400MODE2.
 * Dropped the updation of clk handling as it is taken care in
   previous patches.
 * HS400ES support is enabled based on of_data.
 * Fixed the space in HS400ES comment block.

v17->v18:
 * Collected tag
 * Merged patch #4 and #5 and updated commit description
 * Annotated the empty sentinel entries in the OF match tables with a
   "Sentinel." comment for clarity.
 * Retained the tag as it is a trivial cleanup.
 * New patches drop struct renesas_sdhi_hw_info, instead using
   renesas_sdhi_of_data and tmio_mmc_data.
 * Dropped clk, pinctrl, SoC, and board dtsi from this patch series;
   will send later.
v1->v17:
 * Collected tag for binding patch.
 * Resending the series as there is an issue with patch threading from
   patch #14.

[1]
Logs:
HS200:(With internal divider)
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:    9 (mmc HS200)
signal voltage: 1 (1.80 V)
driver type:    1 (driver type A)

SDR104:(With internal divider)
root@smarc-rzg3l:~# cat /sys/kernel/debug/mmc1/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:      2 (4 bits)
timing spec:    6 (sd uhs SDR104)
signal voltage: 1 (1.80 V)
driver type:    0 (driver type B)

HS400: (Without internal divider)
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)
signal voltage: 1 (1.80 V)
driver type:    1 (driver type A)

HS400 ES: (Without internal divider)
root@smarc-rzg3l:~# cat /proc/cmdline
rw rootwait earlycon root=/dev/mmcblk0p2 net.ifnames=0
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)

s2ram:
root@smarc-rzg3l:~# echo mem > /sys/power/state
[   72.838238] PM: suspend entry (deep)
[   72.864225] Filesystems sync: 0.021 seconds
[   72.875166] Freezing user space processes
[   72.883030] Freezing user space processes completed (elapsed 0.003 seconds)
[   72.890237] OOM killer disabled.
[   72.893612] Freezing remaining freezable tasks
[   72.900038] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[   72.907677] 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 : 11:18:41, Jul 15 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:    eMMC boot from partition 1
INFO:    Loading image id=39 at address 0x44428
INFO:    emmcdrv_block_len: len: 0x00001000
INFO:    Load dst=0x44428 src=(p:1)0x260000(4864) len=0x1000(8)
INFO:    Image id=39 loaded: 0x44428 - 0x45428
INFO:    DDR: Retention Exit (Rev. 02.05)
NOTICE:  BL2: SYS_LSI_MODE: 0x12051
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
[   72.951851] renesas-gbeth 11c30000.ethernet eth0: Link is Down
[   72.955613] Disabling non-boot CPUs ...
[   72.957320] psci: CPU3 killed (polled 4 ms)
[   72.961085] psci: CPU2 killed (polled 0 ms)
[   72.964897] psci: CPU1 killed (polled 0 ms)
[   72.966874] Enabling non-boot CPUs ...
[   72.967144] Detected VIPT I-cache on CPU1
[   72.967202] GICv3: CPU1: found redistributor 100 region 0:0x0000000012460000
[   72.967250] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
[   72.968284] CPU1 is up
[   72.968428] Detected VIPT I-cache on CPU2
[   72.968462] GICv3: CPU2: found redistributor 200 region 0:0x0000000012480000
[   72.968493] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
[   72.969465] CPU2 is up
[   72.969633] Detected VIPT I-cache on CPU3
[   72.969673] GICv3: CPU3: found redistributor 300 region 0:0x00000000124a0000
[   72.969714] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
[   72.970760] CPU3 is up
[   72.989187] dwmac4: Master AXI performs fixed burst length
[   72.989231] renesas-gbeth 11c30000.ethernet eth0: No Safety Features support found
[   72.989275] renesas-gbeth 11c30000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
[   72.990364] renesas-gbeth 11c30000.ethernet eth0: configuring for phy/rgmii-id link mode
[   73.005175] dwmac4: Master AXI performs fixed burst length
[   73.005205] renesas-gbeth 11c40000.ethernet eth1: No Safety Features support found
[   73.005236] renesas-gbeth 11c40000.ethernet eth1: IEEE 1588-2008 Advanced Timestamp supported
[   73.006314] renesas-gbeth 11c40000.ethernet eth1: configuring for phy/rgmii-id link mode
[   73.177702] OOM killer enabled.
[   73.180837] Restarting tasks: Starting
[   73.186007] Restarting tasks: Done
[   73.189570] random: crng reseeded on system resumption
[   73.195001] PM: suspend exit
root@smarc-rzg3l:~# cat /sys/kernel/debug/mmc0/ios[   75.705532] renesas-gbeth 11c30000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx

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:~#

s2idle:
root@smarc-rzg3l:~# echo freeze > /sys/power/state
[   97.634564] PM: suspend entry (s2idle)
[   97.655343] Filesystems sync: 0.016 seconds
[   97.662352] Freezing user space processes
[   97.666531] Freezing user space processes completed (elapsed 0.004 seconds)
[   97.676132] OOM killer disabled.
[   97.679743] Freezing remaining freezable tasks
[   97.687107] Freezing remaining freezable tasks completed (elapsed 0.002 seconds)
[   97.695071] printk: Suspending console(s) (use no_console_suspend to debug)
[   97.744129] renesas-gbeth 11c30000.ethernet eth0: Link is Down
[  100.135760] dwmac4: Master AXI performs fixed burst length
[  100.135805] renesas-gbeth 11c30000.ethernet eth0: No Safety Features support found
[  100.135848] renesas-gbeth 11c30000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
[  100.137950] renesas-gbeth 11c30000.ethernet eth0: configuring for phy/rgmii-id link mode
[  100.154860] dwmac4: Master AXI performs fixed burst length
[  100.154890] renesas-gbeth 11c40000.ethernet eth1: No Safety Features support found
[  100.154919] renesas-gbeth 11c40000.ethernet eth1: IEEE 1588-2008 Advanced Timestamp supported
[  100.154984] renesas-gbeth 11c40000.ethernet eth1: configuring for phy/rgmii-id link mode
[  100.246688] OOM killer enabled.
[  100.249851] Restarting tasks: Starting
[  100.254395] Restarting tasks: Done
[  100.258012] random: crng reseeded on system resumption
[  100.263468] PM: suspend exit
root@smarc-rzg3l:~#
root@smarc-rzg3l:~# cat /sys/kernel/debug/mmc0/ios[  102.690106] renesas-gbeth 11c30000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx

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:~#

SDIO testing:
root@smarc-rzg3l:~# cat /sys/kernel/debug/mmc1/ios
clock:          100000000 Hz
actual clock:   100000000 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:      2 (4 bits)
timing spec:    5 (sd uhs SDR50)
signal voltage: 1 (1.80 V)
driver type:    0 (driver type B)
root@smarc-rzg3l:~#
root@smarc-rzg3l:~# ping google.com
PING google.com (142.250.151.139): 56 data bytes
64 bytes from 142.250.151.139: seq=0 ttl=112 time=7.679 ms
64 bytes from 142.250.151.139: seq=1 ttl=112 time=12.283 ms
^C
google.com ping statistic
packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 7.679/9.981/12.283 ms

Biju Das (15):
  dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC
  mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels
  mmc: renesas_sdhi: Add clk_mask field to support flexible clock
    divider widths
  mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock
    ranges
  mmc: renesas_sdhi: Add SDHI_SD_CLK_CTL_DIV1 macro for 1/1 option
  mmc: renesas_sdhi: Make clock divider mask configurable
  mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
  mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag
  mmc: renesas_sdhi: Add optional axis/axim reset controls
  mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register
    writes
  mmc: renesas_sdhi: Add RZ/G3L SDHI support
  mmc: renesas_sdhi: Save and restore IOVS across suspend/resume
  mmc: renesas_sdhi: Make HS400 OSEL bit configurable per SoC
  mmc: renesas_sdhi: Add RZ/G3L HS400 support
  mmc: renesas_sdhi: Add HS400 enhanced strobe support for RZ/G3L

 .../devicetree/bindings/mmc/renesas,sdhi.yaml | 108 ++++--
 drivers/mmc/host/renesas_sdhi.h               |  13 +-
 drivers/mmc/host/renesas_sdhi_core.c          | 344 +++++++++++++++---
 drivers/mmc/host/renesas_sdhi_internal_dmac.c |  78 +++-
 drivers/mmc/host/renesas_sdhi_sys_dmac.c      |  16 +-
 drivers/mmc/host/tmio_mmc.h                   |   7 +
 drivers/mmc/host/tmio_mmc_core.c              |  13 +-
 include/linux/platform_data/tmio.h            |  19 +
 8 files changed, 504 insertions(+), 94 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH v24 01/15] dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-02 10:45   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels Biju
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm
  Cc: Biju Das, Wolfram Sang, linux-mmc, devicetree, linux-kernel,
	linux-renesas-soc, Prabhakar Mahadev Lad, Biju Das, Conor Dooley

From: Biju Das <biju.das.jz@bp.renesas.com>

Document the RZ/G3L (r9a08g046) SDHI controller. The RZ/G3L SDHI
controller is similar to RZ/G2L but has five clocks (core, clkh,
cd, aclkm, aclks) and three resets (rst, axim, axis), so update the
clocks/clock-names maximum to 5 and resets/reset-names maximum to 3.
It has an internal divider for all modes except HS400, and a 2048-bit
divider compared to 512 on others.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * No change.
v21->v22:
 * No change.
v20->v21:
 * No change.
v19->v20:
 * No change.
v18->v19:
 * Updated commit description
 * Updated clock and reset description with AXI master and AXI slave
 * Added else condition for reset and reset-names.
 * Renamed aclk->aclkm and reordered the axi clocks similar to resets.
 * Retained the tag as the changes are trivial.
v17->v18:
 * No change.
v1->v17:
 * Collected tag.
---
 .../devicetree/bindings/mmc/renesas,sdhi.yaml | 108 +++++++++++++-----
 1 file changed, 81 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
index 4d66966ce290..6d229a41a4b5 100644
--- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
+++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
@@ -18,6 +18,7 @@ properties:
           - renesas,sdhi-r7s9210 # SH-Mobile AG5
           - renesas,sdhi-r8a73a4 # R-Mobile APE6
           - renesas,sdhi-r8a7740 # R-Mobile A1
+          - renesas,sdhi-r9a08g046 # RZ/G3L
           - renesas,sdhi-r9a09g057 # RZ/V2H(P)
           - renesas,sdhi-sh73a0  # R-Mobile APE6
       - items:
@@ -86,11 +87,11 @@ properties:
 
   clocks:
     minItems: 1
-    maxItems: 4
+    maxItems: 5
 
   clock-names:
     minItems: 1
-    maxItems: 4
+    maxItems: 5
 
   dmas:
     minItems: 4
@@ -116,7 +117,12 @@ properties:
     maxItems: 1
 
   resets:
-    maxItems: 1
+    minItems: 1
+    maxItems: 3
+
+  reset-names:
+    minItems: 1
+    maxItems: 3
 
   pinctrl-0:
     minItems: 1
@@ -155,60 +161,106 @@ allOf:
         properties:
           compatible:
             contains:
-              enum:
-                - renesas,sdhi-r9a09g057
-                - renesas,rzg2l-sdhi
+              const: renesas,sdhi-r9a08g046
       then:
         properties:
           clocks:
             items:
               - description: IMCLK, SDHI channel main clock1.
               - description: CLK_HS, SDHI channel High speed clock which operates
-                             4 times that of SDHI channel main clock1.
+                             2 times that of SDHI channel main clock1.
               - description: IMCLK2, SDHI channel main clock2. When this clock is
                              turned off, external SD card detection cannot be
                              detected.
-              - description: ACLK, SDHI channel bus clock.
+              - description: IACLKM, SDHI channel AXI master bus clock.
+              - description: IACLKS, SDHI channel AXI slave bus clock.
           clock-names:
             items:
               - const: core
               - const: clkh
               - const: cd
-              - const: aclk
+              - const: aclkm
+              - const: aclks
+          resets:
+            items:
+              - description: rst, Core reset.
+              - description: axim, SDHI channel AXI master bus reset.
+              - description: axis, SDHI channel AXI slave bus reset.
+          reset-names:
+            items:
+              - const: rst
+              - const: axim
+              - const: axis
         required:
           - clock-names
           - resets
+          - reset-names
       else:
+        properties:
+          resets:
+            maxItems: 1
+          reset-names:
+            maxItems: 1
         if:
           properties:
             compatible:
               contains:
                 enum:
-                  - renesas,rcar-gen2-sdhi
-                  - renesas,rcar-gen3-sdhi
-                  - renesas,rcar-gen4-sdhi
+                  - renesas,sdhi-r9a09g057
+                  - renesas,rzg2l-sdhi
         then:
           properties:
             clocks:
-              minItems: 1
-              maxItems: 3
-            clock-names:
-              minItems: 1
-              uniqueItems: true
               items:
-                - const: core
-                - enum: [ clkh, cd ]
-                - const: cd
-        else:
-          properties:
-            clocks:
-              minItems: 1
-              maxItems: 2
+                - description: IMCLK, SDHI channel main clock1.
+                - description: CLK_HS, SDHI channel High speed clock which operates
+                               4 times that of SDHI channel main clock1.
+                - description: IMCLK2, SDHI channel main clock2. When this clock is
+                               turned off, external SD card detection cannot be
+                               detected.
+                - description: ACLK, SDHI channel bus clock.
             clock-names:
-              minItems: 1
               items:
                 - const: core
+                - const: clkh
                 - const: cd
+                - const: aclk
+            resets:
+              maxItems: 1
+          required:
+            - clock-names
+            - resets
+        else:
+          if:
+            properties:
+              compatible:
+                contains:
+                  enum:
+                    - renesas,rcar-gen2-sdhi
+                    - renesas,rcar-gen3-sdhi
+                    - renesas,rcar-gen4-sdhi
+          then:
+            properties:
+              clocks:
+                minItems: 1
+                maxItems: 3
+              clock-names:
+                minItems: 1
+                uniqueItems: true
+                items:
+                  - const: core
+                  - enum: [ clkh, cd ]
+                  - const: cd
+          else:
+            properties:
+              clocks:
+                minItems: 1
+                maxItems: 2
+              clock-names:
+                minItems: 1
+                items:
+                  - const: core
+                  - const: cd
 
   - if:
       properties:
@@ -247,7 +299,9 @@ allOf:
       properties:
         compatible:
           contains:
-            const: renesas,sdhi-r9a09g057
+            enum:
+              - renesas,sdhi-r9a08g046
+              - renesas,sdhi-r9a09g057
     then:
       properties:
         vqmmc-regulator:
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
  2026-08-20 17:16 ` [PATCH v24 01/15] dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-02 10:47   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths Biju
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

Clean up coding style inconsistencies across the Renesas SDHI host driver
files. Remove redundant internal spacing in the struct definitions and
static initializers to enforce a single space separator or uniform tabs,
aligning the code with standard kernel formatting guidelines.

While at it, add a "Sentinel." comment block to the empty terminating
entries of the Open Firmware (OF) device matching tables to improve
code readability and explicitly mark the table boundaries.

Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * No change.
v21->v22:
 * No change.
v20->v21:
 * No change.
v19->v20:
 * No change.
v18->v19:
 * Updated commit description.
v17->v18:
 * Merged patch#4 and #5
 * Updated commit description
 * Annotate the empty sentinel entries in the OF match tables with a
   "Sentinel." comment for clarity.
 * Retained the tag as it is trivial cleanups.
v1->v17:
 * No change.
---
 drivers/mmc/host/renesas_sdhi.h               | 2 +-
 drivers/mmc/host/renesas_sdhi_internal_dmac.c | 6 +++---
 drivers/mmc/host/renesas_sdhi_sys_dmac.c      | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index afc36a407c2c..09bf9b24a8c3 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -25,7 +25,7 @@ struct renesas_sdhi_scc {
 
 struct renesas_sdhi_of_data {
 	unsigned long tmio_flags;
-	u32	      tmio_ocr_mask;
+	u32 tmio_ocr_mask;
 	unsigned long capabilities;
 	unsigned long capabilities2;
 	enum dma_slave_buswidth dma_buswidth;
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index 0c3967f758c2..b3f4a5f8dec0 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -271,8 +271,8 @@ static const struct renesas_sdhi_of_data_with_quirks of_rcar_gen3_nohs400_compat
 };
 
 static const struct renesas_sdhi_of_data_with_quirks of_rza2_compatible = {
-	.of_data	= &of_data_rza2,
-	.quirks		= &sdhi_quirks_fixed_addr,
+	.of_data = &of_data_rza2,
+	.quirks = &sdhi_quirks_fixed_addr,
 };
 
 static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
@@ -293,7 +293,7 @@ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
 	{ .compatible = "renesas,rzg2l-sdhi", .data = &of_rzg2l_compatible, },
 	{ .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, },
 	{ .compatible = "renesas,rcar-gen4-sdhi", .data = &of_rcar_gen3_compatible, },
-	{},
+	{ /* Sentinel. */ }
 };
 MODULE_DEVICE_TABLE(of, renesas_sdhi_internal_dmac_of_match);
 
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index 426308b73b49..7ae488e5c1e0 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -27,7 +27,7 @@
 #define TMIO_MMC_MIN_DMA_LEN 8
 
 static const struct renesas_sdhi_of_data of_default_cfg = {
-	.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
 };
 
 static const struct renesas_sdhi_of_data of_rz_compatible = {
@@ -89,7 +89,7 @@ static const struct of_device_id renesas_sdhi_sys_dmac_of_match[] = {
 	{ .compatible = "renesas,rcar-gen1-sdhi", .data = &of_rcar_gen1_compatible, },
 	{ .compatible = "renesas,rcar-gen2-sdhi", .data = &of_rcar_gen2_compatible, },
 	{ .compatible = "renesas,sdhi-shmobile" },
-	{},
+	{ /* Sentinel. */ }
 };
 MODULE_DEVICE_TABLE(of, renesas_sdhi_sys_dmac_of_match);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
  2026-08-20 17:16 ` [PATCH v24 01/15] dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC Biju
  2026-08-20 17:16 ` [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-02 10:51   ` Wolfram Sang
  2026-09-02 10:54   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges Biju
                   ` (13 subsequent siblings)
  16 siblings, 2 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

The clock divider on the RZ/G3L SoC features an 11-bit width,
requiring a wider clock mask (0x200000200) in renesas_sdhi_set_clock()
than the historically hardcoded 32-bit value (0x80000080).

To accommodate SoC variants with wider clock divider masks, expand
the internal clock control variables (clk and clock) from u32 to
u64. Introduce a clk_mask field to both struct renesas_sdhi_of_data
and struct tmio_mmc_data to allow platform configuration data to
supply SoC-specific mask properties.

Update renesas_sdhi_set_clock() to read the dynamic mask from
platform data. During the probe phase, assign a default mask
fallback of SDHI_CLK_MASK_DEFAULT (0x80000080) if no specific mask
is specified, ensuring backward compatibility with existing
hardware variants.

Finally, explicitly populate clk_mask with the default value across
all current internal and system DMAC configuration profiles, in
preparation for the upcoming RZ/G3L clock customization.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * No change.
v21->v22:
 * No change.
v20->v21:
 * No change.
v19->v20:
 * Replaced the check mmd->clk_mask with mmc_data->clk_mask and moved
   the code after assignment of variable mmd, this ensures assigning
   the default values for non-DT platforms and DT platforms with no
   device data.
v18->v19:
 * Fixed the clk_mask for non-DT platforms.
v18:
 * New patch dropping struct renesas_sdhi_hw_info instead using
   renesas_sdhi_of_data and tmio_mmc_data.
---
 drivers/mmc/host/renesas_sdhi.h               | 2 ++
 drivers/mmc/host/renesas_sdhi_core.c          | 8 ++++++--
 drivers/mmc/host/renesas_sdhi_internal_dmac.c | 3 +++
 drivers/mmc/host/renesas_sdhi_sys_dmac.c      | 4 ++++
 include/linux/platform_data/tmio.h            | 1 +
 5 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index 09bf9b24a8c3..f926a36f213c 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -22,6 +22,7 @@ struct renesas_sdhi_scc {
 };
 
 #define SDHI_FLAG_NEED_CLKH_FALLBACK	BIT(0)
+#define SDHI_CLK_MASK_DEFAULT		0x80000080
 
 struct renesas_sdhi_of_data {
 	unsigned long tmio_flags;
@@ -37,6 +38,7 @@ struct renesas_sdhi_of_data {
 	unsigned int max_blk_count;
 	unsigned short max_segs;
 	unsigned long sdhi_flags;
+	u64 clk_mask;
 };
 
 #define SDHI_CALIB_TABLE_MAX 32
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index f9ec78d699f4..604d886e483c 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -194,7 +194,7 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
 				   unsigned int new_clock)
 {
 	unsigned int clk_margin;
-	u32 clk = 0, clock;
+	u64 clk = 0, clock;
 
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
 		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
@@ -213,7 +213,7 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
 	 * provided for actual_clock in renesas_sdhi_clk_update().
 	 */
 	clk_margin = new_clock >> 10;
-	for (clk = 0x80000080; new_clock + clk_margin >= (clock << 1); clk >>= 1)
+	for (clk = host->pdata->clk_mask; new_clock + clk_margin >= (clock << 1); clk >>= 1)
 		clock <<= 1;
 
 	/* 1/1 clock is option */
@@ -1136,6 +1136,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 		mmc_data->dma_rx_offset = of_data->dma_rx_offset;
 		mmc_data->max_blk_count = of_data->max_blk_count;
 		mmc_data->max_segs = of_data->max_segs;
+		mmc_data->clk_mask = of_data->clk_mask;
 		dma_priv->dma_buswidth = of_data->dma_buswidth;
 		host->bus_shift = of_data->bus_shift;
 		/* Fallback for old DTs */
@@ -1178,6 +1179,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 	if (mmd)
 		*mmc_data = *mmd;
 
+	if (!mmc_data->clk_mask)
+		mmc_data->clk_mask = SDHI_CLK_MASK_DEFAULT;
+
 	dma_priv->filter = shdma_chan_filter;
 	dma_priv->enable = renesas_sdhi_enable_dma;
 
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index b3f4a5f8dec0..c6db0418de15 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -101,6 +101,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
 	/* DMAC can handle 32bit blk count but only 1 segment */
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
 	.max_segs	= 1,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
@@ -118,6 +119,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
 	.max_segs	= 1,
 	.sdhi_flags	= SDHI_FLAG_NEED_CLKH_FALLBACK,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
@@ -134,6 +136,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
 	/* DMAC can handle 32bit blk count but only 1 segment */
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
 	.max_segs	= 1,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 };
 
 static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index 7ae488e5c1e0..fcd2edfa69db 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -28,6 +28,7 @@
 
 static const struct renesas_sdhi_of_data of_default_cfg = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_rz_compatible = {
@@ -36,6 +37,7 @@ static const struct renesas_sdhi_of_data of_rz_compatible = {
 	.tmio_ocr_mask	= MMC_VDD_32_33,
 	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
 			  MMC_CAP_WAIT_WHILE_BUSY,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = {
@@ -43,6 +45,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = {
 	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
 			  MMC_CAP_WAIT_WHILE_BUSY,
 	.capabilities2	= MMC_CAP2_NO_WRITE_PROTECT,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 };
 
 /* Definitions for sampling clocks */
@@ -70,6 +73,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = {
 	.taps		= rcar_gen2_scc_taps,
 	.taps_num	= ARRAY_SIZE(rcar_gen2_scc_taps),
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 };
 
 static const struct of_device_id renesas_sdhi_sys_dmac_of_match[] = {
diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
index 426291713b83..76056d49f5e0 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -61,5 +61,6 @@ struct tmio_mmc_data {
 	dma_addr_t			dma_rx_offset;
 	unsigned int			max_blk_count;
 	unsigned short			max_segs;
+	u64				clk_mask;
 };
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (2 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-02 11:05   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 05/15] mmc: renesas_sdhi: Add SDHI_SD_CLK_CTL_DIV1 macro for 1/1 option Biju
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

RZ/G3L supports a wider clock divider range than the hardcoded 512
used by existing SoCs. Add a max_divider field to
renesas_sdhi_of_data and tmio_mmc_data, and use it in
renesas_sdhi_clk_enable(), renesas_sdhi_clk_update(), and
renesas_sdhi_set_clock() instead of the fixed value.

Default to SDHI_MAX_DIVIDER_DEFAULT (512) at probe time when
platform data doesn't set it, and populate all existing internal/
sys DMAC of_data tables with this default to keep current SoCs
unaffected. This paves the way for RZ/G3L's extended divider
support.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * Changed the data type of max_divider from unsigned int to signed int.
v21->v22:
 * Updated comit description.
v20->v21:
 * No change.
v19->v20:
 * Replaced the check mmd->max_divider with mmc_data->max_divider and
   moved the code after assignment of variable mmd, this ensures
   assigning the default values for non-DT platforms and DT platforms with
   no device data.
v18->v19:
 * Fixed max-divider setting for non-DT platforms.
 * Replaced the magic number '9' with ilog2 function in
   renesas_sdhi_clk_enable().
v18:
 * New patch.
---
 drivers/mmc/host/renesas_sdhi.h               |  2 ++
 drivers/mmc/host/renesas_sdhi_core.c          | 12 ++++++++----
 drivers/mmc/host/renesas_sdhi_internal_dmac.c |  3 +++
 drivers/mmc/host/renesas_sdhi_sys_dmac.c      |  4 ++++
 include/linux/platform_data/tmio.h            |  1 +
 5 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index f926a36f213c..af56b4bfb1d4 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -23,6 +23,7 @@ struct renesas_sdhi_scc {
 
 #define SDHI_FLAG_NEED_CLKH_FALLBACK	BIT(0)
 #define SDHI_CLK_MASK_DEFAULT		0x80000080
+#define SDHI_MAX_DIVIDER_DEFAULT	512
 
 struct renesas_sdhi_of_data {
 	unsigned long tmio_flags;
@@ -39,6 +40,7 @@ struct renesas_sdhi_of_data {
 	unsigned short max_segs;
 	unsigned long sdhi_flags;
 	u64 clk_mask;
+	int max_divider;
 };
 
 #define SDHI_CALIB_TABLE_MAX 32
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 604d886e483c..d893a263e770 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -117,7 +117,7 @@ static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host)
 	 * Minimum frequency is the minimum input clock frequency
 	 * divided by our maximum divider.
 	 */
-	mmc->f_min = max(clk_round_rate(priv->clk, 1) / 512, 1L);
+	mmc->f_min = max(clk_round_rate(priv->clk, 1) / host->pdata->max_divider, 1L);
 
 	/* enable 16bit data access on SDBUF as default */
 	renesas_sdhi_sdbuf_width(host, 16);
@@ -156,7 +156,7 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
 	/*
 	 * We want the bus clock to be as close as possible to, but no
 	 * greater than, new_clock.  As we can divide by 1 << i for
-	 * any i in [0, 9] we want the input clock to be as close as
+	 * any i in [0, {9,11}] we want the input clock to be as close as
 	 * possible, but no greater than, new_clock << i.
 	 *
 	 * Add an upper limit of 1/1024 rate higher to the clock rate to fix
@@ -165,7 +165,7 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
 	 * for 533.333333 MHz will selects a slower 400 MHz due to rounding
 	 * error (533333333 Hz / 4 * 4 = 533333332 Hz < 533333333 Hz)).
 	 */
-	for (i = min(9, ilog2(UINT_MAX / new_clock)); i >= 0; i--) {
+	for (i = min(ilog2(host->pdata->max_divider), ilog2(UINT_MAX / new_clock)); i >= 0; i--) {
 		freq = clk_round_rate(ref_clk, new_clock << i);
 		new_upper_limit = (new_clock << i) + ((new_clock << i) >> 10);
 		if (freq > new_upper_limit) {
@@ -205,7 +205,7 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
 	}
 
 	host->mmc->actual_clock = renesas_sdhi_clk_update(host, new_clock);
-	clock = host->mmc->actual_clock / 512;
+	clock = host->mmc->actual_clock / host->pdata->max_divider;
 
 	/*
 	 * Add a margin of 1/1024 rate higher to the clock rate in order
@@ -1137,6 +1137,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 		mmc_data->max_blk_count = of_data->max_blk_count;
 		mmc_data->max_segs = of_data->max_segs;
 		mmc_data->clk_mask = of_data->clk_mask;
+		mmc_data->max_divider = of_data->max_divider;
 		dma_priv->dma_buswidth = of_data->dma_buswidth;
 		host->bus_shift = of_data->bus_shift;
 		/* Fallback for old DTs */
@@ -1182,6 +1183,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 	if (!mmc_data->clk_mask)
 		mmc_data->clk_mask = SDHI_CLK_MASK_DEFAULT;
 
+	if (!mmc_data->max_divider)
+		mmc_data->max_divider = SDHI_MAX_DIVIDER_DEFAULT;
+
 	dma_priv->filter = shdma_chan_filter;
 	dma_priv->enable = renesas_sdhi_enable_dma;
 
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index c6db0418de15..2bf354331b2d 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -102,6 +102,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
 	.max_segs	= 1,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
@@ -120,6 +121,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
 	.max_segs	= 1,
 	.sdhi_flags	= SDHI_FLAG_NEED_CLKH_FALLBACK,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
@@ -137,6 +139,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
 	.max_segs	= 1,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
 };
 
 static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index fcd2edfa69db..bb66ff7de065 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -29,6 +29,7 @@
 static const struct renesas_sdhi_of_data of_default_cfg = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_rz_compatible = {
@@ -38,6 +39,7 @@ static const struct renesas_sdhi_of_data of_rz_compatible = {
 	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
 			  MMC_CAP_WAIT_WHILE_BUSY,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
 };
 
 static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = {
@@ -46,6 +48,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = {
 			  MMC_CAP_WAIT_WHILE_BUSY,
 	.capabilities2	= MMC_CAP2_NO_WRITE_PROTECT,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
 };
 
 /* Definitions for sampling clocks */
@@ -74,6 +77,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = {
 	.taps_num	= ARRAY_SIZE(rcar_gen2_scc_taps),
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
 };
 
 static const struct of_device_id renesas_sdhi_sys_dmac_of_match[] = {
diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
index 76056d49f5e0..e104718cf21f 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -62,5 +62,6 @@ struct tmio_mmc_data {
 	unsigned int			max_blk_count;
 	unsigned short			max_segs;
 	u64				clk_mask;
+	int				max_divider;
 };
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 05/15] mmc: renesas_sdhi: Add SDHI_SD_CLK_CTL_DIV1 macro for 1/1 option
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (3 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-02 11:06   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable Biju
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

Replace the magic number 0xff, used for selecting the SD clock 1/1
divider option, with a new SDHI_SD_CLK_CTL_DIV1 macro. This improves
readability and self-documents the purpose of the value at each use
site (setting/clearing the divider bits and comparing against
CLK_CTL_DIV_MASK).

No functional change.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v24:
 * New patch
---
 drivers/mmc/host/renesas_sdhi.h      | 1 +
 drivers/mmc/host/renesas_sdhi_core.c | 6 +++---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index af56b4bfb1d4..a1b2761ceccc 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -24,6 +24,7 @@ struct renesas_sdhi_scc {
 #define SDHI_FLAG_NEED_CLKH_FALLBACK	BIT(0)
 #define SDHI_CLK_MASK_DEFAULT		0x80000080
 #define SDHI_MAX_DIVIDER_DEFAULT	512
+#define SDHI_SD_CLK_CTL_DIV1		0xff
 
 struct renesas_sdhi_of_data {
 	unsigned long tmio_flags;
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index d893a263e770..fbc0a8317b30 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -219,13 +219,13 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
 	/* 1/1 clock is option */
 	if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) && ((clk >> 22) & 0x1)) {
 		if (!(host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
-			clk |= 0xff;
+			clk |= SDHI_SD_CLK_CTL_DIV1;
 		else
-			clk &= ~0xff;
+			clk &= ~SDHI_SD_CLK_CTL_DIV1;
 	}
 
 	clock = clk & CLK_CTL_DIV_MASK;
-	if (clock != CLK_CTL_DIV_MASK)
+	if (clock != SDHI_SD_CLK_CTL_DIV1)
 		host->mmc->actual_clock /= (1 << (ffs(clock) + 1));
 
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clock);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (4 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 05/15] mmc: renesas_sdhi: Add SDHI_SD_CLK_CTL_DIV1 macro for 1/1 option Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-02 11:09   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L Biju
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

Add a clk_div_mask field to renesas_sdhi_of_data and tmio_mmc_data
so each SoC can specify its own divider mask instead of the
hardcoded CLK_CTL_DIV_MASK used in renesas_sdhi_set_clock().

Default to CLK_CTL_DIV_MASK at probe time when unset, and populate all
existing internal/sys DMAC of_data tables with this value to keep
current SoCs unaffected. This lets RZ/G3L, which has a wider
divider field, reuse the same clock-setting code.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * Updated commit description.
 * Replaced  GENMASK(7, 0) with CLK_CTL_DIV_MASK.
v22->v23:
 * Assigned of_data->clk_div_mask in renesas_sdhi_probe().
v21->v22:
 * Updated commit description.
 * Added clk_div_mask to of_default_cfg and of_rcar_gen2_compatible.
v21:
 * New patch.
---
 drivers/mmc/host/renesas_sdhi.h               | 1 +
 drivers/mmc/host/renesas_sdhi_core.c          | 6 +++++-
 drivers/mmc/host/renesas_sdhi_internal_dmac.c | 3 +++
 drivers/mmc/host/renesas_sdhi_sys_dmac.c      | 4 ++++
 include/linux/platform_data/tmio.h            | 1 +
 5 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index a1b2761ceccc..cef043d22dba 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -42,6 +42,7 @@ struct renesas_sdhi_of_data {
 	unsigned long sdhi_flags;
 	u64 clk_mask;
 	int max_divider;
+	u16 clk_div_mask;
 };
 
 #define SDHI_CALIB_TABLE_MAX 32
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index fbc0a8317b30..e11d357225a1 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -224,7 +224,7 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
 			clk &= ~SDHI_SD_CLK_CTL_DIV1;
 	}
 
-	clock = clk & CLK_CTL_DIV_MASK;
+	clock = clk & host->pdata->clk_div_mask;
 	if (clock != SDHI_SD_CLK_CTL_DIV1)
 		host->mmc->actual_clock /= (1 << (ffs(clock) + 1));
 
@@ -1138,6 +1138,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 		mmc_data->max_segs = of_data->max_segs;
 		mmc_data->clk_mask = of_data->clk_mask;
 		mmc_data->max_divider = of_data->max_divider;
+		mmc_data->clk_div_mask = of_data->clk_div_mask;
 		dma_priv->dma_buswidth = of_data->dma_buswidth;
 		host->bus_shift = of_data->bus_shift;
 		/* Fallback for old DTs */
@@ -1186,6 +1187,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 	if (!mmc_data->max_divider)
 		mmc_data->max_divider = SDHI_MAX_DIVIDER_DEFAULT;
 
+	if (!mmc_data->clk_div_mask)
+		mmc_data->clk_div_mask = CLK_CTL_DIV_MASK;
+
 	dma_priv->filter = shdma_chan_filter;
 	dma_priv->enable = renesas_sdhi_enable_dma;
 
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index 2bf354331b2d..b2622ea9ce20 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -103,6 +103,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
 	.max_segs	= 1,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
 static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
@@ -122,6 +123,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
 	.sdhi_flags	= SDHI_FLAG_NEED_CLKH_FALLBACK,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
 static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
@@ -140,6 +142,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
 	.max_segs	= 1,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
 static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
index bb66ff7de065..7a7d254fbba4 100644
--- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c
@@ -30,6 +30,7 @@ static const struct renesas_sdhi_of_data of_default_cfg = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
 static const struct renesas_sdhi_of_data of_rz_compatible = {
@@ -40,6 +41,7 @@ static const struct renesas_sdhi_of_data of_rz_compatible = {
 			  MMC_CAP_WAIT_WHILE_BUSY,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
 static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = {
@@ -49,6 +51,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = {
 	.capabilities2	= MMC_CAP2_NO_WRITE_PROTECT,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
 /* Definitions for sampling clocks */
@@ -78,6 +81,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = {
 	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
 static const struct of_device_id renesas_sdhi_sys_dmac_of_match[] = {
diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
index e104718cf21f..e4232934c7fe 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -63,5 +63,6 @@ struct tmio_mmc_data {
 	unsigned short			max_segs;
 	u64				clk_mask;
 	int				max_divider;
+	u16				clk_div_mask;
 };
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (5 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-03  9:30   ` Wolfram Sang
  2026-09-03  9:34   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag Biju
                   ` (9 subsequent siblings)
  16 siblings, 2 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

RZ/G2L and later SoCs need a hardware adjustment delay written to
SCC_TMPPORT2 on signal-voltage switch during tuning: 0x1 for 1.8V,
0x0 for 3.3V.

Add a TMIO_MMC_TUNING_DELAY flag and
renesas_sdhi_set_hw_adjustment_delay(), called from
renesas_sdhi_start_signal_voltage_switch() after the regulator is
set, and reset SCC_TMPPORT2 to 0 at the start of
renesas_sdhi_execute_tuning() when the flag is set and tap_num == 8.

Add a dedicated of_data_rz_g2l descriptor with this flag and switch
of_rzg2l_compatible to use it instead of the generic R-Car Gen3
descriptor.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * Replaced GENMASK(7, 0) with CLK_CTL_DIV_MASK.
v22->v23:
 * No change.
v21->v22:
 * Updated commit description.
 * Added a renesas_sdhi_set_hw_adjustment_delay() call to
   renesas_sdhi_init_tuning().
v20->v21:
 * Added clk_div_mask to RZ/G2L of_data.
v19->v20:
 * No change.
v18->v19:
 * No change.
v18:
 * New patch.
---
 drivers/mmc/host/renesas_sdhi_core.c          | 88 ++++++++++++-------
 drivers/mmc/host/renesas_sdhi_internal_dmac.c | 22 ++++-
 include/linux/platform_data/tmio.h            |  3 +
 3 files changed, 78 insertions(+), 35 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index e11d357225a1..ff428b6187bb 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -256,40 +256,6 @@ static int renesas_sdhi_card_busy(struct mmc_host *mmc)
 		 TMIO_STAT_DAT0);
 }
 
-static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
-						    struct mmc_ios *ios)
-{
-	struct tmio_mmc_host *host = mmc_priv(mmc);
-	struct renesas_sdhi *priv = host_to_priv(host);
-	struct pinctrl_state *pin_state;
-	int ret;
-
-	switch (ios->signal_voltage) {
-	case MMC_SIGNAL_VOLTAGE_330:
-		pin_state = priv->pins_default;
-		break;
-	case MMC_SIGNAL_VOLTAGE_180:
-		pin_state = priv->pins_uhs;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * If anything is missing, assume signal voltage is fixed at
-	 * 3.3V and succeed/fail accordingly.
-	 */
-	if (IS_ERR(priv->pinctrl) || IS_ERR(pin_state))
-		return ios->signal_voltage ==
-			MMC_SIGNAL_VOLTAGE_330 ? 0 : -EINVAL;
-
-	ret = mmc_regulator_set_vqmmc(host->mmc, ios);
-	if (ret < 0)
-		return ret;
-
-	return pinctrl_select_state(priv->pinctrl, pin_state);
-}
-
 /* SCC registers */
 #define SH_MOBILE_SDHI_SCC_DTCNTL	0x000
 #define SH_MOBILE_SDHI_SCC_TAPSET	0x002
@@ -350,6 +316,55 @@ static inline void sd_scc_write32(struct tmio_mmc_host *host,
 	writel(val, priv->scc_ctl + (addr << host->bus_shift));
 }
 
+static void renesas_sdhi_set_hw_adjustment_delay(struct tmio_mmc_host *host)
+{
+	struct renesas_sdhi *priv = host_to_priv(host);
+
+	if (!(host->pdata->flags & TMIO_MMC_TUNING_DELAY))
+		return;
+
+	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x0);
+	else
+		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1);
+}
+
+static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
+						    struct mmc_ios *ios)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+	struct renesas_sdhi *priv = host_to_priv(host);
+	struct pinctrl_state *pin_state;
+	int ret;
+
+	switch (ios->signal_voltage) {
+	case MMC_SIGNAL_VOLTAGE_330:
+		pin_state = priv->pins_default;
+		break;
+	case MMC_SIGNAL_VOLTAGE_180:
+		pin_state = priv->pins_uhs;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * If anything is missing, assume signal voltage is fixed at
+	 * 3.3V and succeed/fail accordingly.
+	 */
+	if (IS_ERR(priv->pinctrl) || IS_ERR(pin_state))
+		return ios->signal_voltage ==
+			MMC_SIGNAL_VOLTAGE_330 ? 0 : -EINVAL;
+
+	ret = mmc_regulator_set_vqmmc(host->mmc, ios);
+	if (ret < 0)
+		return ret;
+
+	renesas_sdhi_set_hw_adjustment_delay(host);
+
+	return pinctrl_select_state(priv->pinctrl, pin_state);
+}
+
 static unsigned int renesas_sdhi_init_tuning(struct tmio_mmc_host *host)
 {
 	struct renesas_sdhi *priv;
@@ -377,6 +392,8 @@ static unsigned int renesas_sdhi_init_tuning(struct tmio_mmc_host *host)
 
 	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos);
 
+	renesas_sdhi_set_hw_adjustment_delay(host);
+
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
 			sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
 
@@ -709,6 +726,9 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode)
 	if (!priv->tap_num)
 		return 0; /* Tuning is not supported */
 
+	if ((host->pdata->flags & TMIO_MMC_TUNING_DELAY) && priv->tap_num == 8)
+		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0);
+
 	if (priv->tap_num * 2 >= sizeof(priv->taps) * BITS_PER_BYTE) {
 		dev_err(&host->pdev->dev,
 			"Too many taps, please update 'taps' in tmio_mmc_host!\n");
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index b2622ea9ce20..f2c14ec680a8 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -145,6 +145,26 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
 	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
+static const struct renesas_sdhi_of_data of_data_rz_g2l = {
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
+			  TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2 |
+			  TMIO_MMC_64BIT_DATA_PORT | TMIO_MMC_TUNING_DELAY,
+	.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,
+	.bus_shift	= 2,
+	.scc_offset	= 0x1000,
+	.taps		= rcar_gen3_scc_taps,
+	.taps_num	= ARRAY_SIZE(rcar_gen3_scc_taps),
+	/* DMAC can handle 32bit blk count but only 1 segment */
+	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
+	.max_segs	= 1,
+	.sdhi_flags	= SDHI_FLAG_NEED_CLKH_FALLBACK,
+	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
+	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.clk_div_mask	= CLK_CTL_DIV_MASK,
+};
+
 static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
 	{ 3,  3,  3,  3,  3,  3,  3,  4,  4,  5,  6,  7,  8,  9, 10, 15,
 	 16, 16, 16, 16, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 },
@@ -266,7 +286,7 @@ static const struct renesas_sdhi_of_data_with_quirks of_r8a77990_compatible = {
 };
 
 static const struct renesas_sdhi_of_data_with_quirks of_rzg2l_compatible = {
-	.of_data = &of_data_rcar_gen3,
+	.of_data = &of_data_rz_g2l,
 	.quirks = &sdhi_quirks_rzg2l,
 };
 
diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
index e4232934c7fe..abf4134a8bd8 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -50,6 +50,9 @@
 /* Some controllers have a 64-bit wide data port register */
 #define TMIO_MMC_64BIT_DATA_PORT	BIT(12)
 
+/* Some controllers have tuning delay */
+#define TMIO_MMC_TUNING_DELAY		BIT(13)
+
 struct tmio_mmc_data {
 	void				*chan_priv_tx;
 	void				*chan_priv_rx;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (6 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-03  9:37   ` Wolfram Sang
  2026-09-03  9:43   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 09/15] mmc: renesas_sdhi: Add optional axis/axim reset controls Biju
                   ` (8 subsequent siblings)
  16 siblings, 2 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

RZ/G3L has a fixed internal /2 clock divider active in all bus
timing modes except HS400, where the divider is bypassed. Add a
TMIO_MMC_INTERNAL_DIVIDER flag to mark controllers with this
divider.

Add renesas_sdhi_clk_get_rate() to fold the /2 division into the
reported clock rate when the flag is set, and use it in
renesas_sdhi_clk_update() in place of clk_get_rate(). HS400 is not
yet supported in software for this SoC. Adjust clkh_shift for the
internal divider case.

No existing platform sets this flag, so this is infrastructure only,
with no functional change for current SoCs.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * Updated commit description.
v21->v22:
 * Updated commit description.
 * Added renesas_sdhi_is_internal_divider_enabled() and
   renesas_sdhi_clk_get_rate() to simplify the clock rate logic.
v20->v21:
 * No change.
v19->v20:
 * No change.
v18->v19:
 * Updated commit description.
 * Dropped divider variable from struct renesas_sdhi.
 * Updated renesas_sdhi_clk_update() to return rate for HS400mode
   and nonHS400mode(uses 1/2 internal divider).
v18:
 * New patch using flag.
---
 drivers/mmc/host/renesas_sdhi_core.c | 31 +++++++++++++++++++++++++---
 include/linux/platform_data/tmio.h   |  3 +++
 2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index ff428b6187bb..b5f2ff68db75 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -125,6 +125,27 @@ static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host)
 	return 0;
 }
 
+static bool renesas_sdhi_is_internal_divider_enabled(struct tmio_mmc_host *host)
+{
+	bool enable = false;
+
+	if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
+		enable = true;
+
+	return enable;
+}
+
+static unsigned int renesas_sdhi_clk_get_rate(struct tmio_mmc_host *host,
+					      struct clk *clk)
+{
+	unsigned int freq = clk_get_rate(clk);
+
+	if (renesas_sdhi_is_internal_divider_enabled(host))
+		freq /= 2;
+
+	return freq;
+}
+
 static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
 					    unsigned int wanted_clock)
 {
@@ -141,7 +162,7 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
 	 * clock during tuning, so we don't change the external clock setup.
 	 */
 	if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2) || mmc_doing_tune(host->mmc))
-		return clk_get_rate(priv->clk);
+		return renesas_sdhi_clk_get_rate(host, priv->clk);
 
 	if (priv->clkh) {
 		/* HS400 with 4TAP needs different clock settings */
@@ -184,10 +205,14 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
 
 	clk_set_rate(ref_clk, best_freq);
 
-	if (priv->clkh)
+	if (priv->clkh) {
+		if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
+			clkh_shift = 1;
+
 		clk_set_rate(priv->clk, best_freq >> clkh_shift);
+	}
 
-	return clk_get_rate(priv->clk);
+	return renesas_sdhi_clk_get_rate(host, priv->clk);
 }
 
 static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
index abf4134a8bd8..8d435f7690a5 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -53,6 +53,9 @@
 /* Some controllers have tuning delay */
 #define TMIO_MMC_TUNING_DELAY		BIT(13)
 
+/* Some controllers have internal divider */
+#define TMIO_MMC_INTERNAL_DIVIDER	BIT(14)
+
 struct tmio_mmc_data {
 	void				*chan_priv_tx;
 	void				*chan_priv_rx;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 09/15] mmc: renesas_sdhi: Add optional axis/axim reset controls
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (7 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-03  9:48   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes Biju
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson, Philipp Zabel
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

The RZ/G3L SoC has axis/axim resets compared to other SoCs.

Add two optional reset controls, rstc_axis and rstc_axim, to the
renesas_sdhi struct. Both are acquired at probe time using
devm_reset_control_get_optional_exclusive_deasserted() with the
"axis" and "axim" reset names respectively.

Include them alongside the existing rstc in bulk reset/assert/deassert
operations: triggered together in renesas_sdhi_reset(), and managed
via reset_control_bulk_assert/deassert() in the suspend and resume
paths, replacing the previous single-control calls.

Being optional, these resets are a no-op on platforms that do not
provide them, so existing behaviour is preserved.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * No change.
v21->v22:
 * No change.
v20->v21:
 * No change.
v19->v20:
 * Fixed the ordering of resets in suspend/resume paths.
V18->v19:
 * No change.
v17->v18:
 * Fixed ordering of reset in renesas_sdhi_reset().
v1->v17:
 * No change.
---
 drivers/mmc/host/renesas_sdhi.h      |  2 ++
 drivers/mmc/host/renesas_sdhi_core.c | 26 +++++++++++++++++++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index cef043d22dba..25a313e9e7ac 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -102,6 +102,8 @@ struct renesas_sdhi {
 	unsigned int tap_set;
 
 	struct reset_control *rstc;
+	struct reset_control *rstc_axis;
+	struct reset_control *rstc_axim;
 	struct tmio_mmc_host *host;
 	struct regulator_dev *rdev;
 };
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index b5f2ff68db75..99f57f22a7b2 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -641,6 +641,8 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host, bool preserve)
 				sd_status = sd_ctrl_read32(host, CTL_SD_STATUS);
 
 			reset_control_reset(priv->rstc);
+			reset_control_reset(priv->rstc_axim);
+			reset_control_reset(priv->rstc_axis);
 			/* Unknown why but without polling reset status, it will hang */
 			read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100,
 					  false, priv->rstc);
@@ -1155,6 +1157,14 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 	if (IS_ERR(priv->rstc))
 		return PTR_ERR(priv->rstc);
 
+	priv->rstc_axim = devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "axim");
+	if (IS_ERR(priv->rstc_axim))
+		return PTR_ERR(priv->rstc_axim);
+
+	priv->rstc_axis = devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "axis");
+	if (IS_ERR(priv->rstc_axis))
+		return PTR_ERR(priv->rstc_axis);
+
 	priv->pinctrl = devm_pinctrl_get(&pdev->dev);
 	if (!IS_ERR(priv->pinctrl)) {
 		priv->pins_default = pinctrl_lookup_state(priv->pinctrl,
@@ -1385,13 +1395,18 @@ int renesas_sdhi_suspend(struct device *dev)
 {
 	struct tmio_mmc_host *host = dev_get_drvdata(dev);
 	struct renesas_sdhi *priv = host_to_priv(host);
+	struct reset_control_bulk_data resets[] = {
+		{ .rstc = priv->rstc_axis },
+		{ .rstc = priv->rstc_axim },
+		{ .rstc = priv->rstc },
+	};
 	int ret;
 
 	ret = pm_runtime_force_suspend(dev);
 	if (ret)
 		return ret;
 
-	ret = reset_control_assert(priv->rstc);
+	ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		pm_runtime_force_resume(dev);
 
@@ -1403,15 +1418,20 @@ int renesas_sdhi_resume(struct device *dev)
 {
 	struct tmio_mmc_host *host = dev_get_drvdata(dev);
 	struct renesas_sdhi *priv = host_to_priv(host);
+	struct reset_control_bulk_data resets[] = {
+		{ .rstc = priv->rstc_axis },
+		{ .rstc = priv->rstc_axim },
+		{ .rstc = priv->rstc },
+	};
 	int ret;
 
-	ret = reset_control_deassert(priv->rstc);
+	ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		return ret;
 
 	ret = pm_runtime_force_resume(dev);
 	if (ret)
-		reset_control_assert(priv->rstc);
+		reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 
 	return ret;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (8 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 09/15] mmc: renesas_sdhi: Add optional axis/axim reset controls Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-03 10:30   ` Wolfram Sang
  2026-09-03 10:32   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 11/15] mmc: renesas_sdhi: Add RZ/G3L SDHI support Biju
                   ` (6 subsequent siblings)
  16 siblings, 2 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

Add a write32_hook, analogous to the existing write16_hook, so that
sd_ctrl_write32() can wait for the SD bus to become idle before
certain 32-bit register writes.

renesas_sdhi_write32_hook() checks whether the target register is
CTL_SD_CARD_CLK_CTL and, if so, waits for TMIO_STAT_SCLKDIVEN via
renesas_sdhi_wait_idle() before the write proceeds. Other registers
are unaffected. As with write16_hook, the write is skipped if the
hook returns a non-zero error.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v23:
 * New patch.
---
 drivers/mmc/host/renesas_sdhi_core.c | 9 +++++++++
 drivers/mmc/host/tmio_mmc.h          | 7 +++++++
 2 files changed, 16 insertions(+)

diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 99f57f22a7b2..065e175f3b45 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -969,6 +969,14 @@ static int renesas_sdhi_write16_hook(struct tmio_mmc_host *host, int addr)
 	return 0;
 }
 
+static int renesas_sdhi_write32_hook(struct tmio_mmc_host *host, int addr)
+{
+	if (addr == CTL_SD_CARD_CLK_CTL)
+		return renesas_sdhi_wait_idle(host, TMIO_STAT_SCLKDIVEN);
+
+	return 0;
+}
+
 static int renesas_sdhi_multi_io_quirk(struct mmc_card *card,
 				       unsigned int direction, int blk_size)
 {
@@ -1203,6 +1211,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 	}
 
 	host->write16_hook = renesas_sdhi_write16_hook;
+	host->write32_hook = renesas_sdhi_write32_hook;
 	host->clk_enable = renesas_sdhi_clk_enable;
 	host->clk_disable = renesas_sdhi_clk_disable;
 	host->set_clock = renesas_sdhi_set_clock;
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index b9de03325c58..8d6d65a51be7 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -190,6 +190,7 @@ struct tmio_mmc_host {
 	int (*multi_io_quirk)(struct mmc_card *card,
 			      unsigned int direction, int blk_size);
 	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+	int (*write32_hook)(struct tmio_mmc_host *host, int addr);
 	void (*reset)(struct tmio_mmc_host *host, bool preserve);
 	bool (*check_retune)(struct tmio_mmc_host *host, struct mmc_request *mrq);
 	void (*fixup_request)(struct tmio_mmc_host *host, struct mmc_request *mrq);
@@ -284,6 +285,12 @@ static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host,
 
 static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val)
 {
+	/* If there is a hook and it returns non-zero then there
+	 * is an error and the write should be skipped
+	 */
+	if (host->write32_hook && host->write32_hook(host, addr))
+		return;
+
 	iowrite32(val, host->ctl + (addr << host->bus_shift));
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 11/15] mmc: renesas_sdhi: Add RZ/G3L SDHI support
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (9 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-03 12:01   ` Wolfram Sang
  2026-08-20 17:16 ` [PATCH v24 12/15] mmc: renesas_sdhi: Save and restore IOVS across suspend/resume Biju
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

RZ/G3L (r9a08g046) has an SDHI controller that differs from existing
platforms in clock divider width, a second HW adjustment register,
and an extra tuning register.

Add TMIO_MMC_HWADJ to mark controllers with a second HWADJ2 register
(offset 0x010), programmed by renesas_sdhi_set_hw_adjustment_delay()
alongside TMPPORT2 (0x3FFF at 3.3V, 0xFF at 1.8V). Clear the new
HWADJ4 register (0x022) at tuning start when TMIO_MMC_INTERNAL_DIVIDER
is set.

Update renesas_sdhi_set_clock() to write the clock control register
with a 32-bit access when max_divider isn't the default, moving bits
[9:8] of the clock value into bits [17:16] of the register — needed
to drive RZ/G3L's wider 11-bit divider field via the max_divider/
clk_div_mask support added earlier in this series.

Add SDHI_VER_RZ_G3L_SDMMC (0xce10) and handle it in
renesas_sdhi_sdbuf_width(). Add of_data_rzg3l with RZ/G3L's wider
clk_mask, an 11-bit max_divider of 2048, a dedicated tap table, and
the relevant flags including TMIO_MMC_INTERNAL_DIVIDER and
TMIO_MMC_HWADJ. Wire it up via of_rzg3l_compatible (fixed_addr_mode
quirk) and register the "renesas,sdhi-r9a08g046" compatible string.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * Replaced magic bits GENMASK(9, 8) and GENMASK(17, 16) with
   RZG3L_CLK_CTL_DIV9_DIV8 and RZG3L_CLK_CTL_DIV9_DIV8_SRC.
v22->v23:
 * Updated tmio_mmc_reset() to handle 32 bit divider register in RZ/G3L.
v21->v22:
 * Updated commit description.
 * Added `clock &= ~GENMASK(9, 8)` to clear the divider mask bits in
   the register value.
v20->v21:
 * Added clk_div_mask to RZ/G3L of_data.
 * Restored actual_clk calculation in renesas_sdhi_set_clock().
v19->v20:
 * Added bitfield.h header file.
 * Reworked on renesas_sdhi_set_clock() to handle the 11-bit divider
   case and the 32-bit register write.
v18->v19:
 * Update commit description.
 * Updated handling for clk divider.
 * Renamed TMIO_MMC_HWADJ2->TMIO_MMC_HWADJ to make it generic for
   hardware tuning delays
 * Dropped duplicate SH_MOBILE_SDHI_SCC_TMPPORT2 macro
v18:
 * New patch.
---
 drivers/mmc/host/renesas_sdhi_core.c          | 34 +++++++++++++++--
 drivers/mmc/host/renesas_sdhi_internal_dmac.c | 38 +++++++++++++++++++
 drivers/mmc/host/tmio_mmc_core.c              | 13 ++++++-
 include/linux/platform_data/tmio.h            |  3 ++
 4 files changed, 82 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 065e175f3b45..d85db4541160 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -18,6 +18,7 @@
  *
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
@@ -59,9 +60,13 @@
 #define SDHI_VER_GEN2_SDR104	0xcb0d
 #define SDHI_VER_GEN3_SD	0xcc10
 #define SDHI_VER_GEN3_SDMMC	0xcd10
+#define SDHI_VER_RZ_G3L_SDMMC	0xce10
 
 #define SDHI_GEN3_MMC0_ADDR	0xee140000
 
+#define RZG3L_CLK_CTL_DIV9_DIV8		GENMASK(17, 16)
+#define RZG3L_CLK_CTL_DIV9_DIV8_SRC	GENMASK(9, 8)
+
 static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width)
 {
 	u32 val;
@@ -79,6 +84,7 @@ static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width)
 		break;
 	case SDHI_VER_GEN3_SD:
 	case SDHI_VER_GEN3_SDMMC:
+	case SDHI_VER_RZ_G3L_SDMMC:
 		if (width == 64)
 			val = HOST_MODE_GEN3_64BIT;
 		else if (width == 32)
@@ -253,7 +259,17 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
 	if (clock != SDHI_SD_CLK_CTL_DIV1)
 		host->mmc->actual_clock /= (1 << (ffs(clock) + 1));
 
-	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clock);
+	if (host->pdata->max_divider != SDHI_MAX_DIVIDER_DEFAULT) {
+		u64 tmp;
+
+		tmp = FIELD_GET(RZG3L_CLK_CTL_DIV9_DIV8_SRC, clk);
+		clock |= FIELD_PREP(RZG3L_CLK_CTL_DIV9_DIV8, tmp);
+		clock &= ~RZG3L_CLK_CTL_DIV9_DIV8_SRC;
+		sd_ctrl_write32(host, CTL_SD_CARD_CLK_CTL, clock);
+	} else {
+		sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clock);
+	}
+
 	if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2))
 		usleep_range(10000, 11000);
 
@@ -289,12 +305,14 @@ static int renesas_sdhi_card_busy(struct mmc_host *mmc)
 #define SH_MOBILE_SDHI_SCC_RVSCNTL	0x008
 #define SH_MOBILE_SDHI_SCC_RVSREQ	0x00A
 #define SH_MOBILE_SDHI_SCC_SMPCMP       0x00C
-#define SH_MOBILE_SDHI_SCC_TMPPORT2	0x00E
+#define SH_MOBILE_SDHI_SCC_TMPPORT2	0x00E /* G3L: SDm_SCC_HS400MODE1 */
+#define RZG3L_SDHI_SCC_HWADJ2		0x010
 #define SH_MOBILE_SDHI_SCC_TMPPORT3	0x014
 #define SH_MOBILE_SDHI_SCC_TMPPORT4	0x016
 #define SH_MOBILE_SDHI_SCC_TMPPORT5	0x018
 #define SH_MOBILE_SDHI_SCC_TMPPORT6	0x01A
 #define SH_MOBILE_SDHI_SCC_TMPPORT7	0x01C
+#define RZG3L_SDHI_SCC_HWADJ4		0x022
 
 #define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN		BIT(0)
 #define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT	16
@@ -344,14 +362,20 @@ static inline void sd_scc_write32(struct tmio_mmc_host *host,
 static void renesas_sdhi_set_hw_adjustment_delay(struct tmio_mmc_host *host)
 {
 	struct renesas_sdhi *priv = host_to_priv(host);
+	bool hwadj2 = host->pdata->flags & TMIO_MMC_HWADJ;
 
 	if (!(host->pdata->flags & TMIO_MMC_TUNING_DELAY))
 		return;
 
-	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
 		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x0);
-	else
+		if (hwadj2)
+			sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ2, 0x3FFF);
+	} else {
 		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1);
+		if (hwadj2)
+			sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ2, 0xFF);
+	}
 }
 
 static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
@@ -418,6 +442,8 @@ static unsigned int renesas_sdhi_init_tuning(struct tmio_mmc_host *host)
 	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos);
 
 	renesas_sdhi_set_hw_adjustment_delay(host);
+	if (host->pdata->flags & TMIO_MMC_HWADJ)
+		sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ4, 0x0);
 
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
 			sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index f2c14ec680a8..3eccad143526 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -88,6 +88,13 @@ static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = {
 	},
 };
 
+static struct renesas_sdhi_scc rzg3l_scc_taps[] = {
+	{
+		.clk_rate = 0,
+		.tap = 0x00000300,
+	},
+};
+
 static const struct renesas_sdhi_of_data of_data_rza2 = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
 			  TMIO_MMC_HAVE_CBSY,
@@ -165,6 +172,27 @@ static const struct renesas_sdhi_of_data of_data_rz_g2l = {
 	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
+static const struct renesas_sdhi_of_data of_data_rzg3l = {
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
+			  TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2 |
+			  TMIO_MMC_64BIT_DATA_PORT | TMIO_MMC_TUNING_DELAY |
+			  TMIO_MMC_INTERNAL_DIVIDER | TMIO_MMC_HWADJ,
+	.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,
+	.bus_shift	= 2,
+	.scc_offset	= 0x1000,
+	.taps		= rzg3l_scc_taps,
+	.taps_num	= ARRAY_SIZE(rzg3l_scc_taps),
+	/* DMAC can handle 32bit blk count but only 1 segment */
+	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
+	.max_segs	= 1,
+	.sdhi_flags	= SDHI_FLAG_NEED_CLKH_FALLBACK,
+	.clk_mask	= 0x200000200,
+	.max_divider	= 2048,
+	.clk_div_mask	= GENMASK(9, 0),
+};
+
 static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = {
 	{ 3,  3,  3,  3,  3,  3,  3,  4,  4,  5,  6,  7,  8,  9, 10, 15,
 	 16, 16, 16, 16, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 },
@@ -245,6 +273,10 @@ static const struct renesas_sdhi_quirks sdhi_quirks_rzg2l = {
 	.hs400_disabled = true,
 };
 
+static const struct renesas_sdhi_quirks sdhi_quirks_rzg3l = {
+	.fixed_addr_mode = true,
+};
+
 /*
  * Note for r8a7796 / r8a774a1: we can't distinguish ES1.1 and 1.2 as of now.
  * So, we want to treat them equally and only have a match for ES1.2 to enforce
@@ -304,6 +336,11 @@ static const struct renesas_sdhi_of_data_with_quirks of_rza2_compatible = {
 	.quirks = &sdhi_quirks_fixed_addr,
 };
 
+static const struct renesas_sdhi_of_data_with_quirks of_rzg3l_compatible = {
+	.of_data = &of_data_rzg3l,
+	.quirks = &sdhi_quirks_rzg3l,
+};
+
 static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
 	{ .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, },
 	{ .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, },
@@ -317,6 +354,7 @@ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
 	{ .compatible = "renesas,sdhi-r8a77990", .data = &of_r8a77990_compatible, },
 	{ .compatible = "renesas,sdhi-r8a77995", .data = &of_rcar_gen3_nohs400_compatible, },
 	{ .compatible = "renesas,sdhi-r8a779md", .data = &of_rcar_gen3_nohs400_compatible, },
+	{ .compatible = "renesas,sdhi-r9a08g046", .data = &of_rzg3l_compatible, },
 	{ .compatible = "renesas,sdhi-r9a09g011", .data = &of_rzg2l_compatible, },
 	{ .compatible = "renesas,sdhi-r9a09g057", .data = &of_rzg2l_compatible, },
 	{ .compatible = "renesas,rzg2l-sdhi", .data = &of_rzg2l_compatible, },
diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
index 775e0d9353d5..8a34f7d29396 100644
--- a/drivers/mmc/host/tmio_mmc_core.c
+++ b/drivers/mmc/host/tmio_mmc_core.c
@@ -182,10 +182,15 @@ static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host,
 static void tmio_mmc_reset(struct tmio_mmc_host *host, bool preserve)
 {
 	u16 card_opt, clk_ctrl, sdif_mode;
+	u32 clk_ctrl_32;
 
 	if (preserve) {
 		card_opt = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT);
-		clk_ctrl = sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL);
+		if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
+			clk_ctrl_32 = sd_ctrl_read32(host, CTL_SD_CARD_CLK_CTL);
+		else
+			clk_ctrl = sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL);
+
 		if (host->pdata->flags & TMIO_MMC_MIN_RCAR2)
 			sdif_mode = sd_ctrl_read16(host, CTL_SDIF_MODE);
 	}
@@ -217,7 +222,11 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host, bool preserve)
 
 	if (preserve) {
 		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, card_opt);
-		sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk_ctrl);
+		if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
+			sd_ctrl_write32(host, CTL_SD_CARD_CLK_CTL, clk_ctrl_32);
+		else
+			sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk_ctrl);
+
 		if (host->pdata->flags & TMIO_MMC_MIN_RCAR2)
 			sd_ctrl_write16(host, CTL_SDIF_MODE, sdif_mode);
 	}
diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
index 8d435f7690a5..e2273a262a23 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -56,6 +56,9 @@
 /* Some controllers have internal divider */
 #define TMIO_MMC_INTERNAL_DIVIDER	BIT(14)
 
+/* Some controllers have hw adjustment delay */
+#define TMIO_MMC_HWADJ			BIT(15)
+
 struct tmio_mmc_data {
 	void				*chan_priv_tx;
 	void				*chan_priv_rx;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 12/15] mmc: renesas_sdhi: Save and restore IOVS across suspend/resume
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (10 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 11/15] mmc: renesas_sdhi: Add RZ/G3L SDHI support Biju
@ 2026-08-20 17:16 ` Biju
  2026-08-20 17:16 ` [PATCH v24 13/15] mmc: renesas_sdhi: Make HS400 OSEL bit configurable per SoC Biju
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

The SD_STATUS register, specifically the IOVS (I/O Voltage Switch) bit, is
not automatically restored after a suspend/resume cycle, causing the
regulator to report an incorrect voltage on resume.

Fix this by caching the CTL_SD_STATUS register value in the renesas_sdhi
private struct at suspend time and writing it back during resume. The
save/restore is only performed when a regulator device (rdev) is present,
as the IOVS bit is only relevant in that context.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * No change.
v21->v22:
 * No change.
v20->v21:
 * No change.
v19->v20:
 * Updated resume() with scoped PM runtime call.
v18->v19:
 * Updated suspend/resume with scoped runtime calls in suspend.
v17->v18:
 * No change.
v1->v17:
 * No change.
---
 drivers/mmc/host/renesas_sdhi.h      |  2 ++
 drivers/mmc/host/renesas_sdhi_core.c | 26 +++++++++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index 25a313e9e7ac..dd650dd24b27 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -106,6 +106,8 @@ struct renesas_sdhi {
 	struct reset_control *rstc_axim;
 	struct tmio_mmc_host *host;
 	struct regulator_dev *rdev;
+
+	u32 cache_sd_status;
 };
 
 #define host_to_priv(host) \
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index d85db4541160..2f5e02537a94 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -1437,6 +1437,15 @@ int renesas_sdhi_suspend(struct device *dev)
 	};
 	int ret;
 
+	if (priv->rdev) {
+		PM_RUNTIME_ACQUIRE_IF_ENABLED(dev, pm);
+		ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+		if (ret < 0)
+			return ret;
+
+		priv->cache_sd_status = sd_ctrl_read32(host, CTL_SD_STATUS);
+	}
+
 	ret = pm_runtime_force_suspend(dev);
 	if (ret)
 		return ret;
@@ -1466,8 +1475,23 @@ int renesas_sdhi_resume(struct device *dev)
 
 	ret = pm_runtime_force_resume(dev);
 	if (ret)
-		reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
+		goto err_assert;
+
+	if (priv->rdev) {
+		PM_RUNTIME_ACQUIRE_IF_ENABLED(dev, pm);
+		ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+		if (ret < 0)
+			goto err_pm;
+
+		sd_ctrl_write32(host, CTL_SD_STATUS, priv->cache_sd_status);
+	}
+
+	return 0;
 
+err_pm:
+	pm_runtime_force_suspend(dev);
+err_assert:
+	reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(renesas_sdhi_resume);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 13/15] mmc: renesas_sdhi: Make HS400 OSEL bit configurable per SoC
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (11 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 12/15] mmc: renesas_sdhi: Save and restore IOVS across suspend/resume Biju
@ 2026-08-20 17:16 ` Biju
  2026-08-20 17:16 ` [PATCH v24 14/15] mmc: renesas_sdhi: Add RZ/G3L HS400 support Biju
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

RZ/G3L and R-Car both use SH_MOBILE_SDHI_SCC_TMPPORT2 but interpret
its bitfields differently. R-Car uses BIT(4) (HS400OSEL) to control
HS400 data output timing, while RZ/G3L uses the lower 16 bits for tuning
delay and does not require the OSEL bit.

Remove the hardcoded SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL constant
and replace it with a per-platform osel_tmpout field in both
renesas_sdhi_of_data and tmio_mmc_data. The field is propagated
during probe and consumed in renesas_sdhi_hs400_complete() and
renesas_sdhi_reset_hs400_mode() when setting or clearing the HS400EN
bit in TMPPORT2.

Set osel_tmpout = BIT(4) explicitly on of_data_rcar_gen3 and
of_data_rcar_gen3_no_sdh_fallback; platforms that omit it (such as
RZ/G2L and RZ/G3L) default to zero, leaving the OSEL bit untouched
during HS400 mode transitions.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * No change.
v21->v22:
 * No change.
v20->v21:
 * No change.
v19->v20:
 * No change.
v18->v19:
 * No change.
v18:
 * New patch.
---
 drivers/mmc/host/renesas_sdhi.h               | 1 +
 drivers/mmc/host/renesas_sdhi_core.c          | 6 +++---
 drivers/mmc/host/renesas_sdhi_internal_dmac.c | 2 ++
 include/linux/platform_data/tmio.h            | 1 +
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index dd650dd24b27..7c562074d119 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -42,6 +42,7 @@ struct renesas_sdhi_of_data {
 	unsigned long sdhi_flags;
 	u64 clk_mask;
 	int max_divider;
+	u32 osel_tmpout;
 	u16 clk_div_mask;
 };
 
diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 2f5e02537a94..23332539ac65 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -330,7 +330,6 @@ 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_HS400OSEL	BIT(4)
 #define SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN	BIT(31)
 
 /* Definitions for values the SH_MOBILE_SDHI_SCC_TMPPORT4 register */
@@ -478,7 +477,7 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
 
 	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2,
 		       (SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN |
-			SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
+			host->pdata->osel_tmpout) |
 			sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2));
 
 	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
@@ -619,7 +618,7 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host,
 
 	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2,
 		       ~(SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN |
-			 SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) &
+			 host->pdata->osel_tmpout) &
 			sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2));
 
 	if (sdhi_has_quirk(priv, hs400_calib_table) || sdhi_has_quirk(priv, hs400_bad_taps))
@@ -1228,6 +1227,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
 		mmc_data->clk_mask = of_data->clk_mask;
 		mmc_data->max_divider = of_data->max_divider;
 		mmc_data->clk_div_mask = of_data->clk_div_mask;
+		mmc_data->osel_tmpout = of_data->osel_tmpout;
 		dma_priv->dma_buswidth = of_data->dma_buswidth;
 		host->bus_shift = of_data->bus_shift;
 		/* Fallback for old DTs */
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index 3eccad143526..de570f7fc9c4 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -130,6 +130,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
 	.sdhi_flags	= SDHI_FLAG_NEED_CLKH_FALLBACK,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.osel_tmpout	= BIT(4),
 	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
@@ -149,6 +150,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
 	.max_segs	= 1,
 	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
 	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
+	.osel_tmpout	= BIT(4),
 	.clk_div_mask	= CLK_CTL_DIV_MASK,
 };
 
diff --git a/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
index e2273a262a23..fecc61e082de 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -72,6 +72,7 @@ struct tmio_mmc_data {
 	unsigned short			max_segs;
 	u64				clk_mask;
 	int				max_divider;
+	u32				osel_tmpout;
 	u16				clk_div_mask;
 };
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 14/15] mmc: renesas_sdhi: Add RZ/G3L HS400 support
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (12 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 13/15] mmc: renesas_sdhi: Make HS400 OSEL bit configurable per SoC Biju
@ 2026-08-20 17:16 ` Biju
  2026-08-20 17:16 ` [PATCH v24 15/15] mmc: renesas_sdhi: Add HS400 enhanced strobe support for RZ/G3L Biju
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

Add HS400 support for the RZ/G3L SoC.

RZ/G3L needs a second HS400 enable register, SDm_SCC_HS400MODE2
(offset 0x020), alongside the existing TMPPORT2 path. Add a
TMIO_MMC_HS400MODE2 flag (bit 16) for controllers that need it.

renesas_sdhi_hs400_complete() now also sets HS400EN2 in HS400MODE2
when the flag is set, and renesas_sdhi_reset_hs400_mode() clears it
on exit. Add renesas_sdhi_set_tmpport() to mask off only the lower
16 bits (TMPOUT) of TMPPORT2 when writing it, preserving the upper
bits on controllers with HS400MODE2, instead of the previous
unconditional zero write.

RZ/G3L HS400 supports only one divider value, so
renesas_sdhi_set_clock() now forces the clock value to 0 before
masking when HS400MODE2 is set and the internal divider isn't
currently enabled, rejecting any other divider. This also completes
renesas_sdhi_is_internal_divider_enabled() from earlier in the
series, which now additionally checks that the current timing mode
is not MMC_TIMING_MMC_HS400 before reporting the internal divider as
enabled.

Enable TMIO_MMC_HS400MODE2 in of_data_rzg3l to complete RZ/G3L HS400
support.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * Simplified renesas_sdhi_set_tmpport().
 * Replaced GENMASK(15, 0) with RZG3L_SDHI_SCC_HS400MODE1_TMPOUT.
v22->v23:
 * No change.
v21->v22:
 * Updated commit description
 * Added a renesas_sdhi_set_tmpport() helper to set delay values.
 * Added a check in renesas_sdhi_is_internal_divider_enabled() to
   return disabled status when in HS400 mode.
v20->v21:
 * Updated renesas_sdhi_set_clock() for RZ/G3L HS400 clock handling as
   it supports only single clk divider value and other values are
   prohibited.
 * Updated commit description.
v19->v20:
 * No change.
v18->v19:
 * Updated commit description.
 * Fixed extra space in HS400MODE2 comment block.
 * Updated the comment HS400mode2->HS400MODE2.
 * Dropped the updation of clk handling as it is taken care in
   previous patches.
v18:
 * New patch.
---
 drivers/mmc/host/renesas_sdhi_core.c          | 40 +++++++++++++++++--
 drivers/mmc/host/renesas_sdhi_internal_dmac.c |  3 +-
 include/linux/platform_data/tmio.h            |  3 ++
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 23332539ac65..5d9d3c7dedf9 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -135,7 +135,8 @@ static bool renesas_sdhi_is_internal_divider_enabled(struct tmio_mmc_host *host)
 {
 	bool enable = false;
 
-	if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
+	if ((host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER) &&
+	    host->mmc->ios.timing != MMC_TIMING_MMC_HS400)
 		enable = true;
 
 	return enable;
@@ -255,6 +256,14 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
 			clk &= ~SDHI_SD_CLK_CTL_DIV1;
 	}
 
+	/*
+	 * RZ/G3L SoC HS400 mode has only 1 divider value.
+	 * Other divider values are prohibited
+	 */
+	if ((host->pdata->flags & TMIO_MMC_HS400MODE2) &&
+	    !renesas_sdhi_is_internal_divider_enabled(host))
+		clk = 0;
+
 	clock = clk & host->pdata->clk_div_mask;
 	if (clock != SDHI_SD_CLK_CTL_DIV1)
 		host->mmc->actual_clock /= (1 << (ffs(clock) + 1));
@@ -312,6 +321,7 @@ static int renesas_sdhi_card_busy(struct mmc_host *mmc)
 #define SH_MOBILE_SDHI_SCC_TMPPORT5	0x018
 #define SH_MOBILE_SDHI_SCC_TMPPORT6	0x01A
 #define SH_MOBILE_SDHI_SCC_TMPPORT7	0x01C
+#define RZG3L_SDHI_SCC_HS400MODE2	0x020
 #define RZG3L_SDHI_SCC_HWADJ4		0x022
 
 #define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN		BIT(0)
@@ -344,6 +354,9 @@ static int renesas_sdhi_card_busy(struct mmc_host *mmc)
 #define SH_MOBILE_SDHI_SCC_TMPPORT_DISABLE_WP_CODE	0xa5000000
 #define SH_MOBILE_SDHI_SCC_TMPPORT_CALIB_CODE_MASK	0x1f
 #define SH_MOBILE_SDHI_SCC_TMPPORT_MANUAL_MODE		BIT(7)
+#define RZG3L_SDHI_SCC_HS400MODE2_HS400EN2		BIT(0)
+
+#define RZG3L_SDHI_SCC_HS400MODE1_TMPOUT		GENMASK(15, 0)
 
 static inline u32 sd_scc_read32(struct tmio_mmc_host *host,
 				struct renesas_sdhi *priv, int addr)
@@ -358,6 +371,18 @@ static inline void sd_scc_write32(struct tmio_mmc_host *host,
 	writel(val, priv->scc_ctl + (addr << host->bus_shift));
 }
 
+static void renesas_sdhi_set_tmpport(struct tmio_mmc_host *host, u32 tmpport)
+{
+	struct renesas_sdhi *priv = host_to_priv(host);
+	u32 val = tmpport;
+
+	if (host->pdata->flags & TMIO_MMC_HS400MODE2)
+		val |= sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2) &
+		       ~RZG3L_SDHI_SCC_HS400MODE1_TMPOUT;
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, val);
+}
+
 static void renesas_sdhi_set_hw_adjustment_delay(struct tmio_mmc_host *host)
 {
 	struct renesas_sdhi *priv = host_to_priv(host);
@@ -367,11 +392,11 @@ static void renesas_sdhi_set_hw_adjustment_delay(struct tmio_mmc_host *host)
 		return;
 
 	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
-		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x0);
+		renesas_sdhi_set_tmpport(host, 0x0);
 		if (hwadj2)
 			sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ2, 0x3FFF);
 	} else {
-		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1);
+		renesas_sdhi_set_tmpport(host, 0x1);
 		if (hwadj2)
 			sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ2, 0xFF);
 	}
@@ -480,6 +505,10 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
 			host->pdata->osel_tmpout) |
 			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,
+			       RZG3L_SDHI_SCC_HS400MODE2_HS400EN2);
+
 	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
 		       SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
 		       sd_scc_read32(host, priv,
@@ -621,6 +650,9 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host,
 			 host->pdata->osel_tmpout) &
 			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);
+
 	if (sdhi_has_quirk(priv, hs400_calib_table) || sdhi_has_quirk(priv, hs400_bad_taps))
 		renesas_sdhi_adjust_hs400_mode_disable(host);
 
@@ -779,7 +811,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode)
 		return 0; /* Tuning is not supported */
 
 	if ((host->pdata->flags & TMIO_MMC_TUNING_DELAY) && priv->tap_num == 8)
-		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0);
+		renesas_sdhi_set_tmpport(host, 0);
 
 	if (priv->tap_num * 2 >= sizeof(priv->taps) * BITS_PER_BYTE) {
 		dev_err(&host->pdev->dev,
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index de570f7fc9c4..afe259c1566d 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -178,7 +178,8 @@ static const struct renesas_sdhi_of_data of_data_rzg3l = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
 			  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_INTERNAL_DIVIDER | TMIO_MMC_HWADJ |
+			  TMIO_MMC_HS400MODE2,
 	.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 fecc61e082de..88a3744f965a 100644
--- a/include/linux/platform_data/tmio.h
+++ b/include/linux/platform_data/tmio.h
@@ -59,6 +59,9 @@
 /* Some controllers have hw adjustment delay */
 #define TMIO_MMC_HWADJ			BIT(15)
 
+/* Some controllers have HS400MODE2 */
+#define TMIO_MMC_HS400MODE2		BIT(16)
+
 struct tmio_mmc_data {
 	void				*chan_priv_tx;
 	void				*chan_priv_rx;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v24 15/15] mmc: renesas_sdhi: Add HS400 enhanced strobe support for RZ/G3L
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (13 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 14/15] mmc: renesas_sdhi: Add RZ/G3L HS400 support Biju
@ 2026-08-20 17:16 ` Biju
  2026-09-01 14:52 ` [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Wolfram Sang
  2026-09-03 20:11 ` Wolfram Sang
  16 siblings, 0 replies; 42+ messages in thread
From: Biju @ 2026-08-20 17:16 UTC (permalink / raw)
  To: Wolfram Sang, Ulf Hansson
  Cc: Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

RZ/G3L's HS400 enhanced strobe mode needs extra SCC register
programming beyond the standard HS400 path. Add a TMIO_MMC_HS400ES
flag (bit 17) for controllers that support it.

Add renesas_sdhi_hs400_enhanced_strobe(), registered as
host->ops.hs400_enhanced_strobe when the flag is set. On enable, it
clears DTSEL and TAPEN, programs TMPPORT3 and HWADJ2, sets the HS400
interface bit in SDIF_MODE, sets HS400EN2 in HS400MODE2, and sets
HS400EN plus the new HS400MODE1_ENHANCED_STROBE bit in TMPPORT2. On
disable, only the enhanced-strobe-related bits are cleared.

Also mask off HS400MODE1_ENHANCED_STROBE in
renesas_sdhi_reset_hs400_mode() when TMIO_MMC_HS400ES is set, for a
clean reset on mode exit.

Since a controller reset clears these SCC registers,
renesas_sdhi_reset() now re-invokes
renesas_sdhi_hs400_enhanced_strobe() after reset whenever
TMIO_MMC_HS400ES is set and the controller is currently in HS400
with enhanced strobe active, restoring the enhanced-strobe state
instead of losing it across a reset.

Enable TMIO_MMC_HS400ES in of_data_rzg3l to finalize RZ/G3L HS400
support.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v23->v24:
 * No change.
v22->v23:
 * No change.
v21->v22:
 * Updated commit description.
 * Restored the patch after fixing inode corruption.
 * renesas_sdhi_reset() now restores data strobe register values
   after reset.
v20->v21:
 * Dropped the patch due to inode corruption during boot.
v19->v20:
 * SD_CLK_CTRL clk enable turned off before updating SCC_CKSEL_DTSEL
   register.
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          | 68 +++++++++++++++++--
 drivers/mmc/host/renesas_sdhi_internal_dmac.c |  2 +-
 include/linux/platform_data/tmio.h            |  3 +
 3 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
index 5d9d3c7dedf9..fc58f2188852 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -340,7 +340,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)
@@ -636,6 +637,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));
 
@@ -645,10 +648,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);
@@ -679,6 +683,53 @@ static void renesas_sdhi_scc_reset(struct tmio_mmc_host *host, struct renesas_sd
 		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
 }
 
+static void renesas_sdhi_hs400_enhanced_strobe(struct mmc_host *mmc,
+					       struct mmc_ios *ios)
+{
+	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_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+			sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+		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));
+
+		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_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+				sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+		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_TMPPORT2_HS400EN |
+			 SH_MOBILE_SDHI_SCC_HS400MODE1_ENHANCED_STROBE);
+
+		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, 0);
+	}
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, val);
+}
+
 /* only populated for TMIO_MMC_MIN_RCAR2 */
 static void renesas_sdhi_reset(struct tmio_mmc_host *host, bool preserve)
 {
@@ -703,6 +754,13 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host, bool preserve)
 			/* Unknown why but without polling reset status, it will hang */
 			read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100,
 					  false, priv->rstc);
+
+			/* Restore data strobe registers */
+			if ((host->pdata->flags & TMIO_MMC_HS400ES) &&
+			    host->mmc->ios.timing == MMC_TIMING_MMC_HS400 &&
+			    host->mmc->ios.enhanced_strobe)
+				renesas_sdhi_hs400_enhanced_strobe(host->mmc, &host->mmc->ios);
+
 			/* At least SDHI_VER_GEN2_SDR50 needs manual release of reset */
 			sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
 			if (priv->rdev)
@@ -1410,6 +1468,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 afe259c1566d..c64993ee3ec5 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -179,7 +179,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 88a3744f965a..ca1435441628 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (14 preceding siblings ...)
  2026-08-20 17:16 ` [PATCH v24 15/15] mmc: renesas_sdhi: Add HS400 enhanced strobe support for RZ/G3L Biju
@ 2026-09-01 14:52 ` Wolfram Sang
  2026-09-03 20:11 ` Wolfram Sang
  16 siblings, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-01 14:52 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Philipp Zabel, Magnus Damm, Biju Das,
	linux-mmc, devicetree, linux-kernel, linux-renesas-soc,
	Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 530 bytes --]

Hi Biju,

I am starting now to review this series. Probably in batches, though,
not in one go.

> This patch series tested on smarc-rz{v2l,g2l,g2lc,g2ul,g3s,g3l,g3e},
> rz{v2h,t2h}-evk and hihope-rz{g2h,g2m,g2n} boards

This plenty of testing is really good! Hihope boards means you basically
tested it on R-Car Gen3 compatible versions. I will test this on a
SparrowHawk board, so we have R-Car Gen4 covered as well. I don't expect
any problems, though. Gen4 is basically Gen3 when it comes to SDHI.

Happy hacking,

   Wolfram


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 01/15] dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC
  2026-08-20 17:16 ` [PATCH v24 01/15] dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC Biju
@ 2026-09-02 10:45   ` Wolfram Sang
  0 siblings, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-02 10:45 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm, Biju Das, linux-mmc, devicetree,
	linux-kernel, linux-renesas-soc, Prabhakar Mahadev Lad,
	Conor Dooley

[-- Attachment #1: Type: text/plain, Size: 844 bytes --]

On Thu, Aug 20, 2026 at 06:16:31PM +0100, Biju wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
> 
> Document the RZ/G3L (r9a08g046) SDHI controller. The RZ/G3L SDHI
> controller is similar to RZ/G2L but has five clocks (core, clkh,
> cd, aclkm, aclks) and three resets (rst, axim, axis), so update the
> clocks/clock-names maximum to 5 and resets/reset-names maximum to 3.
> It has an internal divider for all modes except HS400, and a 2048-bit
> divider compared to 512 on others.
> 
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>

Looks good to me. Adding new SoCs might turn into an adventure game with
serious logic puzzles, though. Not your fault, of course.

DT checks pass here as well.

Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels
  2026-08-20 17:16 ` [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels Biju
@ 2026-09-02 10:47   ` Wolfram Sang
  2026-09-04  6:40     ` Biju Das
  0 siblings, 1 reply; 42+ messages in thread
From: Wolfram Sang @ 2026-09-02 10:47 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 181 bytes --]


>  static const struct renesas_sdhi_of_data of_default_cfg = {
> -	.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
> +	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
>  };

This one gets worse, or?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths
  2026-08-20 17:16 ` [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths Biju
@ 2026-09-02 10:51   ` Wolfram Sang
  2026-09-04 10:54     ` Biju Das
  2026-09-02 10:54   ` Wolfram Sang
  1 sibling, 1 reply; 42+ messages in thread
From: Wolfram Sang @ 2026-09-02 10:51 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 494 bytes --]


> +#define SDHI_CLK_MASK_DEFAULT		0x80000080

ULL suffix maybe?

> @@ -101,6 +101,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
>  	/* DMAC can handle 32bit blk count but only 1 segment */
>  	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
>  	.max_segs	= 1,
> +	.clk_mask	= SDHI_CLK_MASK_DEFAULT,

I'd vote to not initialize clk_mask when it uses the default value. We
have code handling this case. This makes the instances having a
non-default value more obvious, I'd say.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths
  2026-08-20 17:16 ` [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths Biju
  2026-09-02 10:51   ` Wolfram Sang
@ 2026-09-02 10:54   ` Wolfram Sang
  2026-09-04 11:03     ` Biju Das
  1 sibling, 1 reply; 42+ messages in thread
From: Wolfram Sang @ 2026-09-02 10:54 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 2614 bytes --]

Hi,

Sashiko found issues with your patch. I curated the list and left only those
which I see as valid. Please have a look at these issues.

Thank you and happy hacking,

   Wolfram

> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] A very low or zero clock rate from the clock provider causes an infinite loop in `renesas_sdhi_set_clock`.
> --
> 
> --- Patch [3]: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths ---
> commit 1c7318b14c028686fc8ca703eb8ac2be269937b6
> Author: Biju Das <biju.das.jz@bp.renesas.com>
> 
> mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths
> 
> This patch introduces a clk_mask field in platform data to replace a hardcoded
> 32-bit clock mask, supporting 11-bit clock dividers on newer SoCs like the
> RZ/G3L. It updates renesas_sdhi_set_clock() to use the dynamic mask and sets
> up backward-compatible default mask values.
> 
> > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
> > index f9ec78d699f45..604d886e483c7 100644
> > --- a/drivers/mmc/host/renesas_sdhi_core.c
> > +++ b/drivers/mmc/host/renesas_sdhi_core.c
> [ ... ]
> > @@ -213,7 +213,7 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
> >  	 * provided for actual_clock in renesas_sdhi_clk_update().
> >  	 */
> >  	clk_margin = new_clock >> 10;
> > -	for (clk = 0x80000080; new_clock + clk_margin >= (clock << 1); clk >>= 1)
> > +	for (clk = host->pdata->clk_mask; new_clock + clk_margin >= (clock << 1); clk >>= 1)
> 
> [Severity: High]
> This isn't a bug introduced by this patch, but does this loop risk an
> infinite hang if the clock provider returns a very low rate?
> 
> In renesas_sdhi_set_clock(), if the clock provider supplies a rate smaller
> than the maximum divider, the division to calculate the initial clock value
> can evaluate to 0. Since 0 << 1 is still 0, the loop condition
> new_clock + clk_margin >= (clock << 1) will remain permanently true for any
> strictly positive new_clock value.
> 
> Could this prevent the loop from ever terminating, causing an unrecoverable
> CPU hang? Should there be an additional safety check (such as clk != 0 or
> clock > 0) added to the loop condition to gracefully handle misbehaving
> clock providers?
> 
> >  		clock <<= 1;
> >  
> >  	/* 1/1 clock is option */
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260820171657.62815-1-biju.das.jz@bp.renesas.com?part=3

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges
  2026-08-20 17:16 ` [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges Biju
@ 2026-09-02 11:05   ` Wolfram Sang
  2026-09-04 12:46     ` Biju Das
  0 siblings, 1 reply; 42+ messages in thread
From: Wolfram Sang @ 2026-09-02 11:05 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 1721 bytes --]


> v22->v23:
>  * Changed the data type of max_divider from unsigned int to signed int.

You changed this because of a Sashiko report. While the report was
correct, I think the solution of simply using 'int' is suboptimal...

> -	mmc->f_min = max(clk_round_rate(priv->clk, 1) / 512, 1L);
> +	mmc->f_min = max(clk_round_rate(priv->clk, 1) / host->pdata->max_divider, 1L);

... because the existing code is just too subtle / fragile and hard to
understand. I think we should move clk_round_rate() out of max() and
handle it seperatly before. What do you think?

>  	 * greater than, new_clock.  As we can divide by 1 << i for
> -	 * any i in [0, 9] we want the input clock to be as close as
> +	 * any i in [0, {9,11}] we want the input clock to be as close as

Maybe instead of "{9,11}" use "ilog2(max_divider)" or something? This
matches the code and is more future-proof if the divider gets extended
again.

> diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> index c6db0418de15..2bf354331b2d 100644
> --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> @@ -102,6 +102,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
>  	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
>  	.max_segs	= 1,
>  	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
> +	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,

Same comment as for clk_mask, I would not initialize to the default
value.

> @@ -62,5 +62,6 @@ struct tmio_mmc_data {
>  	unsigned int			max_blk_count;
>  	unsigned short			max_segs;
>  	u64				clk_mask;
> +	int				max_divider;

I hope that moving clk_round_rate() out of max() will allow 'unsigned
int' here again.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 05/15] mmc: renesas_sdhi: Add SDHI_SD_CLK_CTL_DIV1 macro for 1/1 option
  2026-08-20 17:16 ` [PATCH v24 05/15] mmc: renesas_sdhi: Add SDHI_SD_CLK_CTL_DIV1 macro for 1/1 option Biju
@ 2026-09-02 11:06   ` Wolfram Sang
  0 siblings, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-02 11:06 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 561 bytes --]

On Thu, Aug 20, 2026 at 06:16:35PM +0100, Biju wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
> 
> Replace the magic number 0xff, used for selecting the SD clock 1/1
> divider option, with a new SDHI_SD_CLK_CTL_DIV1 macro. This improves
> readability and self-documents the purpose of the value at each use
> site (setting/clearing the divider bits and comparing against
> CLK_CTL_DIV_MASK).
> 
> No functional change.
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>

Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable
  2026-08-20 17:16 ` [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable Biju
@ 2026-09-02 11:09   ` Wolfram Sang
  2026-09-04 12:48     ` Biju Das
  0 siblings, 1 reply; 42+ messages in thread
From: Wolfram Sang @ 2026-09-02 11:09 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 237 bytes --]


> @@ -103,6 +103,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
>  	.max_segs	= 1,
>  	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
>  	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
> +	.clk_div_mask	= CLK_CTL_DIV_MASK,

No defaults?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
  2026-08-20 17:16 ` [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L Biju
@ 2026-09-03  9:30   ` Wolfram Sang
  2026-09-04 14:47     ` Biju Das
  2026-09-03  9:34   ` Wolfram Sang
  1 sibling, 1 reply; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03  9:30 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 2345 bytes --]


> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] The new function renesas_sdhi_set_hw_adjustment_delay() accesses SCC registers via sd_scc_write32() without checking if priv->scc_ctl is initialized.
> --
> 
> --- Patch [7]: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L ---
> commit 4e31e96fb980d0bb6400d3a60dfcc29dca208dcc
> Author: Biju Das <biju.das.jz@bp.renesas.com>
> 
> mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
> 
> This commit adds hardware adjustment delay support for RZ/G2L SoCs during
> signal-voltage switch. It introduces the TMIO_MMC_TUNING_DELAY flag and
> applies a delay by writing to SCC_TMPPORT2 based on the regulator voltage.
> 
> > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
> > --- a/drivers/mmc/host/renesas_sdhi_core.c
> > +++ b/drivers/mmc/host/renesas_sdhi_core.c
> [ ... ]
> > @@ -350,6 +316,55 @@ static inline void sd_scc_write32(struct tmio_mmc_host *host,
> >  	writel(val, priv->scc_ctl + (addr << host->bus_shift));
> >  }
> >  
> > +static void renesas_sdhi_set_hw_adjustment_delay(struct tmio_mmc_host *host)
> > +{
> > +	struct renesas_sdhi *priv = host_to_priv(host);
> > +
> > +	if (!(host->pdata->flags & TMIO_MMC_TUNING_DELAY))
> > +		return;
> > +
> > +	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330)
> > +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x0);
> > +	else
> > +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1);
> 
> [Severity: High]
> Is it possible for priv->scc_ctl to be NULL here?
> 
> If an incorrect device tree binding or a hardware fault causes the
> controller to report a version older than SDHI_VER_GEN2_SDR104,
> priv->scc_ctl might not be mapped during probe.
> 
> However, renesas_sdhi_start_signal_voltage_switch() is registered based
> on TMIO_MMC_MIN_RCAR2 and calls this new function, which writes directly
> to the SCC register via sd_scc_write32().
> 
> Could this cause a NULL pointer dereference during card insertion?

I agree. We should ensure in probe() that either

a) TMIO_MMC_TUNING_DELAY has a valid SCC or bail out otherwise

or

b) clear the TMIO_MMC_TUNING_DELAY flag if there is no SCC present

What do you think?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
  2026-08-20 17:16 ` [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L Biju
  2026-09-03  9:30   ` Wolfram Sang
@ 2026-09-03  9:34   ` Wolfram Sang
  2026-09-04 15:15     ` Biju Das
  1 sibling, 1 reply; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03  9:34 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 1008 bytes --]


This might be over-engineering a bit, but let's discuss:

> +static void renesas_sdhi_set_hw_adjustment_delay(struct tmio_mmc_host *host)

How about adding a 'bool force_clear' parameter here...

> +{
> +	struct renesas_sdhi *priv = host_to_priv(host);
> +
> +	if (!(host->pdata->flags & TMIO_MMC_TUNING_DELAY))
> +		return;
> +
> +	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330)

add '|| force_clear' here ...

> +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x0);
> +	else
> +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1);
> +}

...

> +	if ((host->pdata->flags & TMIO_MMC_TUNING_DELAY) && priv->tap_num == 8)
> +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0);

and simplify this to

	/* add comment why on tap_num == 8 */
	if (priv->tap_num == 8)
		renesas_sdhi_set_hw_adjustment_delay(host, true);

?

The other call to renesas_sdhi_set_hw_adjustment_delay needs the bool
parameter 'false' then, of course.

What do you think? Rest looks good.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag
  2026-08-20 17:16 ` [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag Biju
@ 2026-09-03  9:37   ` Wolfram Sang
  2026-09-03  9:43   ` Wolfram Sang
  1 sibling, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03  9:37 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 2319 bytes --]

> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] Fallback `f_max` and `f_min` initialization fails to account for the internal clock divider.
> --
> 
> --- Patch [8]: [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag ---
> commit c4a63c19303286f5b383bdabaa2a3f3827a8c5c5
> Author: Biju Das <biju.das.jz@bp.renesas.com>
> 
> mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag
> 
> This commit introduces the TMIO_MMC_INTERNAL_DIVIDER flag to support SoCs
> like RZ/G3L that have a fixed internal /2 clock divider. It adds a helper
> function to fold this division into the reported clock rate and uses it in
> the clock update path.
> 
> > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
> > index ff428b6187bbd..b5f2ff68db758 100644
> > --- a/drivers/mmc/host/renesas_sdhi_core.c
> > +++ b/drivers/mmc/host/renesas_sdhi_core.c
> > @@ -125,6 +125,27 @@ static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host)
> >  	return 0;
> >  }
> >  
> 
> [Severity: Medium]
> Since this patch introduces an internal /2 clock divider, should
> renesas_sdhi_clk_enable() (which is just above this hunk) also be updated
> to account for it?
> 
> If the device tree omits the max-frequency property, f_max defaults to
> the raw parent clock rate:
> 
> drivers/mmc/host/renesas_sdhi_core.c:renesas_sdhi_clk_enable() {
>     ...
> 	if (!mmc->f_max)
> 		mmc->f_max = clk_get_rate(priv->clk);
> 
> 	/*
> 	 * Minimum frequency is the minimum input clock frequency
> 	 * divided by our maximum divider.
> 	 */
> 	mmc->f_min = max(clk_round_rate(priv->clk, 1) / host->pdata->max_divider, 1L);
>     ...
> }
> 
> For hardware with the internal divider, this advertises double the actual
> achievable bus frequency. If the clock provider cannot scale up to 4x the
> requested frequency, the MMC core might negotiate a high-speed mode that the
> hardware cannot satisfy, resulting in a mode mismatch where the bus silently
> runs at half the expected speed.
> 
> Could mmc->f_max and mmc->f_min calculation be adjusted when the
> TMIO_MMC_INTERNAL_DIVIDER flag is set?

Looks valid from a glimpse. Please comment if you think this report
makes sense or not.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag
  2026-08-20 17:16 ` [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag Biju
  2026-09-03  9:37   ` Wolfram Sang
@ 2026-09-03  9:43   ` Wolfram Sang
  1 sibling, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03  9:43 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 1159 bytes --]


> +static bool renesas_sdhi_is_internal_divider_enabled(struct tmio_mmc_host *host)
> +{
> +	bool enable = false;
> +
> +	if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
> +		enable = true;
> +
> +	return enable;
> +}
> +
> +static unsigned int renesas_sdhi_clk_get_rate(struct tmio_mmc_host *host,
> +					      struct clk *clk)
> +{
> +	unsigned int freq = clk_get_rate(clk);
> +
> +	if (renesas_sdhi_is_internal_divider_enabled(host))
> +		freq /= 2;
> +
> +	return freq;
> +}

???

static unsigned int renesas_sdhi_clk_get_rate(struct tmio_mmc_host *host,
					      struct clk *clk)
{
	unsigned int freq = clk_get_rate(clk);

	return host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER ? freq / 2 : freq;
}

Was this AI generated?

> @@ -184,10 +205,14 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
>  
>  	clk_set_rate(ref_clk, best_freq);
>  
> -	if (priv->clkh)
> +	if (priv->clkh) {
> +		if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
> +			clkh_shift = 1;

No, this needs to be handled a bit above where clkh_shift is initially
set up, so we have it all in one block.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 09/15] mmc: renesas_sdhi: Add optional axis/axim reset controls
  2026-08-20 17:16 ` [PATCH v24 09/15] mmc: renesas_sdhi: Add optional axis/axim reset controls Biju
@ 2026-09-03  9:48   ` Wolfram Sang
  0 siblings, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03  9:48 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Philipp Zabel, Biju Das, linux-mmc,
	linux-renesas-soc, linux-kernel, Geert Uytterhoeven,
	Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 943 bytes --]

On Thu, Aug 20, 2026 at 06:16:39PM +0100, Biju wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
> 
> The RZ/G3L SoC has axis/axim resets compared to other SoCs.
> 
> Add two optional reset controls, rstc_axis and rstc_axim, to the
> renesas_sdhi struct. Both are acquired at probe time using
> devm_reset_control_get_optional_exclusive_deasserted() with the
> "axis" and "axim" reset names respectively.
> 
> Include them alongside the existing rstc in bulk reset/assert/deassert
> operations: triggered together in renesas_sdhi_reset(), and managed
> via reset_control_bulk_assert/deassert() in the suspend and resume
> paths, replacing the previous single-control calls.
> 
> Being optional, these resets are a no-op on platforms that do not
> provide them, so existing behaviour is preserved.
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>

Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes
  2026-08-20 17:16 ` [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes Biju
@ 2026-09-03 10:30   ` Wolfram Sang
  2026-09-03 10:32   ` Wolfram Sang
  1 sibling, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03 10:30 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 1096 bytes --]

On Thu, Aug 20, 2026 at 06:16:40PM +0100, Biju wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
> 
> Add a write32_hook, analogous to the existing write16_hook, so that
> sd_ctrl_write32() can wait for the SD bus to become idle before
> certain 32-bit register writes.
> 
> renesas_sdhi_write32_hook() checks whether the target register is
> CTL_SD_CARD_CLK_CTL and, if so, waits for TMIO_STAT_SCLKDIVEN via
> renesas_sdhi_wait_idle() before the write proceeds. Other registers
> are unaffected. As with write16_hook, the write is skipped if the
> hook returns a non-zero error.

While technically correct, the commit message is totally not helpful
because it misses to say WHY the change is needed. It only says WHAT is
done but I can see that. G3L exceeds the 16-bit width, this is why we
need to change the code here. I know you use AI to assist with commit
messages but please keep a suspicious eye on the results.

> +	host->write32_hook = renesas_sdhi_write32_hook;

Have you checked that all SoCs handled by this driver support 32-bit
access to this register?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes
  2026-08-20 17:16 ` [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes Biju
  2026-09-03 10:30   ` Wolfram Sang
@ 2026-09-03 10:32   ` Wolfram Sang
  1 sibling, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03 10:32 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 1927 bytes --]

> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] tmio_mmc_host_probe() clears write16_hook when TMIO_MMC_HAS_IDLE_WAIT is not set, but fails to clear the newly added write32_hook.
> --
> 
> --- Patch [10]: [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes ---
> commit 57d55ff6257b421b4e27c4306c5ee441c02c3087
> Author: Biju Das <biju.das.jz@bp.renesas.com>
> 
> mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes
> 
> This patch introduces a write32_hook for the Renesas SDHI driver to wait
> for the SD bus to become idle before 32-bit writes to the
> CTL_SD_CARD_CLK_CTL register. Writes are skipped if the hook returns an
> error.
> 
> > diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
> > --- a/drivers/mmc/host/renesas_sdhi_core.c
> > +++ b/drivers/mmc/host/renesas_sdhi_core.c
> 
> [ ... ]
> 
> > @@ -1203,6 +1211,7 @@ int renesas_sdhi_probe(struct platform_device *pdev,
> >  	}
> >  
> >  	host->write16_hook = renesas_sdhi_write16_hook;
> > +	host->write32_hook = renesas_sdhi_write32_hook;
> 
> [Severity: High]
> Should write32_hook also be conditionally cleared in tmio_mmc_host_probe()
> when TMIO_MMC_HAS_IDLE_WAIT is missing?
> 
> Looking at drivers/mmc/host/tmio_mmc_core.c:tmio_mmc_host_probe(),
> write16_hook is actively cleared for devices without this flag:
> 
>         if (!(pdata->flags & TMIO_MMC_HAS_IDLE_WAIT))
>                 _host->write16_hook = NULL;
> 
> If write32_hook remains set on older or fallback configurations lacking this
> flag, polling for TMIO_STAT_SCLKDIVEN will time out after 1ms. 
> 
> The hook would then return -EBUSY, causing sd_ctrl_write32() to skip the
> register write entirely, which ultimately fails SD controller initialization.

Please check this, too.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 11/15] mmc: renesas_sdhi: Add RZ/G3L SDHI support
  2026-08-20 17:16 ` [PATCH v24 11/15] mmc: renesas_sdhi: Add RZ/G3L SDHI support Biju
@ 2026-09-03 12:01   ` Wolfram Sang
  0 siblings, 0 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03 12:01 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Biju Das, linux-mmc, linux-renesas-soc, linux-kernel,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 4023 bytes --]


Okay, let's start this one high level...

On Thu, Aug 20, 2026 at 06:16:41PM +0100, Biju wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
> 
> RZ/G3L (r9a08g046) has an SDHI controller that differs from existing
> platforms in clock divider width, a second HW adjustment register,
> and an extra tuning register.
> 
> Add TMIO_MMC_HWADJ to mark controllers with a second HWADJ2 register
> (offset 0x010), programmed by renesas_sdhi_set_hw_adjustment_delay()
> alongside TMPPORT2 (0x3FFF at 3.3V, 0xFF at 1.8V). Clear the new
> HWADJ4 register (0x022) at tuning start when TMIO_MMC_INTERNAL_DIVIDER
> is set.
> 
> Update renesas_sdhi_set_clock() to write the clock control register
> with a 32-bit access when max_divider isn't the default, moving bits
> [9:8] of the clock value into bits [17:16] of the register — needed
> to drive RZ/G3L's wider 11-bit divider field via the max_divider/
> clk_div_mask support added earlier in this series.
> 
> Add SDHI_VER_RZ_G3L_SDMMC (0xce10) and handle it in
> renesas_sdhi_sdbuf_width(). Add of_data_rzg3l with RZ/G3L's wider
> clk_mask, an 11-bit max_divider of 2048, a dedicated tap table, and
> the relevant flags including TMIO_MMC_INTERNAL_DIVIDER and
> TMIO_MMC_HWADJ. Wire it up via of_rzg3l_compatible (fixed_addr_mode
> quirk) and register the "renesas,sdhi-r9a08g046" compatible string.

After arriving at patch 11, I feel a significant loss in motivation to
read this patch description. It is very wordy, includes a lot of the
WHAT, hiding the WHY. Maybe you can adjust the prompt, but I would
suggest to write it yourself.

> -	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clock);
> +	if (host->pdata->max_divider != SDHI_MAX_DIVIDER_DEFAULT) {
> +		u64 tmp;
> +
> +		tmp = FIELD_GET(RZG3L_CLK_CTL_DIV9_DIV8_SRC, clk);
> +		clock |= FIELD_PREP(RZG3L_CLK_CTL_DIV9_DIV8, tmp);
> +		clock &= ~RZG3L_CLK_CTL_DIV9_DIV8_SRC;

I am confused. Bit 8+9 are always zero?

> -#define SH_MOBILE_SDHI_SCC_TMPPORT2	0x00E
> +#define SH_MOBILE_SDHI_SCC_TMPPORT2	0x00E /* G3L: SDm_SCC_HS400MODE1 */
> +#define RZG3L_SDHI_SCC_HWADJ2		0x010

Does RZG3L have a dedicated naming? I'd guess *_HWADJ1. I wonder if it
makes sense to have a dedicated define for it. I tend to think so.

> +		if (hwadj2)
> +			sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ2, 0x3FFF);
> +	} else {
>  		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1);
> +		if (hwadj2)
> +			sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ2, 0xFF);

Magic values?

>  	if (preserve) {
>  		card_opt = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT);
> -		clk_ctrl = sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL);
> +		if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
> +			clk_ctrl_32 = sd_ctrl_read32(host, CTL_SD_CARD_CLK_CTL);
> +		else
> +			clk_ctrl = sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL);
> +
>  		if (host->pdata->flags & TMIO_MMC_MIN_RCAR2)
>  			sdif_mode = sd_ctrl_read16(host, CTL_SDIF_MODE);
>  	}
> @@ -217,7 +222,11 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host, bool preserve)
>  
>  	if (preserve) {
>  		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, card_opt);
> -		sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk_ctrl);
> +		if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
> +			sd_ctrl_write32(host, CTL_SD_CARD_CLK_CTL, clk_ctrl_32);
> +		else
> +			sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk_ctrl);
> +

We should hide this complexity in a function, I'd say. To make sure
future updates modifying CTL_SD_CARD_CLK_CTL will have it easy.

> +/* Some controllers have hw adjustment delay */
> +#define TMIO_MMC_HWADJ			BIT(15)

I wonder how likely it is that a SDHI variant has either only this or
only TUNING_DELAY. Do you know of one? What would you think about
merging the two? You know the RZ SDHI much better...

I will stop reviewing at this patch. There are enough issues to tackle,
I'd think. Once we got this right, we can improve HS400 on top of it.

Makes sense to you?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support
  2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
                   ` (15 preceding siblings ...)
  2026-09-01 14:52 ` [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Wolfram Sang
@ 2026-09-03 20:11 ` Wolfram Sang
  2026-09-04  2:24   ` Biju Das
  2026-09-04  8:00   ` Geert Uytterhoeven
  16 siblings, 2 replies; 42+ messages in thread
From: Wolfram Sang @ 2026-09-03 20:11 UTC (permalink / raw)
  To: Biju
  Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Philipp Zabel, Magnus Damm, Biju Das,
	linux-mmc, devicetree, linux-kernel, linux-renesas-soc,
	Prabhakar Mahadev Lad

[-- Attachment #1: Type: text/plain, Size: 178 bytes --]


Although there are still issues to be handled, I tested this series on a
R-Car S4 (Spider) with HS400 eMMC and on a R-Car V4H (SparrowHawk) with
a UHS SD card. No regressions.


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support
  2026-09-03 20:11 ` Wolfram Sang
@ 2026-09-04  2:24   ` Biju Das
  2026-09-04  8:00   ` Geert Uytterhoeven
  1 sibling, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04  2:24 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Philipp Zabel, magnus.damm,
	linux-mmc@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	Prabhakar Mahadev Lad

Hi Wolfram Sang,

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 03 September 2026 21:12
> Subject: Re: [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support
> 
> 
> Although there are still issues to be handled, I tested this series on a R-Car S4 (Spider) with HS400
> eMMC and on a R-Car V4H (SparrowHawk) with a UHS SD card. No regressions.

Thanks for testing. I will start addressing the review comments today.

Cheers,
Biju


^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels
  2026-09-02 10:47   ` Wolfram Sang
@ 2026-09-04  6:40     ` Biju Das
  0 siblings, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04  6:40 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, linux-mmc@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

Hi Wolfram,

Thanks for the feedback.

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 02 September 2026 11:47

> Subject: Re: [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels
> 
> 
> >  static const struct renesas_sdhi_of_data of_default_cfg = {
> > -	.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
> > +	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
> >  };
> 
> This one gets worse, or?

I tried to align with the style (uniform tabs) used in this file for
of_rz_compatible and of_rcar_gen1_compatible.

Please let me know should we use single space separator or
uniform tab for of_default_cfg, of_rz_compatible and
of_rcar_gen1_compatible for uniformity among initializers??

Cheers,
Biju



^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support
  2026-09-03 20:11 ` Wolfram Sang
  2026-09-04  2:24   ` Biju Das
@ 2026-09-04  8:00   ` Geert Uytterhoeven
  1 sibling, 0 replies; 42+ messages in thread
From: Geert Uytterhoeven @ 2026-09-04  8:00 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Biju, Ulf Hansson, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Philipp Zabel, Magnus Damm, Biju Das,
	linux-mmc, devicetree, linux-kernel, linux-renesas-soc,
	Prabhakar Mahadev Lad

On Thu, 3 Sept 2026 at 22:11, Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
> Although there are still issues to be handled, I tested this series on a
> R-Car S4 (Spider) with HS400 eMMC and on a R-Car V4H (SparrowHawk) with
> a UHS SD card. No regressions.

FTR, boot-tested on a wide range of Renesas platforms (RZ/A1H, RZ/A2M,
R-Mobile A1, SH-Mobile AG5, R-Car Gen1-4, RZ/Five)
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths
  2026-09-02 10:51   ` Wolfram Sang
@ 2026-09-04 10:54     ` Biju Das
  0 siblings, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04 10:54 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, linux-mmc@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

Hi Wolfram,

Thanks for the feedback.

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 02 September 2026 11:51
> Subject: Re: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider
> widths
> 
> 
> > +#define SDHI_CLK_MASK_DEFAULT		0x80000080
> 
> ULL suffix maybe?

OK.

> 
> > @@ -101,6 +101,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
> >  	/* DMAC can handle 32bit blk count but only 1 segment */
> >  	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
> >  	.max_segs	= 1,
> > +	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
> 
> I'd vote to not initialize clk_mask when it uses the default value. We have code handling this case. This
> makes the instances having a non-default value more obvious, I'd say.

Agreed.

Cheers,
Biju


^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths
  2026-09-02 10:54   ` Wolfram Sang
@ 2026-09-04 11:03     ` Biju Das
  0 siblings, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04 11:03 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, linux-mmc@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

Hi Wolfram,


> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 02 September 2026 11:54
> Subject: Re: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider
> widths
> 
> Hi,
> 
> Sashiko found issues with your patch. I curated the list and left only those which I see as valid. Please
> have a look at these issues.

We need to discuss potential solution for this issue.

> 
> Thank you and happy hacking,
> 
>    Wolfram
> 
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> >
> > Pre-existing issues:
> > - [High] A very low or zero clock rate from the clock provider causes an infinite loop in
> `renesas_sdhi_set_clock`.
> > --
> >
> > --- Patch [3]: [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field
> > to support flexible clock divider widths --- commit
> > 1c7318b14c028686fc8ca703eb8ac2be269937b6
> > Author: Biju Das <biju.das.jz@bp.renesas.com>
> >
> > mmc: renesas_sdhi: Add clk_mask field to support flexible clock
> > divider widths
> >
> > This patch introduces a clk_mask field in platform data to replace a
> > hardcoded 32-bit clock mask, supporting 11-bit clock dividers on newer
> > SoCs like the RZ/G3L. It updates renesas_sdhi_set_clock() to use the
> > dynamic mask and sets up backward-compatible default mask values.
> >
> > > diff --git a/drivers/mmc/host/renesas_sdhi_core.c
> > > b/drivers/mmc/host/renesas_sdhi_core.c
> > > index f9ec78d699f45..604d886e483c7 100644
> > > --- a/drivers/mmc/host/renesas_sdhi_core.c
> > > +++ b/drivers/mmc/host/renesas_sdhi_core.c
> > [ ... ]
> > > @@ -213,7 +213,7 @@ static void renesas_sdhi_set_clock(struct tmio_mmc_host *host,
> > >  	 * provided for actual_clock in renesas_sdhi_clk_update().
> > >  	 */
> > >  	clk_margin = new_clock >> 10;
> > > -	for (clk = 0x80000080; new_clock + clk_margin >= (clock << 1); clk >>= 1)
> > > +	for (clk = host->pdata->clk_mask; new_clock + clk_margin >= (clock
> > > +<< 1); clk >>= 1)
> >
> > [Severity: High]
> > This isn't a bug introduced by this patch, but does this loop risk an
> > infinite hang if the clock provider returns a very low rate?
> >
> > In renesas_sdhi_set_clock(), if the clock provider supplies a rate
> > smaller than the maximum divider, the division to calculate the
> > initial clock value can evaluate to 0. Since 0 << 1 is still 0, the
> > loop condition new_clock + clk_margin >= (clock << 1) will remain
> > permanently true for any strictly positive new_clock value.


If (host->mmc->actual_clock < 512), we get clock=0.


In this case, shall we set divider to maximum and skip the loop?
So that clk runs with maximum allowable divider value.

Please share your thoughts on this.

Or

Do you have different solution, please let me know?

Cheers,
Biju


> >
> > Could this prevent the loop from ever terminating, causing an
> > unrecoverable CPU hang? Should there be an additional safety check
> > (such as clk != 0 or clock > 0) added to the loop condition to
> > gracefully handle misbehaving clock providers?
> >
> > >  		clock <<= 1;
> > >
> > >  	/* 1/1 clock is option */
> >
> > --
> > Sashiko AI review ·
> > https://sashiko.dev/#/patchset/20260820171657.62815-1-biju.das.jz@bp.r
> > enesas.com?part=3

^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges
  2026-09-02 11:05   ` Wolfram Sang
@ 2026-09-04 12:46     ` Biju Das
  0 siblings, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04 12:46 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, linux-mmc@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

Hi Wolfram,

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 02 September 2026 12:06
> Subject: Re: [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock
> ranges
> 
> 
> > v22->v23:
> >  * Changed the data type of max_divider from unsigned int to signed int.
> 
> You changed this because of a Sashiko report. While the report was correct, I think the solution of
> simply using 'int' is suboptimal...

Yes that is correct, based on Sashiko report I changed the data type.

> 
> > -	mmc->f_min = max(clk_round_rate(priv->clk, 1) / 512, 1L);
> > +	mmc->f_min = max(clk_round_rate(priv->clk, 1) /
> > +host->pdata->max_divider, 1L);
> 
> ... because the existing code is just too subtle / fragile and hard to understand. I think we should move
> clk_round_rate() out of max() and handle it seperatly before. What do you think?

You mean use, max(clk_get_rate(priv->clk) / 512, 1);

clk_get_rate() returns unsigned long compared to clk_round_rate() which return long??

> 
> >  	 * greater than, new_clock.  As we can divide by 1 << i for
> > -	 * any i in [0, 9] we want the input clock to be as close as
> > +	 * any i in [0, {9,11}] we want the input clock to be as close as
> 
> Maybe instead of "{9,11}" use "ilog2(max_divider)" or something? This matches the code and is more
> future-proof if the divider gets extended again.
OK.

> 
> > diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> > b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> > index c6db0418de15..2bf354331b2d 100644
> > --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> > +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> > @@ -102,6 +102,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
> >  	.max_blk_count	= UINT_MAX / TMIO_MAX_BLK_SIZE,
> >  	.max_segs	= 1,
> >  	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
> > +	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
> 
> Same comment as for clk_mask, I would not initialize to the default value.

Agreed will remove.

> 
> > @@ -62,5 +62,6 @@ struct tmio_mmc_data {
> >  	unsigned int			max_blk_count;
> >  	unsigned short			max_segs;
> >  	u64				clk_mask;
> > +	int				max_divider;
> 
> I hope that moving clk_round_rate() out of max() will allow 'unsigned int' here again.

By using clk_get_rate() I can still use unsigned int here.

Or

if you prefer to remove max() then the option is to use clk_round_rate(),
assign the value to 1 if It is 0 or negative.

Please let me know how to proceed.

Cheers,
Biju




^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable
  2026-09-02 11:09   ` Wolfram Sang
@ 2026-09-04 12:48     ` Biju Das
  0 siblings, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04 12:48 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, linux-mmc@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

Hi Wolfram,

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 02 September 2026 12:10
> <geert+renesas@glider.be>; Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Subject: Re: [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable
> 
> 
> > @@ -103,6 +103,7 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
> >  	.max_segs	= 1,
> >  	.clk_mask	= SDHI_CLK_MASK_DEFAULT,
> >  	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
> > +	.clk_div_mask	= CLK_CTL_DIV_MASK,
> 
> No defaults?

OK will remove this in next version.

Cheers,
Biju


^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
  2026-09-03  9:30   ` Wolfram Sang
@ 2026-09-04 14:47     ` Biju Das
  0 siblings, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04 14:47 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, linux-mmc@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

Hi Wolfram,

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 03 September 2026 10:30
> Subject: Re: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
> 
> 
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > - [High] The new function renesas_sdhi_set_hw_adjustment_delay() accesses SCC registers via
> sd_scc_write32() without checking if priv->scc_ctl is initialized.
> > --
> >
> > --- Patch [7]: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay
> > support for RZ/G2L --- commit 4e31e96fb980d0bb6400d3a60dfcc29dca208dcc
> > Author: Biju Das <biju.das.jz@bp.renesas.com>
> >
> > mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
> >
> > This commit adds hardware adjustment delay support for RZ/G2L SoCs
> > during signal-voltage switch. It introduces the TMIO_MMC_TUNING_DELAY
> > flag and applies a delay by writing to SCC_TMPPORT2 based on the regulator voltage.
> >
> > > diff --git a/drivers/mmc/host/renesas_sdhi_core.c
> > > b/drivers/mmc/host/renesas_sdhi_core.c
> > > --- a/drivers/mmc/host/renesas_sdhi_core.c
> > > +++ b/drivers/mmc/host/renesas_sdhi_core.c
> > [ ... ]
> > > @@ -350,6 +316,55 @@ static inline void sd_scc_write32(struct tmio_mmc_host *host,
> > >  	writel(val, priv->scc_ctl + (addr << host->bus_shift));  }
> > >
> > > +static void renesas_sdhi_set_hw_adjustment_delay(struct
> > > +tmio_mmc_host *host) {
> > > +	struct renesas_sdhi *priv = host_to_priv(host);
> > > +
> > > +	if (!(host->pdata->flags & TMIO_MMC_TUNING_DELAY))
> > > +		return;

This check is available only for RZ/G2L+ SoCs.

> > > +
> > > +	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330)
> > > +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x0);
> > > +	else
> > > +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1);
> >
> > [Severity: High]
> > Is it possible for priv->scc_ctl to be NULL here?

This issue can happen only if there is a severe memory corruption in the system during boot.

> >
> > If an incorrect device tree binding or a hardware fault causes the
> > controller to report a version older than SDHI_VER_GEN2_SDR104,
> > priv->scc_ctl might not be mapped during probe.

I agree if there is a memory corruption, any check can lead to
Unpredictable result.

> >
> > However, renesas_sdhi_start_signal_voltage_switch() is registered
> > based on TMIO_MMC_MIN_RCAR2 and calls this new function, which writes
> > directly to the SCC register via sd_scc_write32().
> >
> > Could this cause a NULL pointer dereference during card insertion?

This can happen only if there is a memory corruption, in that case the below check
passes for all the SoCs.

if (!(host->pdata->flags & TMIO_MMC_TUNING_DELAY))
		return;

> 
> I agree. We should ensure in probe() that either
> 
> a) TMIO_MMC_TUNING_DELAY has a valid SCC or bail out otherwise
> 
> or
> 
> b) clear the TMIO_MMC_TUNING_DELAY flag if there is no SCC present
> 
> What do you think?

I agree, we can add defensive check in probe().

TBH, I am not convinced with Sashiko report here, but please recheck my comments
and provide feedback

Or

I may be completely wrong, please correct me in that case.


Cheers,
Biju


^ permalink raw reply	[flat|nested] 42+ messages in thread

* RE: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
  2026-09-03  9:34   ` Wolfram Sang
@ 2026-09-04 15:15     ` Biju Das
  0 siblings, 0 replies; 42+ messages in thread
From: Biju Das @ 2026-09-04 15:15 UTC (permalink / raw)
  To: wsa+renesas, biju.das.au
  Cc: Ulf Hansson, linux-mmc@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Geert Uytterhoeven, Prabhakar Mahadev Lad

Hi Wolfram,

> -----Original Message-----
> From: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Sent: 03 September 2026 10:34
> Subject: Re: [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L
> 
> 
> This might be over-engineering a bit, but let's discuss:

Ok

> 
> > +static void renesas_sdhi_set_hw_adjustment_delay(struct tmio_mmc_host
> > +*host)
> 
> How about adding a 'bool force_clear' parameter here...

Ok.

> 
> > +{
> > +	struct renesas_sdhi *priv = host_to_priv(host);
> > +
> > +	if (!(host->pdata->flags & TMIO_MMC_TUNING_DELAY))
> > +		return;
> > +
> > +	if (host->mmc->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330)
> 
> add '|| force_clear' here ...

Ok.

> 
> > +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x0);
> > +	else
> > +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0x1); }
> 
> ...
> 
> > +	if ((host->pdata->flags & TMIO_MMC_TUNING_DELAY) && priv->tap_num == 8)
> > +		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2, 0);
> 
> and simplify this to
> 
> 	/* add comment why on tap_num == 8 */
> 	if (priv->tap_num == 8)
> 		renesas_sdhi_set_hw_adjustment_delay(host, true);

Ok.

> 
> ?
> 
> The other call to renesas_sdhi_set_hw_adjustment_delay needs the bool parameter 'false' then, of course.
> 
> What do you think? Rest looks good.

I agree, it simplifies the code.

Cheers,
Biju


^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2026-09-04 15:15 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 17:16 [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Biju
2026-08-20 17:16 ` [PATCH v24 01/15] dt-bindings: mmc: renesas,sdhi: Document RZ/G3L (r9a08g046) SoC Biju
2026-09-02 10:45   ` Wolfram Sang
2026-08-20 17:16 ` [PATCH v24 02/15] mmc: renesas_sdhi: Clean up whitespace and add OF table sentinels Biju
2026-09-02 10:47   ` Wolfram Sang
2026-09-04  6:40     ` Biju Das
2026-08-20 17:16 ` [PATCH v24 03/15] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths Biju
2026-09-02 10:51   ` Wolfram Sang
2026-09-04 10:54     ` Biju Das
2026-09-02 10:54   ` Wolfram Sang
2026-09-04 11:03     ` Biju Das
2026-08-20 17:16 ` [PATCH v24 04/15] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges Biju
2026-09-02 11:05   ` Wolfram Sang
2026-09-04 12:46     ` Biju Das
2026-08-20 17:16 ` [PATCH v24 05/15] mmc: renesas_sdhi: Add SDHI_SD_CLK_CTL_DIV1 macro for 1/1 option Biju
2026-09-02 11:06   ` Wolfram Sang
2026-08-20 17:16 ` [PATCH v24 06/15] mmc: renesas_sdhi: Make clock divider mask configurable Biju
2026-09-02 11:09   ` Wolfram Sang
2026-09-04 12:48     ` Biju Das
2026-08-20 17:16 ` [PATCH v24 07/15] mmc: renesas_sdhi: Add tuning delay support for RZ/G2L Biju
2026-09-03  9:30   ` Wolfram Sang
2026-09-04 14:47     ` Biju Das
2026-09-03  9:34   ` Wolfram Sang
2026-09-04 15:15     ` Biju Das
2026-08-20 17:16 ` [PATCH v24 08/15] mmc: renesas_sdhi: Add TMIO_MMC_INTERNAL_DIVIDER flag Biju
2026-09-03  9:37   ` Wolfram Sang
2026-09-03  9:43   ` Wolfram Sang
2026-08-20 17:16 ` [PATCH v24 09/15] mmc: renesas_sdhi: Add optional axis/axim reset controls Biju
2026-09-03  9:48   ` Wolfram Sang
2026-08-20 17:16 ` [PATCH v24 10/15] mmc: renesas_sdhi: Add write32_hook for CTL_SD_CARD_CLK_CTL register writes Biju
2026-09-03 10:30   ` Wolfram Sang
2026-09-03 10:32   ` Wolfram Sang
2026-08-20 17:16 ` [PATCH v24 11/15] mmc: renesas_sdhi: Add RZ/G3L SDHI support Biju
2026-09-03 12:01   ` Wolfram Sang
2026-08-20 17:16 ` [PATCH v24 12/15] mmc: renesas_sdhi: Save and restore IOVS across suspend/resume Biju
2026-08-20 17:16 ` [PATCH v24 13/15] mmc: renesas_sdhi: Make HS400 OSEL bit configurable per SoC Biju
2026-08-20 17:16 ` [PATCH v24 14/15] mmc: renesas_sdhi: Add RZ/G3L HS400 support Biju
2026-08-20 17:16 ` [PATCH v24 15/15] mmc: renesas_sdhi: Add HS400 enhanced strobe support for RZ/G3L Biju
2026-09-01 14:52 ` [PATCH v24 00/15] Add Renesas RZ/G3L SD/eMMC support Wolfram Sang
2026-09-03 20:11 ` Wolfram Sang
2026-09-04  2:24   ` Biju Das
2026-09-04  8:00   ` Geert Uytterhoeven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox