1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 */ 5 6 /* 7 * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors, 8 * the CPU frequency subset and voltage value of each OPP varies 9 * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables 10 * defines the voltage and frequency value based on the msm-id in SMEM 11 * and speedbin blown in the efuse combination. 12 * The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC 13 * to provide the OPP framework with required information. 14 * This is used to determine the voltage and frequency value for each OPP of 15 * operating-points-v2 table when it is parsed by the OPP framework. 16 */ 17 18 #include <linux/cpu.h> 19 #include <linux/err.h> 20 #include <linux/init.h> 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/nvmem-consumer.h> 24 #include <linux/of.h> 25 #include <linux/of_device.h> 26 #include <linux/platform_device.h> 27 #include <linux/pm_domain.h> 28 #include <linux/pm_opp.h> 29 #include <linux/slab.h> 30 #include <linux/soc/qcom/smem.h> 31 32 #include <dt-bindings/arm/qcom,ids.h> 33 34 struct qcom_cpufreq_drv; 35 36 struct qcom_cpufreq_match_data { 37 int (*get_version)(struct device *cpu_dev, 38 struct nvmem_cell *speedbin_nvmem, 39 char **pvs_name, 40 struct qcom_cpufreq_drv *drv); 41 const char **genpd_names; 42 }; 43 44 struct qcom_cpufreq_drv { 45 int *opp_tokens; 46 u32 versions; 47 const struct qcom_cpufreq_match_data *data; 48 }; 49 50 static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev; 51 52 static void get_krait_bin_format_a(struct device *cpu_dev, 53 int *speed, int *pvs, int *pvs_ver, 54 u8 *buf) 55 { 56 u32 pte_efuse; 57 58 pte_efuse = *((u32 *)buf); 59 60 *speed = pte_efuse & 0xf; 61 if (*speed == 0xf) 62 *speed = (pte_efuse >> 4) & 0xf; 63 64 if (*speed == 0xf) { 65 *speed = 0; 66 dev_warn(cpu_dev, "Speed bin: Defaulting to %d\n", *speed); 67 } else { 68 dev_dbg(cpu_dev, "Speed bin: %d\n", *speed); 69 } 70 71 *pvs = (pte_efuse >> 10) & 0x7; 72 if (*pvs == 0x7) 73 *pvs = (pte_efuse >> 13) & 0x7; 74 75 if (*pvs == 0x7) { 76 *pvs = 0; 77 dev_warn(cpu_dev, "PVS bin: Defaulting to %d\n", *pvs); 78 } else { 79 dev_dbg(cpu_dev, "PVS bin: %d\n", *pvs); 80 } 81 } 82 83 static void get_krait_bin_format_b(struct device *cpu_dev, 84 int *speed, int *pvs, int *pvs_ver, 85 u8 *buf) 86 { 87 u32 pte_efuse, redundant_sel; 88 89 pte_efuse = *((u32 *)buf); 90 redundant_sel = (pte_efuse >> 24) & 0x7; 91 92 *pvs_ver = (pte_efuse >> 4) & 0x3; 93 94 switch (redundant_sel) { 95 case 1: 96 *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7); 97 *speed = (pte_efuse >> 27) & 0xf; 98 break; 99 case 2: 100 *pvs = (pte_efuse >> 27) & 0xf; 101 *speed = pte_efuse & 0x7; 102 break; 103 default: 104 /* 4 bits of PVS are in efuse register bits 31, 8-6. */ 105 *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7); 106 *speed = pte_efuse & 0x7; 107 } 108 109 /* Check SPEED_BIN_BLOW_STATUS */ 110 if (pte_efuse & BIT(3)) { 111 dev_dbg(cpu_dev, "Speed bin: %d\n", *speed); 112 } else { 113 dev_warn(cpu_dev, "Speed bin not set. Defaulting to 0!\n"); 114 *speed = 0; 115 } 116 117 /* Check PVS_BLOW_STATUS */ 118 pte_efuse = *(((u32 *)buf) + 1); 119 pte_efuse &= BIT(21); 120 if (pte_efuse) { 121 dev_dbg(cpu_dev, "PVS bin: %d\n", *pvs); 122 } else { 123 dev_warn(cpu_dev, "PVS bin not set. Defaulting to 0!\n"); 124 *pvs = 0; 125 } 126 127 dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver); 128 } 129 130 static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev, 131 struct nvmem_cell *speedbin_nvmem, 132 char **pvs_name, 133 struct qcom_cpufreq_drv *drv) 134 { 135 size_t len; 136 u32 msm_id; 137 u8 *speedbin; 138 int ret; 139 *pvs_name = NULL; 140 141 ret = qcom_smem_get_soc_id(&msm_id); 142 if (ret) 143 return ret; 144 145 speedbin = nvmem_cell_read(speedbin_nvmem, &len); 146 if (IS_ERR(speedbin)) 147 return PTR_ERR(speedbin); 148 149 switch (msm_id) { 150 case QCOM_ID_MSM8996: 151 case QCOM_ID_APQ8096: 152 drv->versions = 1 << (unsigned int)(*speedbin); 153 break; 154 case QCOM_ID_MSM8996SG: 155 case QCOM_ID_APQ8096SG: 156 drv->versions = 1 << ((unsigned int)(*speedbin) + 4); 157 break; 158 default: 159 BUG(); 160 break; 161 } 162 163 kfree(speedbin); 164 return 0; 165 } 166 167 static int qcom_cpufreq_krait_name_version(struct device *cpu_dev, 168 struct nvmem_cell *speedbin_nvmem, 169 char **pvs_name, 170 struct qcom_cpufreq_drv *drv) 171 { 172 int speed = 0, pvs = 0, pvs_ver = 0; 173 u8 *speedbin; 174 size_t len; 175 int ret = 0; 176 177 speedbin = nvmem_cell_read(speedbin_nvmem, &len); 178 179 if (IS_ERR(speedbin)) 180 return PTR_ERR(speedbin); 181 182 switch (len) { 183 case 4: 184 get_krait_bin_format_a(cpu_dev, &speed, &pvs, &pvs_ver, 185 speedbin); 186 break; 187 case 8: 188 get_krait_bin_format_b(cpu_dev, &speed, &pvs, &pvs_ver, 189 speedbin); 190 break; 191 default: 192 dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n"); 193 ret = -ENODEV; 194 goto len_error; 195 } 196 197 snprintf(*pvs_name, sizeof("speedXX-pvsXX-vXX"), "speed%d-pvs%d-v%d", 198 speed, pvs, pvs_ver); 199 200 drv->versions = (1 << speed); 201 202 len_error: 203 kfree(speedbin); 204 return ret; 205 } 206 207 static const struct qcom_cpufreq_match_data match_data_kryo = { 208 .get_version = qcom_cpufreq_kryo_name_version, 209 }; 210 211 static const struct qcom_cpufreq_match_data match_data_krait = { 212 .get_version = qcom_cpufreq_krait_name_version, 213 }; 214 215 static const char *qcs404_genpd_names[] = { "cpr", NULL }; 216 217 static const struct qcom_cpufreq_match_data match_data_qcs404 = { 218 .genpd_names = qcs404_genpd_names, 219 }; 220 221 static int qcom_cpufreq_probe(struct platform_device *pdev) 222 { 223 struct qcom_cpufreq_drv *drv; 224 struct nvmem_cell *speedbin_nvmem; 225 struct device_node *np; 226 struct device *cpu_dev; 227 char pvs_name_buffer[] = "speedXX-pvsXX-vXX"; 228 char *pvs_name = pvs_name_buffer; 229 unsigned cpu; 230 const struct of_device_id *match; 231 int ret; 232 233 cpu_dev = get_cpu_device(0); 234 if (!cpu_dev) 235 return -ENODEV; 236 237 np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); 238 if (!np) 239 return -ENOENT; 240 241 ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); 242 if (!ret) { 243 of_node_put(np); 244 return -ENOENT; 245 } 246 247 drv = kzalloc(sizeof(*drv), GFP_KERNEL); 248 if (!drv) 249 return -ENOMEM; 250 251 match = pdev->dev.platform_data; 252 drv->data = match->data; 253 if (!drv->data) { 254 ret = -ENODEV; 255 goto free_drv; 256 } 257 258 if (drv->data->get_version) { 259 speedbin_nvmem = of_nvmem_cell_get(np, NULL); 260 if (IS_ERR(speedbin_nvmem)) { 261 ret = dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem), 262 "Could not get nvmem cell\n"); 263 goto free_drv; 264 } 265 266 ret = drv->data->get_version(cpu_dev, 267 speedbin_nvmem, &pvs_name, drv); 268 if (ret) { 269 nvmem_cell_put(speedbin_nvmem); 270 goto free_drv; 271 } 272 nvmem_cell_put(speedbin_nvmem); 273 } 274 of_node_put(np); 275 276 drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens), 277 GFP_KERNEL); 278 if (!drv->opp_tokens) { 279 ret = -ENOMEM; 280 goto free_drv; 281 } 282 283 for_each_possible_cpu(cpu) { 284 struct dev_pm_opp_config config = { 285 .supported_hw = NULL, 286 }; 287 288 cpu_dev = get_cpu_device(cpu); 289 if (NULL == cpu_dev) { 290 ret = -ENODEV; 291 goto free_opp; 292 } 293 294 if (drv->data->get_version) { 295 config.supported_hw = &drv->versions; 296 config.supported_hw_count = 1; 297 298 if (pvs_name) 299 config.prop_name = pvs_name; 300 } 301 302 if (drv->data->genpd_names) { 303 config.genpd_names = drv->data->genpd_names; 304 config.virt_devs = NULL; 305 } 306 307 if (config.supported_hw || config.genpd_names) { 308 drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config); 309 if (drv->opp_tokens[cpu] < 0) { 310 ret = drv->opp_tokens[cpu]; 311 dev_err(cpu_dev, "Failed to set OPP config\n"); 312 goto free_opp; 313 } 314 } 315 } 316 317 cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1, 318 NULL, 0); 319 if (!IS_ERR(cpufreq_dt_pdev)) { 320 platform_set_drvdata(pdev, drv); 321 return 0; 322 } 323 324 ret = PTR_ERR(cpufreq_dt_pdev); 325 dev_err(cpu_dev, "Failed to register platform device\n"); 326 327 free_opp: 328 for_each_possible_cpu(cpu) 329 dev_pm_opp_clear_config(drv->opp_tokens[cpu]); 330 kfree(drv->opp_tokens); 331 free_drv: 332 kfree(drv); 333 334 return ret; 335 } 336 337 static int qcom_cpufreq_remove(struct platform_device *pdev) 338 { 339 struct qcom_cpufreq_drv *drv = platform_get_drvdata(pdev); 340 unsigned int cpu; 341 342 platform_device_unregister(cpufreq_dt_pdev); 343 344 for_each_possible_cpu(cpu) 345 dev_pm_opp_clear_config(drv->opp_tokens[cpu]); 346 347 kfree(drv->opp_tokens); 348 kfree(drv); 349 350 return 0; 351 } 352 353 static struct platform_driver qcom_cpufreq_driver = { 354 .probe = qcom_cpufreq_probe, 355 .remove = qcom_cpufreq_remove, 356 .driver = { 357 .name = "qcom-cpufreq-nvmem", 358 }, 359 }; 360 361 static const struct of_device_id qcom_cpufreq_match_list[] __initconst = { 362 { .compatible = "qcom,apq8096", .data = &match_data_kryo }, 363 { .compatible = "qcom,msm8996", .data = &match_data_kryo }, 364 { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, 365 { .compatible = "qcom,ipq8064", .data = &match_data_krait }, 366 { .compatible = "qcom,apq8064", .data = &match_data_krait }, 367 { .compatible = "qcom,msm8974", .data = &match_data_krait }, 368 { .compatible = "qcom,msm8960", .data = &match_data_krait }, 369 {}, 370 }; 371 MODULE_DEVICE_TABLE(of, qcom_cpufreq_match_list); 372 373 /* 374 * Since the driver depends on smem and nvmem drivers, which may 375 * return EPROBE_DEFER, all the real activity is done in the probe, 376 * which may be defered as well. The init here is only registering 377 * the driver and the platform device. 378 */ 379 static int __init qcom_cpufreq_init(void) 380 { 381 struct device_node *np = of_find_node_by_path("/"); 382 const struct of_device_id *match; 383 int ret; 384 385 if (!np) 386 return -ENODEV; 387 388 match = of_match_node(qcom_cpufreq_match_list, np); 389 of_node_put(np); 390 if (!match) 391 return -ENODEV; 392 393 ret = platform_driver_register(&qcom_cpufreq_driver); 394 if (unlikely(ret < 0)) 395 return ret; 396 397 cpufreq_pdev = platform_device_register_data(NULL, "qcom-cpufreq-nvmem", 398 -1, match, sizeof(*match)); 399 ret = PTR_ERR_OR_ZERO(cpufreq_pdev); 400 if (0 == ret) 401 return 0; 402 403 platform_driver_unregister(&qcom_cpufreq_driver); 404 return ret; 405 } 406 module_init(qcom_cpufreq_init); 407 408 static void __exit qcom_cpufreq_exit(void) 409 { 410 platform_device_unregister(cpufreq_pdev); 411 platform_driver_unregister(&qcom_cpufreq_driver); 412 } 413 module_exit(qcom_cpufreq_exit); 414 415 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. CPUfreq driver"); 416 MODULE_LICENSE("GPL v2"); 417