[PATCH v23 03/14] mmc: renesas_sdhi: Add clk_mask field to support flexible clock divider widths
Biju <[email protected]> Thu, 30 Jul 2026 12:31:41 +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]> 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 <[email protected]> --- 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