[PATCH v25 03/11] mmc: renesas_sdhi: Add clk_mask to support wider clock dividers
From: Biju Das
Date: Wed Oct 28 2026 - 08:51:58 EST
From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
The clock divider on the RZ/G3L SoC is 11 bits wide, which needs a
clock mask of 0x200000200 in renesas_sdhi_set_clock() instead of the
hardcoded 0x80000080 used so far.
Add a u64 clk_mask field to struct renesas_sdhi_of_data and struct
tmio_mmc_data so SoC-specific match data can supply its own mask, and
widen the clk and clock variables in renesas_sdhi_set_clock() from
u32 to u64 to hold it.
While at it, clamp the initial clock value to a minimum of 1. If
actual_clock / 512 evaluates to 0, the loop condition
"new_clock + clk_margin >= (clock << 1)" is always true, and the
loop never terminates.
In probe, copy clk_mask from the OF data and fall back to
SDHI_CLK_MASK_DEFAULT when none is provided, so existing
SoCs keep their current behaviour.
Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
---
v24->v25:
* Updated commit header and description.
* Dropped initializing clk_mask as it uses the default value.
* Added suffix ULL to macro SDHI_CLK_MASK_DEFAULT.
* Fixed a very low or zero clock rate from the clock provider that causes
an infinite loop in `renesas_sdhi_set_clock` by max operator.
v23->v24:
* No change.
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 | 10 +++++++---
include/linux/platform_data/tmio.h | 1 +
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index 09bf9b24a8c3..bfa626ea6bee 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 0x80000080ULL
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..495e58fa7728 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));
@@ -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 = max(host->mmc->actual_clock / 512, 1);
/*
* Add a margin of 1/1024 rate higher to the clock rate in order
@@ -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/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