[PATCH v4 2/5] clk: renesas: cpg-mssr: Implement dedicated MSTP delay logic for RZ/T2H LCDC and RTC

From: Prabhakar

Date: Thu Jun 18 2026 - 14:20:06 EST


From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>

Introduce a dedicated clock delay mechanism, cpg_rzt2h_mstp_delay(), to
satisfy the module-stop (MSTP) state release requirements specified in
the RZ/T2H hardware manual.

Per the hardware manual, while a standard 10 us delay (satisfying 7 dummy
reads) is sufficient for most IP blocks, the LCDC requires 100 dummy reads
(142 us) and the RTC requires 300 dummy reads (428 us) to stabilize after
being released from a module-stop state.

Implement a conditional bitmask filter helper that switches wait
intervals based on the packaged module clock index. In
cpg_mstp_clock_endisable(), the clock index and individual target bits are
known, allowing an exact match. In the resume path cpg_mssr_resume_noirq(),
where individual bits are not tracked, pass a fallback register index base
(`reg * 32`) with bit verification masked out to match on the peripheral's
register group block instead.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
---
v3->v4:
- Added RB tag from Geert.

v2->v3:
- No change

v1->v2:
- Dropped using table based approach in favor of direct conditional checks on the clock index.
- Updated commit message to reflect the new approach.
---
drivers/clk/renesas/renesas-cpg-mssr.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index 5b84cbee030b..4ed056b18d31 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -253,6 +253,22 @@ static void cpg_rzt2h_mstp_write(struct cpg_mssr_priv *priv, u16 offset, u32 val
writel(value, base + RZT2H_MSTPCR_OFFSET(offset));
}

+static void cpg_rzt2h_mstp_delay(u32 idx, bool bit_valid)
+{
+ unsigned int mask = bit_valid ? GENMASK(31, 0) : GENMASK(31, 5);
+
+ if (idx == (MOD_CLK_PACK(1204) & mask)) {
+ /* LCDC needs 100 dummy reads, or 142us */
+ udelay(142);
+ } else if (idx == (MOD_CLK_PACK(605) & mask)) {
+ /* RTC needs 300 dummy reads, or 428us */
+ udelay(428);
+ } else {
+ /* default 7 dummy reads, or 10us */
+ udelay(10);
+ }
+}
+
static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
{
struct mstp_clock *clock = to_mstp_clock(hw);
@@ -312,7 +328,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
* register, we simply add a delay after the read operation.
*/
cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
- udelay(10);
+ cpg_rzt2h_mstp_delay(clock->index, true);
return 0;
}

@@ -1142,7 +1158,7 @@ static int cpg_mssr_resume_noirq(struct device *dev)
cpg_rzt2h_mstp_write(priv, priv->control_regs[reg], newval);
/* See cpg_mstp_clock_endisable() on why this is necessary. */
cpg_rzt2h_mstp_read(priv, priv->control_regs[reg]);
- udelay(10);
+ cpg_rzt2h_mstp_delay(reg * 32, false);
continue;
} else
writel(newval, priv->pub.base0 + priv->control_regs[reg]);
--
2.54.0