From c4a16f90797e2d8bebf875fd02547fef76ae3b76 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 15 Jun 2026 11:48:43 +0100 Subject: [PATCH 01/15] dt-bindings: clock: renesas,r9a09g077/87: Add LCDC_CLKD clock ID Add the LCDC clockd (LCDC_CLKD) definition for the Renesas RZ/T2H (R9A09G077) and RZ/N2H (R9A09G087) SoCs. LCDC_CLKD is used as the operating clock for LCDC. Signed-off-by: Lad Prabhakar Acked-by: Conor Dooley Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260615104845.4122868-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h | 1 + include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h | 1 + 2 files changed, 2 insertions(+) diff --git a/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h b/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h index c4863e444458..f6cb8d649a46 100644 --- a/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h +++ b/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h @@ -34,5 +34,6 @@ #define R9A09G077_XSPI_CLK0 22 #define R9A09G077_XSPI_CLK1 23 #define R9A09G077_PCLKCAN 24 +#define R9A09G077_LCDC_CLKD 25 #endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G077_CPG_H__ */ diff --git a/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h b/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h index 0d53f1e65077..312e563b322e 100644 --- a/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h +++ b/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h @@ -34,5 +34,6 @@ #define R9A09G087_XSPI_CLK0 22 #define R9A09G087_XSPI_CLK1 23 #define R9A09G087_PCLKCAN 24 +#define R9A09G087_LCDC_CLKD 25 #endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G087_CPG_H__ */ From 2b005b458f6eeffdbe7705e6667437013b54e209 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 15 Jun 2026 15:39:42 +0100 Subject: [PATCH 02/15] dt-bindings: clock: renesas,r9a09g077/87: Add PCLKRTC clock ID Add the peripheral clock ID definition for the Real-Time Clock (PCLKRTC) on the Renesas RZ/T2H (R9A09G077) and RZ/N2H (R9A09G087) SoCs. Note that the PCLKRTC clock is utilized as the operating clock source for the RTC IP. Signed-off-by: Lad Prabhakar Acked-by: Conor Dooley Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260615143943.1610095-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h | 1 + include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h | 1 + 2 files changed, 2 insertions(+) diff --git a/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h b/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h index f6cb8d649a46..aa47685f329a 100644 --- a/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h +++ b/include/dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h @@ -35,5 +35,6 @@ #define R9A09G077_XSPI_CLK1 23 #define R9A09G077_PCLKCAN 24 #define R9A09G077_LCDC_CLKD 25 +#define R9A09G077_PCLKRTC 26 #endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G077_CPG_H__ */ diff --git a/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h b/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h index 312e563b322e..1c73d0dcef18 100644 --- a/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h +++ b/include/dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h @@ -35,5 +35,6 @@ #define R9A09G087_XSPI_CLK1 23 #define R9A09G087_PCLKCAN 24 #define R9A09G087_LCDC_CLKD 25 +#define R9A09G087_PCLKRTC 26 #endif /* __DT_BINDINGS_CLOCK_RENESAS_R9A09G087_CPG_H__ */ From c67b3c631a1bc02dba2c93bcb75eda54b607eae6 Mon Sep 17 00:00:00 2001 From: John Madieu Date: Mon, 25 May 2026 11:05:56 +0000 Subject: [PATCH 03/15] dt-bindings: clock: renesas: Add audio clock inputs for RZ/V2H family RZ/V2H, RZ/V2N, and RZ/G3E support two optional external audio clock inputs (AUDIO_CLKB and AUDIO_CLKC) that can be used by the Audio Clock Generator (ADG) to derive internal audio clocks. The third ADG input (AUDIO_CLKA) is fed internally by the AUDIO_EXTAL pin and does not need a separate binding entry. Update the bindings to allow these optional clocks for all RZ/V2H family SoCs. Signed-off-by: John Madieu Reviewed-by: Geert Uytterhoeven Acked-by: Conor Dooley Link: https://patch.msgid.link/20260525110603.4018170-2-john.madieu.xa@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../devicetree/bindings/clock/renesas,rzv2h-cpg.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/renesas,rzv2h-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,rzv2h-cpg.yaml index f261445bf341..dd3e66a4559b 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rzv2h-cpg.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,rzv2h-cpg.yaml @@ -26,16 +26,22 @@ properties: maxItems: 1 clocks: + minItems: 3 items: - description: AUDIO_EXTAL clock input - description: RTXIN clock input - description: QEXTAL clock input + - description: AUDIO_CLKB clock input + - description: AUDIO_CLKC clock input clock-names: + minItems: 3 items: - const: audio_extal - const: rtxin - const: qextal + - const: audio_clkb + - const: audio_clkc '#clock-cells': description: | From 7774d5b240e9e1d35775e7a4f58473cf77b25798 Mon Sep 17 00:00:00 2001 From: John Madieu Date: Mon, 25 May 2026 11:05:57 +0000 Subject: [PATCH 04/15] clk: renesas: r9a09g047: Add audio clock and reset support Add clock and reset entries for audio-related modules on the RZ/G3E SoC. Target modules are: - SSIU (Serial Sound Interface Unit) with SSI ch0-ch9, - SCU (Sampling Rate Converter Unit) with SRC ch0-ch9, DVC ch0-ch1, CTU/MIX ch0-ch1, - DMACpp (Audio DMA Controller), - ADG (Audio Clock Generator) with divider input clocks and audio master clock outputs. The ADG SSI clock outputs (adg_ssi[0-9]_clk) are parented on CLK_PLLCLN_DIV8 as a deliberate simplification: the ADG dynamically muxes each output between adg_0_clk_195m and audio_clk[a,b,c] at runtime via ADG_AUDIO_CLK_SEL{0,1,2}, owned by the rsnd-adg driver. While at it, reorder plldty_div16 to group it with the other plldty fixed dividers. Signed-off-by: John Madieu Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260525110603.4018170-3-john.madieu.xa@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g047-cpg.c | 112 +++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g047-cpg.c b/drivers/clk/renesas/r9a09g047-cpg.c index 94158b6834e6..ab9feb5a33ea 100644 --- a/drivers/clk/renesas/r9a09g047-cpg.c +++ b/drivers/clk/renesas/r9a09g047-cpg.c @@ -23,6 +23,8 @@ enum clk_ids { CLK_AUDIO_EXTAL, CLK_RTXIN, CLK_QEXTAL, + CLK_AUDIO_CLKB, + CLK_AUDIO_CLKC, /* PLL Clocks */ CLK_PLLCM33, @@ -44,6 +46,7 @@ enum clk_ids { CLK_SMUX2_XSPI_CLK1, CLK_PLLCM33_XSPI, CLK_PLLCLN_DIV2, + CLK_PLLCLN_DIV4, CLK_PLLCLN_DIV8, CLK_PLLCLN_DIV16, CLK_PLLCLN_DIV20, @@ -159,6 +162,8 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = { DEF_INPUT("audio_extal", CLK_AUDIO_EXTAL), DEF_INPUT("rtxin", CLK_RTXIN), DEF_INPUT("qextal", CLK_QEXTAL), + DEF_INPUT("audio_clkb", CLK_AUDIO_CLKB), + DEF_INPUT("audio_clkc", CLK_AUDIO_CLKC), /* PLL Clocks */ DEF_FIXED(".pllcm33", CLK_PLLCM33, CLK_QEXTAL, 200, 3), @@ -183,6 +188,7 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = { DEF_CSDIV(".pllcm33_xspi", CLK_PLLCM33_XSPI, CLK_SMUX2_XSPI_CLK1, CSDIV0_DIVCTL3, dtable_2_16), DEF_FIXED(".pllcln_div2", CLK_PLLCLN_DIV2, CLK_PLLCLN, 1, 2), + DEF_FIXED(".pllcln_div4", CLK_PLLCLN_DIV4, CLK_PLLCLN, 1, 4), DEF_FIXED(".pllcln_div8", CLK_PLLCLN_DIV8, CLK_PLLCLN, 1, 8), DEF_FIXED(".pllcln_div16", CLK_PLLCLN_DIV16, CLK_PLLCLN, 1, 16), DEF_FIXED(".pllcln_div20", CLK_PLLCLN_DIV20, CLK_PLLCLN, 1, 20), @@ -194,6 +200,7 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = { DEF_FIXED(".plldty_acpu_div2", CLK_PLLDTY_ACPU_DIV2, CLK_PLLDTY_ACPU, 1, 2), DEF_FIXED(".plldty_acpu_div4", CLK_PLLDTY_ACPU_DIV4, CLK_PLLDTY_ACPU, 1, 4), DEF_FIXED(".plldty_div8", CLK_PLLDTY_DIV8, CLK_PLLDTY, 1, 8), + DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16), DEF_FIXED(".plleth_250_fix", CLK_PLLETH_DIV_250_FIX, CLK_PLLETH, 1, 4), DEF_FIXED(".plleth_125_fix", CLK_PLLETH_DIV_125_FIX, CLK_PLLETH_DIV_250_FIX, 1, 2), @@ -205,7 +212,6 @@ static const struct cpg_core_clk r9a09g047_core_clks[] __initconst = { DEF_SMUX(".smux2_gbe0_rxclk", CLK_SMUX2_GBE0_RXCLK, SSEL0_SELCTL3, smux2_gbe0_rxclk), DEF_SMUX(".smux2_gbe1_txclk", CLK_SMUX2_GBE1_TXCLK, SSEL1_SELCTL0, smux2_gbe1_txclk), DEF_SMUX(".smux2_gbe1_rxclk", CLK_SMUX2_GBE1_RXCLK, SSEL1_SELCTL1, smux2_gbe1_rxclk), - DEF_FIXED(".plldty_div16", CLK_PLLDTY_DIV16, CLK_PLLDTY, 1, 16), DEF_DDIV(".plldty_rcpu", CLK_PLLDTY_RCPU, CLK_PLLDTY, CDDIV3_DIVCTL2, dtable_2_64), DEF_FIXED(".plldty_rcpu_div4", CLK_PLLDTY_RCPU_DIV4, CLK_PLLDTY_RCPU, 1, 4), @@ -530,8 +536,98 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = { BUS_MSTOP(3, BIT(4))), DEF_MOD("ge3d_ace_clk", CLK_PLLDTY_ACPU_DIV2, 15, 2, 7, 18, BUS_MSTOP(3, BIT(4))), + DEF_MOD("ssif_0_clk", CLK_PLLCLN_DIV8, 15, 5, 7, 21, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("scu_0_clk", CLK_PLLCLN_DIV8, 15, 6, 7, 22, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("scu_0_clkx2", CLK_PLLCLN_DIV4, 15, 7, 7, 23, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("dmacpp_0_clk", CLK_PLLCLN_DIV8, 15, 8, 7, 24, + BUS_MSTOP(2, BIT(5))), + DEF_MOD("adg_0_clks1", CLK_PLLCLN_DIV8, 15, 9, 7, 25, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_0_clk_195m", CLK_PLLCLN_DIV8, 15, 10, 7, 26, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_0_audio_clka", CLK_AUDIO_EXTAL, 15, 11, 7, 27, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_0_audio_clkb", CLK_AUDIO_CLKB, 15, 12, 7, 28, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_0_audio_clkc", CLK_AUDIO_CLKC, 15, 13, 7, 29, + BUS_MSTOP(2, BIT(2))), DEF_MOD("tsu_1_pclk", CLK_QEXTAL, 16, 10, 8, 10, BUS_MSTOP(2, BIT(15))), + DEF_MOD("adg_ssi0_clk", CLK_PLLCLN_DIV8, 22, 0, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi1_clk", CLK_PLLCLN_DIV8, 22, 1, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi2_clk", CLK_PLLCLN_DIV8, 22, 2, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi3_clk", CLK_PLLCLN_DIV8, 22, 3, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi4_clk", CLK_PLLCLN_DIV8, 22, 4, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi5_clk", CLK_PLLCLN_DIV8, 22, 5, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi6_clk", CLK_PLLCLN_DIV8, 22, 6, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi7_clk", CLK_PLLCLN_DIV8, 22, 7, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi8_clk", CLK_PLLCLN_DIV8, 22, 8, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("adg_ssi9_clk", CLK_PLLCLN_DIV8, 22, 9, -1, -1, + BUS_MSTOP(2, BIT(2))), + DEF_MOD("dvc0_clk", CLK_PLLCLN_DIV8, 23, 0, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("dvc1_clk", CLK_PLLCLN_DIV8, 23, 1, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("ctu0_mix0_clk", CLK_PLLCLN_DIV8, 23, 2, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("ctu1_mix1_clk", CLK_PLLCLN_DIV8, 23, 3, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src0_clk", CLK_PLLCLN_DIV8, 23, 4, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src1_clk", CLK_PLLCLN_DIV8, 23, 5, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src2_clk", CLK_PLLCLN_DIV8, 23, 6, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src3_clk", CLK_PLLCLN_DIV8, 23, 7, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src4_clk", CLK_PLLCLN_DIV8, 23, 8, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src5_clk", CLK_PLLCLN_DIV8, 23, 9, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src6_clk", CLK_PLLCLN_DIV8, 23, 10, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src7_clk", CLK_PLLCLN_DIV8, 23, 11, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src8_clk", CLK_PLLCLN_DIV8, 23, 12, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("src9_clk", CLK_PLLCLN_DIV8, 23, 13, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("scu_supply_clk", CLK_PLLCLN_DIV8, 23, 14, -1, -1, + BUS_MSTOP(2, BIT(0) | BIT(1))), + DEF_MOD("ssiu_supply_clk", CLK_PLLCLN_DIV8, 24, 0, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi0_clk", CLK_PLLCLN_DIV8, 24, 1, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi1_clk", CLK_PLLCLN_DIV8, 24, 2, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi2_clk", CLK_PLLCLN_DIV8, 24, 3, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi3_clk", CLK_PLLCLN_DIV8, 24, 4, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi4_clk", CLK_PLLCLN_DIV8, 24, 5, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi5_clk", CLK_PLLCLN_DIV8, 24, 6, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi6_clk", CLK_PLLCLN_DIV8, 24, 7, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi7_clk", CLK_PLLCLN_DIV8, 24, 8, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi8_clk", CLK_PLLCLN_DIV8, 24, 9, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), + DEF_MOD("ssi9_clk", CLK_PLLCLN_DIV8, 24, 10, -1, -1, + BUS_MSTOP(2, BIT(3) | BIT(4))), DEF_MOD("dsi_0_vclk2", CLK_SMUX2_DSI1_CLK, 25, 0, 10, 21, BUS_MSTOP(9, BIT(15) | BIT(14))), DEF_MOD("lcdc_1_clk_a", CLK_PLLDTY_ACPU_DIV2, 26, 8, 10, 30, @@ -621,6 +717,20 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = { DEF_RST(13, 13, 6, 14), /* GE3D_RESETN */ DEF_RST(13, 14, 6, 15), /* GE3D_AXI_RESETN */ DEF_RST(13, 15, 6, 16), /* GE3D_ACE_RESETN */ + DEF_RST(14, 1, 6, 18), /* SSIF_0_ASYNC_RESET_SSI */ + DEF_RST(14, 2, 6, 19), /* SSIF_0_SYNC_RESET_SSI0 */ + DEF_RST(14, 3, 6, 20), /* SSIF_0_SYNC_RESET_SSI1 */ + DEF_RST(14, 4, 6, 21), /* SSIF_0_SYNC_RESET_SSI2 */ + DEF_RST(14, 5, 6, 22), /* SSIF_0_SYNC_RESET_SSI3 */ + DEF_RST(14, 6, 6, 23), /* SSIF_0_SYNC_RESET_SSI4 */ + DEF_RST(14, 7, 6, 24), /* SSIF_0_SYNC_RESET_SSI5 */ + DEF_RST(14, 8, 6, 25), /* SSIF_0_SYNC_RESET_SSI6 */ + DEF_RST(14, 9, 6, 26), /* SSIF_0_SYNC_RESET_SSI7 */ + DEF_RST(14, 10, 6, 27), /* SSIF_0_SYNC_RESET_SSI8 */ + DEF_RST(14, 11, 6, 28), /* SSIF_0_SYNC_RESET_SSI9 */ + DEF_RST(14, 12, 6, 29), /* SCU_0_RESET_SRU */ + DEF_RST(14, 13, 6, 30), /* DMACpp_0_ARST */ + DEF_RST(14, 14, 6, 31), /* ADG_0_RST_RESET_ADG */ DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */ DEF_RST(17, 14, 8, 15), /* LCDC_1_RESET_N */ }; From a1fa2f528c4b43db2772b26c0700b3f30ff28f38 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 3 Jun 2026 07:57:02 +0100 Subject: [PATCH 05/15] clk: renesas: r9a08g046: Add clock and reset entries for SDHI Add clock and reset entries for SDHI. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260603065731.93243-3-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a08g046-cpg.c | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/drivers/clk/renesas/r9a08g046-cpg.c b/drivers/clk/renesas/r9a08g046-cpg.c index a57638734ce7..272922b76e1e 100644 --- a/drivers/clk/renesas/r9a08g046-cpg.c +++ b/drivers/clk/renesas/r9a08g046-cpg.c @@ -17,10 +17,13 @@ /* RZ/G3L Specific registers. */ #define G3L_CPG_PL2_DDIV (0x204) #define G3L_CPG_PL3_DDIV (0x208) +#define G3L_CPG_SDHI_DDIV (0x218) #define G3L_CPG_CA55CORE_DDIV (0x234) #define G3L_CPG_RSCI_DDIV (0x238) #define G3L_CPG_RSPI_DDIV (0x23c) +#define G3L_CPG_SDHI_DSEL (0x244) #define G3L_CLKDIVSTATUS (0x280) +#define G3L_CLKSELSTATUS (0x284) #define G3L_CPG_ETH_SSEL (0x410) #define G3L_CPG_RSCI_SSEL (0x414) #define G3L_CPG_RSPI_SSEL (0x418) @@ -30,6 +33,9 @@ #define G3L_DIVPL2A DDIV_PACK(G3L_CPG_PL2_DDIV, 0, 2) #define G3L_DIVPL2B DDIV_PACK(G3L_CPG_PL2_DDIV, 4, 2) #define G3L_DIVPL3A DDIV_PACK(G3L_CPG_PL3_DDIV, 0, 2) +#define G3L_DIV_SDHI0 DDIV_PACK(G3L_CPG_SDHI_DDIV, 0, 2) +#define G3L_DIV_SDHI1 DDIV_PACK(G3L_CPG_SDHI_DDIV, 4, 2) +#define G3L_DIV_SDHI2 DDIV_PACK(G3L_CPG_SDHI_DDIV, 8, 2) #define G3L_DIV_CA55_CORE0 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 0, 3) #define G3L_DIV_CA55_CORE1 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 4, 3) #define G3L_DIV_CA55_CORE2 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 8, 3) @@ -61,8 +67,18 @@ #define G3L_DIV_RSPI0_STS DDIV_PACK(G3L_CLKDIVSTATUS, 20, 1) #define G3L_DIV_RSPI1_STS DDIV_PACK(G3L_CLKDIVSTATUS, 21, 1) #define G3L_DIV_RSPI2_STS DDIV_PACK(G3L_CLKDIVSTATUS, 22, 1) +#define G3L_DIV_SDHI0_STS DDIV_PACK(G3L_CLKDIVSTATUS, 24, 1) +#define G3L_DIV_SDHI1_STS DDIV_PACK(G3L_CLKDIVSTATUS, 25, 1) +#define G3L_DIV_SDHI2_STS DDIV_PACK(G3L_CLKDIVSTATUS, 26, 1) + +#define G3L_SEL_SDHI0_STS SEL_PLL_PACK(G3L_CLKSELSTATUS, 16, 1) +#define G3L_SEL_SDHI1_STS SEL_PLL_PACK(G3L_CLKSELSTATUS, 17, 1) +#define G3L_SEL_SDHI2_STS SEL_PLL_PACK(G3L_CLKSELSTATUS, 18, 1) /* RZ/G3L Specific clocks select. */ +#define G3L_SEL_SDHI0 SEL_PLL_PACK(G3L_CPG_SDHI_DSEL, 0, 2) +#define G3L_SEL_SDHI1 SEL_PLL_PACK(G3L_CPG_SDHI_DSEL, 4, 2) +#define G3L_SEL_SDHI2 SEL_PLL_PACK(G3L_CPG_SDHI_DSEL, 8, 2) #define G3L_SEL_ETH0_TX SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 0, 1) #define G3L_SEL_ETH0_RX SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 1, 1) #define G3L_SEL_ETH0_RM SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 2, 1) @@ -94,6 +110,7 @@ enum clk_ids { /* Internal Core Clocks */ CLK_PLL1, + CLK_PLL1_DIV2, CLK_PLL2, CLK_PLL2_DIV2, CLK_PLL2_DIV2_4, @@ -117,16 +134,29 @@ enum clk_ids { CLK_SEL_RSPI0, CLK_SEL_RSPI1, CLK_SEL_RSPI2, + CLK_SEL_SDHI0, + CLK_SEL_SDHI1, + CLK_SEL_SDHI2, CLK_ETH0_TR, CLK_ETH0_RM, CLK_ETH1_TR, CLK_ETH1_RM, + CLK_SD0_DIV2, + CLK_SD1_DIV2, + CLK_SD2_DIV2, /* Module Clocks */ MOD_CLK_BASE, }; /* Divider tables */ +static const struct clk_div_table dtable_1_4[] = { + { 0, 1 }, + { 1, 2 }, + { 2, 4 }, + { 0, 0 }, +}; + static const struct clk_div_table dtable_1_8[] = { { 0, 1 }, { 1, 2 }, @@ -190,11 +220,15 @@ static const char * const sel_eth1_tx[] = { ".div_eth1_tr", "eth1_txc_tx_clk" }; static const char * const sel_eth1_rx[] = { ".div_eth1_tr", "eth1_rxc_rx_clk" }; static const char * const sel_eth1_rm[] = { ".pll6_div10", "eth1_rxc_rx_clk" }; static const char * const sel_rsci_rspi[] = { ".pll2_div5", ".pll2_div6", ".pll2_div7", ".pll2_div2_4" }; +static const char * const sel_sdhi[] = { ".pll2_div2", ".pll1_div2", ".pll6", ".pll2_div6" }; static const char * const sel_eth0_clk_tx_i[] = { ".sel_eth0_tx", ".div_eth0_rm" }; static const char * const sel_eth0_clk_rx_i[] = { ".sel_eth0_rx", ".div_eth0_rm" }; static const char * const sel_eth1_clk_tx_i[] = { ".sel_eth1_tx", ".div_eth1_rm" }; static const char * const sel_eth1_clk_rx_i[] = { ".sel_eth1_rx", ".div_eth1_rm" }; +/* Mux clock indices tables. */ +static const u32 mtable_sd[] = { 0, 1, 2, 3 }; + static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -210,6 +244,7 @@ static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), DEF_G3L_PLL(".pll6", CLK_PLL6, CLK_EXTAL, CPG_PLL_CONF(0x50, 0), 500000000UL), + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 1, 2), DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), DEF_FIXED(".pll2_div2_4", CLK_PLL2_DIV2_4, CLK_PLL2_DIV2, 1, 4), DEF_FIXED(".pll2_div5", CLK_PLL2_DIV5, CLK_PLL2, 1, 5), @@ -217,6 +252,12 @@ static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { DEF_FIXED(".pll2_div7", CLK_PLL2_DIV7, CLK_PLL2, 1, 7), DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), DEF_FIXED(".pll6_div10", CLK_PLL6_DIV10, CLK_PLL6, 1, 10), + DEF_SD_MUX(".sel_sdhi0", CLK_SEL_SDHI0, G3L_SEL_SDHI0, G3L_SEL_SDHI0_STS, sel_sdhi, + mtable_sd, 0, NULL), + DEF_SD_MUX(".sel_sdhi1", CLK_SEL_SDHI1, G3L_SEL_SDHI1, G3L_SEL_SDHI1_STS, sel_sdhi, + mtable_sd, 0, NULL), + DEF_SD_MUX(".sel_sdhi2", CLK_SEL_SDHI2, G3L_SEL_SDHI2, G3L_SEL_SDHI2_STS, sel_sdhi, + mtable_sd, 0, NULL), DEF_MUX(".sel_rsci0", CLK_SEL_RSCI0, G3L_SEL_RSCI0, sel_rsci_rspi), DEF_MUX(".sel_rsci1", CLK_SEL_RSCI1, G3L_SEL_RSCI1, sel_rsci_rspi), DEF_MUX(".sel_rsci2", CLK_SEL_RSCI2, G3L_SEL_RSCI2, sel_rsci_rspi), @@ -264,6 +305,18 @@ static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { dtable_1_8, 0, 200000000UL, 0, NULL), DEF_G3S_DIV("P19", R9A08G046_CLK_P19, CLK_SEL_RSPI2, G3L_DIV_RSPI2, G3L_DIV_RSPI2_STS, dtable_1_8, 0, 200000000UL, 0, NULL), + DEF_G3S_DIV("SD0", R9A08G046_CLK_SD0, CLK_SEL_SDHI0, G3L_DIV_SDHI0, G3L_DIV_SDHI0_STS, + dtable_1_4, 800000000UL, 600000000UL, CLK_SET_RATE_PARENT, + rzg3s_cpg_div_clk_notifier), + DEF_G3S_DIV("SD1", R9A08G046_CLK_SD1, CLK_SEL_SDHI1, G3L_DIV_SDHI1, G3L_DIV_SDHI1_STS, + dtable_1_4, 800000000UL, 600000000UL, CLK_SET_RATE_PARENT, + rzg3s_cpg_div_clk_notifier), + DEF_G3S_DIV("SD2", R9A08G046_CLK_SD2, CLK_SEL_SDHI2, G3L_DIV_SDHI2, G3L_DIV_SDHI2_STS, + dtable_1_4, 800000000UL, 600000000UL, CLK_SET_RATE_PARENT, + rzg3s_cpg_div_clk_notifier), + DEF_FIXED(".sd0_div2", CLK_SD0_DIV2, R9A08G046_CLK_SD0, 1, 2), + DEF_FIXED(".sd1_div2", CLK_SD1_DIV2, R9A08G046_CLK_SD1, 1, 2), + DEF_FIXED(".sd2_div2", CLK_SD2_DIV2, R9A08G046_CLK_SD2, 1, 2), DEF_FIXED("HP", R9A08G046_CLK_HP, CLK_PLL6_DIV10, 1, 1), DEF_MUX_FLAGS("ETHTX01", R9A08G046_CLK_ETHTX01, G3L_SEL_ETH0_CLK_TX_I, sel_eth0_clk_tx_i, CLK_SET_RATE_PARENT), @@ -297,6 +350,36 @@ static const struct rzg2l_mod_clk r9a08g046_mod_clks[] = { MSTOP(BUS_REG0, BIT(0))), DEF_MOD("wdt0_clk", R9A08G046_WDT0_CLK, R9A08G046_OSCCLK, 0x548, 1, MSTOP(BUS_REG0, BIT(0))), + DEF_MOD("sdhi0_imclk", R9A08G046_SDHI0_IMCLK, CLK_SD0_DIV2, 0x554, 0, + MSTOP(BUS_PERI_COM, BIT(0))), + DEF_MOD("sdhi0_imclk2", R9A08G046_SDHI0_IMCLK2, CLK_SD0_DIV2, 0x554, 1, + MSTOP(BUS_PERI_COM, BIT(0))), + DEF_MOD("sdhi0_clk_hs", R9A08G046_SDHI0_CLK_HS, R9A08G046_CLK_SD0, 0x554, 2, + MSTOP(BUS_PERI_COM, BIT(0))), + DEF_MOD("sdhi0_iaclks", R9A08G046_SDHI0_IACLKS, R9A08G046_CLK_P1, 0x554, 3, + MSTOP(BUS_PERI_COM, BIT(0))), + DEF_MOD("sdhi0_iaclkm", R9A08G046_SDHI0_IACLKM, R9A08G046_CLK_P1, 0x554, 12, + MSTOP(BUS_PERI_COM, BIT(0))), + DEF_MOD("sdhi1_imclk", R9A08G046_SDHI1_IMCLK, CLK_SD1_DIV2, 0x554, 4, + MSTOP(BUS_PERI_COM, BIT(1))), + DEF_MOD("sdhi1_imclk2", R9A08G046_SDHI1_IMCLK2, CLK_SD1_DIV2, 0x554, 5, + MSTOP(BUS_PERI_COM, BIT(1))), + DEF_MOD("sdhi1_clk_hs", R9A08G046_SDHI1_CLK_HS, R9A08G046_CLK_SD1, 0x554, 6, + MSTOP(BUS_PERI_COM, BIT(1))), + DEF_MOD("sdhi1_iaclks", R9A08G046_SDHI1_IACLKS, R9A08G046_CLK_P1, 0x554, 7, + MSTOP(BUS_PERI_COM, BIT(1))), + DEF_MOD("sdhi1_iaclkm", R9A08G046_SDHI1_IACLKM, R9A08G046_CLK_P1, 0x554, 13, + MSTOP(BUS_PERI_COM, BIT(1))), + DEF_MOD("sdhi2_imclk", R9A08G046_SDHI2_IMCLK, CLK_SD2_DIV2, 0x554, 8, + MSTOP(BUS_PERI_COM, BIT(11))), + DEF_MOD("sdhi2_imclk2", R9A08G046_SDHI2_IMCLK2, CLK_SD2_DIV2, 0x554, 9, + MSTOP(BUS_PERI_COM, BIT(11))), + DEF_MOD("sdhi2_clk_hs", R9A08G046_SDHI2_CLK_HS, R9A08G046_CLK_SD2, 0x554, 10, + MSTOP(BUS_PERI_COM, BIT(11))), + DEF_MOD("sdhi2_iaclks", R9A08G046_SDHI2_IACLKS, R9A08G046_CLK_P1, 0x554, 11, + MSTOP(BUS_PERI_COM, BIT(11))), + DEF_MOD("sdhi2_iaclkm", R9A08G046_SDHI2_IACLKM, R9A08G046_CLK_P1, 0x554, 14, + MSTOP(BUS_PERI_COM, BIT(11))), DEF_MOD("ssi0_pclk2", R9A08G046_SSI0_PCLK2, R9A08G046_CLK_P0, 0x570, 0, MSTOP(BUS_MCPU1, BIT(10))), DEF_MOD("ssi0_pclk_sfr", R9A08G046_SSI0_PCLK_SFR, R9A08G046_CLK_P0, 0x570, 1, @@ -412,6 +495,15 @@ static const struct rzg2l_reset r9a08g046_resets[] = { DEF_RST(R9A08G046_DMAC_ARESETN, 0x82c, 0), DEF_RST(R9A08G046_DMAC_RST_ASYNC, 0x82c, 1), DEF_RST(R9A08G046_WDT0_PRESETN, 0x848, 0), + DEF_RST(R9A08G046_SDHI0_IXRST, 0x854, 0), + DEF_RST(R9A08G046_SDHI1_IXRST, 0x854, 1), + DEF_RST(R9A08G046_SDHI2_IXRST, 0x854, 2), + DEF_RST(R9A08G046_SDHI0_IXRSTAXIM, 0x854, 3), + DEF_RST(R9A08G046_SDHI0_IXRSTAXIS, 0x854, 4), + DEF_RST(R9A08G046_SDHI1_IXRSTAXIM, 0x854, 5), + DEF_RST(R9A08G046_SDHI1_IXRSTAXIS, 0x854, 6), + DEF_RST(R9A08G046_SDHI2_IXRSTAXIM, 0x854, 7), + DEF_RST(R9A08G046_SDHI2_IXRSTAXIS, 0x854, 8), DEF_RST(R9A08G046_SSI0_RST_M2_REG, 0x870, 0), DEF_RST(R9A08G046_SSI1_RST_M2_REG, 0x870, 1), DEF_RST(R9A08G046_SSI2_RST_M2_REG, 0x870, 2), From b63c613a140f2bd16f68cd23ea56ed5fa83698b8 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Thu, 4 Jun 2026 16:18:49 +0100 Subject: [PATCH 06/15] clk: renesas: r9a08g046: Add clock and reset entries for GE3D Add clock and reset entries for GE3D. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260604151855.307772-2-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a08g046-cpg.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/clk/renesas/r9a08g046-cpg.c b/drivers/clk/renesas/r9a08g046-cpg.c index 272922b76e1e..edc83a4104b2 100644 --- a/drivers/clk/renesas/r9a08g046-cpg.c +++ b/drivers/clk/renesas/r9a08g046-cpg.c @@ -18,12 +18,14 @@ #define G3L_CPG_PL2_DDIV (0x204) #define G3L_CPG_PL3_DDIV (0x208) #define G3L_CPG_SDHI_DDIV (0x218) +#define G3L_CPG_GE3D_DDIV (0x224) #define G3L_CPG_CA55CORE_DDIV (0x234) #define G3L_CPG_RSCI_DDIV (0x238) #define G3L_CPG_RSPI_DDIV (0x23c) #define G3L_CPG_SDHI_DSEL (0x244) #define G3L_CLKDIVSTATUS (0x280) #define G3L_CLKSELSTATUS (0x284) +#define G3L_CPG_GE3D_SSEL (0x40c) #define G3L_CPG_ETH_SSEL (0x410) #define G3L_CPG_RSCI_SSEL (0x414) #define G3L_CPG_RSPI_SSEL (0x418) @@ -36,6 +38,7 @@ #define G3L_DIV_SDHI0 DDIV_PACK(G3L_CPG_SDHI_DDIV, 0, 2) #define G3L_DIV_SDHI1 DDIV_PACK(G3L_CPG_SDHI_DDIV, 4, 2) #define G3L_DIV_SDHI2 DDIV_PACK(G3L_CPG_SDHI_DDIV, 8, 2) +#define G3L_DIV_GE3D DDIV_PACK(G3L_CPG_GE3D_DDIV, 0, 3) #define G3L_DIV_CA55_CORE0 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 0, 3) #define G3L_DIV_CA55_CORE1 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 4, 3) #define G3L_DIV_CA55_CORE2 DDIV_PACK(G3L_CPG_CA55CORE_DDIV, 8, 3) @@ -74,6 +77,7 @@ #define G3L_SEL_SDHI0_STS SEL_PLL_PACK(G3L_CLKSELSTATUS, 16, 1) #define G3L_SEL_SDHI1_STS SEL_PLL_PACK(G3L_CLKSELSTATUS, 17, 1) #define G3L_SEL_SDHI2_STS SEL_PLL_PACK(G3L_CLKSELSTATUS, 18, 1) +#define G3L_DIV_GE3D_STS DDIV_PACK(G3L_CLKDIVSTATUS, 27, 1) /* RZ/G3L Specific clocks select. */ #define G3L_SEL_SDHI0 SEL_PLL_PACK(G3L_CPG_SDHI_DSEL, 0, 2) @@ -89,6 +93,7 @@ #define G3L_SEL_ETH1_RM SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 10, 1) #define G3L_SEL_ETH1_CLK_TX_I SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 11, 1) #define G3L_SEL_ETH1_CLK_RX_I SEL_PLL_PACK(G3L_CPG_ETH_SSEL, 12, 1) +#define G3L_SEL_GE3D SEL_PLL_PACK(G3L_CPG_GE3D_SSEL, 0, 2) #define G3L_SEL_RSCI0 SEL_PLL_PACK(G3L_CPG_RSCI_SSEL, 0, 2) #define G3L_SEL_RSCI1 SEL_PLL_PACK(G3L_CPG_RSCI_SSEL, 2, 2) #define G3L_SEL_RSCI2 SEL_PLL_PACK(G3L_CPG_RSCI_SSEL, 4, 2) @@ -119,6 +124,8 @@ enum clk_ids { CLK_PLL2_DIV7, CLK_PLL3, CLK_PLL3_DIV2, + CLK_PLL3_DIV2_2, + CLK_PLL3_DIV3, CLK_PLL6, CLK_PLL6_DIV10, CLK_SEL_ETH0_TX, @@ -127,6 +134,7 @@ enum clk_ids { CLK_SEL_ETH1_TX, CLK_SEL_ETH1_RX, CLK_SEL_ETH1_RM, + CLK_SEL_GE3D, CLK_SEL_RSCI0, CLK_SEL_RSCI1, CLK_SEL_RSCI2, @@ -219,6 +227,7 @@ static const char * const sel_eth0_rm[] = { ".pll6_div10", "eth0_rxc_rx_clk" }; static const char * const sel_eth1_tx[] = { ".div_eth1_tr", "eth1_txc_tx_clk" }; static const char * const sel_eth1_rx[] = { ".div_eth1_tr", "eth1_rxc_rx_clk" }; static const char * const sel_eth1_rm[] = { ".pll6_div10", "eth1_rxc_rx_clk" }; +static const char * const sel_ge3d[] = { ".pll1_div2", ".pll3_div3", ".pll6", ".pll3_div2_2" }; static const char * const sel_rsci_rspi[] = { ".pll2_div5", ".pll2_div6", ".pll2_div7", ".pll2_div2_4" }; static const char * const sel_sdhi[] = { ".pll2_div2", ".pll1_div2", ".pll6", ".pll2_div6" }; static const char * const sel_eth0_clk_tx_i[] = { ".sel_eth0_tx", ".div_eth0_rm" }; @@ -251,6 +260,8 @@ static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { DEF_FIXED(".pll2_div6", CLK_PLL2_DIV6, CLK_PLL2, 1, 6), DEF_FIXED(".pll2_div7", CLK_PLL2_DIV7, CLK_PLL2, 1, 7), DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), + DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2), + DEF_FIXED(".pll3_div3", CLK_PLL3_DIV3, CLK_PLL3, 1, 3), DEF_FIXED(".pll6_div10", CLK_PLL6_DIV10, CLK_PLL6, 1, 10), DEF_SD_MUX(".sel_sdhi0", CLK_SEL_SDHI0, G3L_SEL_SDHI0, G3L_SEL_SDHI0_STS, sel_sdhi, mtable_sd, 0, NULL), @@ -258,6 +269,7 @@ static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { mtable_sd, 0, NULL), DEF_SD_MUX(".sel_sdhi2", CLK_SEL_SDHI2, G3L_SEL_SDHI2, G3L_SEL_SDHI2_STS, sel_sdhi, mtable_sd, 0, NULL), + DEF_MUX(".sel_ge3d", CLK_SEL_GE3D, G3L_SEL_GE3D, sel_ge3d), DEF_MUX(".sel_rsci0", CLK_SEL_RSCI0, G3L_SEL_RSCI0, sel_rsci_rspi), DEF_MUX(".sel_rsci1", CLK_SEL_RSCI1, G3L_SEL_RSCI1, sel_rsci_rspi), DEF_MUX(".sel_rsci2", CLK_SEL_RSCI2, G3L_SEL_RSCI2, sel_rsci_rspi), @@ -332,6 +344,8 @@ static const struct cpg_core_clk r9a08g046_core_clks[] __initconst = { DEF_FIXED("ETHRM1", R9A08G046_CLK_ETHRM1, CLK_SEL_ETH1_RM, 1, 1), DEF_FIXED("ETHTX12", R9A08G046_CLK_ETHTX12, CLK_SEL_ETH1_TX, 1, 1), DEF_FIXED("ETHRX12", R9A08G046_CLK_ETHRX12, CLK_SEL_ETH1_RX, 1, 1), + DEF_G3S_DIV("G", R9A08G046_CLK_G, CLK_SEL_GE3D, G3L_DIV_GE3D, G3L_DIV_GE3D_STS, + dtable_1_32, 0, 0, 0, NULL), DEF_FIXED("OSCCLK", R9A08G046_OSCCLK, CLK_EXTAL, 1, 1), }; @@ -380,6 +394,12 @@ static const struct rzg2l_mod_clk r9a08g046_mod_clks[] = { MSTOP(BUS_PERI_COM, BIT(11))), DEF_MOD("sdhi2_iaclkm", R9A08G046_SDHI2_IACLKM, R9A08G046_CLK_P1, 0x554, 14, MSTOP(BUS_PERI_COM, BIT(11))), + DEF_MOD("ge3d_clk", R9A08G046_GE3D_CLK, R9A08G046_CLK_G, 0x558, 0, + MSTOP(BUS_PERI_VIDEO, BIT(12))), + DEF_MOD("ge3d_axi_clk", R9A08G046_GE3D_AXI_CLK, R9A08G046_CLK_P1, 0x558, 1, + MSTOP(BUS_PERI_VIDEO, BIT(12))), + DEF_MOD("ge3d_ace_clk", R9A08G046_GE3D_ACE_CLK, R9A08G046_CLK_P1, 0x558, 2, + MSTOP(BUS_PERI_VIDEO, BIT(12))), DEF_MOD("ssi0_pclk2", R9A08G046_SSI0_PCLK2, R9A08G046_CLK_P0, 0x570, 0, MSTOP(BUS_MCPU1, BIT(10))), DEF_MOD("ssi0_pclk_sfr", R9A08G046_SSI0_PCLK_SFR, R9A08G046_CLK_P0, 0x570, 1, @@ -504,6 +524,9 @@ static const struct rzg2l_reset r9a08g046_resets[] = { DEF_RST(R9A08G046_SDHI1_IXRSTAXIS, 0x854, 6), DEF_RST(R9A08G046_SDHI2_IXRSTAXIM, 0x854, 7), DEF_RST(R9A08G046_SDHI2_IXRSTAXIS, 0x854, 8), + DEF_RST(R9A08G046_GE3D_RESETN, 0x858, 0), + DEF_RST(R9A08G046_GE3D_AXI_RESETN, 0x858, 1), + DEF_RST(R9A08G046_GE3D_ACE_RESETN, 0x858, 2), DEF_RST(R9A08G046_SSI0_RST_M2_REG, 0x870, 0), DEF_RST(R9A08G046_SSI1_RST_M2_REG, 0x870, 1), DEF_RST(R9A08G046_SSI2_RST_M2_REG, 0x870, 2), From 0a6643b1a5ee72f76ed0c606c1b34c7cf632cbfb Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 15 Jun 2026 11:48:42 +0100 Subject: [PATCH 07/15] clk: renesas: cpg-mssr: Implement dedicated MSTP delay logic for RZ/T2H LCDC and RTC 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 Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260615104845.4122868-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- 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]); From 182b03cbe80fea16c8a2f6faaf890e0d8ee0ba46 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 15 Jun 2026 15:39:43 +0100 Subject: [PATCH 08/15] clk: renesas: r9a09g077: Add RTC clocks Add the core and module clock definitions for the Real-Time Clock (RTC) peripheral on the Renesas RZ/T2H (R9A09G077) and RZ/N2H (R9A09G087) SoCs. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260615143943.1610095-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g077-cpg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index f777601a23b9..e8f760776c99 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -86,7 +86,7 @@ enum rzt2h_clk_types { enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R9A09G077_PCLKCAN, + LAST_DT_CORE_CLK = R9A09G077_PCLKRTC, /* External Input Clocks */ CLK_EXTAL, @@ -242,6 +242,7 @@ static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = { FSELXSPI1, dtable_6_8_16_32_64), DEF_MUX("PCLKCAN", R9A09G077_PCLKCAN, FSELCANFD, sel_clk_pll4d3_div10_div20, ARRAY_SIZE(sel_clk_pll4d3_div10_div20), 0), + DEF_FIXED("PCLKRTC", R9A09G077_PCLKRTC, CLK_EXTAL, 128, 1), }; static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { @@ -272,6 +273,7 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { DEF_MOD("sci5fck", 600, CLK_SCI5ASYNC), DEF_MOD("iic2", 601, R9A09G077_CLK_PCLKL), DEF_MOD("spi3", 602, CLK_SPI3ASYNC), + DEF_MOD("rtc", 605, R9A09G077_CLK_PCLKL), DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM), DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM), }; From 2bbc0f34ef0c056a98f0235fcd8b611e90de5592 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 16 Jun 2026 11:44:45 +0100 Subject: [PATCH 09/15] clk: renesas: r9a08g046: Add USB2.0 clock and reset entries Add module clock and reset definitions for the USB2.0 interfaces on the RZ/G3L (r9a08g046) SoC. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260616104459.410743-4-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a08g046-cpg.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clk/renesas/r9a08g046-cpg.c b/drivers/clk/renesas/r9a08g046-cpg.c index edc83a4104b2..4488bd1988e8 100644 --- a/drivers/clk/renesas/r9a08g046-cpg.c +++ b/drivers/clk/renesas/r9a08g046-cpg.c @@ -416,6 +416,16 @@ static const struct rzg2l_mod_clk r9a08g046_mod_clks[] = { MSTOP(BUS_MCPU1, BIT(13))), DEF_MOD("ssi3_pclk_sfr", R9A08G046_SSI3_PCLK_SFR, R9A08G046_CLK_P0, 0x570, 7, MSTOP(BUS_MCPU1, BIT(13))), + DEF_MOD("usb_u2h0_hclk", R9A08G046_USB_U2H0_HCLK, R9A08G046_CLK_P1, 0x578, 0, + MSTOP(BUS_PERI_COM, BIT(5))), + DEF_MOD("usb_u2h1_hclk", R9A08G046_USB_U2H1_HCLK, R9A08G046_CLK_P1, 0x578, 1, + MSTOP(BUS_PERI_COM, BIT(7))), + DEF_MOD("usb_u2p0_exr_cpuclk", R9A08G046_USB_U2P0_EXR_CPUCLK, R9A08G046_CLK_P1, 0x578, 2, + MSTOP(BUS_PERI_COM, BIT(6))), + DEF_MOD("usb_pclk", R9A08G046_USB_PCLK, R9A08G046_CLK_P1, 0x578, 3, + MSTOP(BUS_PERI_COM, BIT(4))), + DEF_MOD("usb_u2p1_exr_cpuclk", R9A08G046_USB_U2P1_EXR_CPUCLK, R9A08G046_CLK_P1, 0x578, 4, + MSTOP(BUS_PERI_COM, BIT(13))), DEF_MOD("eth0_clk_axi", R9A08G046_ETH0_CLK_AXI, R9A08G046_CLK_P1, 0x57c, 0, MSTOP(BUS_PERI_COM, BIT(2))), DEF_MOD("eth1_clk_axi", R9A08G046_ETH1_CLK_AXI, R9A08G046_CLK_P1, 0x57c, 1, @@ -531,6 +541,11 @@ static const struct rzg2l_reset r9a08g046_resets[] = { DEF_RST(R9A08G046_SSI1_RST_M2_REG, 0x870, 1), DEF_RST(R9A08G046_SSI2_RST_M2_REG, 0x870, 2), DEF_RST(R9A08G046_SSI3_RST_M2_REG, 0x870, 3), + DEF_RST(R9A08G046_USB_U2H0_HRESETN, 0x878, 0), + DEF_RST(R9A08G046_USB_U2H1_HRESETN, 0x878, 1), + DEF_RST(R9A08G046_USB_U2P0_EXL_SYSRST, 0x878, 2), + DEF_RST(R9A08G046_USB_PRESETN, 0x878, 3), + DEF_RST(R9A08G046_USB_U2P1_EXL_SYSRST, 0x878, 4), DEF_RST(R9A08G046_ETH0_ARESET_N, 0x87c, 0), DEF_RST(R9A08G046_ETH1_ARESET_N, 0x87c, 1), DEF_RST(R9A08G046_I2C0_MRST, 0x880, 0), From 4f4230ff5d0aec3a5f3b3d9bab39b3db13800a44 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 18 Jun 2026 19:19:45 +0100 Subject: [PATCH 10/15] clk: renesas: rzv2h-cpg: Use per-SoC PLL reference frequency for calculations Introduce a per-SoC PLL reference input frequency parameter to avoid relying on a hardcoded 24MHz constant during PLL configuration math. Add an input_fref member to struct rzv2h_pll_limits. In the core calculation helper rzv2h_get_pll_pars(), derive the base input clock rate from limits->input_fref, utilizing the conditional ternary operator to fall back to 24MHz if the struct field is left uninitialized (0), and drop the obsolete macro RZ_V2H_OSC_CLK_IN_MEGA. This abstraction permits the reuse of the common PLL divider logic on newer SoC platforms like the RZ/T2H, which feature a 48 MHz PLL reference clock input instead of the 24 MHz signal used by RZ/V2H(P), without disrupting existing platforms. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260618181949.3036280-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzv2h-cpg.c | 8 ++++---- include/linux/clk/renesas.h | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index e271c04cee34..fff89f2bdc0b 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -218,7 +218,6 @@ struct rzv2h_plldsi_div_clk { #define to_plldsi_div_clk(_hw) \ container_of(_hw, struct rzv2h_plldsi_div_clk, hw) -#define RZ_V2H_OSC_CLK_IN_MEGA (24 * MEGA) #define RZV2H_MAX_DIV_TABLES (16) /** @@ -242,6 +241,7 @@ struct rzv2h_plldsi_div_clk { bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, struct rzv2h_pll_pars *pars, u64 freq_millihz) { + unsigned long input_fref = limits->input_fref ?: (24 * MEGA); u64 fout_min_millihz = mul_u32_u32(limits->fout.min, MILLI); u64 fout_max_millihz = mul_u32_u32(limits->fout.max, MILLI); struct rzv2h_pll_pars p, best; @@ -254,7 +254,7 @@ bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, best.error_millihz = S64_MAX; for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) { - u32 fref = RZ_V2H_OSC_CLK_IN_MEGA / p.p; + u32 fref = input_fref / p.p; u16 divider; for (divider = 1 << limits->s.min, p.s = limits->s.min; @@ -335,9 +335,9 @@ bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, continue; /* PLL_M component of (output * 65536 * PLL_P) */ - output = mul_u32_u32(p.m * 65536, RZ_V2H_OSC_CLK_IN_MEGA); + output = mul_u32_u32(p.m * 65536, input_fref); /* PLL_K component of (output * 65536 * PLL_P) */ - output += p.k * RZ_V2H_OSC_CLK_IN_MEGA; + output += p.k * input_fref; /* Make it in mHz */ output *= MILLI; output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider); diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 0949400f44de..798bb0b54bab 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -53,6 +53,9 @@ static inline void rzg2l_cpg_dsi_div_set_divider(u8 divider, int target) { } * various parameters used to configure a PLL. These limits ensure * the PLL operates within valid and stable ranges. * + * @input_fref: Reference input frequency to the PLL (in Hz). If set + * to 0, a default value of 24MHz is used. + * * @fout: Output frequency range (in MHz) * @fout.min: Minimum allowed output frequency * @fout.max: Maximum allowed output frequency @@ -78,6 +81,8 @@ static inline void rzg2l_cpg_dsi_div_set_divider(u8 divider, int target) { } * @k.max: Maximum delta-sigma value */ struct rzv2h_pll_limits { + u32 input_fref; + struct { u32 min; u32 max; From 73c360100dec2ecb0e905ceb58a01df45fda8988 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 18 Jun 2026 19:19:48 +0100 Subject: [PATCH 11/15] clk: renesas: rzv2h-cpg: Extract PLL calculation helpers into shared library Move the RZ/V2H PLL and divider parameter calculation helpers from rzv2h-cpg.c into a new reusable library. Introduce the CLK_RZV2H_CPG_LIB Kconfig symbol and add rzv2h-cpg-lib.c to host the PLL parameter search algorithms currently implemented by rzv2h_get_pll_pars() and rzv2h_get_pll_divs_pars(). Export the helpers as rzv2h_cpg_get_pll_pars() and rzv2h_cpg_get_pll_divs_pars() for use by other drivers. Update the public clock header to expose the new interfaces and provide compatibility aliases for the existing helper names, avoiding build breakage for current users while allowing future conversions to the new API. This prepares for reuse of the PLL and divider calculation logic by other Renesas clock drivers, including upcoming RZ/T2H and RZ/N2H CPG support, without duplicating the implementation. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260618181949.3036280-5-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 4 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/rzv2h-cpg-lib.c | 217 ++++++++++++++++++++++++++++ drivers/clk/renesas/rzv2h-cpg.c | 203 -------------------------- include/linux/clk/renesas.h | 29 ++-- 5 files changed, 238 insertions(+), 216 deletions(-) create mode 100644 drivers/clk/renesas/rzv2h-cpg-lib.c diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 0203ecbb3882..7659550b8566 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -260,8 +260,12 @@ config CLK_RZG2L config CLK_RZV2H bool "RZ/{G3E,V2H(P)} family clock support" if COMPILE_TEST + select CLK_RZV2H_CPG_LIB select RESET_CONTROLLER +config CLK_RZV2H_CPG_LIB + bool "RZV2H CPG library functions" if COMPILE_TEST + config CLK_RENESAS_VBATTB tristate "Renesas VBATTB clock controller" depends on ARCH_RZG2L || COMPILE_TEST diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index bd2bed91ab29..ac790e56034b 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o obj-$(CONFIG_CLK_RCAR_GEN4_CPG) += rcar-gen4-cpg.o obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o +obj-$(CONFIG_CLK_RZV2H_CPG_LIB) += rzv2h-cpg-lib.o obj-$(CONFIG_CLK_RZV2H) += rzv2h-cpg.o # Generic diff --git a/drivers/clk/renesas/rzv2h-cpg-lib.c b/drivers/clk/renesas/rzv2h-cpg-lib.c new file mode 100644 index 000000000000..124239c7327e --- /dev/null +++ b/drivers/clk/renesas/rzv2h-cpg-lib.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZV2H CPG Library. This library provides common functions to calculate + * PLL parameters for the RZV2H SoC. + * + * Copyright (C) 2026 Renesas Electronics Corp. + * + */ + +#include +#include +#include +#include +#include + +/** + * rzv2h_cpg_get_pll_pars - Finds the best combination of PLL parameters + * for a given frequency. + * + * @limits: Pointer to the structure containing the limits for the PLL parameters + * @pars: Pointer to the structure where the best calculated PLL parameters values + * will be stored + * @freq_millihz: Target output frequency in millihertz + * + * This function calculates the best set of PLL parameters (M, K, P, S) to achieve + * the desired frequency. + * There is no direct formula to calculate the PLL parameters, as it's an open + * system of equations, therefore this function uses an iterative approach to + * determine the best solution. The best solution is one that minimizes the error + * (desired frequency - actual frequency). + * + * Return: true if a valid set of parameters values is found, false otherwise. + */ +bool rzv2h_cpg_get_pll_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_pars *pars, u64 freq_millihz) +{ + unsigned long input_fref = limits->input_fref ?: (24 * MEGA); + u64 fout_min_millihz = mul_u32_u32(limits->fout.min, MILLI); + u64 fout_max_millihz = mul_u32_u32(limits->fout.max, MILLI); + struct rzv2h_pll_pars p, best; + + if (freq_millihz > fout_max_millihz || + freq_millihz < fout_min_millihz) + return false; + + /* Initialize best error to maximum possible value */ + best.error_millihz = S64_MAX; + + for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) { + u32 fref = input_fref / p.p; + u16 divider; + + for (divider = 1 << limits->s.min, p.s = limits->s.min; + p.s <= limits->s.max; p.s++, divider <<= 1) { + for (p.m = limits->m.min; p.m <= limits->m.max; p.m++) { + u64 output_m, output_k_range; + s64 pll_k, output_k; + u64 fvco, output; + + /* + * The frequency generated by the PLL + divider + * is calculated as follows: + * + * With: + * Freq = Ffout = Ffvco / 2^(pll_s) + * Ffvco = (pll_m + (pll_k / 65536)) * Ffref + * Ffref = 24MHz / pll_p + * + * Freq can also be rewritten as: + * Freq = Ffvco / 2^(pll_s) + * = ((pll_m + (pll_k / 65536)) * Ffref) / 2^(pll_s) + * = (pll_m * Ffref) / 2^(pll_s) + ((pll_k / 65536) * Ffref) / 2^(pll_s) + * = output_m + output_k + * + * Every parameter has been determined at this + * point, but pll_k. + * + * Considering that: + * limits->k.min <= pll_k <= limits->k.max + * Then: + * -0.5 <= (pll_k / 65536) < 0.5 + * Therefore: + * -Ffref / (2 * 2^(pll_s)) <= output_k < Ffref / (2 * 2^(pll_s)) + */ + + /* Compute output M component (in mHz) */ + output_m = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(p.m, fref) * MILLI, + divider); + /* Compute range for output K (in mHz) */ + output_k_range = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(fref, MILLI), + 2 * divider); + /* + * No point in continuing if we can't achieve + * the desired frequency + */ + if (freq_millihz < (output_m - output_k_range) || + freq_millihz >= (output_m + output_k_range)) { + continue; + } + + /* + * Compute the K component + * + * Since: + * Freq = output_m + output_k + * Then: + * output_k = Freq - output_m + * = ((pll_k / 65536) * Ffref) / 2^(pll_s) + * Therefore: + * pll_k = (output_k * 65536 * 2^(pll_s)) / Ffref + */ + output_k = freq_millihz - output_m; + pll_k = div_s64(output_k * 65536ULL * divider, + fref); + pll_k = DIV_S64_ROUND_CLOSEST(pll_k, MILLI); + + /* Validate K value within allowed limits */ + if (pll_k < limits->k.min || + pll_k > limits->k.max) + continue; + + p.k = pll_k; + + /* Compute (Ffvco * 65536) */ + fvco = mul_u32_u32(p.m * 65536 + p.k, fref); + if (fvco < mul_u32_u32(limits->fvco.min, 65536) || + fvco > mul_u32_u32(limits->fvco.max, 65536)) + continue; + + /* PLL_M component of (output * 65536 * PLL_P) */ + output = mul_u32_u32(p.m * 65536, input_fref); + /* PLL_K component of (output * 65536 * PLL_P) */ + output += p.k * input_fref; + /* Make it in mHz */ + output *= MILLI; + output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider); + + /* Check output frequency against limits */ + if (output < fout_min_millihz || + output > fout_max_millihz) + continue; + + p.error_millihz = freq_millihz - output; + p.freq_millihz = output; + + /* If an exact match is found, return immediately */ + if (p.error_millihz == 0) { + *pars = p; + return true; + } + + /* Update best match if error is smaller */ + if (abs(best.error_millihz) > abs(p.error_millihz)) + best = p; + } + } + } + + /* If no valid parameters were found, return false */ + if (best.error_millihz == S64_MAX) + return false; + + *pars = best; + return true; +} +EXPORT_SYMBOL_NS_GPL(rzv2h_cpg_get_pll_pars, "RZV2H_CPG"); + +/* + * rzv2h_cpg_get_pll_divs_pars - Finds the best combination of PLL parameters + * and divider value for a given frequency. + * + * @limits: Pointer to the structure containing the limits for the PLL parameters + * @pars: Pointer to the structure where the best calculated PLL parameters and + * divider values will be stored + * @table: Pointer to the array of valid divider values + * @table_size: Size of the divider values array + * @freq_millihz: Target output frequency in millihertz + * + * This function calculates the best set of PLL parameters (M, K, P, S) and divider + * value to achieve the desired frequency. See rzv2h_cpg_get_pll_pars() for more + * details on how the PLL parameters are calculated. + * + * freq_millihz is the desired frequency generated by the PLL followed by a + * a gear. + */ +bool rzv2h_cpg_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_div_pars *pars, + const u8 *table, u8 table_size, u64 freq_millihz) +{ + struct rzv2h_pll_div_pars p, best; + + best.div.error_millihz = S64_MAX; + p.div.error_millihz = S64_MAX; + for (unsigned int i = 0; i < table_size; i++) { + if (!rzv2h_cpg_get_pll_pars(limits, &p.pll, freq_millihz * table[i])) + continue; + + p.div.divider_value = table[i]; + p.div.freq_millihz = DIV_U64_ROUND_CLOSEST(p.pll.freq_millihz, table[i]); + p.div.error_millihz = freq_millihz - p.div.freq_millihz; + + if (p.div.error_millihz == 0) { + *pars = p; + return true; + } + + if (abs(best.div.error_millihz) > abs(p.div.error_millihz)) + best = p; + } + + if (best.div.error_millihz == S64_MAX) + return false; + + *pars = best; + return true; +} +EXPORT_SYMBOL_NS_GPL(rzv2h_cpg_get_pll_divs_pars, "RZV2H_CPG"); diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index fff89f2bdc0b..738dfafc6d9c 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -220,209 +220,6 @@ struct rzv2h_plldsi_div_clk { #define RZV2H_MAX_DIV_TABLES (16) -/** - * rzv2h_get_pll_pars - Finds the best combination of PLL parameters - * for a given frequency. - * - * @limits: Pointer to the structure containing the limits for the PLL parameters - * @pars: Pointer to the structure where the best calculated PLL parameters values - * will be stored - * @freq_millihz: Target output frequency in millihertz - * - * This function calculates the best set of PLL parameters (M, K, P, S) to achieve - * the desired frequency. - * There is no direct formula to calculate the PLL parameters, as it's an open - * system of equations, therefore this function uses an iterative approach to - * determine the best solution. The best solution is one that minimizes the error - * (desired frequency - actual frequency). - * - * Return: true if a valid set of parameters values is found, false otherwise. - */ -bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, - struct rzv2h_pll_pars *pars, u64 freq_millihz) -{ - unsigned long input_fref = limits->input_fref ?: (24 * MEGA); - u64 fout_min_millihz = mul_u32_u32(limits->fout.min, MILLI); - u64 fout_max_millihz = mul_u32_u32(limits->fout.max, MILLI); - struct rzv2h_pll_pars p, best; - - if (freq_millihz > fout_max_millihz || - freq_millihz < fout_min_millihz) - return false; - - /* Initialize best error to maximum possible value */ - best.error_millihz = S64_MAX; - - for (p.p = limits->p.min; p.p <= limits->p.max; p.p++) { - u32 fref = input_fref / p.p; - u16 divider; - - for (divider = 1 << limits->s.min, p.s = limits->s.min; - p.s <= limits->s.max; p.s++, divider <<= 1) { - for (p.m = limits->m.min; p.m <= limits->m.max; p.m++) { - u64 output_m, output_k_range; - s64 pll_k, output_k; - u64 fvco, output; - - /* - * The frequency generated by the PLL + divider - * is calculated as follows: - * - * With: - * Freq = Ffout = Ffvco / 2^(pll_s) - * Ffvco = (pll_m + (pll_k / 65536)) * Ffref - * Ffref = 24MHz / pll_p - * - * Freq can also be rewritten as: - * Freq = Ffvco / 2^(pll_s) - * = ((pll_m + (pll_k / 65536)) * Ffref) / 2^(pll_s) - * = (pll_m * Ffref) / 2^(pll_s) + ((pll_k / 65536) * Ffref) / 2^(pll_s) - * = output_m + output_k - * - * Every parameter has been determined at this - * point, but pll_k. - * - * Considering that: - * limits->k.min <= pll_k <= limits->k.max - * Then: - * -0.5 <= (pll_k / 65536) < 0.5 - * Therefore: - * -Ffref / (2 * 2^(pll_s)) <= output_k < Ffref / (2 * 2^(pll_s)) - */ - - /* Compute output M component (in mHz) */ - output_m = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(p.m, fref) * MILLI, - divider); - /* Compute range for output K (in mHz) */ - output_k_range = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(fref, MILLI), - 2 * divider); - /* - * No point in continuing if we can't achieve - * the desired frequency - */ - if (freq_millihz < (output_m - output_k_range) || - freq_millihz >= (output_m + output_k_range)) { - continue; - } - - /* - * Compute the K component - * - * Since: - * Freq = output_m + output_k - * Then: - * output_k = Freq - output_m - * = ((pll_k / 65536) * Ffref) / 2^(pll_s) - * Therefore: - * pll_k = (output_k * 65536 * 2^(pll_s)) / Ffref - */ - output_k = freq_millihz - output_m; - pll_k = div_s64(output_k * 65536ULL * divider, - fref); - pll_k = DIV_S64_ROUND_CLOSEST(pll_k, MILLI); - - /* Validate K value within allowed limits */ - if (pll_k < limits->k.min || - pll_k > limits->k.max) - continue; - - p.k = pll_k; - - /* Compute (Ffvco * 65536) */ - fvco = mul_u32_u32(p.m * 65536 + p.k, fref); - if (fvco < mul_u32_u32(limits->fvco.min, 65536) || - fvco > mul_u32_u32(limits->fvco.max, 65536)) - continue; - - /* PLL_M component of (output * 65536 * PLL_P) */ - output = mul_u32_u32(p.m * 65536, input_fref); - /* PLL_K component of (output * 65536 * PLL_P) */ - output += p.k * input_fref; - /* Make it in mHz */ - output *= MILLI; - output = DIV_U64_ROUND_CLOSEST(output, 65536 * p.p * divider); - - /* Check output frequency against limits */ - if (output < fout_min_millihz || - output > fout_max_millihz) - continue; - - p.error_millihz = freq_millihz - output; - p.freq_millihz = output; - - /* If an exact match is found, return immediately */ - if (p.error_millihz == 0) { - *pars = p; - return true; - } - - /* Update best match if error is smaller */ - if (abs(best.error_millihz) > abs(p.error_millihz)) - best = p; - } - } - } - - /* If no valid parameters were found, return false */ - if (best.error_millihz == S64_MAX) - return false; - - *pars = best; - return true; -} -EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_pars, "RZV2H_CPG"); - -/* - * rzv2h_get_pll_divs_pars - Finds the best combination of PLL parameters - * and divider value for a given frequency. - * - * @limits: Pointer to the structure containing the limits for the PLL parameters - * @pars: Pointer to the structure where the best calculated PLL parameters and - * divider values will be stored - * @table: Pointer to the array of valid divider values - * @table_size: Size of the divider values array - * @freq_millihz: Target output frequency in millihertz - * - * This function calculates the best set of PLL parameters (M, K, P, S) and divider - * value to achieve the desired frequency. See rzv2h_get_pll_pars() for more details - * on how the PLL parameters are calculated. - * - * freq_millihz is the desired frequency generated by the PLL followed by a - * a gear. - */ -bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, - struct rzv2h_pll_div_pars *pars, - const u8 *table, u8 table_size, u64 freq_millihz) -{ - struct rzv2h_pll_div_pars p, best; - - best.div.error_millihz = S64_MAX; - p.div.error_millihz = S64_MAX; - for (unsigned int i = 0; i < table_size; i++) { - if (!rzv2h_get_pll_pars(limits, &p.pll, freq_millihz * table[i])) - continue; - - p.div.divider_value = table[i]; - p.div.freq_millihz = DIV_U64_ROUND_CLOSEST(p.pll.freq_millihz, table[i]); - p.div.error_millihz = freq_millihz - p.div.freq_millihz; - - if (p.div.error_millihz == 0) { - *pars = p; - return true; - } - - if (abs(best.div.error_millihz) > abs(p.div.error_millihz)) - best = p; - } - - if (best.div.error_millihz == S64_MAX) - return false; - - *pars = best; - return true; -} -EXPORT_SYMBOL_NS_GPL(rzv2h_get_pll_divs_pars, "RZV2H_CPG"); - /** * struct rzv2h_plldsi_mux_clk - PLL DSI MUX clock * diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h index 798bb0b54bab..c9495558cd5c 100644 --- a/include/linux/clk/renesas.h +++ b/include/linux/clk/renesas.h @@ -189,28 +189,31 @@ struct rzv2h_pll_div_pars { .k = { .min = -32768, .max = 32767 }, \ } \ -#ifdef CONFIG_CLK_RZV2H -bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, - struct rzv2h_pll_pars *pars, u64 freq_millihz); +#ifdef CONFIG_CLK_RZV2H_CPG_LIB +bool rzv2h_cpg_get_pll_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_pars *pars, u64 freq_millihz); -bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, - struct rzv2h_pll_div_pars *pars, - const u8 *table, u8 table_size, u64 freq_millihz); +bool rzv2h_cpg_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_div_pars *pars, + const u8 *table, u8 table_size, u64 freq_millihz); #else -static inline bool rzv2h_get_pll_pars(const struct rzv2h_pll_limits *limits, - struct rzv2h_pll_pars *pars, - u64 freq_millihz) +static inline bool rzv2h_cpg_get_pll_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_pars *pars, + u64 freq_millihz) { return false; } -static inline bool rzv2h_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, - struct rzv2h_pll_div_pars *pars, - const u8 *table, u8 table_size, - u64 freq_millihz) +static inline bool rzv2h_cpg_get_pll_divs_pars(const struct rzv2h_pll_limits *limits, + struct rzv2h_pll_div_pars *pars, + const u8 *table, u8 table_size, + u64 freq_millihz) { return false; } #endif +#define rzv2h_get_pll_pars rzv2h_cpg_get_pll_pars +#define rzv2h_get_pll_divs_pars rzv2h_cpg_get_pll_divs_pars + #endif From 6745ca5d95040ddfd3669c27d90b8b1bb126a75f Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 18 Jun 2026 19:19:49 +0100 Subject: [PATCH 12/15] clk: renesas: r9a09g077: Add LCDC and PLL3 clock support for RZ/T2H display pipeline Add the clock definitions and PLL logic required to supply the LCDC (VSPD/FCPVD/DU) blocks on the RZ/T2H (R9A09G077) SoC. The RZ/T2H display subsystem depends on a dedicated PLL (PLL3) and a set of new derived clocks. Introduce a new PLL clock type and implement rate recalculation, programming and locking sequences for PLL3 using the RZ/T2H specific divider and VCO limits. Add the corresponding muxes and divider entries, expose the LCDC core clock, and register the LCDC module clock using the correct PCLK parent. This enables the RZ/T2H clock driver to generate the display pipeline clocking tree needed by the DU and VSP-based composition engines, allowing upcoming display support to be integrated without duplicating CPG logic. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260618181949.3036280-6-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 2 + drivers/clk/renesas/r9a09g077-cpg.c | 371 ++++++++++++++++++++++++++++ 2 files changed, 373 insertions(+) diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 7659550b8566..5c0238e878b7 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -218,10 +218,12 @@ config CLK_R9A09G057 config CLK_R9A09G077 bool "RZ/T2H clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSSR + select CLK_RZV2H_CPG_LIB config CLK_R9A09G087 bool "RZ/N2H clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSSR + select CLK_RZV2H_CPG_LIB config CLK_SH73A0 bool "SH-Mobile AG5 clock support" if COMPILE_TEST diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a09g077-cpg.c index e8f760776c99..5640c2035e5a 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -8,16 +8,23 @@ #include #include +#include #include #include +#include +#include #include #include +#include #include +#include #include #include #include "renesas-cpg-mssr.h" +MODULE_IMPORT_NS("RZV2H_CPG"); + #define RZT2H_REG_BLOCK_SHIFT 11 #define RZT2H_REG_OFFSET_MASK GENMASK(10, 0) #define RZT2H_REG_CONF(block, offset) (((block) << RZT2H_REG_BLOCK_SHIFT) | \ @@ -66,11 +73,26 @@ #define DIVSCI2ASYNC CONF_PACK(SCKCR3, 10, 2) #define DIVSCI3ASYNC CONF_PACK(SCKCR3, 12, 2) #define DIVSCI4ASYNC CONF_PACK(SCKCR3, 14, 2) +#define LCDCDIVSEL CONF_PACK(SCKCR3, 20, 4) + +#define PLL3EN FIELD_PREP_CONST(OFFSET_MASK, (0xc0)) + +#define CPG_PLL_EN_EN BIT(0) +#define CPG_PLL3_VCO_CTR0(x) ((x) + 0x4) +#define CPG_PLL3_VCO_CTR0_PDIV GENMASK(21, 16) +#define CPG_PLL3_VCO_CTR0_MDIV GENMASK(9, 0) +#define CPG_PLL3_VCO_CTR1(x) ((x) + 0x8) +#define CPG_PLL3_VCO_CTR1_KDIV GENMASK(31, 16) +#define CPG_PLL3_VCO_CTR1_SDIV GENMASK(2, 0) +#define CPG_PLL_MON(x) ((x) - 0x10) +#define CPG_PLL_MON_LOCK BIT(0) enum rzt2h_clk_types { CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM, /* Clock with divider */ CLK_TYPE_RZT2H_MUX, /* Clock with clock source selector */ CLK_TYPE_RZT2H_FSELXSPI, /* Clock with FSELXSPIn source selector */ + CLK_TYPE_RZT2H_PLL3, /* PLL3 Clock */ + CLK_TYPE_RZT2H_LCDCDIV, /* LCDC divider clock */ }; #define DEF_DIV(_name, _id, _parent, _conf, _dtable) \ @@ -83,6 +105,47 @@ enum rzt2h_clk_types { #define DEF_DIV_FSELXSPI(_name, _id, _parent, _conf, _dtable) \ DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_FSELXSPI, .conf = _conf, \ .parent = _parent, .dtable = _dtable, .flag = 0) +#define DEF_PLL3(_name, _id, _parent, _conf) \ + DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_PLL3, .conf = _conf, \ + .parent = _parent) +#define DEF_DIV_LCDC(_name, _id, _parent, _conf, _dtable) \ + DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_LCDCDIV, .conf = _conf, \ + .parent = _parent, .dtable = _dtable, .flag = CLK_SET_RATE_PARENT) + +struct pll_clk { + void __iomem *reg; + const struct rzv2h_pll_limits *limits; + struct device *dev; + struct rzv2h_pll_pars pll_parameters; + struct clk_hw hw; + unsigned long cur_rate; +}; + +#define to_pll(_hw) container_of(_hw, struct pll_clk, hw) + +struct r9a09g077_lcdc_div_clk { + const struct clk_div_table *dtable; + void __iomem *reg; + struct device *dev; + struct clk_hw hw; + u32 conf; + u8 divider; +}; + +#define to_lcdc_div_clk(_hw) \ + container_of(_hw, struct r9a09g077_lcdc_div_clk, hw) + +#define RZT2H_MAX_LCDC_DIV_TABLES 16 + +static const struct rzv2h_pll_limits r9a09g077_cpg_pll3_limits = { + .input_fref = 48 * MEGA, + .fout = { .min = 25 * MEGA, .max = 430 * MEGA }, + .fvco = { .min = 1600 * MEGA, .max = 3200 * MEGA }, + .m = { .min = 0x40, .max = 0x3ff }, + .p = { .min = 0x2, .max = 0x8 }, + .s = { .min = 0x0, .max = 0x6 }, + .k = { .min = -32768, .max = 32767 }, +}; enum clk_ids { /* Core Clock Outputs exported to DT */ @@ -96,10 +159,12 @@ enum clk_ids { CLK_PLL0, CLK_PLL1, CLK_PLL2, + CLK_PLL3, CLK_PLL4, CLK_SEL_CLK_PLL0, CLK_SEL_CLK_PLL1, CLK_SEL_CLK_PLL2, + CLK_SEL_CLK_PLL3, CLK_SEL_CLK_PLL4, CLK_PLL4D1, CLK_PLL4D1_DIV3, @@ -107,6 +172,7 @@ enum clk_ids { CLK_PLL4D3, CLK_PLL4D3_DIV10, CLK_PLL4D3_DIV20, + CLK_PLL4D50, CLK_SCI0ASYNC, CLK_SCI1ASYNC, CLK_SCI2ASYNC, @@ -119,6 +185,7 @@ enum clk_ids { CLK_SPI3ASYNC, CLK_DIVSELXSPI0_SCKCR, CLK_DIVSELXSPI1_SCKCR, + CLK_LCDDIVSEL, /* Module Clocks */ MOD_CLK_BASE, @@ -130,6 +197,26 @@ static const struct clk_div_table dtable_1_2[] = { {0, 0}, }; +static const struct clk_div_table dtable_2_32[] = { + {0, 2}, + {1, 4}, + {2, 6}, + {3, 8}, + {4, 10}, + {5, 12}, + {6, 14}, + {7, 16}, + {8, 18}, + {9, 20}, + {10, 22}, + {11, 24}, + {12, 26}, + {13, 28}, + {14, 30}, + {15, 32}, + {0, 0}, +}; + static const struct clk_div_table dtable_6_8_16_32_64[] = { {6, 64}, {5, 32}, @@ -152,6 +239,7 @@ static const struct clk_div_table dtable_24_25_30_32[] = { static const char * const sel_clk_pll0[] = { ".loco", ".pll0" }; static const char * const sel_clk_pll1[] = { ".loco", ".pll1" }; static const char * const sel_clk_pll2[] = { ".loco", ".pll2" }; +static const char * const sel_clk_pll3[] = { ".loco", ".pll3" }; static const char * const sel_clk_pll4[] = { ".loco", ".pll4" }; static const char * const sel_clk_pll4d1_div3_div4[] = { ".pll4d1_div3", ".pll4d1_div4" }; static const char * const sel_clk_pll4d3_div10_div20[] = { ".pll4d3_div10", ".pll4d3_div20" }; @@ -173,10 +261,14 @@ static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = { sel_clk_pll1, ARRAY_SIZE(sel_clk_pll1), CLK_MUX_READ_ONLY), DEF_MUX(".sel_clk_pll2", CLK_SEL_CLK_PLL2, SEL_PLL, sel_clk_pll2, ARRAY_SIZE(sel_clk_pll2), CLK_MUX_READ_ONLY), + DEF_MUX(".sel_clk_pll3", CLK_SEL_CLK_PLL3, SEL_PLL, + sel_clk_pll3, ARRAY_SIZE(sel_clk_pll3), CLK_MUX_READ_ONLY), DEF_MUX(".sel_clk_pll4", CLK_SEL_CLK_PLL4, SEL_PLL, sel_clk_pll4, ARRAY_SIZE(sel_clk_pll4), CLK_MUX_READ_ONLY), DEF_FIXED(".pll4d1", CLK_PLL4D1, CLK_SEL_CLK_PLL4, 1, 1), + DEF_FIXED(".pll4d50", CLK_PLL4D50, CLK_SEL_CLK_PLL4, 50, 1), + DEF_PLL3(".pll3", CLK_PLL3, CLK_PLL4D50, PLL3EN), DEF_FIXED(".pll4d1_div3", CLK_PLL4D1_DIV3, CLK_PLL4D1, 3, 1), DEF_FIXED(".pll4d1_div4", CLK_PLL4D1_DIV4, CLK_PLL4D1, 4, 1), DEF_FIXED(".pll4d3", CLK_PLL4D3, CLK_SEL_CLK_PLL4, 3, 1), @@ -229,6 +321,7 @@ static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = { DEF_FIXED("PCLKL", R9A09G077_CLK_PCLKL, CLK_SEL_CLK_PLL1, 16, 1), DEF_FIXED("PCLKAH", R9A09G077_CLK_PCLKAH, CLK_PLL4D1, 6, 1), DEF_FIXED("PCLKAM", R9A09G077_CLK_PCLKAM, CLK_PLL4D1, 12, 1), + DEF_FIXED("PCLKAL", R9A09G077_CLK_PCLKAL, CLK_PLL4D1, 24, 1), DEF_FIXED("SDHI_CLKHS", R9A09G077_SDHI_CLKHS, CLK_SEL_CLK_PLL2, 1, 1), DEF_FIXED("USB_CLK", R9A09G077_USB_CLK, CLK_PLL4D1, 48, 1), DEF_FIXED("ETCLKA", R9A09G077_ETCLKA, CLK_SEL_CLK_PLL1, 5, 1), @@ -242,6 +335,8 @@ static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = { FSELXSPI1, dtable_6_8_16_32_64), DEF_MUX("PCLKCAN", R9A09G077_PCLKCAN, FSELCANFD, sel_clk_pll4d3_div10_div20, ARRAY_SIZE(sel_clk_pll4d3_div10_div20), 0), + DEF_DIV_LCDC("LCDC_CLKD", R9A09G077_LCDC_CLKD, CLK_SEL_CLK_PLL3, LCDCDIVSEL, + dtable_2_32), DEF_FIXED("PCLKRTC", R9A09G077_PCLKRTC, CLK_EXTAL, 128, 1), }; @@ -274,6 +369,7 @@ static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = { DEF_MOD("iic2", 601, R9A09G077_CLK_PCLKL), DEF_MOD("spi3", 602, CLK_SPI3ASYNC), DEF_MOD("rtc", 605, R9A09G077_CLK_PCLKL), + DEF_MOD("lcdc", 1204, R9A09G077_CLK_PCLKAL), DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM), DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM), }; @@ -483,6 +579,276 @@ r9a09g077_cpg_fselxspi_div_clk_register(struct device *dev, return hw->clk; } +static unsigned long r9a09g077_cpg_pll3_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct pll_clk *pll_clk = to_pll(hw); + u32 ctr0, ctr1; + u8 pdiv, sdiv; + u64 rate; + u16 mdiv; + s16 kdiv; + + ctr0 = readl(CPG_PLL3_VCO_CTR0(pll_clk->reg)); + ctr1 = readl(CPG_PLL3_VCO_CTR1(pll_clk->reg)); + + pdiv = FIELD_GET(CPG_PLL3_VCO_CTR0_PDIV, ctr0); + mdiv = FIELD_GET(CPG_PLL3_VCO_CTR0_MDIV, ctr0); + kdiv = (s16)FIELD_GET(CPG_PLL3_VCO_CTR1_KDIV, ctr1); + sdiv = FIELD_GET(CPG_PLL3_VCO_CTR1_SDIV, ctr1); + + rate = mul_u64_u32_shr(parent_rate, (mdiv << 16) + kdiv, 16 + sdiv); + + return DIV_ROUND_CLOSEST_ULL(rate, pdiv); +} + +static int r9a09g077_cpg_pll3_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct pll_clk *pll_clk = to_pll(hw); + u64 rate_millihz; + + if (req->rate == pll_clk->cur_rate) + return 0; + + rate_millihz = mul_u32_u32(req->rate, MILLI); + if (!rzv2h_cpg_get_pll_pars(pll_clk->limits, &pll_clk->pll_parameters, + rate_millihz)) { + dev_dbg(pll_clk->dev, + "failed to determine rate for req->rate: %lu\n", + req->rate); + return -EINVAL; + } + req->rate = DIV_ROUND_CLOSEST_ULL(pll_clk->pll_parameters.freq_millihz, MILLI); + pll_clk->cur_rate = req->rate; + + return 0; +} + +static int r9a09g077_cpg_pll3_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct pll_clk *pll_clk = to_pll(hw); + struct rzv2h_pll_pars *params = &pll_clk->pll_parameters; + void __iomem *offset = pll_clk->reg; + u32 val; + int ret; + + /* Put PLL into standby mode */ + writel(0, offset); + ret = readl_poll_timeout_atomic(CPG_PLL_MON(offset), + val, !(val & CPG_PLL_MON_LOCK), + 100, 2000); + if (ret) { + dev_err(pll_clk->dev, "Failed to put PLL into standby mode"); + return ret; + } + + /* Output clock setting 1 */ + val = readl(CPG_PLL3_VCO_CTR0(offset)); + FIELD_MODIFY(CPG_PLL3_VCO_CTR0_MDIV, &val, params->m); + FIELD_MODIFY(CPG_PLL3_VCO_CTR0_PDIV, &val, params->p); + writel(val, CPG_PLL3_VCO_CTR0(offset)); + + /* Output clock setting 2 */ + val = readl(CPG_PLL3_VCO_CTR1(offset)); + FIELD_MODIFY(CPG_PLL3_VCO_CTR1_KDIV, &val, params->k); + FIELD_MODIFY(CPG_PLL3_VCO_CTR1_SDIV, &val, params->s); + writel(val, CPG_PLL3_VCO_CTR1(offset)); + + writel(CPG_PLL_EN_EN, offset); + + /* PLL normal mode transition, output clock stability check */ + ret = readl_poll_timeout_atomic(CPG_PLL_MON(offset), + val, (val & CPG_PLL_MON_LOCK), + 100, 2000); + if (ret) { + writel(0, offset); + dev_err(pll_clk->dev, "Failed to put PLL into normal mode"); + return ret; + } + + return 0; +} + +static const struct clk_ops r9a09g077_cpg_pll3_ops = { + .recalc_rate = r9a09g077_cpg_pll3_clk_recalc_rate, + .determine_rate = r9a09g077_cpg_pll3_determine_rate, + .set_rate = r9a09g077_cpg_pll3_set_rate, +}; + +static struct clk * __init +r9a09g077_cpg_pll3_clk_register(struct device *dev, + const struct cpg_core_clk *core, + void __iomem *addr, + struct cpg_mssr_pub *pub, + const struct rzv2h_pll_limits *limits) +{ + struct clk_init_data init = {}; + const struct clk *parent; + const char *parent_name; + struct pll_clk *pll_clk; + int ret; + + parent = pub->clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) + return ERR_PTR(-ENOMEM); + + parent_name = __clk_get_name(parent); + init.name = core->name; + init.ops = &r9a09g077_cpg_pll3_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + pll_clk->dev = dev; + pll_clk->hw.init = &init; + pll_clk->reg = addr; + pll_clk->limits = limits; + + ret = devm_clk_hw_register(dev, &pll_clk->hw); + if (ret) + return ERR_PTR(ret); + + return pll_clk->hw.clk; +} + +static int r9a09g077_cpg_lcdc_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct r9a09g077_lcdc_div_clk *dsi_div = to_lcdc_div_clk(hw); + struct clk_hw *mux_hw = clk_hw_get_parent(hw); + u8 table[RZT2H_MAX_LCDC_DIV_TABLES] = { 0 }; + struct rzv2h_pll_div_pars dsi_params; + const struct clk_div_table *div; + struct pll_clk *pll_clk; + unsigned int i = 0; + u64 freq_millihz; + + /* index 1 is always .pll3 in sel_clk_pll3[] */ + pll_clk = to_pll(clk_hw_get_parent_by_index(mux_hw, 1)); + + for (div = dsi_div->dtable; div->div; div++) { + if (i >= RZT2H_MAX_LCDC_DIV_TABLES) + return -EINVAL; + table[i++] = div->div; + } + + freq_millihz = mul_u32_u32(req->rate, MILLI); + + if (!rzv2h_cpg_get_pll_divs_pars(pll_clk->limits, &dsi_params, table, + i, freq_millihz)) { + dev_err(dsi_div->dev, + "LCDC divider failed to determine rate for req->rate: %lu\n", + req->rate); + return -EINVAL; + } + + req->rate = DIV_ROUND_CLOSEST_ULL(dsi_params.div.freq_millihz, MILLI); + req->best_parent_rate = req->rate * dsi_params.div.divider_value; + dsi_div->divider = dsi_params.div.divider_value; + pll_clk->cur_rate = req->best_parent_rate; + pll_clk->pll_parameters = dsi_params.pll; + + return 0; +} + +static int r9a09g077_cpg_lcdc_div_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct r9a09g077_lcdc_div_clk *dsi_div = to_lcdc_div_clk(hw); + const struct clk_div_table *clkt; + bool divider_found = false; + u32 val, shift; + + for (clkt = dsi_div->dtable; clkt->div; clkt++) { + if (clkt->div == dsi_div->divider) { + divider_found = true; + break; + } + } + + if (!divider_found) + return -EINVAL; + + shift = GET_SHIFT(dsi_div->conf); + val = readl(dsi_div->reg); + val &= ~(clk_div_mask(GET_WIDTH(dsi_div->conf)) << shift); + val |= clkt->val << shift; + writel(val, dsi_div->reg); + + return 0; +} + +static unsigned long +r9a09g077_cpg_lcdc_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct r9a09g077_lcdc_div_clk *dsi_div = to_lcdc_div_clk(hw); + u32 div; + + div = readl(dsi_div->reg); + div >>= GET_SHIFT(dsi_div->conf); + div &= clk_div_mask(GET_WIDTH(dsi_div->conf)); + div = dsi_div->dtable[div].div; + + return DIV_ROUND_CLOSEST_ULL(parent_rate, div); +} + +static const struct clk_ops r9a09g077_cpg_lcdc_div_ops = { + .recalc_rate = r9a09g077_cpg_lcdc_div_recalc_rate, + .determine_rate = r9a09g077_cpg_lcdc_div_determine_rate, + .set_rate = r9a09g077_cpg_lcdc_div_set_rate, +}; + +static struct clk * __init +r9a09g077_cpg_lcdc_div_clk_register(struct device *dev, + const struct cpg_core_clk *core, + void __iomem *addr, + struct cpg_mssr_pub *pub) +{ + struct r9a09g077_lcdc_div_clk *clk_hw_data; + struct clk_init_data init = {}; + struct clk **clks = pub->clks; + const struct clk *parent; + const char *parent_name; + struct clk_hw *hw; + int ret; + + parent = clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + clk_hw_data = devm_kzalloc(dev, sizeof(*clk_hw_data), GFP_KERNEL); + if (!clk_hw_data) + return ERR_PTR(-ENOMEM); + + clk_hw_data->dtable = core->dtable; + clk_hw_data->reg = addr; + clk_hw_data->conf = core->conf; + clk_hw_data->dev = dev; + clk_hw_data->divider = 32; /* Initialize divider for LCDC */ + + parent_name = __clk_get_name(parent); + init.name = core->name; + init.ops = &r9a09g077_cpg_lcdc_div_ops; + init.flags = core->flag; + init.parent_names = &parent_name; + init.num_parents = 1; + + hw = &clk_hw_data->hw; + hw->init = &init; + ret = devm_clk_hw_register(dev, hw); + if (ret) + return ERR_PTR(ret); + + return hw->clk; +} + static struct clk * __init r9a09g077_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, @@ -499,6 +865,11 @@ r9a09g077_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, return r9a09g077_cpg_mux_clk_register(dev, core, addr, pub); case CLK_TYPE_RZT2H_FSELXSPI: return r9a09g077_cpg_fselxspi_div_clk_register(dev, core, addr, pub); + case CLK_TYPE_RZT2H_PLL3: + return r9a09g077_cpg_pll3_clk_register(dev, core, pub->base1 + offset, + pub, &r9a09g077_cpg_pll3_limits); + case CLK_TYPE_RZT2H_LCDCDIV: + return r9a09g077_cpg_lcdc_div_clk_register(dev, core, addr, pub); default: return ERR_PTR(-EINVAL); } From b3044f9e8f1387c0f5fb2e9ff57227c5ba1f768c Mon Sep 17 00:00:00 2001 From: Tommaso Merciai Date: Tue, 23 Jun 2026 17:28:49 +0200 Subject: [PATCH 13/15] clk: renesas: r9a09g047: Add LVDS clocks and resets Add LVDS clocks and resets entries to the r9a09g047 CPG driver. Signed-off-by: Tommaso Merciai Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20260623152851.478573-1-tommaso.merciai.xr@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a09g047-cpg.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/clk/renesas/r9a09g047-cpg.c b/drivers/clk/renesas/r9a09g047-cpg.c index ab9feb5a33ea..f576dd441a11 100644 --- a/drivers/clk/renesas/r9a09g047-cpg.c +++ b/drivers/clk/renesas/r9a09g047-cpg.c @@ -630,6 +630,16 @@ static const struct rzv2h_mod_clk r9a09g047_mod_clks[] __initconst = { BUS_MSTOP(2, BIT(3) | BIT(4))), DEF_MOD("dsi_0_vclk2", CLK_SMUX2_DSI1_CLK, 25, 0, 10, 21, BUS_MSTOP(9, BIT(15) | BIT(14))), + DEF_MOD("lvds_top_clk_ch0", CLK_PLLDSI0, 26, 0, 10, 22, + BUS_MSTOP(13, BIT(0))), + DEF_MOD("lvds_top_clk_ch1", CLK_PLLDSI1, 26, 1, 10, 23, + BUS_MSTOP(13, BIT(0))), + DEF_MOD("lvds_top_clk_dot_ch0", CLK_SMUX2_DSI0_CLK, 26, 2, 10, 24, + BUS_MSTOP(13, BIT(0))), + DEF_MOD("lvds_top_clk_dot_ch1", CLK_SMUX2_DSI1_CLK, 26, 3, 10, 25, + BUS_MSTOP(13, BIT(0))), + DEF_MOD("lvds_top_pclk", CLK_PLLDTY_DIV16, 26, 4, 10, 26, + BUS_MSTOP(13, BIT(0))), DEF_MOD("lcdc_1_clk_a", CLK_PLLDTY_ACPU_DIV2, 26, 8, 10, 30, BUS_MSTOP(13, BIT(5) | BIT(4) | BIT(3))), DEF_MOD("lcdc_1_clk_p", CLK_PLLDTY_DIV16, 26, 9, 10, 31, @@ -732,6 +742,7 @@ static const struct rzv2h_reset r9a09g047_resets[] __initconst = { DEF_RST(14, 13, 6, 30), /* DMACpp_0_ARST */ DEF_RST(14, 14, 6, 31), /* ADG_0_RST_RESET_ADG */ DEF_RST(15, 8, 7, 9), /* TSU_1_PRESETN */ + DEF_RST(17, 10, 8, 11), /* LVDS_TOP_RESET_N */ DEF_RST(17, 14, 8, 15), /* LCDC_1_RESET_N */ }; From 91fb4643954379f8493dba649d520c23f0d1f4e6 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 23 Jun 2026 17:20:37 +0100 Subject: [PATCH 14/15] dt-bindings: clock: renesas,versaclock7: Update maintainer Alex' email is bouncing. Update the maintainers list with my contact details to take over the schema maintenance. While at it, extend the entry in MAINTAINERS to the Versaclock 3 clock driver. Signed-off-by: Biju Das Reviewed-by: Brian Masney Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20250905143441.7082-1-biju.das.jz@bp.renesas.com Link: https://patch.msgid.link/20260623162039.153291-1-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../devicetree/bindings/clock/renesas,versaclock7.yaml | 2 +- MAINTAINERS | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml b/Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml index b339f1f9f072..990d287d0a90 100644 --- a/Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Renesas Versaclock7 Programmable Clock maintainers: - - Alex Helms + - Biju Das description: | Renesas Versaclock7 is a family of configurable clock generator and diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a9..112e5f031007 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23090,10 +23090,12 @@ L: linux-renesas-soc@vger.kernel.org S: Maintained F: drivers/phy/renesas/phy-rcar-gen3-usb*.c -RENESAS VERSACLOCK 7 CLOCK DRIVER -M: Alex Helms +RENESAS VERSACLOCK 3 and VERSACLOCK 7 CLOCK DRIVER +M: Biju Das S: Maintained +F: Documentation/devicetree/bindings/clock/renesas,5p35023.yaml F: Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml +F: drivers/clk/clk-versaclock3.c F: drivers/clk/clk-versaclock7.c RENESAS X9250 DIGITAL POTENTIOMETERS DRIVER From 2df26b8663b6f315d0e9364927c8503280fe3dd3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 9 Jul 2026 21:23:25 +0300 Subject: [PATCH 15/15] clk: r9a08g045: Add clocks and resets for CAN-FD Renesas RZ/G3S SoC has a CAN-FD IP. Add clocks and resets for it. Reviewed-by: Biju Das Reviewed-by: Geert Uytterhoeven Signed-off-by: Claudiu Beznea Link: https://patch.msgid.link/20260709182332.876408-2-claudiu.beznea+renesas@tuxon.dev Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a08g045-cpg.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c index 624fc5e6fb24..ea2a6a71aebd 100644 --- a/drivers/clk/renesas/r9a08g045-cpg.c +++ b/drivers/clk/renesas/r9a08g045-cpg.c @@ -77,6 +77,7 @@ enum clk_ids { CLK_SEL_PLL4, CLK_P1_DIV2, CLK_P3_DIV2, + CLK_P4_DIV2, CLK_SD0_DIV4, CLK_SD1_DIV4, CLK_SD2_DIV4, @@ -172,6 +173,8 @@ static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = { DEF_G3S_DIV("P3", R9A08G045_CLK_P3, CLK_PLL3_DIV2_4, DIVPL3C, G3S_DIVPL3C_STS, dtable_1_32, 0, 0, 0, NULL), DEF_FIXED("P3_DIV2", CLK_P3_DIV2, R9A08G045_CLK_P3, 1, 2), + DEF_FIXED("P4", R9A08G045_CLK_P4, CLK_PLL2_DIV2, 1, 5), + DEF_FIXED("P4_DIV2", CLK_P4_DIV2, R9A08G045_CLK_P4, 1, 2), DEF_FIXED("P5", R9A08G045_CLK_P5, CLK_PLL2_DIV2, 1, 4), DEF_FIXED("ZT", R9A08G045_CLK_ZT, CLK_PLL3_DIV2_8, 1, 1), DEF_FIXED("S0", R9A08G045_CLK_S0, CLK_SEL_PLL4, 1, 2), @@ -274,6 +277,10 @@ static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = { MSTOP(BUS_MCPU2, BIT(5))), DEF_MOD("scif5_clk_pck", R9A08G045_SCIF5_CLK_PCK, R9A08G045_CLK_P0, 0x584, 5, MSTOP(BUS_MCPU3, BIT(4))), + DEF_MOD("canfd_pclk", R9A08G045_CANFD_PCLK, CLK_P4_DIV2, 0x594, 0, + MSTOP(BUS_MCPU2, BIT(9))), + DEF_MOD("canfd_clk_ram", R9A08G045_CANFD_CLK_RAM, R9A08G045_CLK_P4, 0x594, 1, + MSTOP(BUS_MCPU2, BIT(9))), DEF_MOD("gpio_hclk", R9A08G045_GPIO_HCLK, R9A08G045_OSCCLK, 0x598, 0, MSTOP(BUS_PERI_CPU, BIT(6))), DEF_MOD("adc_adclk", R9A08G045_ADC_ADCLK, R9A08G045_CLK_TSU, 0x5a8, 0, @@ -324,6 +331,8 @@ static const struct rzg2l_reset r9a08g045_resets[] = { DEF_RST(R9A08G045_SCIF3_RST_SYSTEM_N, 0x884, 3), DEF_RST(R9A08G045_SCIF4_RST_SYSTEM_N, 0x884, 4), DEF_RST(R9A08G045_SCIF5_RST_SYSTEM_N, 0x884, 5), + DEF_RST(R9A08G045_CANFD_RSTP_N, 0x894, 0), + DEF_RST(R9A08G045_CANFD_RSTC_N, 0x894, 1), DEF_RST(R9A08G045_GPIO_RSTN, 0x898, 0), DEF_RST(R9A08G045_GPIO_PORT_RESETN, 0x898, 1), DEF_RST(R9A08G045_GPIO_SPARE_RESETN, 0x898, 2),