1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * TI CPUFreq/OPP hw-supported driver 4 * 5 * Copyright (C) 2016-2017 Texas Instruments, Inc. 6 * Dave Gerlach <d-gerlach@ti.com> 7 */ 8 9 #include <linux/cpu.h> 10 #include <linux/io.h> 11 #include <linux/mfd/syscon.h> 12 #include <linux/module.h> 13 #include <linux/init.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/pm_opp.h> 17 #include <linux/regmap.h> 18 #include <linux/slab.h> 19 #include <linux/sys_soc.h> 20 21 #define REVISION_MASK 0xF 22 #define REVISION_SHIFT 28 23 24 #define AM33XX_800M_ARM_MPU_MAX_FREQ 0x1E2F 25 #define AM43XX_600M_ARM_MPU_MAX_FREQ 0xFFA 26 27 #define DRA7_EFUSE_HAS_OD_MPU_OPP 11 28 #define DRA7_EFUSE_HAS_HIGH_MPU_OPP 15 29 #define DRA76_EFUSE_HAS_PLUS_MPU_OPP 18 30 #define DRA7_EFUSE_HAS_ALL_MPU_OPP 23 31 #define DRA76_EFUSE_HAS_ALL_MPU_OPP 24 32 33 #define DRA7_EFUSE_NOM_MPU_OPP BIT(0) 34 #define DRA7_EFUSE_OD_MPU_OPP BIT(1) 35 #define DRA7_EFUSE_HIGH_MPU_OPP BIT(2) 36 #define DRA76_EFUSE_PLUS_MPU_OPP BIT(3) 37 38 #define OMAP3_CONTROL_DEVICE_STATUS 0x4800244C 39 #define OMAP3_CONTROL_IDCODE 0x4830A204 40 #define OMAP34xx_ProdID_SKUID 0x4830A20C 41 #define OMAP3_SYSCON_BASE (0x48000000 + 0x2000 + 0x270) 42 43 #define AM625_EFUSE_K_MPU_OPP 11 44 #define AM625_EFUSE_S_MPU_OPP 19 45 #define AM625_EFUSE_T_MPU_OPP 20 46 47 #define AM625_SUPPORT_K_MPU_OPP BIT(0) 48 #define AM625_SUPPORT_S_MPU_OPP BIT(1) 49 #define AM625_SUPPORT_T_MPU_OPP BIT(2) 50 51 enum { 52 AM62A7_EFUSE_M_MPU_OPP = 13, 53 AM62A7_EFUSE_N_MPU_OPP, 54 AM62A7_EFUSE_O_MPU_OPP, 55 AM62A7_EFUSE_P_MPU_OPP, 56 AM62A7_EFUSE_Q_MPU_OPP, 57 AM62A7_EFUSE_R_MPU_OPP, 58 AM62A7_EFUSE_S_MPU_OPP, 59 /* 60 * The V, U, and T speed grade numbering is out of order 61 * to align with the AM625 more uniformly. I promise I know 62 * my ABCs ;) 63 */ 64 AM62A7_EFUSE_V_MPU_OPP, 65 AM62A7_EFUSE_U_MPU_OPP, 66 AM62A7_EFUSE_T_MPU_OPP, 67 }; 68 69 #define AM62A7_SUPPORT_N_MPU_OPP BIT(0) 70 #define AM62A7_SUPPORT_R_MPU_OPP BIT(1) 71 #define AM62A7_SUPPORT_V_MPU_OPP BIT(2) 72 73 #define AM62P5_EFUSE_O_MPU_OPP 15 74 #define AM62P5_EFUSE_S_MPU_OPP 19 75 #define AM62P5_EFUSE_T_MPU_OPP 20 76 #define AM62P5_EFUSE_U_MPU_OPP 21 77 #define AM62P5_EFUSE_V_MPU_OPP 22 78 79 #define AM62P5_SUPPORT_O_MPU_OPP BIT(0) 80 #define AM62P5_SUPPORT_U_MPU_OPP BIT(2) 81 82 #define VERSION_COUNT 2 83 84 struct ti_cpufreq_data; 85 86 struct ti_cpufreq_soc_data { 87 const char * const *reg_names; 88 unsigned long (*efuse_xlate)(struct ti_cpufreq_data *opp_data, 89 unsigned long efuse); 90 unsigned long efuse_fallback; 91 unsigned long efuse_offset; 92 unsigned long efuse_mask; 93 unsigned long efuse_shift; 94 unsigned long rev_offset; 95 bool multi_regulator; 96 /* Backward compatibility hack: Might have missing syscon */ 97 #define TI_QUIRK_SYSCON_MAY_BE_MISSING 0x1 98 /* Backward compatibility hack: new syscon size is 1 register wide */ 99 #define TI_QUIRK_SYSCON_IS_SINGLE_REG 0x2 100 u8 quirks; 101 }; 102 103 struct ti_cpufreq_data { 104 struct device *cpu_dev; 105 struct device_node *opp_node; 106 struct regmap *syscon; 107 const struct ti_cpufreq_soc_data *soc_data; 108 }; 109 110 static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data, 111 unsigned long efuse) 112 { 113 if (!efuse) 114 efuse = opp_data->soc_data->efuse_fallback; 115 /* AM335x and AM437x use "OPP disable" bits, so invert */ 116 return ~efuse; 117 } 118 119 static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data, 120 unsigned long efuse) 121 { 122 unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP; 123 124 /* 125 * The efuse on dra7 and am57 parts contains a specific 126 * value indicating the highest available OPP. 127 */ 128 129 switch (efuse) { 130 case DRA76_EFUSE_HAS_PLUS_MPU_OPP: 131 case DRA76_EFUSE_HAS_ALL_MPU_OPP: 132 calculated_efuse |= DRA76_EFUSE_PLUS_MPU_OPP; 133 fallthrough; 134 case DRA7_EFUSE_HAS_ALL_MPU_OPP: 135 case DRA7_EFUSE_HAS_HIGH_MPU_OPP: 136 calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP; 137 fallthrough; 138 case DRA7_EFUSE_HAS_OD_MPU_OPP: 139 calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP; 140 } 141 142 return calculated_efuse; 143 } 144 145 static unsigned long omap3_efuse_xlate(struct ti_cpufreq_data *opp_data, 146 unsigned long efuse) 147 { 148 /* OPP enable bit ("Speed Binned") */ 149 return BIT(efuse); 150 } 151 152 static unsigned long am62p5_efuse_xlate(struct ti_cpufreq_data *opp_data, 153 unsigned long efuse) 154 { 155 unsigned long calculated_efuse = AM62P5_SUPPORT_O_MPU_OPP; 156 157 switch (efuse) { 158 case AM62P5_EFUSE_V_MPU_OPP: 159 case AM62P5_EFUSE_U_MPU_OPP: 160 case AM62P5_EFUSE_T_MPU_OPP: 161 case AM62P5_EFUSE_S_MPU_OPP: 162 calculated_efuse |= AM62P5_SUPPORT_U_MPU_OPP; 163 fallthrough; 164 case AM62P5_EFUSE_O_MPU_OPP: 165 calculated_efuse |= AM62P5_SUPPORT_O_MPU_OPP; 166 } 167 168 return calculated_efuse; 169 } 170 171 static unsigned long am62a7_efuse_xlate(struct ti_cpufreq_data *opp_data, 172 unsigned long efuse) 173 { 174 unsigned long calculated_efuse = AM62A7_SUPPORT_N_MPU_OPP; 175 176 switch (efuse) { 177 case AM62A7_EFUSE_V_MPU_OPP: 178 case AM62A7_EFUSE_U_MPU_OPP: 179 case AM62A7_EFUSE_T_MPU_OPP: 180 case AM62A7_EFUSE_S_MPU_OPP: 181 calculated_efuse |= AM62A7_SUPPORT_V_MPU_OPP; 182 fallthrough; 183 case AM62A7_EFUSE_R_MPU_OPP: 184 case AM62A7_EFUSE_Q_MPU_OPP: 185 case AM62A7_EFUSE_P_MPU_OPP: 186 case AM62A7_EFUSE_O_MPU_OPP: 187 calculated_efuse |= AM62A7_SUPPORT_R_MPU_OPP; 188 fallthrough; 189 case AM62A7_EFUSE_N_MPU_OPP: 190 case AM62A7_EFUSE_M_MPU_OPP: 191 calculated_efuse |= AM62A7_SUPPORT_N_MPU_OPP; 192 } 193 194 return calculated_efuse; 195 } 196 197 static unsigned long am625_efuse_xlate(struct ti_cpufreq_data *opp_data, 198 unsigned long efuse) 199 { 200 unsigned long calculated_efuse = AM625_SUPPORT_K_MPU_OPP; 201 202 switch (efuse) { 203 case AM625_EFUSE_T_MPU_OPP: 204 calculated_efuse |= AM625_SUPPORT_T_MPU_OPP; 205 fallthrough; 206 case AM625_EFUSE_S_MPU_OPP: 207 calculated_efuse |= AM625_SUPPORT_S_MPU_OPP; 208 fallthrough; 209 case AM625_EFUSE_K_MPU_OPP: 210 calculated_efuse |= AM625_SUPPORT_K_MPU_OPP; 211 } 212 213 return calculated_efuse; 214 } 215 216 static struct ti_cpufreq_soc_data am3x_soc_data = { 217 .efuse_xlate = amx3_efuse_xlate, 218 .efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ, 219 .efuse_offset = 0x07fc, 220 .efuse_mask = 0x1fff, 221 .rev_offset = 0x600, 222 .multi_regulator = false, 223 }; 224 225 static struct ti_cpufreq_soc_data am4x_soc_data = { 226 .efuse_xlate = amx3_efuse_xlate, 227 .efuse_fallback = AM43XX_600M_ARM_MPU_MAX_FREQ, 228 .efuse_offset = 0x0610, 229 .efuse_mask = 0x3f, 230 .rev_offset = 0x600, 231 .multi_regulator = false, 232 }; 233 234 static struct ti_cpufreq_soc_data dra7_soc_data = { 235 .efuse_xlate = dra7_efuse_xlate, 236 .efuse_offset = 0x020c, 237 .efuse_mask = 0xf80000, 238 .efuse_shift = 19, 239 .rev_offset = 0x204, 240 .multi_regulator = true, 241 }; 242 243 /* 244 * OMAP35x TRM (SPRUF98K): 245 * CONTROL_IDCODE (0x4830 A204) describes Silicon revisions. 246 * Control OMAP Status Register 15:0 (Address 0x4800 244C) 247 * to separate between omap3503, omap3515, omap3525, omap3530 248 * and feature presence. 249 * There are encodings for versions limited to 400/266MHz 250 * but we ignore. 251 * Not clear if this also holds for omap34xx. 252 * some eFuse values e.g. CONTROL_FUSE_OPP1_VDD1 253 * are stored in the SYSCON register range 254 * Register 0x4830A20C [ProdID.SKUID] [0:3] 255 * 0x0 for normal 600/430MHz device. 256 * 0x8 for 720/520MHz device. 257 * Not clear what omap34xx value is. 258 */ 259 260 static struct ti_cpufreq_soc_data omap34xx_soc_data = { 261 .efuse_xlate = omap3_efuse_xlate, 262 .efuse_offset = OMAP34xx_ProdID_SKUID - OMAP3_SYSCON_BASE, 263 .efuse_shift = 3, 264 .efuse_mask = BIT(3), 265 .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, 266 .multi_regulator = false, 267 .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, 268 }; 269 270 /* 271 * AM/DM37x TRM (SPRUGN4M) 272 * CONTROL_IDCODE (0x4830 A204) describes Silicon revisions. 273 * Control Device Status Register 15:0 (Address 0x4800 244C) 274 * to separate between am3703, am3715, dm3725, dm3730 275 * and feature presence. 276 * Speed Binned = Bit 9 277 * 0 800/600 MHz 278 * 1 1000/800 MHz 279 * some eFuse values e.g. CONTROL_FUSE_OPP 1G_VDD1 280 * are stored in the SYSCON register range. 281 * There is no 0x4830A20C [ProdID.SKUID] register (exists but 282 * seems to always read as 0). 283 */ 284 285 static const char * const omap3_reg_names[] = {"cpu0", "vbb", NULL}; 286 287 static struct ti_cpufreq_soc_data omap36xx_soc_data = { 288 .reg_names = omap3_reg_names, 289 .efuse_xlate = omap3_efuse_xlate, 290 .efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE, 291 .efuse_shift = 9, 292 .efuse_mask = BIT(9), 293 .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, 294 .multi_regulator = true, 295 .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, 296 }; 297 298 /* 299 * AM3517 is quite similar to AM/DM37x except that it has no 300 * high speed grade eFuse and no abb ldo 301 */ 302 303 static struct ti_cpufreq_soc_data am3517_soc_data = { 304 .efuse_xlate = omap3_efuse_xlate, 305 .efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE, 306 .efuse_shift = 0, 307 .efuse_mask = 0, 308 .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, 309 .multi_regulator = false, 310 .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, 311 }; 312 313 static const struct soc_device_attribute k3_cpufreq_soc[] = { 314 { .family = "AM62X", }, 315 { .family = "AM62AX", }, 316 { .family = "AM62PX", }, 317 { .family = "AM62DX", }, 318 { /* sentinel */ } 319 }; 320 321 static struct ti_cpufreq_soc_data am625_soc_data = { 322 .efuse_xlate = am625_efuse_xlate, 323 .efuse_offset = 0x0018, 324 .efuse_mask = 0x07c0, 325 .efuse_shift = 0x6, 326 .multi_regulator = false, 327 .quirks = TI_QUIRK_SYSCON_IS_SINGLE_REG, 328 }; 329 330 static struct ti_cpufreq_soc_data am62a7_soc_data = { 331 .efuse_xlate = am62a7_efuse_xlate, 332 .efuse_offset = 0x0, 333 .efuse_mask = 0x07c0, 334 .efuse_shift = 0x6, 335 .multi_regulator = false, 336 }; 337 338 static struct ti_cpufreq_soc_data am62p5_soc_data = { 339 .efuse_xlate = am62p5_efuse_xlate, 340 .efuse_offset = 0x0, 341 .efuse_mask = 0x07c0, 342 .efuse_shift = 0x6, 343 .multi_regulator = false, 344 }; 345 346 /** 347 * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC 348 * @opp_data: pointer to ti_cpufreq_data context 349 * @efuse_value: Set to the value parsed from efuse 350 * 351 * Returns error code if efuse not read properly. 352 */ 353 static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data, 354 u32 *efuse_value) 355 { 356 struct device *dev = opp_data->cpu_dev; 357 u32 efuse; 358 int ret; 359 360 ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset, 361 &efuse); 362 363 if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_IS_SINGLE_REG && ret == -EIO) 364 ret = regmap_read(opp_data->syscon, 0x0, &efuse); 365 366 if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { 367 /* not a syscon register! */ 368 void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + 369 opp_data->soc_data->efuse_offset, 4); 370 371 if (!regs) 372 return -ENOMEM; 373 efuse = readl(regs); 374 iounmap(regs); 375 } 376 else if (ret) { 377 dev_err(dev, 378 "Failed to read the efuse value from syscon: %d\n", 379 ret); 380 return ret; 381 } 382 383 efuse = (efuse & opp_data->soc_data->efuse_mask); 384 efuse >>= opp_data->soc_data->efuse_shift; 385 386 *efuse_value = opp_data->soc_data->efuse_xlate(opp_data, efuse); 387 388 return 0; 389 } 390 391 /** 392 * ti_cpufreq_get_rev() - Parse and return rev value present on SoC 393 * @opp_data: pointer to ti_cpufreq_data context 394 * @revision_value: Set to the value parsed from revision register 395 * 396 * Returns error code if revision not read properly. 397 */ 398 static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data, 399 u32 *revision_value) 400 { 401 struct device *dev = opp_data->cpu_dev; 402 u32 revision; 403 int ret; 404 if (soc_device_match(k3_cpufreq_soc)) { 405 /* 406 * Since the SR is 1.0, hard code the revision_value as 407 * 0x1 here. This way we avoid re using the same register 408 * that is giving us required information inside socinfo 409 * anyway. 410 */ 411 *revision_value = 0x1; 412 goto done; 413 } 414 415 ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset, 416 &revision); 417 if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { 418 /* not a syscon register! */ 419 void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + 420 opp_data->soc_data->rev_offset, 4); 421 422 if (!regs) 423 return -ENOMEM; 424 revision = readl(regs); 425 iounmap(regs); 426 } 427 else if (ret) { 428 dev_err(dev, 429 "Failed to read the revision number from syscon: %d\n", 430 ret); 431 return ret; 432 } 433 434 *revision_value = BIT((revision >> REVISION_SHIFT) & REVISION_MASK); 435 436 done: 437 return 0; 438 } 439 440 static int ti_cpufreq_setup_syscon_register(struct ti_cpufreq_data *opp_data) 441 { 442 struct device *dev = opp_data->cpu_dev; 443 struct device_node *np = opp_data->opp_node; 444 445 opp_data->syscon = syscon_regmap_lookup_by_phandle(np, 446 "syscon"); 447 if (IS_ERR(opp_data->syscon)) { 448 dev_err(dev, 449 "\"syscon\" is missing, cannot use OPPv2 table.\n"); 450 return PTR_ERR(opp_data->syscon); 451 } 452 453 return 0; 454 } 455 456 static const struct of_device_id ti_cpufreq_of_match[] __maybe_unused = { 457 { .compatible = "ti,am33xx", .data = &am3x_soc_data, }, 458 { .compatible = "ti,am3517", .data = &am3517_soc_data, }, 459 { .compatible = "ti,am43", .data = &am4x_soc_data, }, 460 { .compatible = "ti,dra7", .data = &dra7_soc_data }, 461 { .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, }, 462 { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, }, 463 { .compatible = "ti,am625", .data = &am625_soc_data, }, 464 { .compatible = "ti,am62a7", .data = &am62a7_soc_data, }, 465 { .compatible = "ti,am62d2", .data = &am62a7_soc_data, }, 466 { .compatible = "ti,am62p5", .data = &am62p5_soc_data, }, 467 /* legacy */ 468 { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, }, 469 { .compatible = "ti,omap3630", .data = &omap36xx_soc_data, }, 470 {}, 471 }; 472 473 static const struct of_device_id *ti_cpufreq_match_node(void) 474 { 475 struct device_node *np __free(device_node) = of_find_node_by_path("/"); 476 const struct of_device_id *match; 477 478 match = of_match_node(ti_cpufreq_of_match, np); 479 480 return match; 481 } 482 483 static int ti_cpufreq_probe(struct platform_device *pdev) 484 { 485 u32 version[VERSION_COUNT]; 486 const struct of_device_id *match; 487 struct ti_cpufreq_data *opp_data; 488 const char * const default_reg_names[] = {"vdd", "vbb", NULL}; 489 int ret; 490 struct dev_pm_opp_config config = { 491 .supported_hw = version, 492 .supported_hw_count = ARRAY_SIZE(version), 493 }; 494 495 match = dev_get_platdata(&pdev->dev); 496 if (!match) 497 return -ENODEV; 498 499 opp_data = devm_kzalloc(&pdev->dev, sizeof(*opp_data), GFP_KERNEL); 500 if (!opp_data) 501 return -ENOMEM; 502 503 opp_data->soc_data = match->data; 504 505 opp_data->cpu_dev = get_cpu_device(0); 506 if (!opp_data->cpu_dev) { 507 pr_err("%s: Failed to get device for CPU0\n", __func__); 508 return -ENODEV; 509 } 510 511 opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev); 512 if (!opp_data->opp_node) { 513 dev_info(opp_data->cpu_dev, 514 "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n"); 515 goto register_cpufreq_dt; 516 } 517 518 ret = ti_cpufreq_setup_syscon_register(opp_data); 519 if (ret) 520 goto fail_put_node; 521 522 /* 523 * OPPs determine whether or not they are supported based on 524 * two metrics: 525 * 0 - SoC Revision 526 * 1 - eFuse value 527 */ 528 ret = ti_cpufreq_get_rev(opp_data, &version[0]); 529 if (ret) 530 goto fail_put_node; 531 532 ret = ti_cpufreq_get_efuse(opp_data, &version[1]); 533 if (ret) 534 goto fail_put_node; 535 536 if (opp_data->soc_data->multi_regulator) { 537 if (opp_data->soc_data->reg_names) 538 config.regulator_names = opp_data->soc_data->reg_names; 539 else 540 config.regulator_names = default_reg_names; 541 } 542 543 ret = dev_pm_opp_set_config(opp_data->cpu_dev, &config); 544 if (ret < 0) { 545 dev_err_probe(opp_data->cpu_dev, ret, "Failed to set OPP config\n"); 546 goto fail_put_node; 547 } 548 549 of_node_put(opp_data->opp_node); 550 551 register_cpufreq_dt: 552 platform_device_register_simple("cpufreq-dt", -1, NULL, 0); 553 554 return 0; 555 556 fail_put_node: 557 of_node_put(opp_data->opp_node); 558 559 return ret; 560 } 561 562 static int __init ti_cpufreq_init(void) 563 { 564 const struct of_device_id *match; 565 566 /* Check to ensure we are on a compatible platform */ 567 match = ti_cpufreq_match_node(); 568 if (match) 569 platform_device_register_data(NULL, "ti-cpufreq", -1, match, 570 sizeof(*match)); 571 572 return 0; 573 } 574 module_init(ti_cpufreq_init); 575 576 static struct platform_driver ti_cpufreq_driver = { 577 .probe = ti_cpufreq_probe, 578 .driver = { 579 .name = "ti-cpufreq", 580 }, 581 }; 582 builtin_platform_driver(ti_cpufreq_driver); 583 584 MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver"); 585 MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>"); 586 MODULE_LICENSE("GPL v2"); 587