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