1 From cc41a266280cad0b55319e614167c88dff344248 Mon Sep 17 00:00:00 2001
2 From: Ansuel Smith <ansuelsmth@gmail.com>
3 Date: Sat, 22 Feb 2020 16:33:10 +0100
4 Subject: [PATCH 1/8] cpufreq: add Krait dedicated scaling driver
6 This new driver is based on generic cpufreq-dt driver.
7 Krait SoCs have 2-4 cpu and one shared L2 cache that can
8 operate at different frequency based on the maximum cpu clk
10 L2 frequency and voltage are scaled on every frequency change
11 if needed. On Krait SoCs is present a bug that can cause
12 transition problem between frequency bin, to workaround this
13 on more than one transition, the L2 frequency is first set to the
14 base rate and then to the target rate.
15 The L2 frequency use the OPP framework and use the opp-level
16 bindings to link the l2 freq to different cpu freq. This is needed
17 as the Krait l2 clk are note mapped 1:1 to the core clks and some
18 of the l2 clk is set based on a range of the cpu clks. If the driver
19 find a broken config (for example no opp-level set) the l2 scaling is
22 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
24 drivers/cpufreq/Kconfig.arm | 14 +-
25 drivers/cpufreq/Makefile | 2 +
26 drivers/cpufreq/qcom-cpufreq-krait.c | 589 +++++++++++++++++++++++++++
27 3 files changed, 604 insertions(+), 1 deletion(-)
28 create mode 100644 drivers/cpufreq/qcom-cpufreq-krait.c
30 --- a/drivers/cpufreq/Kconfig.arm
31 +++ b/drivers/cpufreq/Kconfig.arm
32 @@ -150,6 +150,18 @@ config ARM_QCOM_CPUFREQ_HW
33 The driver implements the cpufreq interface for this HW engine.
34 Say Y if you want to support CPUFreq HW.
36 +config ARM_QCOM_CPUFREQ_KRAIT
37 + tristate "CPU Frequency scaling support for Krait SoCs"
38 + depends on ARCH_QCOM || COMPILE_TEST
40 + select ARM_QCOM_CPUFREQ_NVMEM
42 + This adds the CPUFreq driver for Qualcomm Krait SoC based boards.
43 + This scale the cache clk and regulator based on the different cpu
44 + clks when scaling the different cores clk.
48 config ARM_RASPBERRYPI_CPUFREQ
49 tristate "Raspberry Pi cpufreq support"
50 depends on CLK_RASPBERRYPI || COMPILE_TEST
51 @@ -339,4 +351,4 @@ config ARM_PXA2xx_CPUFREQ
53 This add the CPUFreq driver support for Intel PXA2xx SOCs.
57 \ No newline at end of file
58 --- a/drivers/cpufreq/Makefile
59 +++ b/drivers/cpufreq/Makefile
60 @@ -63,6 +63,7 @@ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2
61 obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
62 obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o
63 obj-$(CONFIG_ARM_QCOM_CPUFREQ_NVMEM) += qcom-cpufreq-nvmem.o
64 +obj-$(CONFIG_ARM_QCOM_CPUFREQ_KRAIT) += qcom-cpufreq-krait.o
65 obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ) += raspberrypi-cpufreq.o
66 obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o
67 obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o
68 @@ -86,6 +87,7 @@ obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += te
69 obj-$(CONFIG_ARM_TEGRA194_CPUFREQ) += tegra194-cpufreq.o
70 obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-cpufreq.o
71 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
72 +obj-$(CONFIG_ARM_KRAIT_CPUFREQ) += krait-cpufreq.o
75 ##################################################################################
77 +++ b/drivers/cpufreq/qcom-cpufreq-krait.c
79 +// SPDX-License-Identifier: GPL-2.0
81 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
83 +#include <linux/clk.h>
84 +#include <linux/cpu.h>
85 +#include <linux/cpufreq.h>
86 +#include <linux/cpumask.h>
87 +#include <linux/err.h>
88 +#include <linux/module.h>
89 +#include <linux/of.h>
90 +#include <linux/of_device.h>
91 +#include <linux/pm_opp.h>
92 +#include <linux/platform_device.h>
93 +#include <linux/regulator/consumer.h>
94 +#include <linux/slab.h>
95 +#include <linux/thermal.h>
97 +#include "cpufreq-dt.h"
99 +static struct platform_device *l2_pdev;
101 +struct private_data {
102 + struct opp_table *opp_table;
103 + struct device *cpu_dev;
104 + const char *reg_name;
105 + bool have_static_opps;
108 +static int set_target(struct cpufreq_policy *policy, unsigned int index)
110 + struct private_data *priv = policy->driver_data;
111 + unsigned long freq = policy->freq_table[index].frequency;
112 + unsigned long target_freq = freq * 1000;
113 + struct dev_pm_opp *opp;
114 + unsigned int level;
118 + int policy_cpu = policy->cpu;
120 + /* find the max freq across all core */
121 + for_each_present_cpu(cpu)
122 + if (cpu != policy_cpu)
125 + (unsigned long)cpufreq_quick_get(cpu));
127 + opp = dev_pm_opp_find_freq_exact(priv->cpu_dev, target_freq,
130 + dev_err(&l2_pdev->dev, "failed to find OPP for %ld\n",
132 + return PTR_ERR(opp);
134 + level = dev_pm_opp_get_level(opp);
135 + dev_pm_opp_put(opp);
138 + * Hardware constraint:
139 + * Krait CPU cannot operate at 384MHz with L2 at 1Ghz.
140 + * Assume index 0 with the idle freq and level > 0 as
141 + * any L2 freq > 384MHz.
142 + * Skip CPU freq change in this corner case.
144 + if (unlikely(index == 0 && level != 0)) {
145 + dev_err(priv->cpu_dev, "Krait CPU can't operate at idle freq with L2 at 1GHz");
149 + opp = dev_pm_opp_find_level_exact(&l2_pdev->dev, level);
151 + dev_err(&l2_pdev->dev,
152 + "failed to find level OPP for %d\n", level);
153 + return PTR_ERR(opp);
155 + target_freq = dev_pm_opp_get_freq(opp);
156 + dev_pm_opp_put(opp);
158 + ret = dev_pm_opp_set_rate(&l2_pdev->dev, target_freq);
163 + ret = dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);
167 + arch_set_freq_scale(policy->related_cpus, freq,
168 + policy->cpuinfo.max_freq);
174 + * An earlier version of opp-v1 bindings used to name the regulator
175 + * "cpu0-supply", we still need to handle that for backwards compatibility.
177 +static const char *find_supply_name(struct device *dev)
179 + struct device_node *np;
180 + struct property *pp;
182 + const char *name = NULL;
184 + np = of_node_get(dev->of_node);
186 + /* This must be valid for sure */
190 + /* Try "cpu0" for older DTs */
192 + pp = of_find_property(np, "cpu0-supply", NULL);
199 + pp = of_find_property(np, "cpu-supply", NULL);
205 + dev_dbg(dev, "no regulator for cpu%d\n", cpu);
211 +static int resources_available(void)
213 + struct device *cpu_dev;
214 + struct regulator *cpu_reg;
215 + struct clk *cpu_clk;
219 + cpu_dev = get_cpu_device(0);
221 + pr_err("failed to get cpu0 device\n");
225 + cpu_clk = clk_get(cpu_dev, NULL);
226 + ret = PTR_ERR_OR_ZERO(cpu_clk);
229 + * If cpu's clk node is present, but clock is not yet
230 + * registered, we should try defering probe.
232 + if (ret == -EPROBE_DEFER)
233 + dev_dbg(cpu_dev, "clock not ready, retry\n");
235 + dev_err(cpu_dev, "failed to get clock: %d\n", ret);
242 + name = find_supply_name(cpu_dev);
243 + /* Platform doesn't require regulator */
247 + cpu_reg = regulator_get_optional(cpu_dev, name);
248 + ret = PTR_ERR_OR_ZERO(cpu_reg);
251 + * If cpu's regulator supply node is present, but regulator is
252 + * not yet registered, we should try defering probe.
254 + if (ret == -EPROBE_DEFER)
255 + dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n");
257 + dev_dbg(cpu_dev, "no regulator for cpu0: %d\n", ret);
262 + regulator_put(cpu_reg);
266 +static int cpufreq_init(struct cpufreq_policy *policy)
268 + struct cpufreq_frequency_table *freq_table;
269 + struct opp_table *opp_table = NULL;
270 + unsigned int transition_latency;
271 + struct private_data *priv;
272 + struct device *cpu_dev;
273 + bool fallback = false;
274 + struct clk *cpu_clk;
278 + cpu_dev = get_cpu_device(policy->cpu);
280 + pr_err("failed to get cpu%d device\n", policy->cpu);
284 + cpu_clk = clk_get(cpu_dev, NULL);
285 + if (IS_ERR(cpu_clk)) {
286 + ret = PTR_ERR(cpu_clk);
287 + dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
291 + /* Get OPP-sharing information from "operating-points-v2" bindings */
292 + ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, policy->cpus);
294 + if (ret != -ENOENT)
298 + * operating-points-v2 not supported, fallback to old method of
299 + * finding shared-OPPs for backward compatibility if the
300 + * platform hasn't set sharing CPUs.
302 + if (dev_pm_opp_get_sharing_cpus(cpu_dev, policy->cpus))
307 + * OPP layer will be taking care of regulators now, but it needs to know
308 + * the name of the regulator first.
310 + name = find_supply_name(cpu_dev);
312 + opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
313 + if (IS_ERR(opp_table)) {
314 + ret = PTR_ERR(opp_table);
316 + "Failed to set regulator for cpu%d: %d\n",
322 + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
325 + goto out_put_regulator;
328 + priv->reg_name = name;
329 + priv->opp_table = opp_table;
332 + * Initialize OPP tables for all policy->cpus. They will be shared by
333 + * all CPUs which have marked their CPUs shared with OPP bindings.
335 + * For platforms not using operating-points-v2 bindings, we do this
336 + * before updating policy->cpus. Otherwise, we will end up creating
337 + * duplicate OPPs for policy->cpus.
339 + * OPPs might be populated at runtime, don't check for error here
341 + if (!dev_pm_opp_of_cpumask_add_table(policy->cpus))
342 + priv->have_static_opps = true;
345 + * But we need OPP table to function so if it is not there let's
346 + * give platform code chance to provide it for us.
348 + ret = dev_pm_opp_get_opp_count(cpu_dev);
350 + dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
351 + ret = -EPROBE_DEFER;
356 + cpumask_setall(policy->cpus);
359 + * OPP tables are initialized only for policy->cpu, do it for
362 + ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
365 + "%s: failed to mark OPPs as shared: %d\n",
369 + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
371 + dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
375 + priv->cpu_dev = cpu_dev;
377 + policy->driver_data = priv;
378 + policy->clk = cpu_clk;
379 + policy->freq_table = freq_table;
381 + policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
383 + transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
384 + if (!transition_latency)
385 + transition_latency = CPUFREQ_ETERNAL;
387 + policy->cpuinfo.transition_latency = transition_latency;
388 + policy->dvfs_possible_from_any_cpu = true;
390 + dev_pm_opp_of_register_em(cpu_dev, policy->cpus);
395 + if (priv->have_static_opps)
396 + dev_pm_opp_of_cpumask_remove_table(policy->cpus);
400 + dev_pm_opp_put_regulators(opp_table);
407 +static int cpufreq_online(struct cpufreq_policy *policy)
409 + /* We did light-weight tear down earlier, nothing to do here */
413 +static int cpufreq_offline(struct cpufreq_policy *policy)
416 + * Preserve policy->driver_data and don't free resources on light-weight
422 +static int cpufreq_exit(struct cpufreq_policy *policy)
424 + struct private_data *priv = policy->driver_data;
426 + dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
427 + if (priv->have_static_opps)
428 + dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
429 + if (priv->reg_name)
430 + dev_pm_opp_put_regulators(priv->opp_table);
432 + clk_put(policy->clk);
438 +static struct freq_attr *krait_cpufreq_attr[] = {
439 + &cpufreq_freq_attr_scaling_available_freqs,
443 +static struct cpufreq_driver krait_cpufreq_driver = {
444 + .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
445 + CPUFREQ_IS_COOLING_DEV,
446 + .verify = cpufreq_generic_frequency_table_verify,
447 + .target_index = set_target,
448 + .get = cpufreq_generic_get,
449 + .init = cpufreq_init,
450 + .exit = cpufreq_exit,
451 + .online = cpufreq_online,
452 + .offline = cpufreq_offline,
453 + .name = "krait-cpufreq",
454 + .attr = krait_cpufreq_attr,
455 + .suspend = cpufreq_generic_suspend,
459 + unsigned long idle_freq;
460 + bool regulator_enabled;
463 +static int krait_cache_set_opp(struct dev_pm_set_opp_data *data)
465 + unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
466 + struct dev_pm_opp_supply *supply = &data->new_opp.supplies[0];
467 + struct regulator *reg = data->regulators[0];
468 + struct clk *clk = data->clk;
469 + struct krait_data *kdata;
470 + unsigned long idle_freq;
473 + kdata = (struct krait_data *)dev_get_drvdata(data->dev);
474 + idle_freq = kdata->idle_freq;
476 + /* Scaling up? Scale voltage before frequency */
477 + if (freq >= old_freq) {
478 + ret = regulator_set_voltage_triplet(reg, supply->u_volt_min,
480 + supply->u_volt_max);
486 + * Set to idle bin if switching from normal to high bin
487 + * or vice versa. It has been notice that a bug is triggered
488 + * in cache scaling when more than one bin is scaled, to fix
489 + * this we first need to transition to the base rate and then
492 + if (likely(freq != idle_freq && old_freq != idle_freq)) {
493 + ret = clk_set_rate(clk, idle_freq);
498 + ret = clk_set_rate(clk, freq);
502 + /* Scaling down? Scale voltage after frequency */
503 + if (freq < old_freq) {
504 + ret = regulator_set_voltage_triplet(reg, supply->u_volt_min,
506 + supply->u_volt_max);
509 + if (unlikely(!kdata->regulator_enabled)) {
510 + ret = regulator_enable(reg);
512 + dev_warn(data->dev, "Failed to enable regulator: %d", ret);
514 + kdata->regulator_enabled = true;
521 +static int krait_cache_probe(struct platform_device *pdev)
523 + struct device *dev = &pdev->dev;
524 + struct krait_data *data;
525 + struct opp_table *table;
526 + struct dev_pm_opp *opp;
527 + struct device *cpu_dev;
530 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
534 + table = dev_pm_opp_set_regulators(dev, (const char *[]){ "l2" }, 1);
535 + if (IS_ERR(table)) {
536 + ret = PTR_ERR(table);
537 + if (ret != -EPROBE_DEFER)
538 + dev_err(dev, "failed to set regulators %d\n", ret);
543 + ret = PTR_ERR_OR_ZERO(
544 + dev_pm_opp_register_set_opp_helper(dev, krait_cache_set_opp));
548 + ret = dev_pm_opp_of_add_table(dev);
550 + dev_err(dev, "failed to parse L2 freq thresholds\n");
554 + opp = dev_pm_opp_find_freq_ceil(dev, &data->idle_freq);
555 + dev_pm_opp_put(opp);
558 + * Check opp-level configuration
559 + * At least 2 level must be set or the cache will always be scaled
560 + * the idle freq causing some performance problem
562 + * In case of invalid configuration, the l2 scaling is skipped
564 + cpu_dev = get_cpu_device(0);
566 + pr_err("failed to get cpu0 device\n");
571 + * Check if we have at least opp-level 1, 0 should always be set to
574 + opp = dev_pm_opp_find_level_exact(dev, 1);
577 + "Invalid configuration found of l2 opp. Can't find opp-level 1");
580 + dev_pm_opp_put(opp);
583 + * Check if we have at least opp-level 1 in the cpu opp, 0 should always
584 + * be set to the idle freq
586 + opp = dev_pm_opp_find_level_exact(cpu_dev, 1);
589 + "Invalid configuration found of cpu opp. Can't find opp-level 1");
592 + dev_pm_opp_put(opp);
594 + platform_set_drvdata(pdev, data);
596 + /* The l2 scaling is enabled by linking the cpufreq driver */
602 + dev_pm_opp_remove_table(dev);
603 + dev_pm_opp_put_regulators(table);
604 + dev_pm_opp_unregister_set_opp_helper(table);
609 +static int krait_cache_remove(struct platform_device *pdev)
611 + struct device *dev = &pdev->dev;
612 + struct opp_table *table = dev_pm_opp_get_opp_table(dev);
614 + dev_pm_opp_remove_table(dev);
615 + dev_pm_opp_put_regulators(table);
616 + dev_pm_opp_unregister_set_opp_helper(table);
621 +static const struct of_device_id krait_cache_match_table[] = {
622 + { .compatible = "qcom,krait-cache" },
626 +static struct platform_driver krait_cache_driver = {
628 + .name = "krait-cache",
629 + .of_match_table = krait_cache_match_table,
631 + .probe = krait_cache_probe,
632 + .remove = krait_cache_remove,
634 +module_platform_driver(krait_cache_driver);
636 +static int krait_cpufreq_probe(struct platform_device *pdev)
638 + struct cpufreq_dt_platform_data *data = dev_get_platdata(&pdev->dev);
642 + * All per-cluster (CPUs sharing clock/voltages) initialization is done
643 + * from ->init(). In probe(), we just need to make sure that clk and
644 + * regulators are available. Else defer probe and retry.
646 + * FIXME: Is checking this only for CPU0 sufficient ?
648 + ret = resources_available();
653 + if (data->have_governor_per_policy)
654 + krait_cpufreq_driver.flags |=
655 + CPUFREQ_HAVE_GOVERNOR_PER_POLICY;
657 + krait_cpufreq_driver.resume = data->resume;
659 + krait_cpufreq_driver.suspend = data->suspend;
662 + ret = cpufreq_register_driver(&krait_cpufreq_driver);
664 + dev_err(&pdev->dev, "failed register driver: %d\n", ret);
669 +static int krait_cpufreq_remove(struct platform_device *pdev)
671 + cpufreq_unregister_driver(&krait_cpufreq_driver);
675 +static struct platform_driver krait_cpufreq_platdrv = {
677 + .name = "krait-cpufreq",
679 + .probe = krait_cpufreq_probe,
680 + .remove = krait_cpufreq_remove,
682 +module_platform_driver(krait_cpufreq_platdrv);
684 +MODULE_ALIAS("platform:krait-cpufreq");
685 +MODULE_AUTHOR("Ansuel Smith <ansuelsmth@gmail.com>");
686 +MODULE_DESCRIPTION("Dedicated Krait SoC cpufreq driver");
687 +MODULE_LICENSE("GPL");