Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

clk: renesas: rzv2h: Add MSTOP support

Add MSTOP support to control buses for the individual units on RZ/V2H.
Use per-bit (instead of group-based) configuration and atomic counters,
to ensure precise control over individual MSTOP bits, and to prevent
issues with shared dependencies between module clocks.

Co-developed-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Co-developed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/20241213123550.289193-2-biju.das.jz@bp.renesas.com
Link: https://lore.kernel.org/20250102181839.352599-2-prabhakar.mahadev-lad.rj@bp.renesas.com
Link: https://lore.kernel.org/20250102181839.352599-3-prabhakar.mahadev-lad.rj@bp.renesas.com
Link: https://lore.kernel.org/20250102181839.352599-4-prabhakar.mahadev-lad.rj@bp.renesas.com
Link: https://lore.kernel.org/20250102181839.352599-5-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>

authored by

Biju Das and committed by
Geert Uytterhoeven
9b6e63a7 f9627452

+253 -80
+104 -51
drivers/clk/renesas/r9a09g057-cpg.c
··· 115 115 }; 116 116 117 117 static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { 118 - DEF_MOD_CRITICAL("icu_0_pclk_i", CLK_PLLCM33_DIV16, 0, 5, 0, 5), 119 - DEF_MOD("gtm_0_pclk", CLK_PLLCM33_DIV16, 4, 3, 2, 3), 120 - DEF_MOD("gtm_1_pclk", CLK_PLLCM33_DIV16, 4, 4, 2, 4), 121 - DEF_MOD("gtm_2_pclk", CLK_PLLCLN_DIV16, 4, 5, 2, 5), 122 - DEF_MOD("gtm_3_pclk", CLK_PLLCLN_DIV16, 4, 6, 2, 6), 123 - DEF_MOD("gtm_4_pclk", CLK_PLLCLN_DIV16, 4, 7, 2, 7), 124 - DEF_MOD("gtm_5_pclk", CLK_PLLCLN_DIV16, 4, 8, 2, 8), 125 - DEF_MOD("gtm_6_pclk", CLK_PLLCLN_DIV16, 4, 9, 2, 9), 126 - DEF_MOD("gtm_7_pclk", CLK_PLLCLN_DIV16, 4, 10, 2, 10), 127 - DEF_MOD("wdt_0_clkp", CLK_PLLCM33_DIV16, 4, 11, 2, 11), 128 - DEF_MOD("wdt_0_clk_loco", CLK_QEXTAL, 4, 12, 2, 12), 129 - DEF_MOD("wdt_1_clkp", CLK_PLLCLN_DIV16, 4, 13, 2, 13), 130 - DEF_MOD("wdt_1_clk_loco", CLK_QEXTAL, 4, 14, 2, 14), 131 - DEF_MOD("wdt_2_clkp", CLK_PLLCLN_DIV16, 4, 15, 2, 15), 132 - DEF_MOD("wdt_2_clk_loco", CLK_QEXTAL, 5, 0, 2, 16), 133 - DEF_MOD("wdt_3_clkp", CLK_PLLCLN_DIV16, 5, 1, 2, 17), 134 - DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18), 135 - DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15), 136 - DEF_MOD("riic_8_ckm", CLK_PLLCM33_DIV16, 9, 3, 4, 19), 137 - DEF_MOD("riic_0_ckm", CLK_PLLCLN_DIV16, 9, 4, 4, 20), 138 - DEF_MOD("riic_1_ckm", CLK_PLLCLN_DIV16, 9, 5, 4, 21), 139 - DEF_MOD("riic_2_ckm", CLK_PLLCLN_DIV16, 9, 6, 4, 22), 140 - DEF_MOD("riic_3_ckm", CLK_PLLCLN_DIV16, 9, 7, 4, 23), 141 - DEF_MOD("riic_4_ckm", CLK_PLLCLN_DIV16, 9, 8, 4, 24), 142 - DEF_MOD("riic_5_ckm", CLK_PLLCLN_DIV16, 9, 9, 4, 25), 143 - DEF_MOD("riic_6_ckm", CLK_PLLCLN_DIV16, 9, 10, 4, 26), 144 - DEF_MOD("riic_7_ckm", CLK_PLLCLN_DIV16, 9, 11, 4, 27), 145 - DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3), 146 - DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4), 147 - DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5), 148 - DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6), 149 - DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7), 150 - DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8), 151 - DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9), 152 - DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10), 153 - DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11), 154 - DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12), 155 - DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13), 156 - DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14), 157 - DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18), 158 - DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19), 159 - DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20), 160 - DEF_MOD("cru_1_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 5, 6, 21), 161 - DEF_MOD_NO_PM("cru_1_vclk", CLK_PLLVDO_CRU1, 13, 6, 6, 22), 162 - DEF_MOD("cru_1_pclk", CLK_PLLDTY_DIV16, 13, 7, 6, 23), 163 - DEF_MOD("cru_2_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 8, 6, 24), 164 - DEF_MOD_NO_PM("cru_2_vclk", CLK_PLLVDO_CRU2, 13, 9, 6, 25), 165 - DEF_MOD("cru_2_pclk", CLK_PLLDTY_DIV16, 13, 10, 6, 26), 166 - DEF_MOD("cru_3_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 11, 6, 27), 167 - DEF_MOD_NO_PM("cru_3_vclk", CLK_PLLVDO_CRU3, 13, 12, 6, 28), 168 - DEF_MOD("cru_3_pclk", CLK_PLLDTY_DIV16, 13, 13, 6, 29), 118 + DEF_MOD_CRITICAL("icu_0_pclk_i", CLK_PLLCM33_DIV16, 0, 5, 0, 5, 119 + BUS_MSTOP_NONE), 120 + DEF_MOD("gtm_0_pclk", CLK_PLLCM33_DIV16, 4, 3, 2, 3, 121 + BUS_MSTOP(5, BIT(10))), 122 + DEF_MOD("gtm_1_pclk", CLK_PLLCM33_DIV16, 4, 4, 2, 4, 123 + BUS_MSTOP(5, BIT(11))), 124 + DEF_MOD("gtm_2_pclk", CLK_PLLCLN_DIV16, 4, 5, 2, 5, 125 + BUS_MSTOP(2, BIT(13))), 126 + DEF_MOD("gtm_3_pclk", CLK_PLLCLN_DIV16, 4, 6, 2, 6, 127 + BUS_MSTOP(2, BIT(14))), 128 + DEF_MOD("gtm_4_pclk", CLK_PLLCLN_DIV16, 4, 7, 2, 7, 129 + BUS_MSTOP(11, BIT(13))), 130 + DEF_MOD("gtm_5_pclk", CLK_PLLCLN_DIV16, 4, 8, 2, 8, 131 + BUS_MSTOP(11, BIT(14))), 132 + DEF_MOD("gtm_6_pclk", CLK_PLLCLN_DIV16, 4, 9, 2, 9, 133 + BUS_MSTOP(11, BIT(15))), 134 + DEF_MOD("gtm_7_pclk", CLK_PLLCLN_DIV16, 4, 10, 2, 10, 135 + BUS_MSTOP(12, BIT(0))), 136 + DEF_MOD("wdt_0_clkp", CLK_PLLCM33_DIV16, 4, 11, 2, 11, 137 + BUS_MSTOP(3, BIT(10))), 138 + DEF_MOD("wdt_0_clk_loco", CLK_QEXTAL, 4, 12, 2, 12, 139 + BUS_MSTOP(3, BIT(10))), 140 + DEF_MOD("wdt_1_clkp", CLK_PLLCLN_DIV16, 4, 13, 2, 13, 141 + BUS_MSTOP(1, BIT(0))), 142 + DEF_MOD("wdt_1_clk_loco", CLK_QEXTAL, 4, 14, 2, 14, 143 + BUS_MSTOP(1, BIT(0))), 144 + DEF_MOD("wdt_2_clkp", CLK_PLLCLN_DIV16, 4, 15, 2, 15, 145 + BUS_MSTOP(5, BIT(12))), 146 + DEF_MOD("wdt_2_clk_loco", CLK_QEXTAL, 5, 0, 2, 16, 147 + BUS_MSTOP(5, BIT(12))), 148 + DEF_MOD("wdt_3_clkp", CLK_PLLCLN_DIV16, 5, 1, 2, 17, 149 + BUS_MSTOP(5, BIT(13))), 150 + DEF_MOD("wdt_3_clk_loco", CLK_QEXTAL, 5, 2, 2, 18, 151 + BUS_MSTOP(5, BIT(13))), 152 + DEF_MOD("scif_0_clk_pck", CLK_PLLCM33_DIV16, 8, 15, 4, 15, 153 + BUS_MSTOP(3, BIT(14))), 154 + DEF_MOD("riic_8_ckm", CLK_PLLCM33_DIV16, 9, 3, 4, 19, 155 + BUS_MSTOP(3, BIT(13))), 156 + DEF_MOD("riic_0_ckm", CLK_PLLCLN_DIV16, 9, 4, 4, 20, 157 + BUS_MSTOP(1, BIT(1))), 158 + DEF_MOD("riic_1_ckm", CLK_PLLCLN_DIV16, 9, 5, 4, 21, 159 + BUS_MSTOP(1, BIT(2))), 160 + DEF_MOD("riic_2_ckm", CLK_PLLCLN_DIV16, 9, 6, 4, 22, 161 + BUS_MSTOP(1, BIT(3))), 162 + DEF_MOD("riic_3_ckm", CLK_PLLCLN_DIV16, 9, 7, 4, 23, 163 + BUS_MSTOP(1, BIT(4))), 164 + DEF_MOD("riic_4_ckm", CLK_PLLCLN_DIV16, 9, 8, 4, 24, 165 + BUS_MSTOP(1, BIT(5))), 166 + DEF_MOD("riic_5_ckm", CLK_PLLCLN_DIV16, 9, 9, 4, 25, 167 + BUS_MSTOP(1, BIT(6))), 168 + DEF_MOD("riic_6_ckm", CLK_PLLCLN_DIV16, 9, 10, 4, 26, 169 + BUS_MSTOP(1, BIT(7))), 170 + DEF_MOD("riic_7_ckm", CLK_PLLCLN_DIV16, 9, 11, 4, 27, 171 + BUS_MSTOP(1, BIT(8))), 172 + DEF_MOD("sdhi_0_imclk", CLK_PLLCLN_DIV8, 10, 3, 5, 3, 173 + BUS_MSTOP(8, BIT(2))), 174 + DEF_MOD("sdhi_0_imclk2", CLK_PLLCLN_DIV8, 10, 4, 5, 4, 175 + BUS_MSTOP(8, BIT(2))), 176 + DEF_MOD("sdhi_0_clk_hs", CLK_PLLCLN_DIV2, 10, 5, 5, 5, 177 + BUS_MSTOP(8, BIT(2))), 178 + DEF_MOD("sdhi_0_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 6, 5, 6, 179 + BUS_MSTOP(8, BIT(2))), 180 + DEF_MOD("sdhi_1_imclk", CLK_PLLCLN_DIV8, 10, 7, 5, 7, 181 + BUS_MSTOP(8, BIT(3))), 182 + DEF_MOD("sdhi_1_imclk2", CLK_PLLCLN_DIV8, 10, 8, 5, 8, 183 + BUS_MSTOP(8, BIT(3))), 184 + DEF_MOD("sdhi_1_clk_hs", CLK_PLLCLN_DIV2, 10, 9, 5, 9, 185 + BUS_MSTOP(8, BIT(3))), 186 + DEF_MOD("sdhi_1_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 10, 5, 10, 187 + BUS_MSTOP(8, BIT(3))), 188 + DEF_MOD("sdhi_2_imclk", CLK_PLLCLN_DIV8, 10, 11, 5, 11, 189 + BUS_MSTOP(8, BIT(4))), 190 + DEF_MOD("sdhi_2_imclk2", CLK_PLLCLN_DIV8, 10, 12, 5, 12, 191 + BUS_MSTOP(8, BIT(4))), 192 + DEF_MOD("sdhi_2_clk_hs", CLK_PLLCLN_DIV2, 10, 13, 5, 13, 193 + BUS_MSTOP(8, BIT(4))), 194 + DEF_MOD("sdhi_2_aclk", CLK_PLLDTY_ACPU_DIV4, 10, 14, 5, 14, 195 + BUS_MSTOP(8, BIT(4))), 196 + DEF_MOD("cru_0_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 2, 6, 18, 197 + BUS_MSTOP(9, BIT(4))), 198 + DEF_MOD_NO_PM("cru_0_vclk", CLK_PLLVDO_CRU0, 13, 3, 6, 19, 199 + BUS_MSTOP(9, BIT(4))), 200 + DEF_MOD("cru_0_pclk", CLK_PLLDTY_DIV16, 13, 4, 6, 20, 201 + BUS_MSTOP(9, BIT(4))), 202 + DEF_MOD("cru_1_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 5, 6, 21, 203 + BUS_MSTOP(9, BIT(5))), 204 + DEF_MOD_NO_PM("cru_1_vclk", CLK_PLLVDO_CRU1, 13, 6, 6, 22, 205 + BUS_MSTOP(9, BIT(5))), 206 + DEF_MOD("cru_1_pclk", CLK_PLLDTY_DIV16, 13, 7, 6, 23, 207 + BUS_MSTOP(9, BIT(5))), 208 + DEF_MOD("cru_2_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 8, 6, 24, 209 + BUS_MSTOP(9, BIT(6))), 210 + DEF_MOD_NO_PM("cru_2_vclk", CLK_PLLVDO_CRU2, 13, 9, 6, 25, 211 + BUS_MSTOP(9, BIT(6))), 212 + DEF_MOD("cru_2_pclk", CLK_PLLDTY_DIV16, 13, 10, 6, 26, 213 + BUS_MSTOP(9, BIT(6))), 214 + DEF_MOD("cru_3_aclk", CLK_PLLDTY_ACPU_DIV2, 13, 11, 6, 27, 215 + BUS_MSTOP(9, BIT(7))), 216 + DEF_MOD_NO_PM("cru_3_vclk", CLK_PLLVDO_CRU3, 13, 12, 6, 28, 217 + BUS_MSTOP(9, BIT(7))), 218 + DEF_MOD("cru_3_pclk", CLK_PLLDTY_DIV16, 13, 13, 6, 29, 219 + BUS_MSTOP(9, BIT(7))), 169 220 }; 170 221 171 222 static const struct rzv2h_reset r9a09g057_resets[] __initconst = { ··· 275 224 /* Resets */ 276 225 .resets = r9a09g057_resets, 277 226 .num_resets = ARRAY_SIZE(r9a09g057_resets), 227 + 228 + .num_mstop_bits = 192, 278 229 };
+126 -22
drivers/clk/renesas/rzv2h-cpg.c
··· 23 23 #include <linux/platform_device.h> 24 24 #include <linux/pm_clock.h> 25 25 #include <linux/pm_domain.h> 26 + #include <linux/refcount.h> 26 27 #include <linux/reset-controller.h> 27 28 28 29 #include <dt-bindings/clock/renesas-cpg-mssr.h> ··· 40 39 #define GET_CLK_MON_OFFSET(x) (0x800 + ((x) * 4)) 41 40 #define GET_RST_OFFSET(x) (0x900 + ((x) * 4)) 42 41 #define GET_RST_MON_OFFSET(x) (0xA00 + ((x) * 4)) 42 + 43 + #define CPG_BUS_1_MSTOP (0xd00) 44 + #define CPG_BUS_MSTOP(m) (CPG_BUS_1_MSTOP + ((m) - 1) * 4) 43 45 44 46 #define KDIV(val) ((s16)FIELD_GET(GENMASK(31, 16), (val))) 45 47 #define MDIV(val) FIELD_GET(GENMASK(15, 6), (val)) ··· 68 64 * @resets: Array of resets 69 65 * @num_resets: Number of Module Resets in info->resets[] 70 66 * @last_dt_core_clk: ID of the last Core Clock exported to DT 67 + * @mstop_count: Array of mstop values 71 68 * @rcdev: Reset controller entity 72 69 */ 73 70 struct rzv2h_cpg_priv { ··· 82 77 struct rzv2h_reset *resets; 83 78 unsigned int num_resets; 84 79 unsigned int last_dt_core_clk; 80 + 81 + atomic_t *mstop_count; 85 82 86 83 struct reset_controller_dev rcdev; 87 84 }; ··· 104 97 * struct mod_clock - Module clock 105 98 * 106 99 * @priv: CPG private data 100 + * @mstop_data: mstop data relating to module clock 107 101 * @hw: handle between common and hardware-specific interfaces 108 102 * @no_pm: flag to indicate PM is not supported 109 103 * @on_index: register offset ··· 114 106 */ 115 107 struct mod_clock { 116 108 struct rzv2h_cpg_priv *priv; 109 + unsigned int mstop_data; 117 110 struct clk_hw hw; 118 111 bool no_pm; 119 112 u8 on_index; ··· 442 433 core->name, PTR_ERR(clk)); 443 434 } 444 435 436 + static void rzv2h_mod_clock_mstop_enable(struct rzv2h_cpg_priv *priv, 437 + u32 mstop_data) 438 + { 439 + unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, mstop_data); 440 + u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, mstop_data); 441 + unsigned int index = (mstop_index - 1) * 16; 442 + atomic_t *mstop = &priv->mstop_count[index]; 443 + unsigned long flags; 444 + unsigned int i; 445 + u32 val = 0; 446 + 447 + spin_lock_irqsave(&priv->rmw_lock, flags); 448 + for_each_set_bit(i, &mstop_mask, 16) { 449 + if (!atomic_read(&mstop[i])) 450 + val |= BIT(i) << 16; 451 + atomic_inc(&mstop[i]); 452 + } 453 + if (val) 454 + writel(val, priv->base + CPG_BUS_MSTOP(mstop_index)); 455 + spin_unlock_irqrestore(&priv->rmw_lock, flags); 456 + } 457 + 458 + static void rzv2h_mod_clock_mstop_disable(struct rzv2h_cpg_priv *priv, 459 + u32 mstop_data) 460 + { 461 + unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, mstop_data); 462 + u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, mstop_data); 463 + unsigned int index = (mstop_index - 1) * 16; 464 + atomic_t *mstop = &priv->mstop_count[index]; 465 + unsigned long flags; 466 + unsigned int i; 467 + u32 val = 0; 468 + 469 + spin_lock_irqsave(&priv->rmw_lock, flags); 470 + for_each_set_bit(i, &mstop_mask, 16) { 471 + if (!atomic_read(&mstop[i]) || 472 + atomic_dec_and_test(&mstop[i])) 473 + val |= BIT(i) << 16 | BIT(i); 474 + } 475 + if (val) 476 + writel(val, priv->base + CPG_BUS_MSTOP(mstop_index)); 477 + spin_unlock_irqrestore(&priv->rmw_lock, flags); 478 + } 479 + 480 + static int rzv2h_mod_clock_is_enabled(struct clk_hw *hw) 481 + { 482 + struct mod_clock *clock = to_mod_clock(hw); 483 + struct rzv2h_cpg_priv *priv = clock->priv; 484 + u32 bitmask; 485 + u32 offset; 486 + 487 + if (clock->mon_index >= 0) { 488 + offset = GET_CLK_MON_OFFSET(clock->mon_index); 489 + bitmask = BIT(clock->mon_bit); 490 + } else { 491 + offset = GET_CLK_ON_OFFSET(clock->on_index); 492 + bitmask = BIT(clock->on_bit); 493 + } 494 + 495 + return readl(priv->base + offset) & bitmask; 496 + } 497 + 445 498 static int rzv2h_mod_clock_endisable(struct clk_hw *hw, bool enable) 446 499 { 500 + bool enabled = rzv2h_mod_clock_is_enabled(hw); 447 501 struct mod_clock *clock = to_mod_clock(hw); 448 502 unsigned int reg = GET_CLK_ON_OFFSET(clock->on_index); 449 503 struct rzv2h_cpg_priv *priv = clock->priv; ··· 518 446 dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", reg, hw->clk, 519 447 enable ? "ON" : "OFF"); 520 448 521 - value = bitmask << 16; 522 - if (enable) 523 - value |= bitmask; 449 + if (enabled == enable) 450 + return 0; 524 451 525 - writel(value, priv->base + reg); 452 + value = bitmask << 16; 453 + if (enable) { 454 + value |= bitmask; 455 + writel(value, priv->base + reg); 456 + if (clock->mstop_data != BUS_MSTOP_NONE) 457 + rzv2h_mod_clock_mstop_enable(priv, clock->mstop_data); 458 + } else { 459 + if (clock->mstop_data != BUS_MSTOP_NONE) 460 + rzv2h_mod_clock_mstop_disable(priv, clock->mstop_data); 461 + writel(value, priv->base + reg); 462 + } 526 463 527 464 if (!enable || clock->mon_index < 0) 528 465 return 0; ··· 555 474 static void rzv2h_mod_clock_disable(struct clk_hw *hw) 556 475 { 557 476 rzv2h_mod_clock_endisable(hw, false); 558 - } 559 - 560 - static int rzv2h_mod_clock_is_enabled(struct clk_hw *hw) 561 - { 562 - struct mod_clock *clock = to_mod_clock(hw); 563 - struct rzv2h_cpg_priv *priv = clock->priv; 564 - u32 bitmask; 565 - u32 offset; 566 - 567 - if (clock->mon_index >= 0) { 568 - offset = GET_CLK_MON_OFFSET(clock->mon_index); 569 - bitmask = BIT(clock->mon_bit); 570 - } else { 571 - offset = GET_CLK_ON_OFFSET(clock->on_index); 572 - bitmask = BIT(clock->on_bit); 573 - } 574 - 575 - return readl(priv->base + offset) & bitmask; 576 477 } 577 478 578 479 static const struct clk_ops rzv2h_mod_clock_ops = { ··· 609 546 clock->no_pm = mod->no_pm; 610 547 clock->priv = priv; 611 548 clock->hw.init = &init; 549 + clock->mstop_data = mod->mstop_data; 612 550 613 551 ret = devm_clk_hw_register(dev, &clock->hw); 614 552 if (ret) { ··· 618 554 } 619 555 620 556 priv->clks[id] = clock->hw.clk; 557 + 558 + /* 559 + * Ensure the module clocks and MSTOP bits are synchronized when they are 560 + * turned ON by the bootloader. Enable MSTOP bits for module clocks that were 561 + * turned ON in an earlier boot stage. 562 + */ 563 + if (clock->mstop_data != BUS_MSTOP_NONE && 564 + !mod->critical && rzv2h_mod_clock_is_enabled(&clock->hw)) { 565 + rzv2h_mod_clock_mstop_enable(priv, clock->mstop_data); 566 + } else if (clock->mstop_data != BUS_MSTOP_NONE && mod->critical) { 567 + unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, clock->mstop_data); 568 + u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, clock->mstop_data); 569 + unsigned int index = (mstop_index - 1) * 16; 570 + atomic_t *mstop = &priv->mstop_count[index]; 571 + unsigned long flags; 572 + unsigned int i; 573 + u32 val = 0; 574 + 575 + /* 576 + * Critical clocks are turned ON immediately upon registration, and the 577 + * MSTOP counter is updated through the rzv2h_mod_clock_enable() path. 578 + * However, if the critical clocks were already turned ON by the initial 579 + * bootloader, synchronize the atomic counter here and clear the MSTOP bit. 580 + */ 581 + spin_lock_irqsave(&priv->rmw_lock, flags); 582 + for_each_set_bit(i, &mstop_mask, 16) { 583 + if (atomic_read(&mstop[i])) 584 + continue; 585 + val |= BIT(i) << 16; 586 + atomic_inc(&mstop[i]); 587 + } 588 + if (val) 589 + writel(val, priv->base + CPG_BUS_MSTOP(mstop_index)); 590 + spin_unlock_irqrestore(&priv->rmw_lock, flags); 591 + } 621 592 622 593 return; 623 594 ··· 919 820 nclks = info->num_total_core_clks + info->num_hw_mod_clks; 920 821 clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL); 921 822 if (!clks) 823 + return -ENOMEM; 824 + 825 + priv->mstop_count = devm_kcalloc(dev, info->num_mstop_bits, 826 + sizeof(*priv->mstop_count), GFP_KERNEL); 827 + if (!priv->mstop_count) 922 828 return -ENOMEM; 923 829 924 830 priv->resets = devm_kmemdup(dev, info->resets, sizeof(*info->resets) *
+23 -7
drivers/clk/renesas/rzv2h-cpg.h
··· 8 8 #ifndef __RENESAS_RZV2H_CPG_H__ 9 9 #define __RENESAS_RZV2H_CPG_H__ 10 10 11 + #include <linux/bitfield.h> 12 + 11 13 /** 12 14 * struct ddiv - Structure for dynamic switching divider 13 15 * ··· 47 45 #define CDDIV4_DIVCTL0 DDIV_PACK(CPG_CDDIV4, 0, 1, 16) 48 46 #define CDDIV4_DIVCTL1 DDIV_PACK(CPG_CDDIV4, 4, 1, 17) 49 47 #define CDDIV4_DIVCTL2 DDIV_PACK(CPG_CDDIV4, 8, 1, 18) 48 + 49 + #define BUS_MSTOP_IDX_MASK GENMASK(31, 16) 50 + #define BUS_MSTOP_BITS_MASK GENMASK(15, 0) 51 + #define BUS_MSTOP(idx, mask) (FIELD_PREP_CONST(BUS_MSTOP_IDX_MASK, (idx)) | \ 52 + FIELD_PREP_CONST(BUS_MSTOP_BITS_MASK, (mask))) 53 + #define BUS_MSTOP_NONE GENMASK(31, 0) 50 54 51 55 /** 52 56 * Definitions of CPG Core Clocks ··· 112 104 * struct rzv2h_mod_clk - Module Clocks definitions 113 105 * 114 106 * @name: handle between common and hardware-specific interfaces 107 + * @mstop_data: packed data mstop register offset and mask 115 108 * @parent: id of parent clock 116 109 * @critical: flag to indicate the clock is critical 117 110 * @no_pm: flag to indicate PM is not supported ··· 123 114 */ 124 115 struct rzv2h_mod_clk { 125 116 const char *name; 117 + u32 mstop_data; 126 118 u16 parent; 127 119 bool critical; 128 120 bool no_pm; ··· 133 123 u8 mon_bit; 134 124 }; 135 125 136 - #define DEF_MOD_BASE(_name, _parent, _critical, _no_pm, _onindex, _onbit, _monindex, _monbit) \ 126 + #define DEF_MOD_BASE(_name, _mstop, _parent, _critical, _no_pm, _onindex, _onbit, _monindex, _monbit) \ 137 127 { \ 138 128 .name = (_name), \ 129 + .mstop_data = (_mstop), \ 139 130 .parent = (_parent), \ 140 131 .critical = (_critical), \ 141 132 .no_pm = (_no_pm), \ ··· 146 135 .mon_bit = (_monbit), \ 147 136 } 148 137 149 - #define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit) \ 150 - DEF_MOD_BASE(_name, _parent, false, false, _onindex, _onbit, _monindex, _monbit) 138 + #define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \ 139 + DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit) 151 140 152 - #define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex, _monbit) \ 153 - DEF_MOD_BASE(_name, _parent, true, false, _onindex, _onbit, _monindex, _monbit) 141 + #define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \ 142 + DEF_MOD_BASE(_name, _mstop, _parent, true, false, _onindex, _onbit, _monindex, _monbit) 154 143 155 - #define DEF_MOD_NO_PM(_name, _parent, _onindex, _onbit, _monindex, _monbit) \ 156 - DEF_MOD_BASE(_name, _parent, false, true, _onindex, _onbit, _monindex, _monbit) 144 + #define DEF_MOD_NO_PM(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \ 145 + DEF_MOD_BASE(_name, _mstop, _parent, false, true, _onindex, _onbit, _monindex, _monbit) 157 146 158 147 /** 159 148 * struct rzv2h_reset - Reset definitions ··· 195 184 * 196 185 * @resets: Array of Module Reset definitions 197 186 * @num_resets: Number of entries in resets[] 187 + * 188 + * @num_mstop_bits: Maximum number of MSTOP bits supported, equivalent to the 189 + * number of CPG_BUS_m_MSTOP registers multiplied by 16. 198 190 */ 199 191 struct rzv2h_cpg_info { 200 192 /* Core Clocks */ ··· 214 200 /* Resets */ 215 201 const struct rzv2h_reset *resets; 216 202 unsigned int num_resets; 203 + 204 + unsigned int num_mstop_bits; 217 205 }; 218 206 219 207 extern const struct rzv2h_cpg_info r9a09g057_cpg_info;