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 20 #define REVISION_MASK 0xF 21 #define REVISION_SHIFT 28 22 23 #define AM33XX_800M_ARM_MPU_MAX_FREQ 0x1E2F 24 #define AM43XX_600M_ARM_MPU_MAX_FREQ 0xFFA 25 26 #define DRA7_EFUSE_HAS_OD_MPU_OPP 11 27 #define DRA7_EFUSE_HAS_HIGH_MPU_OPP 15 28 #define DRA76_EFUSE_HAS_PLUS_MPU_OPP 18 29 #define DRA7_EFUSE_HAS_ALL_MPU_OPP 23 30 #define DRA76_EFUSE_HAS_ALL_MPU_OPP 24 31 32 #define DRA7_EFUSE_NOM_MPU_OPP BIT(0) 33 #define DRA7_EFUSE_OD_MPU_OPP BIT(1) 34 #define DRA7_EFUSE_HIGH_MPU_OPP BIT(2) 35 #define DRA76_EFUSE_PLUS_MPU_OPP BIT(3) 36 37 #define OMAP3_CONTROL_DEVICE_STATUS 0x4800244C 38 #define OMAP3_CONTROL_IDCODE 0x4830A204 39 #define OMAP34xx_ProdID_SKUID 0x4830A20C 40 #define OMAP3_SYSCON_BASE (0x48000000 + 0x2000 + 0x270) 41 42 #define AM625_EFUSE_K_MPU_OPP 11 43 #define AM625_EFUSE_S_MPU_OPP 19 44 #define AM625_EFUSE_T_MPU_OPP 20 45 46 #define AM625_SUPPORT_K_MPU_OPP BIT(0) 47 #define AM625_SUPPORT_S_MPU_OPP BIT(1) 48 #define AM625_SUPPORT_T_MPU_OPP BIT(2) 49 50 #define VERSION_COUNT 2 51 52 struct ti_cpufreq_data; 53 54 struct ti_cpufreq_soc_data { 55 const char * const *reg_names; 56 unsigned long (*efuse_xlate)(struct ti_cpufreq_data *opp_data, 57 unsigned long efuse); 58 unsigned long efuse_fallback; 59 unsigned long efuse_offset; 60 unsigned long efuse_mask; 61 unsigned long efuse_shift; 62 unsigned long rev_offset; 63 bool multi_regulator; 64 /* Backward compatibility hack: Might have missing syscon */ 65 #define TI_QUIRK_SYSCON_MAY_BE_MISSING 0x1 66 u8 quirks; 67 }; 68 69 struct ti_cpufreq_data { 70 struct device *cpu_dev; 71 struct device_node *opp_node; 72 struct regmap *syscon; 73 const struct ti_cpufreq_soc_data *soc_data; 74 }; 75 76 static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data, 77 unsigned long efuse) 78 { 79 if (!efuse) 80 efuse = opp_data->soc_data->efuse_fallback; 81 /* AM335x and AM437x use "OPP disable" bits, so invert */ 82 return ~efuse; 83 } 84 85 static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data, 86 unsigned long efuse) 87 { 88 unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP; 89 90 /* 91 * The efuse on dra7 and am57 parts contains a specific 92 * value indicating the highest available OPP. 93 */ 94 95 switch (efuse) { 96 case DRA76_EFUSE_HAS_PLUS_MPU_OPP: 97 case DRA76_EFUSE_HAS_ALL_MPU_OPP: 98 calculated_efuse |= DRA76_EFUSE_PLUS_MPU_OPP; 99 fallthrough; 100 case DRA7_EFUSE_HAS_ALL_MPU_OPP: 101 case DRA7_EFUSE_HAS_HIGH_MPU_OPP: 102 calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP; 103 fallthrough; 104 case DRA7_EFUSE_HAS_OD_MPU_OPP: 105 calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP; 106 } 107 108 return calculated_efuse; 109 } 110 111 static unsigned long omap3_efuse_xlate(struct ti_cpufreq_data *opp_data, 112 unsigned long efuse) 113 { 114 /* OPP enable bit ("Speed Binned") */ 115 return BIT(efuse); 116 } 117 118 static unsigned long am625_efuse_xlate(struct ti_cpufreq_data *opp_data, 119 unsigned long efuse) 120 { 121 unsigned long calculated_efuse = AM625_SUPPORT_K_MPU_OPP; 122 123 switch (efuse) { 124 case AM625_EFUSE_T_MPU_OPP: 125 calculated_efuse |= AM625_SUPPORT_T_MPU_OPP; 126 fallthrough; 127 case AM625_EFUSE_S_MPU_OPP: 128 calculated_efuse |= AM625_SUPPORT_S_MPU_OPP; 129 fallthrough; 130 case AM625_EFUSE_K_MPU_OPP: 131 calculated_efuse |= AM625_SUPPORT_K_MPU_OPP; 132 } 133 134 return calculated_efuse; 135 } 136 137 static struct ti_cpufreq_soc_data am3x_soc_data = { 138 .efuse_xlate = amx3_efuse_xlate, 139 .efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ, 140 .efuse_offset = 0x07fc, 141 .efuse_mask = 0x1fff, 142 .rev_offset = 0x600, 143 .multi_regulator = false, 144 }; 145 146 static struct ti_cpufreq_soc_data am4x_soc_data = { 147 .efuse_xlate = amx3_efuse_xlate, 148 .efuse_fallback = AM43XX_600M_ARM_MPU_MAX_FREQ, 149 .efuse_offset = 0x0610, 150 .efuse_mask = 0x3f, 151 .rev_offset = 0x600, 152 .multi_regulator = false, 153 }; 154 155 static struct ti_cpufreq_soc_data dra7_soc_data = { 156 .efuse_xlate = dra7_efuse_xlate, 157 .efuse_offset = 0x020c, 158 .efuse_mask = 0xf80000, 159 .efuse_shift = 19, 160 .rev_offset = 0x204, 161 .multi_regulator = true, 162 }; 163 164 /* 165 * OMAP35x TRM (SPRUF98K): 166 * CONTROL_IDCODE (0x4830 A204) describes Silicon revisions. 167 * Control OMAP Status Register 15:0 (Address 0x4800 244C) 168 * to separate between omap3503, omap3515, omap3525, omap3530 169 * and feature presence. 170 * There are encodings for versions limited to 400/266MHz 171 * but we ignore. 172 * Not clear if this also holds for omap34xx. 173 * some eFuse values e.g. CONTROL_FUSE_OPP1_VDD1 174 * are stored in the SYSCON register range 175 * Register 0x4830A20C [ProdID.SKUID] [0:3] 176 * 0x0 for normal 600/430MHz device. 177 * 0x8 for 720/520MHz device. 178 * Not clear what omap34xx value is. 179 */ 180 181 static struct ti_cpufreq_soc_data omap34xx_soc_data = { 182 .efuse_xlate = omap3_efuse_xlate, 183 .efuse_offset = OMAP34xx_ProdID_SKUID - OMAP3_SYSCON_BASE, 184 .efuse_shift = 3, 185 .efuse_mask = BIT(3), 186 .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, 187 .multi_regulator = false, 188 .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, 189 }; 190 191 /* 192 * AM/DM37x TRM (SPRUGN4M) 193 * CONTROL_IDCODE (0x4830 A204) describes Silicon revisions. 194 * Control Device Status Register 15:0 (Address 0x4800 244C) 195 * to separate between am3703, am3715, dm3725, dm3730 196 * and feature presence. 197 * Speed Binned = Bit 9 198 * 0 800/600 MHz 199 * 1 1000/800 MHz 200 * some eFuse values e.g. CONTROL_FUSE_OPP 1G_VDD1 201 * are stored in the SYSCON register range. 202 * There is no 0x4830A20C [ProdID.SKUID] register (exists but 203 * seems to always read as 0). 204 */ 205 206 static const char * const omap3_reg_names[] = {"cpu0", "vbb", NULL}; 207 208 static struct ti_cpufreq_soc_data omap36xx_soc_data = { 209 .reg_names = omap3_reg_names, 210 .efuse_xlate = omap3_efuse_xlate, 211 .efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE, 212 .efuse_shift = 9, 213 .efuse_mask = BIT(9), 214 .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, 215 .multi_regulator = true, 216 .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, 217 }; 218 219 /* 220 * AM3517 is quite similar to AM/DM37x except that it has no 221 * high speed grade eFuse and no abb ldo 222 */ 223 224 static struct ti_cpufreq_soc_data am3517_soc_data = { 225 .efuse_xlate = omap3_efuse_xlate, 226 .efuse_offset = OMAP3_CONTROL_DEVICE_STATUS - OMAP3_SYSCON_BASE, 227 .efuse_shift = 0, 228 .efuse_mask = 0, 229 .rev_offset = OMAP3_CONTROL_IDCODE - OMAP3_SYSCON_BASE, 230 .multi_regulator = false, 231 .quirks = TI_QUIRK_SYSCON_MAY_BE_MISSING, 232 }; 233 234 static struct ti_cpufreq_soc_data am625_soc_data = { 235 .efuse_xlate = am625_efuse_xlate, 236 .efuse_offset = 0x0018, 237 .efuse_mask = 0x07c0, 238 .efuse_shift = 0x6, 239 .rev_offset = 0x0014, 240 .multi_regulator = false, 241 }; 242 243 /** 244 * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC 245 * @opp_data: pointer to ti_cpufreq_data context 246 * @efuse_value: Set to the value parsed from efuse 247 * 248 * Returns error code if efuse not read properly. 249 */ 250 static int ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data, 251 u32 *efuse_value) 252 { 253 struct device *dev = opp_data->cpu_dev; 254 u32 efuse; 255 int ret; 256 257 ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset, 258 &efuse); 259 if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { 260 /* not a syscon register! */ 261 void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + 262 opp_data->soc_data->efuse_offset, 4); 263 264 if (!regs) 265 return -ENOMEM; 266 efuse = readl(regs); 267 iounmap(regs); 268 } 269 else if (ret) { 270 dev_err(dev, 271 "Failed to read the efuse value from syscon: %d\n", 272 ret); 273 return ret; 274 } 275 276 efuse = (efuse & opp_data->soc_data->efuse_mask); 277 efuse >>= opp_data->soc_data->efuse_shift; 278 279 *efuse_value = opp_data->soc_data->efuse_xlate(opp_data, efuse); 280 281 return 0; 282 } 283 284 /** 285 * ti_cpufreq_get_rev() - Parse and return rev value present on SoC 286 * @opp_data: pointer to ti_cpufreq_data context 287 * @revision_value: Set to the value parsed from revision register 288 * 289 * Returns error code if revision not read properly. 290 */ 291 static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data, 292 u32 *revision_value) 293 { 294 struct device *dev = opp_data->cpu_dev; 295 u32 revision; 296 int ret; 297 298 ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset, 299 &revision); 300 if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { 301 /* not a syscon register! */ 302 void __iomem *regs = ioremap(OMAP3_SYSCON_BASE + 303 opp_data->soc_data->rev_offset, 4); 304 305 if (!regs) 306 return -ENOMEM; 307 revision = readl(regs); 308 iounmap(regs); 309 } 310 else if (ret) { 311 dev_err(dev, 312 "Failed to read the revision number from syscon: %d\n", 313 ret); 314 return ret; 315 } 316 317 *revision_value = BIT((revision >> REVISION_SHIFT) & REVISION_MASK); 318 319 return 0; 320 } 321 322 static int ti_cpufreq_setup_syscon_register(struct ti_cpufreq_data *opp_data) 323 { 324 struct device *dev = opp_data->cpu_dev; 325 struct device_node *np = opp_data->opp_node; 326 327 opp_data->syscon = syscon_regmap_lookup_by_phandle(np, 328 "syscon"); 329 if (IS_ERR(opp_data->syscon)) { 330 dev_err(dev, 331 "\"syscon\" is missing, cannot use OPPv2 table.\n"); 332 return PTR_ERR(opp_data->syscon); 333 } 334 335 return 0; 336 } 337 338 static const struct of_device_id ti_cpufreq_of_match[] = { 339 { .compatible = "ti,am33xx", .data = &am3x_soc_data, }, 340 { .compatible = "ti,am3517", .data = &am3517_soc_data, }, 341 { .compatible = "ti,am43", .data = &am4x_soc_data, }, 342 { .compatible = "ti,dra7", .data = &dra7_soc_data }, 343 { .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, }, 344 { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, }, 345 { .compatible = "ti,am625", .data = &am625_soc_data, }, 346 { .compatible = "ti,am62a7", .data = &am625_soc_data, }, 347 /* legacy */ 348 { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, }, 349 { .compatible = "ti,omap3630", .data = &omap36xx_soc_data, }, 350 {}, 351 }; 352 353 static const struct of_device_id *ti_cpufreq_match_node(void) 354 { 355 struct device_node *np; 356 const struct of_device_id *match; 357 358 np = of_find_node_by_path("/"); 359 match = of_match_node(ti_cpufreq_of_match, np); 360 of_node_put(np); 361 362 return match; 363 } 364 365 static int ti_cpufreq_probe(struct platform_device *pdev) 366 { 367 u32 version[VERSION_COUNT]; 368 const struct of_device_id *match; 369 struct ti_cpufreq_data *opp_data; 370 const char * const default_reg_names[] = {"vdd", "vbb", NULL}; 371 int ret; 372 struct dev_pm_opp_config config = { 373 .supported_hw = version, 374 .supported_hw_count = ARRAY_SIZE(version), 375 }; 376 377 match = dev_get_platdata(&pdev->dev); 378 if (!match) 379 return -ENODEV; 380 381 opp_data = devm_kzalloc(&pdev->dev, sizeof(*opp_data), GFP_KERNEL); 382 if (!opp_data) 383 return -ENOMEM; 384 385 opp_data->soc_data = match->data; 386 387 opp_data->cpu_dev = get_cpu_device(0); 388 if (!opp_data->cpu_dev) { 389 pr_err("%s: Failed to get device for CPU0\n", __func__); 390 return -ENODEV; 391 } 392 393 opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev); 394 if (!opp_data->opp_node) { 395 dev_info(opp_data->cpu_dev, 396 "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n"); 397 goto register_cpufreq_dt; 398 } 399 400 ret = ti_cpufreq_setup_syscon_register(opp_data); 401 if (ret) 402 goto fail_put_node; 403 404 /* 405 * OPPs determine whether or not they are supported based on 406 * two metrics: 407 * 0 - SoC Revision 408 * 1 - eFuse value 409 */ 410 ret = ti_cpufreq_get_rev(opp_data, &version[0]); 411 if (ret) 412 goto fail_put_node; 413 414 ret = ti_cpufreq_get_efuse(opp_data, &version[1]); 415 if (ret) 416 goto fail_put_node; 417 418 if (opp_data->soc_data->multi_regulator) { 419 if (opp_data->soc_data->reg_names) 420 config.regulator_names = opp_data->soc_data->reg_names; 421 else 422 config.regulator_names = default_reg_names; 423 } 424 425 ret = dev_pm_opp_set_config(opp_data->cpu_dev, &config); 426 if (ret < 0) { 427 dev_err_probe(opp_data->cpu_dev, ret, "Failed to set OPP config\n"); 428 goto fail_put_node; 429 } 430 431 of_node_put(opp_data->opp_node); 432 433 register_cpufreq_dt: 434 platform_device_register_simple("cpufreq-dt", -1, NULL, 0); 435 436 return 0; 437 438 fail_put_node: 439 of_node_put(opp_data->opp_node); 440 441 return ret; 442 } 443 444 static int __init ti_cpufreq_init(void) 445 { 446 const struct of_device_id *match; 447 448 /* Check to ensure we are on a compatible platform */ 449 match = ti_cpufreq_match_node(); 450 if (match) 451 platform_device_register_data(NULL, "ti-cpufreq", -1, match, 452 sizeof(*match)); 453 454 return 0; 455 } 456 module_init(ti_cpufreq_init); 457 458 static struct platform_driver ti_cpufreq_driver = { 459 .probe = ti_cpufreq_probe, 460 .driver = { 461 .name = "ti-cpufreq", 462 }, 463 }; 464 builtin_platform_driver(ti_cpufreq_driver); 465 466 MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver"); 467 MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>"); 468 MODULE_LICENSE("GPL v2"); 469