[PATCH v23 04/14] mmc: renesas_sdhi: Add max_divider field to support SoC-specific clock ranges
Biju <[email protected]> Thu, 30 Jul 2026 12:31:42 +0100
| Newsgroups | org.kernel.vger.linux-mmc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc |
|---|---|
| Message-ID | <[email protected]> |
From: Biju Das <[email protected]> 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 <[email protected]> --- 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