LCOV - code coverage report
Current view: top level - drivers/cpufreq - cpufreq-dt.c (source / functions) Hit Total Coverage
Test: Real Lines: 70 126 55.6 %
Date: 2020-10-17 15:46:43 Functions: 5 11 45.5 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * Copyright (C) 2012 Freescale Semiconductor, Inc.
       4                 :            :  *
       5                 :            :  * Copyright (C) 2014 Linaro.
       6                 :            :  * Viresh Kumar <viresh.kumar@linaro.org>
       7                 :            :  */
       8                 :            : 
       9                 :            : #define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
      10                 :            : 
      11                 :            : #include <linux/clk.h>
      12                 :            : #include <linux/cpu.h>
      13                 :            : #include <linux/cpufreq.h>
      14                 :            : #include <linux/cpumask.h>
      15                 :            : #include <linux/err.h>
      16                 :            : #include <linux/module.h>
      17                 :            : #include <linux/of.h>
      18                 :            : #include <linux/pm_opp.h>
      19                 :            : #include <linux/platform_device.h>
      20                 :            : #include <linux/regulator/consumer.h>
      21                 :            : #include <linux/slab.h>
      22                 :            : #include <linux/thermal.h>
      23                 :            : 
      24                 :            : #include "cpufreq-dt.h"
      25                 :            : 
      26                 :            : struct private_data {
      27                 :            :         struct opp_table *opp_table;
      28                 :            :         struct device *cpu_dev;
      29                 :            :         const char *reg_name;
      30                 :            :         bool have_static_opps;
      31                 :            : };
      32                 :            : 
      33                 :            : static struct freq_attr *cpufreq_dt_attr[] = {
      34                 :            :         &cpufreq_freq_attr_scaling_available_freqs,
      35                 :            :         NULL,   /* Extra space for boost-attr if required */
      36                 :            :         NULL,
      37                 :            : };
      38                 :            : 
      39                 :          2 : static int set_target(struct cpufreq_policy *policy, unsigned int index)
      40                 :            : {
      41                 :          2 :         struct private_data *priv = policy->driver_data;
      42                 :          2 :         unsigned long freq = policy->freq_table[index].frequency;
      43                 :            :         int ret;
      44                 :            : 
      45                 :          2 :         ret = dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);
      46                 :            : 
      47                 :          2 :         if (!ret) {
      48                 :          2 :                 arch_set_freq_scale(policy->related_cpus, freq,
      49                 :          2 :                                     policy->cpuinfo.max_freq);
      50                 :            :         }
      51                 :            : 
      52                 :          2 :         return ret;
      53                 :            : }
      54                 :            : 
      55                 :            : /*
      56                 :            :  * An earlier version of opp-v1 bindings used to name the regulator
      57                 :            :  * "cpu0-supply", we still need to handle that for backwards compatibility.
      58                 :            :  */
      59                 :          2 : static const char *find_supply_name(struct device *dev)
      60                 :            : {
      61                 :            :         struct device_node *np;
      62                 :            :         struct property *pp;
      63                 :          2 :         int cpu = dev->id;
      64                 :            :         const char *name = NULL;
      65                 :            : 
      66                 :          2 :         np = of_node_get(dev->of_node);
      67                 :            : 
      68                 :            :         /* This must be valid for sure */
      69                 :          2 :         if (WARN_ON(!np))
      70                 :            :                 return NULL;
      71                 :            : 
      72                 :            :         /* Try "cpu0" for older DTs */
      73                 :          2 :         if (!cpu) {
      74                 :          2 :                 pp = of_find_property(np, "cpu0-supply", NULL);
      75                 :          2 :                 if (pp) {
      76                 :            :                         name = "cpu0";
      77                 :            :                         goto node_put;
      78                 :            :                 }
      79                 :            :         }
      80                 :            : 
      81                 :          2 :         pp = of_find_property(np, "cpu-supply", NULL);
      82                 :          2 :         if (pp) {
      83                 :            :                 name = "cpu";
      84                 :          0 :                 goto node_put;
      85                 :            :         }
      86                 :            : 
      87                 :            :         dev_dbg(dev, "no regulator for cpu%d\n", cpu);
      88                 :            : node_put:
      89                 :          2 :         of_node_put(np);
      90                 :          2 :         return name;
      91                 :            : }
      92                 :            : 
      93                 :          2 : static int resources_available(void)
      94                 :            : {
      95                 :            :         struct device *cpu_dev;
      96                 :            :         struct regulator *cpu_reg;
      97                 :            :         struct clk *cpu_clk;
      98                 :            :         int ret = 0;
      99                 :            :         const char *name;
     100                 :            : 
     101                 :          2 :         cpu_dev = get_cpu_device(0);
     102                 :          2 :         if (!cpu_dev) {
     103                 :          0 :                 pr_err("failed to get cpu0 device\n");
     104                 :          0 :                 return -ENODEV;
     105                 :            :         }
     106                 :            : 
     107                 :          2 :         cpu_clk = clk_get(cpu_dev, NULL);
     108                 :            :         ret = PTR_ERR_OR_ZERO(cpu_clk);
     109                 :          2 :         if (ret) {
     110                 :            :                 /*
     111                 :            :                  * If cpu's clk node is present, but clock is not yet
     112                 :            :                  * registered, we should try defering probe.
     113                 :            :                  */
     114                 :          0 :                 if (ret == -EPROBE_DEFER)
     115                 :            :                         dev_dbg(cpu_dev, "clock not ready, retry\n");
     116                 :            :                 else
     117                 :          0 :                         dev_err(cpu_dev, "failed to get clock: %d\n", ret);
     118                 :            : 
     119                 :          0 :                 return ret;
     120                 :            :         }
     121                 :            : 
     122                 :          2 :         clk_put(cpu_clk);
     123                 :            : 
     124                 :          2 :         name = find_supply_name(cpu_dev);
     125                 :            :         /* Platform doesn't require regulator */
     126                 :          2 :         if (!name)
     127                 :            :                 return 0;
     128                 :            : 
     129                 :          0 :         cpu_reg = regulator_get_optional(cpu_dev, name);
     130                 :            :         ret = PTR_ERR_OR_ZERO(cpu_reg);
     131                 :          0 :         if (ret) {
     132                 :            :                 /*
     133                 :            :                  * If cpu's regulator supply node is present, but regulator is
     134                 :            :                  * not yet registered, we should try defering probe.
     135                 :            :                  */
     136                 :            :                 if (ret == -EPROBE_DEFER)
     137                 :            :                         dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n");
     138                 :            :                 else
     139                 :            :                         dev_dbg(cpu_dev, "no regulator for cpu0: %d\n", ret);
     140                 :            : 
     141                 :            :                 return ret;
     142                 :            :         }
     143                 :            : 
     144                 :          0 :         regulator_put(cpu_reg);
     145                 :          0 :         return 0;
     146                 :            : }
     147                 :            : 
     148                 :          2 : static int cpufreq_init(struct cpufreq_policy *policy)
     149                 :            : {
     150                 :            :         struct cpufreq_frequency_table *freq_table;
     151                 :            :         struct opp_table *opp_table = NULL;
     152                 :            :         struct private_data *priv;
     153                 :            :         struct device *cpu_dev;
     154                 :            :         struct clk *cpu_clk;
     155                 :            :         unsigned int transition_latency;
     156                 :            :         bool fallback = false;
     157                 :            :         const char *name;
     158                 :            :         int ret;
     159                 :            : 
     160                 :          2 :         cpu_dev = get_cpu_device(policy->cpu);
     161                 :          2 :         if (!cpu_dev) {
     162                 :          0 :                 pr_err("failed to get cpu%d device\n", policy->cpu);
     163                 :          0 :                 return -ENODEV;
     164                 :            :         }
     165                 :            : 
     166                 :          2 :         cpu_clk = clk_get(cpu_dev, NULL);
     167                 :          2 :         if (IS_ERR(cpu_clk)) {
     168                 :            :                 ret = PTR_ERR(cpu_clk);
     169                 :          0 :                 dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
     170                 :          0 :                 return ret;
     171                 :            :         }
     172                 :            : 
     173                 :            :         /* Get OPP-sharing information from "operating-points-v2" bindings */
     174                 :          2 :         ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, policy->cpus);
     175                 :          2 :         if (ret) {
     176                 :          2 :                 if (ret != -ENOENT)
     177                 :            :                         goto out_put_clk;
     178                 :            : 
     179                 :            :                 /*
     180                 :            :                  * operating-points-v2 not supported, fallback to old method of
     181                 :            :                  * finding shared-OPPs for backward compatibility if the
     182                 :            :                  * platform hasn't set sharing CPUs.
     183                 :            :                  */
     184                 :          2 :                 if (dev_pm_opp_get_sharing_cpus(cpu_dev, policy->cpus))
     185                 :            :                         fallback = true;
     186                 :            :         }
     187                 :            : 
     188                 :            :         /*
     189                 :            :          * OPP layer will be taking care of regulators now, but it needs to know
     190                 :            :          * the name of the regulator first.
     191                 :            :          */
     192                 :          2 :         name = find_supply_name(cpu_dev);
     193                 :          2 :         if (name) {
     194                 :          0 :                 opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
     195                 :          0 :                 if (IS_ERR(opp_table)) {
     196                 :            :                         ret = PTR_ERR(opp_table);
     197                 :          0 :                         dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
     198                 :            :                                 policy->cpu, ret);
     199                 :          0 :                         goto out_put_clk;
     200                 :            :                 }
     201                 :            :         }
     202                 :            : 
     203                 :          2 :         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
     204                 :          2 :         if (!priv) {
     205                 :            :                 ret = -ENOMEM;
     206                 :            :                 goto out_put_regulator;
     207                 :            :         }
     208                 :            : 
     209                 :          2 :         priv->reg_name = name;
     210                 :          2 :         priv->opp_table = opp_table;
     211                 :            : 
     212                 :            :         /*
     213                 :            :          * Initialize OPP tables for all policy->cpus. They will be shared by
     214                 :            :          * all CPUs which have marked their CPUs shared with OPP bindings.
     215                 :            :          *
     216                 :            :          * For platforms not using operating-points-v2 bindings, we do this
     217                 :            :          * before updating policy->cpus. Otherwise, we will end up creating
     218                 :            :          * duplicate OPPs for policy->cpus.
     219                 :            :          *
     220                 :            :          * OPPs might be populated at runtime, don't check for error here
     221                 :            :          */
     222                 :          2 :         if (!dev_pm_opp_of_cpumask_add_table(policy->cpus))
     223                 :          0 :                 priv->have_static_opps = true;
     224                 :            : 
     225                 :            :         /*
     226                 :            :          * But we need OPP table to function so if it is not there let's
     227                 :            :          * give platform code chance to provide it for us.
     228                 :            :          */
     229                 :          2 :         ret = dev_pm_opp_get_opp_count(cpu_dev);
     230                 :          2 :         if (ret <= 0) {
     231                 :            :                 dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
     232                 :            :                 ret = -EPROBE_DEFER;
     233                 :            :                 goto out_free_opp;
     234                 :            :         }
     235                 :            : 
     236                 :          2 :         if (fallback) {
     237                 :            :                 cpumask_setall(policy->cpus);
     238                 :            : 
     239                 :            :                 /*
     240                 :            :                  * OPP tables are initialized only for policy->cpu, do it for
     241                 :            :                  * others as well.
     242                 :            :                  */
     243                 :          2 :                 ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
     244                 :          2 :                 if (ret)
     245                 :          0 :                         dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
     246                 :            :                                 __func__, ret);
     247                 :            :         }
     248                 :            : 
     249                 :          2 :         ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
     250                 :          2 :         if (ret) {
     251                 :          0 :                 dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
     252                 :          0 :                 goto out_free_opp;
     253                 :            :         }
     254                 :            : 
     255                 :          2 :         priv->cpu_dev = cpu_dev;
     256                 :          2 :         policy->driver_data = priv;
     257                 :          2 :         policy->clk = cpu_clk;
     258                 :          2 :         policy->freq_table = freq_table;
     259                 :            : 
     260                 :          2 :         policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
     261                 :            : 
     262                 :            :         /* Support turbo/boost mode */
     263                 :          2 :         if (policy_has_boost_freq(policy)) {
     264                 :            :                 /* This gets disabled by core on driver unregister */
     265                 :          0 :                 ret = cpufreq_enable_boost_support();
     266                 :          0 :                 if (ret)
     267                 :            :                         goto out_free_cpufreq_table;
     268                 :          0 :                 cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
     269                 :            :         }
     270                 :            : 
     271                 :          2 :         transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
     272                 :          2 :         if (!transition_latency)
     273                 :            :                 transition_latency = CPUFREQ_ETERNAL;
     274                 :            : 
     275                 :          2 :         policy->cpuinfo.transition_latency = transition_latency;
     276                 :          2 :         policy->dvfs_possible_from_any_cpu = true;
     277                 :            : 
     278                 :          2 :         dev_pm_opp_of_register_em(policy->cpus);
     279                 :            : 
     280                 :          2 :         return 0;
     281                 :            : 
     282                 :            : out_free_cpufreq_table:
     283                 :          0 :         dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
     284                 :            : out_free_opp:
     285                 :          0 :         if (priv->have_static_opps)
     286                 :          0 :                 dev_pm_opp_of_cpumask_remove_table(policy->cpus);
     287                 :          0 :         kfree(priv);
     288                 :            : out_put_regulator:
     289                 :          0 :         if (name)
     290                 :          0 :                 dev_pm_opp_put_regulators(opp_table);
     291                 :            : out_put_clk:
     292                 :          0 :         clk_put(cpu_clk);
     293                 :            : 
     294                 :          0 :         return ret;
     295                 :            : }
     296                 :            : 
     297                 :          0 : static int cpufreq_online(struct cpufreq_policy *policy)
     298                 :            : {
     299                 :            :         /* We did light-weight tear down earlier, nothing to do here */
     300                 :          0 :         return 0;
     301                 :            : }
     302                 :            : 
     303                 :          0 : static int cpufreq_offline(struct cpufreq_policy *policy)
     304                 :            : {
     305                 :            :         /*
     306                 :            :          * Preserve policy->driver_data and don't free resources on light-weight
     307                 :            :          * tear down.
     308                 :            :          */
     309                 :          0 :         return 0;
     310                 :            : }
     311                 :            : 
     312                 :          0 : static int cpufreq_exit(struct cpufreq_policy *policy)
     313                 :            : {
     314                 :          0 :         struct private_data *priv = policy->driver_data;
     315                 :            : 
     316                 :          0 :         dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
     317                 :          0 :         if (priv->have_static_opps)
     318                 :          0 :                 dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
     319                 :          0 :         if (priv->reg_name)
     320                 :          0 :                 dev_pm_opp_put_regulators(priv->opp_table);
     321                 :            : 
     322                 :          0 :         clk_put(policy->clk);
     323                 :          0 :         kfree(priv);
     324                 :            : 
     325                 :          0 :         return 0;
     326                 :            : }
     327                 :            : 
     328                 :            : static struct cpufreq_driver dt_cpufreq_driver = {
     329                 :            :         .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
     330                 :            :                  CPUFREQ_IS_COOLING_DEV,
     331                 :            :         .verify = cpufreq_generic_frequency_table_verify,
     332                 :            :         .target_index = set_target,
     333                 :            :         .get = cpufreq_generic_get,
     334                 :            :         .init = cpufreq_init,
     335                 :            :         .exit = cpufreq_exit,
     336                 :            :         .online = cpufreq_online,
     337                 :            :         .offline = cpufreq_offline,
     338                 :            :         .name = "cpufreq-dt",
     339                 :            :         .attr = cpufreq_dt_attr,
     340                 :            :         .suspend = cpufreq_generic_suspend,
     341                 :            : };
     342                 :            : 
     343                 :          2 : static int dt_cpufreq_probe(struct platform_device *pdev)
     344                 :            : {
     345                 :            :         struct cpufreq_dt_platform_data *data = dev_get_platdata(&pdev->dev);
     346                 :            :         int ret;
     347                 :            : 
     348                 :            :         /*
     349                 :            :          * All per-cluster (CPUs sharing clock/voltages) initialization is done
     350                 :            :          * from ->init(). In probe(), we just need to make sure that clk and
     351                 :            :          * regulators are available. Else defer probe and retry.
     352                 :            :          *
     353                 :            :          * FIXME: Is checking this only for CPU0 sufficient ?
     354                 :            :          */
     355                 :          2 :         ret = resources_available();
     356                 :          2 :         if (ret)
     357                 :            :                 return ret;
     358                 :            : 
     359                 :          2 :         if (data) {
     360                 :          0 :                 if (data->have_governor_per_policy)
     361                 :          0 :                         dt_cpufreq_driver.flags |= CPUFREQ_HAVE_GOVERNOR_PER_POLICY;
     362                 :            : 
     363                 :          0 :                 dt_cpufreq_driver.resume = data->resume;
     364                 :          0 :                 if (data->suspend)
     365                 :          0 :                         dt_cpufreq_driver.suspend = data->suspend;
     366                 :            :         }
     367                 :            : 
     368                 :          2 :         ret = cpufreq_register_driver(&dt_cpufreq_driver);
     369                 :          2 :         if (ret)
     370                 :          0 :                 dev_err(&pdev->dev, "failed register driver: %d\n", ret);
     371                 :            : 
     372                 :          2 :         return ret;
     373                 :            : }
     374                 :            : 
     375                 :          0 : static int dt_cpufreq_remove(struct platform_device *pdev)
     376                 :            : {
     377                 :          0 :         cpufreq_unregister_driver(&dt_cpufreq_driver);
     378                 :          0 :         return 0;
     379                 :            : }
     380                 :            : 
     381                 :            : static struct platform_driver dt_cpufreq_platdrv = {
     382                 :            :         .driver = {
     383                 :            :                 .name   = "cpufreq-dt",
     384                 :            :         },
     385                 :            :         .probe          = dt_cpufreq_probe,
     386                 :            :         .remove         = dt_cpufreq_remove,
     387                 :            : };
     388                 :          3 : module_platform_driver(dt_cpufreq_platdrv);
     389                 :            : 
     390                 :            : MODULE_ALIAS("platform:cpufreq-dt");
     391                 :            : MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
     392                 :            : MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
     393                 :            : MODULE_DESCRIPTION("Generic cpufreq driver");
     394                 :            : MODULE_LICENSE("GPL");
    

Generated by: LCOV version 1.14