]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/cpufreq/mt8173-cpufreq.c
cpufreq: mt8173: remove redundant regulator_get_voltage() call
[mirror_ubuntu-artful-kernel.git] / drivers / cpufreq / mt8173-cpufreq.c
CommitLineData
1453863f
PCC
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);
1453863f
PCC
62 /* Vsram should not exceed the maximum allowed voltage of SoC. */
63 new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
64
65 if (old_vproc < new_vproc) {
66 /*
67 * When scaling up voltages, Vsram and Vproc scale up step
68 * by step. At each step, set Vsram to (Vproc + 200mV) first,
69 * then set Vproc to (Vsram - 100mV).
70 * Keep doing it until Vsram and Vproc hit target voltages.
71 */
72 do {
73 old_vsram = regulator_get_voltage(sram_reg);
74 old_vproc = regulator_get_voltage(proc_reg);
75
76 vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT);
77
78 if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
79 vsram = MAX_VOLT_LIMIT;
80
81 /*
82 * If the target Vsram hits the maximum voltage,
83 * try to set the exact voltage value first.
84 */
85 ret = regulator_set_voltage(sram_reg, vsram,
86 vsram);
87 if (ret)
88 ret = regulator_set_voltage(sram_reg,
89 vsram - VOLT_TOL,
90 vsram);
91
92 vproc = new_vproc;
93 } else {
94 ret = regulator_set_voltage(sram_reg, vsram,
95 vsram + VOLT_TOL);
96
97 vproc = vsram - MIN_VOLT_SHIFT;
98 }
99 if (ret)
100 return ret;
101
102 ret = regulator_set_voltage(proc_reg, vproc,
103 vproc + VOLT_TOL);
104 if (ret) {
105 regulator_set_voltage(sram_reg, old_vsram,
106 old_vsram);
107 return ret;
108 }
109 } while (vproc < new_vproc || vsram < new_vsram);
110 } else if (old_vproc > new_vproc) {
111 /*
112 * When scaling down voltages, Vsram and Vproc scale down step
113 * by step. At each step, set Vproc to (Vsram - 200mV) first,
114 * then set Vproc to (Vproc + 100mV).
115 * Keep doing it until Vsram and Vproc hit target voltages.
116 */
117 do {
118 old_vproc = regulator_get_voltage(proc_reg);
119 old_vsram = regulator_get_voltage(sram_reg);
120
121 vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT);
122 ret = regulator_set_voltage(proc_reg, vproc,
123 vproc + VOLT_TOL);
124 if (ret)
125 return ret;
126
127 if (vproc == new_vproc)
128 vsram = new_vsram;
129 else
130 vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT);
131
132 if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
133 vsram = MAX_VOLT_LIMIT;
134
135 /*
136 * If the target Vsram hits the maximum voltage,
137 * try to set the exact voltage value first.
138 */
139 ret = regulator_set_voltage(sram_reg, vsram,
140 vsram);
141 if (ret)
142 ret = regulator_set_voltage(sram_reg,
143 vsram - VOLT_TOL,
144 vsram);
145 } else {
146 ret = regulator_set_voltage(sram_reg, vsram,
147 vsram + VOLT_TOL);
148 }
149
150 if (ret) {
151 regulator_set_voltage(proc_reg, old_vproc,
152 old_vproc);
153 return ret;
154 }
155 } while (vproc > new_vproc + VOLT_TOL ||
156 vsram > new_vsram + VOLT_TOL);
157 }
158
159 return 0;
160}
161
162static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
163{
164 if (info->need_voltage_tracking)
165 return mtk_cpufreq_voltage_tracking(info, vproc);
166 else
167 return regulator_set_voltage(info->proc_reg, vproc,
168 vproc + VOLT_TOL);
169}
170
171static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
172 unsigned int index)
173{
174 struct cpufreq_frequency_table *freq_table = policy->freq_table;
175 struct clk *cpu_clk = policy->clk;
176 struct clk *armpll = clk_get_parent(cpu_clk);
177 struct mtk_cpu_dvfs_info *info = policy->driver_data;
178 struct device *cpu_dev = info->cpu_dev;
179 struct dev_pm_opp *opp;
180 long freq_hz, old_freq_hz;
181 int vproc, old_vproc, inter_vproc, target_vproc, ret;
182
183 inter_vproc = info->intermediate_voltage;
184
185 old_freq_hz = clk_get_rate(cpu_clk);
186 old_vproc = regulator_get_voltage(info->proc_reg);
187
188 freq_hz = freq_table[index].frequency * 1000;
189
190 rcu_read_lock();
191 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
192 if (IS_ERR(opp)) {
193 rcu_read_unlock();
194 pr_err("cpu%d: failed to find OPP for %ld\n",
195 policy->cpu, freq_hz);
196 return PTR_ERR(opp);
197 }
198 vproc = dev_pm_opp_get_voltage(opp);
199 rcu_read_unlock();
200
201 /*
202 * If the new voltage or the intermediate voltage is higher than the
203 * current voltage, scale up voltage first.
204 */
205 target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc;
206 if (old_vproc < target_vproc) {
207 ret = mtk_cpufreq_set_voltage(info, target_vproc);
208 if (ret) {
209 pr_err("cpu%d: failed to scale up voltage!\n",
210 policy->cpu);
211 mtk_cpufreq_set_voltage(info, old_vproc);
212 return ret;
213 }
214 }
215
216 /* Reparent the CPU clock to intermediate clock. */
217 ret = clk_set_parent(cpu_clk, info->inter_clk);
218 if (ret) {
219 pr_err("cpu%d: failed to re-parent cpu clock!\n",
220 policy->cpu);
221 mtk_cpufreq_set_voltage(info, old_vproc);
222 WARN_ON(1);
223 return ret;
224 }
225
226 /* Set the original PLL to target rate. */
227 ret = clk_set_rate(armpll, freq_hz);
228 if (ret) {
229 pr_err("cpu%d: failed to scale cpu clock rate!\n",
230 policy->cpu);
231 clk_set_parent(cpu_clk, armpll);
232 mtk_cpufreq_set_voltage(info, old_vproc);
233 return ret;
234 }
235
236 /* Set parent of CPU clock back to the original PLL. */
237 ret = clk_set_parent(cpu_clk, armpll);
238 if (ret) {
239 pr_err("cpu%d: failed to re-parent cpu clock!\n",
240 policy->cpu);
241 mtk_cpufreq_set_voltage(info, inter_vproc);
242 WARN_ON(1);
243 return ret;
244 }
245
246 /*
247 * If the new voltage is lower than the intermediate voltage or the
248 * original voltage, scale down to the new voltage.
249 */
250 if (vproc < inter_vproc || vproc < old_vproc) {
251 ret = mtk_cpufreq_set_voltage(info, vproc);
252 if (ret) {
253 pr_err("cpu%d: failed to scale down voltage!\n",
254 policy->cpu);
255 clk_set_parent(cpu_clk, info->inter_clk);
256 clk_set_rate(armpll, old_freq_hz);
257 clk_set_parent(cpu_clk, armpll);
258 return ret;
259 }
260 }
261
262 return 0;
263}
264
265static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
266{
267 struct mtk_cpu_dvfs_info *info = policy->driver_data;
268 struct device_node *np = of_node_get(info->cpu_dev->of_node);
269
270 if (WARN_ON(!np))
271 return;
272
273 if (of_find_property(np, "#cooling-cells", NULL)) {
274 info->cdev = of_cpufreq_cooling_register(np,
275 policy->related_cpus);
276
277 if (IS_ERR(info->cdev)) {
278 dev_err(info->cpu_dev,
279 "running cpufreq without cooling device: %ld\n",
280 PTR_ERR(info->cdev));
281
282 info->cdev = NULL;
283 }
284 }
285
286 of_node_put(np);
287}
288
289static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
290{
291 struct device *cpu_dev;
292 struct regulator *proc_reg = ERR_PTR(-ENODEV);
293 struct regulator *sram_reg = ERR_PTR(-ENODEV);
294 struct clk *cpu_clk = ERR_PTR(-ENODEV);
295 struct clk *inter_clk = ERR_PTR(-ENODEV);
296 struct dev_pm_opp *opp;
297 unsigned long rate;
298 int ret;
299
300 cpu_dev = get_cpu_device(cpu);
301 if (!cpu_dev) {
302 pr_err("failed to get cpu%d device\n", cpu);
303 return -ENODEV;
304 }
305
306 cpu_clk = clk_get(cpu_dev, "cpu");
307 if (IS_ERR(cpu_clk)) {
308 if (PTR_ERR(cpu_clk) == -EPROBE_DEFER)
309 pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu);
310 else
311 pr_err("failed to get cpu clk for cpu%d\n", cpu);
312
313 ret = PTR_ERR(cpu_clk);
314 return ret;
315 }
316
317 inter_clk = clk_get(cpu_dev, "intermediate");
318 if (IS_ERR(inter_clk)) {
319 if (PTR_ERR(inter_clk) == -EPROBE_DEFER)
320 pr_warn("intermediate clk for cpu%d not ready, retry.\n",
321 cpu);
322 else
323 pr_err("failed to get intermediate clk for cpu%d\n",
324 cpu);
325
326 ret = PTR_ERR(inter_clk);
327 goto out_free_resources;
328 }
329
330 proc_reg = regulator_get_exclusive(cpu_dev, "proc");
331 if (IS_ERR(proc_reg)) {
332 if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
333 pr_warn("proc regulator for cpu%d not ready, retry.\n",
334 cpu);
335 else
336 pr_err("failed to get proc regulator for cpu%d\n",
337 cpu);
338
339 ret = PTR_ERR(proc_reg);
340 goto out_free_resources;
341 }
342
343 /* Both presence and absence of sram regulator are valid cases. */
344 sram_reg = regulator_get_exclusive(cpu_dev, "sram");
345
8f8d37b2 346 ret = dev_pm_opp_of_add_table(cpu_dev);
1453863f
PCC
347 if (ret) {
348 pr_warn("no OPP table for cpu%d\n", cpu);
349 goto out_free_resources;
350 }
351
352 /* Search a safe voltage for intermediate frequency. */
353 rate = clk_get_rate(inter_clk);
354 rcu_read_lock();
355 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
356 if (IS_ERR(opp)) {
357 rcu_read_unlock();
358 pr_err("failed to get intermediate opp for cpu%d\n", cpu);
359 ret = PTR_ERR(opp);
360 goto out_free_opp_table;
361 }
362 info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
363 rcu_read_unlock();
364
365 info->cpu_dev = cpu_dev;
366 info->proc_reg = proc_reg;
367 info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
368 info->cpu_clk = cpu_clk;
369 info->inter_clk = inter_clk;
370
371 /*
372 * If SRAM regulator is present, software "voltage tracking" is needed
373 * for this CPU power domain.
374 */
375 info->need_voltage_tracking = !IS_ERR(sram_reg);
376
377 return 0;
378
379out_free_opp_table:
8f8d37b2 380 dev_pm_opp_of_remove_table(cpu_dev);
1453863f
PCC
381
382out_free_resources:
383 if (!IS_ERR(proc_reg))
384 regulator_put(proc_reg);
385 if (!IS_ERR(sram_reg))
386 regulator_put(sram_reg);
387 if (!IS_ERR(cpu_clk))
388 clk_put(cpu_clk);
389 if (!IS_ERR(inter_clk))
390 clk_put(inter_clk);
391
392 return ret;
393}
394
395static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
396{
397 if (!IS_ERR(info->proc_reg))
398 regulator_put(info->proc_reg);
399 if (!IS_ERR(info->sram_reg))
400 regulator_put(info->sram_reg);
401 if (!IS_ERR(info->cpu_clk))
402 clk_put(info->cpu_clk);
403 if (!IS_ERR(info->inter_clk))
404 clk_put(info->inter_clk);
405
8f8d37b2 406 dev_pm_opp_of_remove_table(info->cpu_dev);
1453863f
PCC
407}
408
409static int mtk_cpufreq_init(struct cpufreq_policy *policy)
410{
411 struct mtk_cpu_dvfs_info *info;
412 struct cpufreq_frequency_table *freq_table;
413 int ret;
414
415 info = kzalloc(sizeof(*info), GFP_KERNEL);
416 if (!info)
417 return -ENOMEM;
418
419 ret = mtk_cpu_dvfs_info_init(info, policy->cpu);
420 if (ret) {
421 pr_err("%s failed to initialize dvfs info for cpu%d\n",
422 __func__, policy->cpu);
423 goto out_free_dvfs_info;
424 }
425
426 ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
427 if (ret) {
428 pr_err("failed to init cpufreq table for cpu%d: %d\n",
429 policy->cpu, ret);
430 goto out_release_dvfs_info;
431 }
432
433 ret = cpufreq_table_validate_and_show(policy, freq_table);
434 if (ret) {
435 pr_err("%s: invalid frequency table: %d\n", __func__, ret);
436 goto out_free_cpufreq_table;
437 }
438
439 /* CPUs in the same cluster share a clock and power domain. */
440 cpumask_copy(policy->cpus, &cpu_topology[policy->cpu].core_sibling);
441 policy->driver_data = info;
442 policy->clk = info->cpu_clk;
443
444 return 0;
445
446out_free_cpufreq_table:
447 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table);
448
449out_release_dvfs_info:
450 mtk_cpu_dvfs_info_release(info);
451
452out_free_dvfs_info:
453 kfree(info);
454
455 return ret;
456}
457
458static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
459{
460 struct mtk_cpu_dvfs_info *info = policy->driver_data;
461
462 cpufreq_cooling_unregister(info->cdev);
463 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
464 mtk_cpu_dvfs_info_release(info);
465 kfree(info);
466
467 return 0;
468}
469
470static struct cpufreq_driver mt8173_cpufreq_driver = {
9bb46b87
PCC
471 .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
472 CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
1453863f
PCC
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);