RE: [PATCH v19 04/12] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges

Biju Das <[email protected]> Fri, 10 Jul 2026 08:36:52 +0000
Newsgroups org.kernel.vger.linux-mmc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc
Message-ID <TY3PR01MB113463ED102C262BEA039BEF086FD2@TY3PR01MB11346.jpnprd01.prod.outlook.com>
Hi All,

> -----Original Message-----
> From: Biju <[email protected]>
> Sent: 09 July 2026 20:29
> Subject: [PATCH v19 04/12] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges
> 
> From: Biju Das <[email protected]>
> 
> The clock hardware on the RZ/G3L SoC supports a broader clock divider range extending beyond the
> historically hardcoded value of 512.
> This requires a flexible mechanism to pass SoC-specific divider boundaries down to the core clock
> management logic.
> 
> Introduce a max_divider field to both struct renesas_sdhi_of_data and struct tmio_mmc_data. Replace the
> static 512 constants inside the core functions renesas_sdhi_clk_enable(), renesas_sdhi_clk_update(), and
> renesas_sdhi_set_clock() with the dynamically supplied field.
> 
> To preserve backward compatibility with existing hardware variants, implement a probe-time fallback
> mechanism that defaults to SDHI_MAX_DIVIDER_DEFAULT (512) if no explicit constraint value is assigned by
> platform data.
> 
> Finally, explicitly populate max_divider with the legacy default across all current internal and system
> DMAC configuration profiles, in preparation for the upcoming RZ/G3L extended divider support.
> 
> Signed-off-by: Biju Das <[email protected]>
> ---
> 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..438b2a7afe76 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;
> +	unsigned 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 1787f91d1ff2..5c478995d660 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 */
> @@ -1148,6 +1149,9 @@ int renesas_sdhi_probe(struct platform_device *pdev,
>  	if (mmd && !mmd->clk_mask)
>  		mmd->clk_mask = SDHI_CLK_MASK_DEFAULT;
> 
> +	if (mmd && !mmd->max_divider)
> +		mmd->max_divider = SDHI_MAX_DIVIDER_DEFAULT;
> +

As sashiko [1], pointed out "renesas,sdhi-shmobile" lacks device data,
Ao will add similar fix like previous patch.

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

Cheers,
Biju

>  	host->write16_hook = renesas_sdhi_write16_hook;
>  	host->clk_enable = renesas_sdhi_clk_enable;
>  	host->clk_disable = renesas_sdhi_clk_disable; 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..27ea21c00419 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;
> +	unsigned int			max_divider;
>  };
>  #endif
> --
> 2.43.0