RE: [PATCH v18 08/12] mmc: renesas_sdhi: Add RZ/G3L SDHI support

Biju Das <[email protected]>
Newsgroups org.kernel.vger.linux-renesas-soc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-mmc
Message-ID <TY3PR01MB11346F7E9B88B043978BAF1CE86F02@TY3PR01MB11346.jpnprd01.prod.outlook.com>
Hi Wolfram,

> -----Original Message-----
> From: Biju <[email protected]>
> Sent: 22 June 2026 16:56
> Subject: [PATCH v18 08/12] mmc: renesas_sdhi: Add RZ/G3L SDHI support
> 
> From: Biju Das <[email protected]>
> 
> The RZ/G3L SoC (r9a08g046) has an SDHI controller with several differences from existing platforms that
> require dedicated handling.
> 
> Introduce a TMIO_MMC_HWADJ2 flag (bit 15) to identify controllers that carry a second hardware adjustment
> register (SDm_SCC_HWADJ2 at offset 0x010). When both TMIO_MMC_TUNING_DELAY and TMIO_MMC_HWADJ2 are set,
> renesas_sdhi_set_hw_adjustment_delay() additionally programs
> HWADJ2 with 0x3FFF at 3.3 V and 0xFF at 1.8 V. A new
> RZG3L_SDHI_SCC_HWADJ4 register (offset 0x022) is also cleared at the start of tuning when
> TMIO_MMC_INTERNAL_DIVIDER is set.
> 
> Add a new version constant SDHI_VER_RZ_G3L_SDMMC (0xce10) and extend renesas_sdhi_sdbuf_width() to handle
> it alongside the existing
> Gen3 variants.
> 
> Introduce of_data_rzg3l with RZ/G3L-specific parameters: a wider clk_mask of 0x200000200, max_divider of
> 2048 (reflecting the 11-bit divider), a dedicated rzg3l_scc_taps table, and all relevant tmio_flags
> including TMIO_MMC_INTERNAL_DIVIDER and TMIO_MMC_HWADJ2. Wire it to a new of_rzg3l_compatible entry using
> sdhi_quirks_rzg3l (which sets fixed_addr_mode) and register the
> renesas,sdhi-r9a08g046 compatible string in the OF match table.
> 
> Signed-off-by: Biju Das <[email protected]>
> ---
> v18:
>  * New patch.
> ---
>  drivers/mmc/host/renesas_sdhi_core.c          | 20 ++++++++--
>  drivers/mmc/host/renesas_sdhi_internal_dmac.c | 37 +++++++++++++++++++
>  include/linux/platform_data/tmio.h            |  3 ++
>  3 files changed, 57 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c
> index f3ce29cb3053..8e14ce3ca7ba 100644
> --- a/drivers/mmc/host/renesas_sdhi_core.c
> +++ b/drivers/mmc/host/renesas_sdhi_core.c
> @@ -59,6 +59,7 @@
>  #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
> 
> @@ -79,6 +80,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)
> @@ -264,12 +266,15 @@ 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_TMPPORT2	0x00E  /* G3L: SDm_SCC_HWADJ3 */

As sashiko pointed out[1]

This duplicate definition is wrong.

[1] https://sashiko.dev/#/patchset/20260622155610.184271-1-biju.das.jz%40bp.renesas.com




>  #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
> @@ -319,14 +324,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_HWADJ2;
> 
>  	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, @@ -392,6 +403,9 @@ 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);
> 
> +	if (host->pdata->flags & TMIO_MMC_INTERNAL_DIVIDER)
> +		sd_scc_write32(host, priv, RZG3L_SDHI_SCC_HWADJ4, 0x0);
> +

As sashiko pointed out, will introduce a new scc related feature flag.

Cheers,
Biju

>  	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 93219706a4d6..9cb69003ac96 100644
> --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
> @@ -89,6 +89,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,
> @@ -162,6 +169,26 @@ static const struct renesas_sdhi_of_data of_data_rz_g2l = {
>  	.max_divider	= SDHI_MAX_DIVIDER_DEFAULT,
>  };
> 
> +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_HWADJ2,
> +	.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,
> +};
> +
>  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 }, @@ -242,6 +269,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 @@ -301,6 +332,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, }, @@ -314,6 +350,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/include/linux/platform_data/tmio.h b/include/linux/platform_data/tmio.h
> index 6c512e96e192..96eff17179cc 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_HWADJ2			BIT(15)
> +
>  struct tmio_mmc_data {
>  	void				*chan_priv_tx;
>  	void				*chan_priv_rx;
> --
> 2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.