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

Configure Feed

Select the types of activity you want to include in your feed.

at v4.4-rc2 527 lines 14 kB view raw
1/* 2 * Copyright (c) 2015 Linaro Ltd. 3 * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15#include <linux/clk.h> 16#include <linux/cpu.h> 17#include <linux/cpu_cooling.h> 18#include <linux/cpufreq.h> 19#include <linux/cpumask.h> 20#include <linux/of.h> 21#include <linux/platform_device.h> 22#include <linux/pm_opp.h> 23#include <linux/regulator/consumer.h> 24#include <linux/slab.h> 25#include <linux/thermal.h> 26 27#define MIN_VOLT_SHIFT (100000) 28#define MAX_VOLT_SHIFT (200000) 29#define MAX_VOLT_LIMIT (1150000) 30#define VOLT_TOL (10000) 31 32/* 33 * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS 34 * on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in 35 * Mediatek SoCs has two voltage inputs, Vproc and Vsram. In some cases the two 36 * voltage inputs need to be controlled under a hardware limitation: 37 * 100mV < Vsram - Vproc < 200mV 38 * 39 * When scaling the clock frequency of a CPU clock domain, the clock source 40 * needs to be switched to another stable PLL clock temporarily until 41 * the original PLL becomes stable at target frequency. 42 */ 43struct mtk_cpu_dvfs_info { 44 struct device *cpu_dev; 45 struct regulator *proc_reg; 46 struct regulator *sram_reg; 47 struct clk *cpu_clk; 48 struct clk *inter_clk; 49 struct thermal_cooling_device *cdev; 50 int intermediate_voltage; 51 bool need_voltage_tracking; 52}; 53 54static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, 55 int new_vproc) 56{ 57 struct regulator *proc_reg = info->proc_reg; 58 struct regulator *sram_reg = info->sram_reg; 59 int old_vproc, old_vsram, new_vsram, vsram, vproc, ret; 60 61 old_vproc = regulator_get_voltage(proc_reg); 62 old_vsram = regulator_get_voltage(sram_reg); 63 /* Vsram should not exceed the maximum allowed voltage of SoC. */ 64 new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); 65 66 if (old_vproc < new_vproc) { 67 /* 68 * When scaling up voltages, Vsram and Vproc scale up step 69 * by step. At each step, set Vsram to (Vproc + 200mV) first, 70 * then set Vproc to (Vsram - 100mV). 71 * Keep doing it until Vsram and Vproc hit target voltages. 72 */ 73 do { 74 old_vsram = regulator_get_voltage(sram_reg); 75 old_vproc = regulator_get_voltage(proc_reg); 76 77 vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT); 78 79 if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { 80 vsram = MAX_VOLT_LIMIT; 81 82 /* 83 * If the target Vsram hits the maximum voltage, 84 * try to set the exact voltage value first. 85 */ 86 ret = regulator_set_voltage(sram_reg, vsram, 87 vsram); 88 if (ret) 89 ret = regulator_set_voltage(sram_reg, 90 vsram - VOLT_TOL, 91 vsram); 92 93 vproc = new_vproc; 94 } else { 95 ret = regulator_set_voltage(sram_reg, vsram, 96 vsram + VOLT_TOL); 97 98 vproc = vsram - MIN_VOLT_SHIFT; 99 } 100 if (ret) 101 return ret; 102 103 ret = regulator_set_voltage(proc_reg, vproc, 104 vproc + VOLT_TOL); 105 if (ret) { 106 regulator_set_voltage(sram_reg, old_vsram, 107 old_vsram); 108 return ret; 109 } 110 } while (vproc < new_vproc || vsram < new_vsram); 111 } else if (old_vproc > new_vproc) { 112 /* 113 * When scaling down voltages, Vsram and Vproc scale down step 114 * by step. At each step, set Vproc to (Vsram - 200mV) first, 115 * then set Vproc to (Vproc + 100mV). 116 * Keep doing it until Vsram and Vproc hit target voltages. 117 */ 118 do { 119 old_vproc = regulator_get_voltage(proc_reg); 120 old_vsram = regulator_get_voltage(sram_reg); 121 122 vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT); 123 ret = regulator_set_voltage(proc_reg, vproc, 124 vproc + VOLT_TOL); 125 if (ret) 126 return ret; 127 128 if (vproc == new_vproc) 129 vsram = new_vsram; 130 else 131 vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT); 132 133 if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { 134 vsram = MAX_VOLT_LIMIT; 135 136 /* 137 * If the target Vsram hits the maximum voltage, 138 * try to set the exact voltage value first. 139 */ 140 ret = regulator_set_voltage(sram_reg, vsram, 141 vsram); 142 if (ret) 143 ret = regulator_set_voltage(sram_reg, 144 vsram - VOLT_TOL, 145 vsram); 146 } else { 147 ret = regulator_set_voltage(sram_reg, vsram, 148 vsram + VOLT_TOL); 149 } 150 151 if (ret) { 152 regulator_set_voltage(proc_reg, old_vproc, 153 old_vproc); 154 return ret; 155 } 156 } while (vproc > new_vproc + VOLT_TOL || 157 vsram > new_vsram + VOLT_TOL); 158 } 159 160 return 0; 161} 162 163static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc) 164{ 165 if (info->need_voltage_tracking) 166 return mtk_cpufreq_voltage_tracking(info, vproc); 167 else 168 return regulator_set_voltage(info->proc_reg, vproc, 169 vproc + VOLT_TOL); 170} 171 172static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, 173 unsigned int index) 174{ 175 struct cpufreq_frequency_table *freq_table = policy->freq_table; 176 struct clk *cpu_clk = policy->clk; 177 struct clk *armpll = clk_get_parent(cpu_clk); 178 struct mtk_cpu_dvfs_info *info = policy->driver_data; 179 struct device *cpu_dev = info->cpu_dev; 180 struct dev_pm_opp *opp; 181 long freq_hz, old_freq_hz; 182 int vproc, old_vproc, inter_vproc, target_vproc, ret; 183 184 inter_vproc = info->intermediate_voltage; 185 186 old_freq_hz = clk_get_rate(cpu_clk); 187 old_vproc = regulator_get_voltage(info->proc_reg); 188 189 freq_hz = freq_table[index].frequency * 1000; 190 191 rcu_read_lock(); 192 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); 193 if (IS_ERR(opp)) { 194 rcu_read_unlock(); 195 pr_err("cpu%d: failed to find OPP for %ld\n", 196 policy->cpu, freq_hz); 197 return PTR_ERR(opp); 198 } 199 vproc = dev_pm_opp_get_voltage(opp); 200 rcu_read_unlock(); 201 202 /* 203 * If the new voltage or the intermediate voltage is higher than the 204 * current voltage, scale up voltage first. 205 */ 206 target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; 207 if (old_vproc < target_vproc) { 208 ret = mtk_cpufreq_set_voltage(info, target_vproc); 209 if (ret) { 210 pr_err("cpu%d: failed to scale up voltage!\n", 211 policy->cpu); 212 mtk_cpufreq_set_voltage(info, old_vproc); 213 return ret; 214 } 215 } 216 217 /* Reparent the CPU clock to intermediate clock. */ 218 ret = clk_set_parent(cpu_clk, info->inter_clk); 219 if (ret) { 220 pr_err("cpu%d: failed to re-parent cpu clock!\n", 221 policy->cpu); 222 mtk_cpufreq_set_voltage(info, old_vproc); 223 WARN_ON(1); 224 return ret; 225 } 226 227 /* Set the original PLL to target rate. */ 228 ret = clk_set_rate(armpll, freq_hz); 229 if (ret) { 230 pr_err("cpu%d: failed to scale cpu clock rate!\n", 231 policy->cpu); 232 clk_set_parent(cpu_clk, armpll); 233 mtk_cpufreq_set_voltage(info, old_vproc); 234 return ret; 235 } 236 237 /* Set parent of CPU clock back to the original PLL. */ 238 ret = clk_set_parent(cpu_clk, armpll); 239 if (ret) { 240 pr_err("cpu%d: failed to re-parent cpu clock!\n", 241 policy->cpu); 242 mtk_cpufreq_set_voltage(info, inter_vproc); 243 WARN_ON(1); 244 return ret; 245 } 246 247 /* 248 * If the new voltage is lower than the intermediate voltage or the 249 * original voltage, scale down to the new voltage. 250 */ 251 if (vproc < inter_vproc || vproc < old_vproc) { 252 ret = mtk_cpufreq_set_voltage(info, vproc); 253 if (ret) { 254 pr_err("cpu%d: failed to scale down voltage!\n", 255 policy->cpu); 256 clk_set_parent(cpu_clk, info->inter_clk); 257 clk_set_rate(armpll, old_freq_hz); 258 clk_set_parent(cpu_clk, armpll); 259 return ret; 260 } 261 } 262 263 return 0; 264} 265 266static void mtk_cpufreq_ready(struct cpufreq_policy *policy) 267{ 268 struct mtk_cpu_dvfs_info *info = policy->driver_data; 269 struct device_node *np = of_node_get(info->cpu_dev->of_node); 270 271 if (WARN_ON(!np)) 272 return; 273 274 if (of_find_property(np, "#cooling-cells", NULL)) { 275 info->cdev = of_cpufreq_cooling_register(np, 276 policy->related_cpus); 277 278 if (IS_ERR(info->cdev)) { 279 dev_err(info->cpu_dev, 280 "running cpufreq without cooling device: %ld\n", 281 PTR_ERR(info->cdev)); 282 283 info->cdev = NULL; 284 } 285 } 286 287 of_node_put(np); 288} 289 290static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) 291{ 292 struct device *cpu_dev; 293 struct regulator *proc_reg = ERR_PTR(-ENODEV); 294 struct regulator *sram_reg = ERR_PTR(-ENODEV); 295 struct clk *cpu_clk = ERR_PTR(-ENODEV); 296 struct clk *inter_clk = ERR_PTR(-ENODEV); 297 struct dev_pm_opp *opp; 298 unsigned long rate; 299 int ret; 300 301 cpu_dev = get_cpu_device(cpu); 302 if (!cpu_dev) { 303 pr_err("failed to get cpu%d device\n", cpu); 304 return -ENODEV; 305 } 306 307 cpu_clk = clk_get(cpu_dev, "cpu"); 308 if (IS_ERR(cpu_clk)) { 309 if (PTR_ERR(cpu_clk) == -EPROBE_DEFER) 310 pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu); 311 else 312 pr_err("failed to get cpu clk for cpu%d\n", cpu); 313 314 ret = PTR_ERR(cpu_clk); 315 return ret; 316 } 317 318 inter_clk = clk_get(cpu_dev, "intermediate"); 319 if (IS_ERR(inter_clk)) { 320 if (PTR_ERR(inter_clk) == -EPROBE_DEFER) 321 pr_warn("intermediate clk for cpu%d not ready, retry.\n", 322 cpu); 323 else 324 pr_err("failed to get intermediate clk for cpu%d\n", 325 cpu); 326 327 ret = PTR_ERR(inter_clk); 328 goto out_free_resources; 329 } 330 331 proc_reg = regulator_get_exclusive(cpu_dev, "proc"); 332 if (IS_ERR(proc_reg)) { 333 if (PTR_ERR(proc_reg) == -EPROBE_DEFER) 334 pr_warn("proc regulator for cpu%d not ready, retry.\n", 335 cpu); 336 else 337 pr_err("failed to get proc regulator for cpu%d\n", 338 cpu); 339 340 ret = PTR_ERR(proc_reg); 341 goto out_free_resources; 342 } 343 344 /* Both presence and absence of sram regulator are valid cases. */ 345 sram_reg = regulator_get_exclusive(cpu_dev, "sram"); 346 347 ret = dev_pm_opp_of_add_table(cpu_dev); 348 if (ret) { 349 pr_warn("no OPP table for cpu%d\n", cpu); 350 goto out_free_resources; 351 } 352 353 /* Search a safe voltage for intermediate frequency. */ 354 rate = clk_get_rate(inter_clk); 355 rcu_read_lock(); 356 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); 357 if (IS_ERR(opp)) { 358 rcu_read_unlock(); 359 pr_err("failed to get intermediate opp for cpu%d\n", cpu); 360 ret = PTR_ERR(opp); 361 goto out_free_opp_table; 362 } 363 info->intermediate_voltage = dev_pm_opp_get_voltage(opp); 364 rcu_read_unlock(); 365 366 info->cpu_dev = cpu_dev; 367 info->proc_reg = proc_reg; 368 info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg; 369 info->cpu_clk = cpu_clk; 370 info->inter_clk = inter_clk; 371 372 /* 373 * If SRAM regulator is present, software "voltage tracking" is needed 374 * for this CPU power domain. 375 */ 376 info->need_voltage_tracking = !IS_ERR(sram_reg); 377 378 return 0; 379 380out_free_opp_table: 381 dev_pm_opp_of_remove_table(cpu_dev); 382 383out_free_resources: 384 if (!IS_ERR(proc_reg)) 385 regulator_put(proc_reg); 386 if (!IS_ERR(sram_reg)) 387 regulator_put(sram_reg); 388 if (!IS_ERR(cpu_clk)) 389 clk_put(cpu_clk); 390 if (!IS_ERR(inter_clk)) 391 clk_put(inter_clk); 392 393 return ret; 394} 395 396static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) 397{ 398 if (!IS_ERR(info->proc_reg)) 399 regulator_put(info->proc_reg); 400 if (!IS_ERR(info->sram_reg)) 401 regulator_put(info->sram_reg); 402 if (!IS_ERR(info->cpu_clk)) 403 clk_put(info->cpu_clk); 404 if (!IS_ERR(info->inter_clk)) 405 clk_put(info->inter_clk); 406 407 dev_pm_opp_of_remove_table(info->cpu_dev); 408} 409 410static int mtk_cpufreq_init(struct cpufreq_policy *policy) 411{ 412 struct mtk_cpu_dvfs_info *info; 413 struct cpufreq_frequency_table *freq_table; 414 int ret; 415 416 info = kzalloc(sizeof(*info), GFP_KERNEL); 417 if (!info) 418 return -ENOMEM; 419 420 ret = mtk_cpu_dvfs_info_init(info, policy->cpu); 421 if (ret) { 422 pr_err("%s failed to initialize dvfs info for cpu%d\n", 423 __func__, policy->cpu); 424 goto out_free_dvfs_info; 425 } 426 427 ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); 428 if (ret) { 429 pr_err("failed to init cpufreq table for cpu%d: %d\n", 430 policy->cpu, ret); 431 goto out_release_dvfs_info; 432 } 433 434 ret = cpufreq_table_validate_and_show(policy, freq_table); 435 if (ret) { 436 pr_err("%s: invalid frequency table: %d\n", __func__, ret); 437 goto out_free_cpufreq_table; 438 } 439 440 /* CPUs in the same cluster share a clock and power domain. */ 441 cpumask_copy(policy->cpus, &cpu_topology[policy->cpu].core_sibling); 442 policy->driver_data = info; 443 policy->clk = info->cpu_clk; 444 445 return 0; 446 447out_free_cpufreq_table: 448 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table); 449 450out_release_dvfs_info: 451 mtk_cpu_dvfs_info_release(info); 452 453out_free_dvfs_info: 454 kfree(info); 455 456 return ret; 457} 458 459static int mtk_cpufreq_exit(struct cpufreq_policy *policy) 460{ 461 struct mtk_cpu_dvfs_info *info = policy->driver_data; 462 463 cpufreq_cooling_unregister(info->cdev); 464 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table); 465 mtk_cpu_dvfs_info_release(info); 466 kfree(info); 467 468 return 0; 469} 470 471static struct cpufreq_driver mt8173_cpufreq_driver = { 472 .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, 473 .verify = cpufreq_generic_frequency_table_verify, 474 .target_index = mtk_cpufreq_set_target, 475 .get = cpufreq_generic_get, 476 .init = mtk_cpufreq_init, 477 .exit = mtk_cpufreq_exit, 478 .ready = mtk_cpufreq_ready, 479 .name = "mtk-cpufreq", 480 .attr = cpufreq_generic_attr, 481}; 482 483static int mt8173_cpufreq_probe(struct platform_device *pdev) 484{ 485 int ret; 486 487 ret = cpufreq_register_driver(&mt8173_cpufreq_driver); 488 if (ret) 489 pr_err("failed to register mtk cpufreq driver\n"); 490 491 return ret; 492} 493 494static struct platform_driver mt8173_cpufreq_platdrv = { 495 .driver = { 496 .name = "mt8173-cpufreq", 497 }, 498 .probe = mt8173_cpufreq_probe, 499}; 500 501static int mt8173_cpufreq_driver_init(void) 502{ 503 struct platform_device *pdev; 504 int err; 505 506 if (!of_machine_is_compatible("mediatek,mt8173")) 507 return -ENODEV; 508 509 err = platform_driver_register(&mt8173_cpufreq_platdrv); 510 if (err) 511 return err; 512 513 /* 514 * Since there's no place to hold device registration code and no 515 * device tree based way to match cpufreq driver yet, both the driver 516 * and the device registration codes are put here to handle defer 517 * probing. 518 */ 519 pdev = platform_device_register_simple("mt8173-cpufreq", -1, NULL, 0); 520 if (IS_ERR(pdev)) { 521 pr_err("failed to register mtk-cpufreq platform device\n"); 522 return PTR_ERR(pdev); 523 } 524 525 return 0; 526} 527device_initcall(mt8173_cpufreq_driver_init);