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

clk: rockchip: support more core div setting

Use arrays to support more core independent div settings.
A55 supports each core to work at different frequencies, and each core
has an independent divider control.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
Link: https://lore.kernel.org/r/20210315085608.16010-4-zhangqing@rock-chips.com
Signed-off-by: Heiko Stuebner <heiko@sntech.de>

authored by

Elaine Zhang and committed by
Heiko Stuebner
a3561e77 0cd74eec

+98 -77
+29 -24
drivers/clk/rockchip/clk-cpu.c
··· 84 84 { 85 85 struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_hw(hw); 86 86 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; 87 - u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg); 87 + u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg[0]); 88 88 89 - clksel0 >>= reg_data->div_core_shift; 90 - clksel0 &= reg_data->div_core_mask; 89 + clksel0 >>= reg_data->div_core_shift[0]; 90 + clksel0 &= reg_data->div_core_mask[0]; 91 91 return parent_rate / (clksel0 + 1); 92 92 } 93 93 ··· 120 120 const struct rockchip_cpuclk_rate_table *rate; 121 121 unsigned long alt_prate, alt_div; 122 122 unsigned long flags; 123 + int i = 0; 123 124 124 125 /* check validity of the new rate */ 125 126 rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate); ··· 143 142 if (alt_prate > ndata->old_rate) { 144 143 /* calculate dividers */ 145 144 alt_div = DIV_ROUND_UP(alt_prate, ndata->old_rate) - 1; 146 - if (alt_div > reg_data->div_core_mask) { 145 + if (alt_div > reg_data->div_core_mask[0]) { 147 146 pr_warn("%s: limiting alt-divider %lu to %d\n", 148 - __func__, alt_div, reg_data->div_core_mask); 149 - alt_div = reg_data->div_core_mask; 147 + __func__, alt_div, reg_data->div_core_mask[0]); 148 + alt_div = reg_data->div_core_mask[0]; 150 149 } 151 150 152 151 /* ··· 159 158 pr_debug("%s: setting div %lu as alt-rate %lu > old-rate %lu\n", 160 159 __func__, alt_div, alt_prate, ndata->old_rate); 161 160 162 - writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask, 163 - reg_data->div_core_shift) | 164 - HIWORD_UPDATE(reg_data->mux_core_alt, 165 - reg_data->mux_core_mask, 166 - reg_data->mux_core_shift), 167 - cpuclk->reg_base + reg_data->core_reg); 168 - } else { 169 - /* select alternate parent */ 170 - writel(HIWORD_UPDATE(reg_data->mux_core_alt, 171 - reg_data->mux_core_mask, 172 - reg_data->mux_core_shift), 173 - cpuclk->reg_base + reg_data->core_reg); 161 + for (i = 0; i < reg_data->num_cores; i++) { 162 + writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask[i], 163 + reg_data->div_core_shift[i]), 164 + cpuclk->reg_base + reg_data->core_reg[i]); 165 + } 174 166 } 167 + /* select alternate parent */ 168 + writel(HIWORD_UPDATE(reg_data->mux_core_alt, 169 + reg_data->mux_core_mask, 170 + reg_data->mux_core_shift), 171 + cpuclk->reg_base + reg_data->core_reg[0]); 175 172 176 173 spin_unlock_irqrestore(cpuclk->lock, flags); 177 174 return 0; ··· 181 182 const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; 182 183 const struct rockchip_cpuclk_rate_table *rate; 183 184 unsigned long flags; 185 + int i = 0; 184 186 185 187 rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate); 186 188 if (!rate) { ··· 202 202 * primary parent by the extra dividers that were needed for the alt. 203 203 */ 204 204 205 - writel(HIWORD_UPDATE(0, reg_data->div_core_mask, 206 - reg_data->div_core_shift) | 207 - HIWORD_UPDATE(reg_data->mux_core_main, 208 - reg_data->mux_core_mask, 209 - reg_data->mux_core_shift), 210 - cpuclk->reg_base + reg_data->core_reg); 205 + writel(HIWORD_UPDATE(reg_data->mux_core_main, 206 + reg_data->mux_core_mask, 207 + reg_data->mux_core_shift), 208 + cpuclk->reg_base + reg_data->core_reg[0]); 209 + 210 + /* remove dividers */ 211 + for (i = 0; i < reg_data->num_cores; i++) { 212 + writel(HIWORD_UPDATE(0, reg_data->div_core_mask[i], 213 + reg_data->div_core_shift[i]), 214 + cpuclk->reg_base + reg_data->core_reg[i]); 215 + } 211 216 212 217 if (ndata->old_rate > ndata->new_rate) 213 218 rockchip_cpuclk_set_dividers(cpuclk, rate);
+4 -3
drivers/clk/rockchip/clk-px30.c
··· 124 124 }; 125 125 126 126 static const struct rockchip_cpuclk_reg_data px30_cpuclk_data = { 127 - .core_reg = PX30_CLKSEL_CON(0), 128 - .div_core_shift = 0, 129 - .div_core_mask = 0xf, 127 + .core_reg[0] = PX30_CLKSEL_CON(0), 128 + .div_core_shift[0] = 0, 129 + .div_core_mask[0] = 0xf, 130 + .num_cores = 1, 130 131 .mux_core_alt = 1, 131 132 .mux_core_main = 0, 132 133 .mux_core_shift = 7,
+4 -3
drivers/clk/rockchip/clk-rk3036.c
··· 102 102 }; 103 103 104 104 static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = { 105 - .core_reg = RK2928_CLKSEL_CON(0), 106 - .div_core_shift = 0, 107 - .div_core_mask = 0x1f, 105 + .core_reg[0] = RK2928_CLKSEL_CON(0), 106 + .div_core_shift[0] = 0, 107 + .div_core_mask[0] = 0x1f, 108 + .num_cores = 1, 108 109 .mux_core_alt = 1, 109 110 .mux_core_main = 0, 110 111 .mux_core_shift = 7,
+4 -3
drivers/clk/rockchip/clk-rk3128.c
··· 117 117 }; 118 118 119 119 static const struct rockchip_cpuclk_reg_data rk3128_cpuclk_data = { 120 - .core_reg = RK2928_CLKSEL_CON(0), 121 - .div_core_shift = 0, 122 - .div_core_mask = 0x1f, 120 + .core_reg[0] = RK2928_CLKSEL_CON(0), 121 + .div_core_shift[0] = 0, 122 + .div_core_mask[0] = 0x1f, 123 + .num_cores = 1, 123 124 .mux_core_alt = 1, 124 125 .mux_core_main = 0, 125 126 .mux_core_shift = 7,
+8 -6
drivers/clk/rockchip/clk-rk3188.c
··· 145 145 }; 146 146 147 147 static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = { 148 - .core_reg = RK2928_CLKSEL_CON(0), 149 - .div_core_shift = 0, 150 - .div_core_mask = 0x1f, 148 + .core_reg[0] = RK2928_CLKSEL_CON(0), 149 + .div_core_shift[0] = 0, 150 + .div_core_mask[0] = 0x1f, 151 + .num_cores = 1, 151 152 .mux_core_alt = 1, 152 153 .mux_core_main = 0, 153 154 .mux_core_shift = 8, ··· 185 184 }; 186 185 187 186 static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = { 188 - .core_reg = RK2928_CLKSEL_CON(0), 189 - .div_core_shift = 9, 190 - .div_core_mask = 0x1f, 187 + .core_reg[0] = RK2928_CLKSEL_CON(0), 188 + .div_core_shift[0] = 9, 189 + .div_core_mask[0] = 0x1f, 190 + .num_cores = 1, 191 191 .mux_core_alt = 1, 192 192 .mux_core_main = 0, 193 193 .mux_core_shift = 8,
+4 -3
drivers/clk/rockchip/clk-rk3228.c
··· 119 119 }; 120 120 121 121 static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = { 122 - .core_reg = RK2928_CLKSEL_CON(0), 123 - .div_core_shift = 0, 124 - .div_core_mask = 0x1f, 122 + .core_reg[0] = RK2928_CLKSEL_CON(0), 123 + .div_core_shift[0] = 0, 124 + .div_core_mask[0] = 0x1f, 125 + .num_cores = 1, 125 126 .mux_core_alt = 1, 126 127 .mux_core_main = 0, 127 128 .mux_core_shift = 6,
+4 -3
drivers/clk/rockchip/clk-rk3288.c
··· 179 179 }; 180 180 181 181 static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = { 182 - .core_reg = RK3288_CLKSEL_CON(0), 183 - .div_core_shift = 8, 184 - .div_core_mask = 0x1f, 182 + .core_reg[0] = RK3288_CLKSEL_CON(0), 183 + .div_core_shift[0] = 8, 184 + .div_core_mask[0] = 0x1f, 185 + .num_cores = 1, 185 186 .mux_core_alt = 1, 186 187 .mux_core_main = 0, 187 188 .mux_core_shift = 15,
+4 -3
drivers/clk/rockchip/clk-rk3308.c
··· 109 109 }; 110 110 111 111 static const struct rockchip_cpuclk_reg_data rk3308_cpuclk_data = { 112 - .core_reg = RK3308_CLKSEL_CON(0), 113 - .div_core_shift = 0, 114 - .div_core_mask = 0xf, 112 + .core_reg[0] = RK3308_CLKSEL_CON(0), 113 + .div_core_shift[0] = 0, 114 + .div_core_mask[0] = 0xf, 115 + .num_cores = 1, 115 116 .mux_core_alt = 1, 116 117 .mux_core_main = 0, 117 118 .mux_core_shift = 6,
+4 -3
drivers/clk/rockchip/clk-rk3328.c
··· 130 130 }; 131 131 132 132 static const struct rockchip_cpuclk_reg_data rk3328_cpuclk_data = { 133 - .core_reg = RK3328_CLKSEL_CON(0), 134 - .div_core_shift = 0, 135 - .div_core_mask = 0x1f, 133 + .core_reg[0] = RK3328_CLKSEL_CON(0), 134 + .div_core_shift[0] = 0, 135 + .div_core_mask[0] = 0x1f, 136 + .num_cores = 1, 136 137 .mux_core_alt = 1, 137 138 .mux_core_main = 3, 138 139 .mux_core_shift = 6,
+8 -6
drivers/clk/rockchip/clk-rk3368.c
··· 154 154 #define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK 155 155 156 156 static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = { 157 - .core_reg = RK3368_CLKSEL_CON(0), 158 - .div_core_shift = 0, 159 - .div_core_mask = 0x1f, 157 + .core_reg[0] = RK3368_CLKSEL_CON(0), 158 + .div_core_shift[0] = 0, 159 + .div_core_mask[0] = 0x1f, 160 + .num_cores = 1, 160 161 .mux_core_alt = 1, 161 162 .mux_core_main = 0, 162 163 .mux_core_shift = 7, ··· 165 164 }; 166 165 167 166 static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = { 168 - .core_reg = RK3368_CLKSEL_CON(2), 169 - .div_core_shift = 0, 167 + .core_reg[0] = RK3368_CLKSEL_CON(2), 168 + .div_core_shift[0] = 0, 170 169 .mux_core_alt = 1, 170 + .num_cores = 1, 171 171 .mux_core_main = 0, 172 - .div_core_mask = 0x1f, 172 + .div_core_mask[0] = 0x1f, 173 173 .mux_core_shift = 7, 174 174 .mux_core_mask = 0x1, 175 175 };
+8 -6
drivers/clk/rockchip/clk-rk3399.c
··· 291 291 RK3399_PMU_CLKSEL_CON(1), 14, 1, MFLAGS); 292 292 293 293 static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = { 294 - .core_reg = RK3399_CLKSEL_CON(0), 295 - .div_core_shift = 0, 296 - .div_core_mask = 0x1f, 294 + .core_reg[0] = RK3399_CLKSEL_CON(0), 295 + .div_core_shift[0] = 0, 296 + .div_core_mask[0] = 0x1f, 297 + .num_cores = 1, 297 298 .mux_core_alt = 3, 298 299 .mux_core_main = 0, 299 300 .mux_core_shift = 6, ··· 302 301 }; 303 302 304 303 static const struct rockchip_cpuclk_reg_data rk3399_cpuclkb_data = { 305 - .core_reg = RK3399_CLKSEL_CON(2), 306 - .div_core_shift = 0, 307 - .div_core_mask = 0x1f, 304 + .core_reg[0] = RK3399_CLKSEL_CON(2), 305 + .div_core_shift[0] = 0, 306 + .div_core_mask[0] = 0x1f, 307 + .num_cores = 1, 308 308 .mux_core_alt = 3, 309 309 .mux_core_main = 1, 310 310 .mux_core_shift = 6,
+4 -3
drivers/clk/rockchip/clk-rv1108.c
··· 106 106 }; 107 107 108 108 static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { 109 - .core_reg = RV1108_CLKSEL_CON(0), 110 - .div_core_shift = 0, 111 - .div_core_mask = 0x1f, 109 + .core_reg[0] = RV1108_CLKSEL_CON(0), 110 + .div_core_shift[0] = 0, 111 + .div_core_mask[0] = 0x1f, 112 + .num_cores = 1, 112 113 .mux_core_alt = 1, 113 114 .mux_core_main = 0, 114 115 .mux_core_shift = 8,
+13 -11
drivers/clk/rockchip/clk.h
··· 323 323 }; 324 324 325 325 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 326 + #define ROCKCHIP_CPUCLK_MAX_CORES 4 326 327 struct rockchip_cpuclk_rate_table { 327 328 unsigned long prate; 328 329 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; ··· 331 330 332 331 /** 333 332 * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock 334 - * @core_reg: register offset of the core settings register 335 - * @div_core_shift: core divider offset used to divide the pll value 336 - * @div_core_mask: core divider mask 337 - * @mux_core_alt: mux value to select alternate parent 333 + * @core_reg[]: register offset of the cores setting register 334 + * @div_core_shift[]: cores divider offset used to divide the pll value 335 + * @div_core_mask[]: cores divider mask 336 + * @num_cores: number of cpu cores 338 337 * @mux_core_main: mux value to select main parent of core 339 338 * @mux_core_shift: offset of the core multiplexer 340 339 * @mux_core_mask: core multiplexer mask 341 340 */ 342 341 struct rockchip_cpuclk_reg_data { 343 - int core_reg; 344 - u8 div_core_shift; 345 - u32 div_core_mask; 346 - u8 mux_core_alt; 347 - u8 mux_core_main; 348 - u8 mux_core_shift; 349 - u32 mux_core_mask; 342 + int core_reg[ROCKCHIP_CPUCLK_MAX_CORES]; 343 + u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES]; 344 + u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES]; 345 + int num_cores; 346 + u8 mux_core_alt; 347 + u8 mux_core_main; 348 + u8 mux_core_shift; 349 + u32 mux_core_mask; 350 350 }; 351 351 352 352 struct clk *rockchip_clk_register_cpuclk(const char *name,