1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * CPU frequency scaling support for Armada 37xx platform. 4 * 5 * Copyright (C) 2017 Marvell 6 * 7 * Gregory CLEMENT <gregory.clement@free-electrons.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/cpu.h> 12 #include <linux/cpufreq.h> 13 #include <linux/err.h> 14 #include <linux/interrupt.h> 15 #include <linux/io.h> 16 #include <linux/mfd/syscon.h> 17 #include <linux/module.h> 18 #include <linux/of_address.h> 19 #include <linux/of_device.h> 20 #include <linux/of_irq.h> 21 #include <linux/platform_device.h> 22 #include <linux/pm_opp.h> 23 #include <linux/regmap.h> 24 #include <linux/slab.h> 25 26 #include "cpufreq-dt.h" 27 28 /* Clk register set */ 29 #define ARMADA_37XX_CLK_TBG_SEL 0 30 #define ARMADA_37XX_CLK_TBG_SEL_CPU_OFF 22 31 32 /* Power management in North Bridge register set */ 33 #define ARMADA_37XX_NB_L0L1 0x18 34 #define ARMADA_37XX_NB_L2L3 0x1C 35 #define ARMADA_37XX_NB_TBG_DIV_OFF 13 36 #define ARMADA_37XX_NB_TBG_DIV_MASK 0x7 37 #define ARMADA_37XX_NB_CLK_SEL_OFF 11 38 #define ARMADA_37XX_NB_CLK_SEL_MASK 0x1 39 #define ARMADA_37XX_NB_CLK_SEL_TBG 0x1 40 #define ARMADA_37XX_NB_TBG_SEL_OFF 9 41 #define ARMADA_37XX_NB_TBG_SEL_MASK 0x3 42 #define ARMADA_37XX_NB_VDD_SEL_OFF 6 43 #define ARMADA_37XX_NB_VDD_SEL_MASK 0x3 44 #define ARMADA_37XX_NB_CONFIG_SHIFT 16 45 #define ARMADA_37XX_NB_DYN_MOD 0x24 46 #define ARMADA_37XX_NB_CLK_SEL_EN BIT(26) 47 #define ARMADA_37XX_NB_TBG_EN BIT(28) 48 #define ARMADA_37XX_NB_DIV_EN BIT(29) 49 #define ARMADA_37XX_NB_VDD_EN BIT(30) 50 #define ARMADA_37XX_NB_DFS_EN BIT(31) 51 #define ARMADA_37XX_NB_CPU_LOAD 0x30 52 #define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3 53 #define ARMADA_37XX_DVFS_LOAD_0 0 54 #define ARMADA_37XX_DVFS_LOAD_1 1 55 #define ARMADA_37XX_DVFS_LOAD_2 2 56 #define ARMADA_37XX_DVFS_LOAD_3 3 57 58 /* AVS register set */ 59 #define ARMADA_37XX_AVS_CTL0 0x0 60 #define ARMADA_37XX_AVS_ENABLE BIT(30) 61 #define ARMADA_37XX_AVS_HIGH_VDD_LIMIT 16 62 #define ARMADA_37XX_AVS_LOW_VDD_LIMIT 22 63 #define ARMADA_37XX_AVS_VDD_MASK 0x3F 64 #define ARMADA_37XX_AVS_CTL2 0x8 65 #define ARMADA_37XX_AVS_LOW_VDD_EN BIT(6) 66 #define ARMADA_37XX_AVS_VSET(x) (0x1C + 4 * (x)) 67 68 /* 69 * On Armada 37xx the Power management manages 4 level of CPU load, 70 * each level can be associated with a CPU clock source, a CPU 71 * divider, a VDD level, etc... 72 */ 73 #define LOAD_LEVEL_NR 4 74 75 #define MIN_VOLT_MV 1000 76 77 /* AVS value for the corresponding voltage (in mV) */ 78 static int avs_map[] = { 79 747, 758, 770, 782, 793, 805, 817, 828, 840, 852, 863, 875, 887, 898, 80 910, 922, 933, 945, 957, 968, 980, 992, 1003, 1015, 1027, 1038, 1050, 81 1062, 1073, 1085, 1097, 1108, 1120, 1132, 1143, 1155, 1167, 1178, 1190, 82 1202, 1213, 1225, 1237, 1248, 1260, 1272, 1283, 1295, 1307, 1318, 1330, 83 1342 84 }; 85 86 struct armada37xx_cpufreq_state { 87 struct regmap *regmap; 88 u32 nb_l0l1; 89 u32 nb_l2l3; 90 u32 nb_dyn_mod; 91 u32 nb_cpu_load; 92 }; 93 94 static struct armada37xx_cpufreq_state *armada37xx_cpufreq_state; 95 96 struct armada_37xx_dvfs { 97 u32 cpu_freq_max; 98 u8 divider[LOAD_LEVEL_NR]; 99 u32 avs[LOAD_LEVEL_NR]; 100 }; 101 102 static struct armada_37xx_dvfs armada_37xx_dvfs[] = { 103 {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, 104 {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} }, 105 {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} }, 106 {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} }, 107 }; 108 109 static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq) 110 { 111 int i; 112 113 for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) { 114 if (freq == armada_37xx_dvfs[i].cpu_freq_max) 115 return &armada_37xx_dvfs[i]; 116 } 117 118 pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000); 119 return NULL; 120 } 121 122 /* 123 * Setup the four level managed by the hardware. Once the four level 124 * will be configured then the DVFS will be enabled. 125 */ 126 static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, 127 struct regmap *clk_base, u8 *divider) 128 { 129 u32 cpu_tbg_sel; 130 int load_lvl; 131 132 /* Determine to which TBG clock is CPU connected */ 133 regmap_read(clk_base, ARMADA_37XX_CLK_TBG_SEL, &cpu_tbg_sel); 134 cpu_tbg_sel >>= ARMADA_37XX_CLK_TBG_SEL_CPU_OFF; 135 cpu_tbg_sel &= ARMADA_37XX_NB_TBG_SEL_MASK; 136 137 for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) { 138 unsigned int reg, mask, val, offset = 0; 139 140 if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1) 141 reg = ARMADA_37XX_NB_L0L1; 142 else 143 reg = ARMADA_37XX_NB_L2L3; 144 145 if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 || 146 load_lvl == ARMADA_37XX_DVFS_LOAD_2) 147 offset += ARMADA_37XX_NB_CONFIG_SHIFT; 148 149 /* Set cpu clock source, for all the level we use TBG */ 150 val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF; 151 mask = (ARMADA_37XX_NB_CLK_SEL_MASK 152 << ARMADA_37XX_NB_CLK_SEL_OFF); 153 154 /* Set TBG index, for all levels we use the same TBG */ 155 val = cpu_tbg_sel << ARMADA_37XX_NB_TBG_SEL_OFF; 156 mask = (ARMADA_37XX_NB_TBG_SEL_MASK 157 << ARMADA_37XX_NB_TBG_SEL_OFF); 158 159 /* 160 * Set cpu divider based on the pre-computed array in 161 * order to have balanced step. 162 */ 163 val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF; 164 mask |= (ARMADA_37XX_NB_TBG_DIV_MASK 165 << ARMADA_37XX_NB_TBG_DIV_OFF); 166 167 /* Set VDD divider which is actually the load level. */ 168 val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF; 169 mask |= (ARMADA_37XX_NB_VDD_SEL_MASK 170 << ARMADA_37XX_NB_VDD_SEL_OFF); 171 172 val <<= offset; 173 mask <<= offset; 174 175 regmap_update_bits(base, reg, mask, val); 176 } 177 } 178 179 /* 180 * Find out the armada 37x supported AVS value whose voltage value is 181 * the round-up closest to the target voltage value. 182 */ 183 static u32 armada_37xx_avs_val_match(int target_vm) 184 { 185 u32 avs; 186 187 /* Find out the round-up closest supported voltage value */ 188 for (avs = 0; avs < ARRAY_SIZE(avs_map); avs++) 189 if (avs_map[avs] >= target_vm) 190 break; 191 192 /* 193 * If all supported voltages are smaller than target one, 194 * choose the largest supported voltage 195 */ 196 if (avs == ARRAY_SIZE(avs_map)) 197 avs = ARRAY_SIZE(avs_map) - 1; 198 199 return avs; 200 } 201 202 /* 203 * For Armada 37xx soc, L0(VSET0) VDD AVS value is set to SVC revision 204 * value or a default value when SVC is not supported. 205 * - L0 can be read out from the register of AVS_CTRL_0 and L0 voltage 206 * can be got from the mapping table of avs_map. 207 * - L1 voltage should be about 100mv smaller than L0 voltage 208 * - L2 & L3 voltage should be about 150mv smaller than L0 voltage. 209 * This function calculates L1 & L2 & L3 AVS values dynamically based 210 * on L0 voltage and fill all AVS values to the AVS value table. 211 */ 212 static void __init armada37xx_cpufreq_avs_configure(struct regmap *base, 213 struct armada_37xx_dvfs *dvfs) 214 { 215 unsigned int target_vm; 216 int load_level = 0; 217 u32 l0_vdd_min; 218 219 if (base == NULL) 220 return; 221 222 /* Get L0 VDD min value */ 223 regmap_read(base, ARMADA_37XX_AVS_CTL0, &l0_vdd_min); 224 l0_vdd_min = (l0_vdd_min >> ARMADA_37XX_AVS_LOW_VDD_LIMIT) & 225 ARMADA_37XX_AVS_VDD_MASK; 226 if (l0_vdd_min >= ARRAY_SIZE(avs_map)) { 227 pr_err("L0 VDD MIN %d is not correct.\n", l0_vdd_min); 228 return; 229 } 230 dvfs->avs[0] = l0_vdd_min; 231 232 if (avs_map[l0_vdd_min] <= MIN_VOLT_MV) { 233 /* 234 * If L0 voltage is smaller than 1000mv, then all VDD sets 235 * use L0 voltage; 236 */ 237 u32 avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV); 238 239 for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++) 240 dvfs->avs[load_level] = avs_min; 241 242 return; 243 } 244 245 /* 246 * L1 voltage is equal to L0 voltage - 100mv and it must be 247 * larger than 1000mv 248 */ 249 250 target_vm = avs_map[l0_vdd_min] - 100; 251 target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV; 252 dvfs->avs[1] = armada_37xx_avs_val_match(target_vm); 253 254 /* 255 * L2 & L3 voltage is equal to L0 voltage - 150mv and it must 256 * be larger than 1000mv 257 */ 258 target_vm = avs_map[l0_vdd_min] - 150; 259 target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV; 260 dvfs->avs[2] = dvfs->avs[3] = armada_37xx_avs_val_match(target_vm); 261 } 262 263 static void __init armada37xx_cpufreq_avs_setup(struct regmap *base, 264 struct armada_37xx_dvfs *dvfs) 265 { 266 unsigned int avs_val = 0; 267 int load_level = 0; 268 269 if (base == NULL) 270 return; 271 272 /* Disable AVS before the configuration */ 273 regmap_update_bits(base, ARMADA_37XX_AVS_CTL0, 274 ARMADA_37XX_AVS_ENABLE, 0); 275 276 277 /* Enable low voltage mode */ 278 regmap_update_bits(base, ARMADA_37XX_AVS_CTL2, 279 ARMADA_37XX_AVS_LOW_VDD_EN, 280 ARMADA_37XX_AVS_LOW_VDD_EN); 281 282 283 for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++) { 284 avs_val = dvfs->avs[load_level]; 285 regmap_update_bits(base, ARMADA_37XX_AVS_VSET(load_level-1), 286 ARMADA_37XX_AVS_VDD_MASK << ARMADA_37XX_AVS_HIGH_VDD_LIMIT | 287 ARMADA_37XX_AVS_VDD_MASK << ARMADA_37XX_AVS_LOW_VDD_LIMIT, 288 avs_val << ARMADA_37XX_AVS_HIGH_VDD_LIMIT | 289 avs_val << ARMADA_37XX_AVS_LOW_VDD_LIMIT); 290 } 291 292 /* Enable AVS after the configuration */ 293 regmap_update_bits(base, ARMADA_37XX_AVS_CTL0, 294 ARMADA_37XX_AVS_ENABLE, 295 ARMADA_37XX_AVS_ENABLE); 296 297 } 298 299 static void armada37xx_cpufreq_disable_dvfs(struct regmap *base) 300 { 301 unsigned int reg = ARMADA_37XX_NB_DYN_MOD, 302 mask = ARMADA_37XX_NB_DFS_EN; 303 304 regmap_update_bits(base, reg, mask, 0); 305 } 306 307 static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base) 308 { 309 unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD, 310 mask = ARMADA_37XX_NB_CPU_LOAD_MASK; 311 312 /* Start with the highest load (0) */ 313 val = ARMADA_37XX_DVFS_LOAD_0; 314 regmap_update_bits(base, reg, mask, val); 315 316 /* Now enable DVFS for the CPUs */ 317 reg = ARMADA_37XX_NB_DYN_MOD; 318 mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN | 319 ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN | 320 ARMADA_37XX_NB_DFS_EN; 321 322 regmap_update_bits(base, reg, mask, mask); 323 } 324 325 static int armada37xx_cpufreq_suspend(struct cpufreq_policy *policy) 326 { 327 struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state; 328 329 regmap_read(state->regmap, ARMADA_37XX_NB_L0L1, &state->nb_l0l1); 330 regmap_read(state->regmap, ARMADA_37XX_NB_L2L3, &state->nb_l2l3); 331 regmap_read(state->regmap, ARMADA_37XX_NB_CPU_LOAD, 332 &state->nb_cpu_load); 333 regmap_read(state->regmap, ARMADA_37XX_NB_DYN_MOD, &state->nb_dyn_mod); 334 335 return 0; 336 } 337 338 static int armada37xx_cpufreq_resume(struct cpufreq_policy *policy) 339 { 340 struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state; 341 342 /* Ensure DVFS is disabled otherwise the following registers are RO */ 343 armada37xx_cpufreq_disable_dvfs(state->regmap); 344 345 regmap_write(state->regmap, ARMADA_37XX_NB_L0L1, state->nb_l0l1); 346 regmap_write(state->regmap, ARMADA_37XX_NB_L2L3, state->nb_l2l3); 347 regmap_write(state->regmap, ARMADA_37XX_NB_CPU_LOAD, 348 state->nb_cpu_load); 349 350 /* 351 * NB_DYN_MOD register is the one that actually enable back DVFS if it 352 * was enabled before the suspend operation. This must be done last 353 * otherwise other registers are not writable. 354 */ 355 regmap_write(state->regmap, ARMADA_37XX_NB_DYN_MOD, state->nb_dyn_mod); 356 357 return 0; 358 } 359 360 static int __init armada37xx_cpufreq_driver_init(void) 361 { 362 struct cpufreq_dt_platform_data pdata; 363 struct armada_37xx_dvfs *dvfs; 364 struct platform_device *pdev; 365 unsigned long freq; 366 unsigned int cur_frequency, base_frequency; 367 struct regmap *nb_clk_base, *nb_pm_base, *avs_base; 368 struct device *cpu_dev; 369 int load_lvl, ret; 370 struct clk *clk, *parent; 371 372 nb_clk_base = 373 syscon_regmap_lookup_by_compatible("marvell,armada-3700-periph-clock-nb"); 374 if (IS_ERR(nb_clk_base)) 375 return -ENODEV; 376 377 nb_pm_base = 378 syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm"); 379 380 if (IS_ERR(nb_pm_base)) 381 return -ENODEV; 382 383 avs_base = 384 syscon_regmap_lookup_by_compatible("marvell,armada-3700-avs"); 385 386 /* if AVS is not present don't use it but still try to setup dvfs */ 387 if (IS_ERR(avs_base)) { 388 pr_info("Syscon failed for Adapting Voltage Scaling: skip it\n"); 389 avs_base = NULL; 390 } 391 /* Before doing any configuration on the DVFS first, disable it */ 392 armada37xx_cpufreq_disable_dvfs(nb_pm_base); 393 394 /* 395 * On CPU 0 register the operating points supported (which are 396 * the nominal CPU frequency and full integer divisions of 397 * it). 398 */ 399 cpu_dev = get_cpu_device(0); 400 if (!cpu_dev) { 401 dev_err(cpu_dev, "Cannot get CPU\n"); 402 return -ENODEV; 403 } 404 405 clk = clk_get(cpu_dev, 0); 406 if (IS_ERR(clk)) { 407 dev_err(cpu_dev, "Cannot get clock for CPU0\n"); 408 return PTR_ERR(clk); 409 } 410 411 parent = clk_get_parent(clk); 412 if (IS_ERR(parent)) { 413 dev_err(cpu_dev, "Cannot get parent clock for CPU0\n"); 414 clk_put(clk); 415 return PTR_ERR(parent); 416 } 417 418 /* Get parent CPU frequency */ 419 base_frequency = clk_get_rate(parent); 420 421 if (!base_frequency) { 422 dev_err(cpu_dev, "Failed to get parent clock rate for CPU\n"); 423 clk_put(clk); 424 return -EINVAL; 425 } 426 427 /* Get nominal (current) CPU frequency */ 428 cur_frequency = clk_get_rate(clk); 429 if (!cur_frequency) { 430 dev_err(cpu_dev, "Failed to get clock rate for CPU\n"); 431 clk_put(clk); 432 return -EINVAL; 433 } 434 435 dvfs = armada_37xx_cpu_freq_info_get(cur_frequency); 436 if (!dvfs) { 437 clk_put(clk); 438 return -EINVAL; 439 } 440 441 armada37xx_cpufreq_state = kmalloc(sizeof(*armada37xx_cpufreq_state), 442 GFP_KERNEL); 443 if (!armada37xx_cpufreq_state) { 444 clk_put(clk); 445 return -ENOMEM; 446 } 447 448 armada37xx_cpufreq_state->regmap = nb_pm_base; 449 450 armada37xx_cpufreq_avs_configure(avs_base, dvfs); 451 armada37xx_cpufreq_avs_setup(avs_base, dvfs); 452 453 armada37xx_cpufreq_dvfs_setup(nb_pm_base, nb_clk_base, dvfs->divider); 454 clk_put(clk); 455 456 for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; 457 load_lvl++) { 458 unsigned long u_volt = avs_map[dvfs->avs[load_lvl]] * 1000; 459 freq = base_frequency / dvfs->divider[load_lvl]; 460 ret = dev_pm_opp_add(cpu_dev, freq, u_volt); 461 if (ret) 462 goto remove_opp; 463 464 465 } 466 467 /* Now that everything is setup, enable the DVFS at hardware level */ 468 armada37xx_cpufreq_enable_dvfs(nb_pm_base); 469 470 memset(&pdata, 0, sizeof(pdata)); 471 pdata.suspend = armada37xx_cpufreq_suspend; 472 pdata.resume = armada37xx_cpufreq_resume; 473 474 pdev = platform_device_register_data(NULL, "cpufreq-dt", -1, &pdata, 475 sizeof(pdata)); 476 ret = PTR_ERR_OR_ZERO(pdev); 477 if (ret) 478 goto disable_dvfs; 479 480 return 0; 481 482 disable_dvfs: 483 armada37xx_cpufreq_disable_dvfs(nb_pm_base); 484 remove_opp: 485 /* clean-up the already added opp before leaving */ 486 while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) { 487 freq = cur_frequency / dvfs->divider[load_lvl]; 488 dev_pm_opp_remove(cpu_dev, freq); 489 } 490 491 kfree(armada37xx_cpufreq_state); 492 493 return ret; 494 } 495 /* late_initcall, to guarantee the driver is loaded after A37xx clock driver */ 496 late_initcall(armada37xx_cpufreq_driver_init); 497 498 static const struct of_device_id __maybe_unused armada37xx_cpufreq_of_match[] = { 499 { .compatible = "marvell,armada-3700-nb-pm" }, 500 { }, 501 }; 502 MODULE_DEVICE_TABLE(of, armada37xx_cpufreq_of_match); 503 504 MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>"); 505 MODULE_DESCRIPTION("Armada 37xx cpufreq driver"); 506 MODULE_LICENSE("GPL"); 507