Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2012 Freescale Semiconductor, Inc.
0004  *
0005  * Copyright (C) 2014 Linaro.
0006  * Viresh Kumar <viresh.kumar@linaro.org>
0007  */
0008 
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 
0011 #include <linux/clk.h>
0012 #include <linux/cpu.h>
0013 #include <linux/cpufreq.h>
0014 #include <linux/cpumask.h>
0015 #include <linux/err.h>
0016 #include <linux/list.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/pm_opp.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/regulator/consumer.h>
0022 #include <linux/slab.h>
0023 #include <linux/thermal.h>
0024 
0025 #include "cpufreq-dt.h"
0026 
0027 struct private_data {
0028     struct list_head node;
0029 
0030     cpumask_var_t cpus;
0031     struct device *cpu_dev;
0032     struct cpufreq_frequency_table *freq_table;
0033     bool have_static_opps;
0034     int opp_token;
0035 };
0036 
0037 static LIST_HEAD(priv_list);
0038 
0039 static struct freq_attr *cpufreq_dt_attr[] = {
0040     &cpufreq_freq_attr_scaling_available_freqs,
0041     NULL,   /* Extra space for boost-attr if required */
0042     NULL,
0043 };
0044 
0045 static struct private_data *cpufreq_dt_find_data(int cpu)
0046 {
0047     struct private_data *priv;
0048 
0049     list_for_each_entry(priv, &priv_list, node) {
0050         if (cpumask_test_cpu(cpu, priv->cpus))
0051             return priv;
0052     }
0053 
0054     return NULL;
0055 }
0056 
0057 static int set_target(struct cpufreq_policy *policy, unsigned int index)
0058 {
0059     struct private_data *priv = policy->driver_data;
0060     unsigned long freq = policy->freq_table[index].frequency;
0061 
0062     return dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);
0063 }
0064 
0065 /*
0066  * An earlier version of opp-v1 bindings used to name the regulator
0067  * "cpu0-supply", we still need to handle that for backwards compatibility.
0068  */
0069 static const char *find_supply_name(struct device *dev)
0070 {
0071     struct device_node *np;
0072     struct property *pp;
0073     int cpu = dev->id;
0074     const char *name = NULL;
0075 
0076     np = of_node_get(dev->of_node);
0077 
0078     /* This must be valid for sure */
0079     if (WARN_ON(!np))
0080         return NULL;
0081 
0082     /* Try "cpu0" for older DTs */
0083     if (!cpu) {
0084         pp = of_find_property(np, "cpu0-supply", NULL);
0085         if (pp) {
0086             name = "cpu0";
0087             goto node_put;
0088         }
0089     }
0090 
0091     pp = of_find_property(np, "cpu-supply", NULL);
0092     if (pp) {
0093         name = "cpu";
0094         goto node_put;
0095     }
0096 
0097     dev_dbg(dev, "no regulator for cpu%d\n", cpu);
0098 node_put:
0099     of_node_put(np);
0100     return name;
0101 }
0102 
0103 static int cpufreq_init(struct cpufreq_policy *policy)
0104 {
0105     struct private_data *priv;
0106     struct device *cpu_dev;
0107     struct clk *cpu_clk;
0108     unsigned int transition_latency;
0109     int ret;
0110 
0111     priv = cpufreq_dt_find_data(policy->cpu);
0112     if (!priv) {
0113         pr_err("failed to find data for cpu%d\n", policy->cpu);
0114         return -ENODEV;
0115     }
0116     cpu_dev = priv->cpu_dev;
0117 
0118     cpu_clk = clk_get(cpu_dev, NULL);
0119     if (IS_ERR(cpu_clk)) {
0120         ret = PTR_ERR(cpu_clk);
0121         dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
0122         return ret;
0123     }
0124 
0125     transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
0126     if (!transition_latency)
0127         transition_latency = CPUFREQ_ETERNAL;
0128 
0129     cpumask_copy(policy->cpus, priv->cpus);
0130     policy->driver_data = priv;
0131     policy->clk = cpu_clk;
0132     policy->freq_table = priv->freq_table;
0133     policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
0134     policy->cpuinfo.transition_latency = transition_latency;
0135     policy->dvfs_possible_from_any_cpu = true;
0136 
0137     /* Support turbo/boost mode */
0138     if (policy_has_boost_freq(policy)) {
0139         /* This gets disabled by core on driver unregister */
0140         ret = cpufreq_enable_boost_support();
0141         if (ret)
0142             goto out_clk_put;
0143         cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
0144     }
0145 
0146     return 0;
0147 
0148 out_clk_put:
0149     clk_put(cpu_clk);
0150 
0151     return ret;
0152 }
0153 
0154 static int cpufreq_online(struct cpufreq_policy *policy)
0155 {
0156     /* We did light-weight tear down earlier, nothing to do here */
0157     return 0;
0158 }
0159 
0160 static int cpufreq_offline(struct cpufreq_policy *policy)
0161 {
0162     /*
0163      * Preserve policy->driver_data and don't free resources on light-weight
0164      * tear down.
0165      */
0166     return 0;
0167 }
0168 
0169 static int cpufreq_exit(struct cpufreq_policy *policy)
0170 {
0171     clk_put(policy->clk);
0172     return 0;
0173 }
0174 
0175 static struct cpufreq_driver dt_cpufreq_driver = {
0176     .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
0177          CPUFREQ_IS_COOLING_DEV,
0178     .verify = cpufreq_generic_frequency_table_verify,
0179     .target_index = set_target,
0180     .get = cpufreq_generic_get,
0181     .init = cpufreq_init,
0182     .exit = cpufreq_exit,
0183     .online = cpufreq_online,
0184     .offline = cpufreq_offline,
0185     .register_em = cpufreq_register_em_with_opp,
0186     .name = "cpufreq-dt",
0187     .attr = cpufreq_dt_attr,
0188     .suspend = cpufreq_generic_suspend,
0189 };
0190 
0191 static int dt_cpufreq_early_init(struct device *dev, int cpu)
0192 {
0193     struct private_data *priv;
0194     struct device *cpu_dev;
0195     bool fallback = false;
0196     const char *reg_name[] = { NULL, NULL };
0197     int ret;
0198 
0199     /* Check if this CPU is already covered by some other policy */
0200     if (cpufreq_dt_find_data(cpu))
0201         return 0;
0202 
0203     cpu_dev = get_cpu_device(cpu);
0204     if (!cpu_dev)
0205         return -EPROBE_DEFER;
0206 
0207     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0208     if (!priv)
0209         return -ENOMEM;
0210 
0211     if (!alloc_cpumask_var(&priv->cpus, GFP_KERNEL))
0212         return -ENOMEM;
0213 
0214     cpumask_set_cpu(cpu, priv->cpus);
0215     priv->cpu_dev = cpu_dev;
0216 
0217     /*
0218      * OPP layer will be taking care of regulators now, but it needs to know
0219      * the name of the regulator first.
0220      */
0221     reg_name[0] = find_supply_name(cpu_dev);
0222     if (reg_name[0]) {
0223         priv->opp_token = dev_pm_opp_set_regulators(cpu_dev, reg_name);
0224         if (priv->opp_token < 0) {
0225             ret = priv->opp_token;
0226             if (ret != -EPROBE_DEFER)
0227                 dev_err(cpu_dev, "failed to set regulators: %d\n",
0228                     ret);
0229             goto free_cpumask;
0230         }
0231     }
0232 
0233     /* Get OPP-sharing information from "operating-points-v2" bindings */
0234     ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->cpus);
0235     if (ret) {
0236         if (ret != -ENOENT)
0237             goto out;
0238 
0239         /*
0240          * operating-points-v2 not supported, fallback to all CPUs share
0241          * OPP for backward compatibility if the platform hasn't set
0242          * sharing CPUs.
0243          */
0244         if (dev_pm_opp_get_sharing_cpus(cpu_dev, priv->cpus))
0245             fallback = true;
0246     }
0247 
0248     /*
0249      * Initialize OPP tables for all priv->cpus. They will be shared by
0250      * all CPUs which have marked their CPUs shared with OPP bindings.
0251      *
0252      * For platforms not using operating-points-v2 bindings, we do this
0253      * before updating priv->cpus. Otherwise, we will end up creating
0254      * duplicate OPPs for the CPUs.
0255      *
0256      * OPPs might be populated at runtime, don't fail for error here unless
0257      * it is -EPROBE_DEFER.
0258      */
0259     ret = dev_pm_opp_of_cpumask_add_table(priv->cpus);
0260     if (!ret) {
0261         priv->have_static_opps = true;
0262     } else if (ret == -EPROBE_DEFER) {
0263         goto out;
0264     }
0265 
0266     /*
0267      * The OPP table must be initialized, statically or dynamically, by this
0268      * point.
0269      */
0270     ret = dev_pm_opp_get_opp_count(cpu_dev);
0271     if (ret <= 0) {
0272         dev_err(cpu_dev, "OPP table can't be empty\n");
0273         ret = -ENODEV;
0274         goto out;
0275     }
0276 
0277     if (fallback) {
0278         cpumask_setall(priv->cpus);
0279         ret = dev_pm_opp_set_sharing_cpus(cpu_dev, priv->cpus);
0280         if (ret)
0281             dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
0282                 __func__, ret);
0283     }
0284 
0285     ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &priv->freq_table);
0286     if (ret) {
0287         dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
0288         goto out;
0289     }
0290 
0291     list_add(&priv->node, &priv_list);
0292     return 0;
0293 
0294 out:
0295     if (priv->have_static_opps)
0296         dev_pm_opp_of_cpumask_remove_table(priv->cpus);
0297     dev_pm_opp_put_regulators(priv->opp_token);
0298 free_cpumask:
0299     free_cpumask_var(priv->cpus);
0300     return ret;
0301 }
0302 
0303 static void dt_cpufreq_release(void)
0304 {
0305     struct private_data *priv, *tmp;
0306 
0307     list_for_each_entry_safe(priv, tmp, &priv_list, node) {
0308         dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table);
0309         if (priv->have_static_opps)
0310             dev_pm_opp_of_cpumask_remove_table(priv->cpus);
0311         dev_pm_opp_put_regulators(priv->opp_token);
0312         free_cpumask_var(priv->cpus);
0313         list_del(&priv->node);
0314     }
0315 }
0316 
0317 static int dt_cpufreq_probe(struct platform_device *pdev)
0318 {
0319     struct cpufreq_dt_platform_data *data = dev_get_platdata(&pdev->dev);
0320     int ret, cpu;
0321 
0322     /* Request resources early so we can return in case of -EPROBE_DEFER */
0323     for_each_possible_cpu(cpu) {
0324         ret = dt_cpufreq_early_init(&pdev->dev, cpu);
0325         if (ret)
0326             goto err;
0327     }
0328 
0329     if (data) {
0330         if (data->have_governor_per_policy)
0331             dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY;
0332 
0333         dt_cpufreq_driver.resume = data->resume;
0334         if (data->suspend)
0335             dt_cpufreq_driver.suspend = data->suspend;
0336         if (data->get_intermediate) {
0337             dt_cpufreq_driver.target_intermediate = data->target_intermediate;
0338             dt_cpufreq_driver.get_intermediate = data->get_intermediate;
0339         }
0340     }
0341 
0342     ret = cpufreq_register_driver(&dt_cpufreq_driver);
0343     if (ret) {
0344         dev_err(&pdev->dev, "failed register driver: %d\n", ret);
0345         goto err;
0346     }
0347 
0348     return 0;
0349 err:
0350     dt_cpufreq_release();
0351     return ret;
0352 }
0353 
0354 static int dt_cpufreq_remove(struct platform_device *pdev)
0355 {
0356     cpufreq_unregister_driver(&dt_cpufreq_driver);
0357     dt_cpufreq_release();
0358     return 0;
0359 }
0360 
0361 static struct platform_driver dt_cpufreq_platdrv = {
0362     .driver = {
0363         .name   = "cpufreq-dt",
0364     },
0365     .probe      = dt_cpufreq_probe,
0366     .remove     = dt_cpufreq_remove,
0367 };
0368 module_platform_driver(dt_cpufreq_platdrv);
0369 
0370 MODULE_ALIAS("platform:cpufreq-dt");
0371 MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
0372 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
0373 MODULE_DESCRIPTION("Generic cpufreq driver");
0374 MODULE_LICENSE("GPL");