Merge branch 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel...
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 6 Oct 2020 10:26:45 +0000 (12:26 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 6 Oct 2020 10:26:45 +0000 (12:26 +0200)
Pull ARM cpufreq updates for 5.10-rc1 from Viresh Kumar:

"- STI cpufreq driver updates to allow new hardware (Alain Volmat).

 - Minor tegra driver fixes around initial frequency mismatch warnings (Jon
   Hunter).

 - dev_err simplification for s5pv210 driver (Krzysztof Kozlowski).

 - Qcom driver updates to allow new hardware and minor cleanup (Manivannan
   Sadhasivam and Matthias Kaehlcke).

 - Add missing MODULE_DEVICE_TABLE for armada driver (Pali Rohár).

 - Improved defer-probe handling in cpufreq-dt driver (Stephan Gerhold).

 - Call dev_pm_opp_of_remove_table() unconditionally for imx driver (Viresh
   Kumar)."

* 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  cpufreq: qcom: Don't add frequencies without an OPP
  cpufreq: qcom-hw: Add cpufreq support for SM8250 SoC
  cpufreq: qcom-hw: Use of_device_get_match_data for offsets and row size
  cpufreq: qcom-hw: Use devm_platform_ioremap_resource() to simplify code
  dt-bindings: cpufreq: cpufreq-qcom-hw: Document Qcom EPSS compatible
  cpufreq: qcom-hw: Make use of cpufreq driver_data for passing pdev
  cpufreq: armada-37xx: Add missing MODULE_DEVICE_TABLE
  cpufreq: arm: Kconfig: add CPUFREQ_DT depend for STI CPUFREQ
  cpufreq: dt-platdev: Blacklist st,stih418 SoC
  cpufreq: sti-cpufreq: add stih418 support
  cpufreq: s5pv210: Use dev_err instead of pr_err in probe
  cpufreq: s5pv210: Simplify with dev_err_probe()
  cpufreq: tegra186: Fix initial frequency
  cpufreq: dt: Refactor initialization to handle probe deferral properly
  opp: Handle multiple calls for same OPP table in _of_add_opp_table_v1()
  cpufreq: imx6q: Unconditionally call dev_pm_opp_of_remove_table()
  opp: Allow dev_pm_opp_get_opp_table() to return -EPROBE_DEFER

1  2 
drivers/cpufreq/cpufreq-dt.c
drivers/cpufreq/qcom-cpufreq-hw.c
drivers/opp/core.c

@@@ -13,6 -13,7 +13,7 @@@
  #include <linux/cpufreq.h>
  #include <linux/cpumask.h>
  #include <linux/err.h>
+ #include <linux/list.h>
  #include <linux/module.h>
  #include <linux/of.h>
  #include <linux/pm_opp.h>
  #include "cpufreq-dt.h"
  
  struct private_data {
-       struct opp_table *opp_table;
+       struct list_head node;
+       cpumask_var_t cpus;
        struct device *cpu_dev;
-       const char *reg_name;
+       struct opp_table *opp_table;
+       struct opp_table *reg_opp_table;
        bool have_static_opps;
  };
  
+ static LIST_HEAD(priv_list);
  static struct freq_attr *cpufreq_dt_attr[] = {
        &cpufreq_freq_attr_scaling_available_freqs,
        NULL,   /* Extra space for boost-attr if required */
        NULL,
  };
  
+ static struct private_data *cpufreq_dt_find_data(int cpu)
+ {
+       struct private_data *priv;
+       list_for_each_entry(priv, &priv_list, node) {
+               if (cpumask_test_cpu(cpu, priv->cpus))
+                       return priv;
+       }
+       return NULL;
+ }
  static int set_target(struct cpufreq_policy *policy, unsigned int index)
  {
        struct private_data *priv = policy->driver_data;
        unsigned long freq = policy->freq_table[index].frequency;
 -      int ret;
  
 -      ret = dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);
 -
 -      if (!ret) {
 -              arch_set_freq_scale(policy->related_cpus, freq,
 -                                  policy->cpuinfo.max_freq);
 -      }
 -
 -      return ret;
 +      return dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);
  }
  
  /*
@@@ -82,83 -108,24 +100,24 @@@ node_put
        return name;
  }
  
- static int resources_available(void)
- {
-       struct device *cpu_dev;
-       struct regulator *cpu_reg;
-       struct clk *cpu_clk;
-       int ret = 0;
-       const char *name;
-       cpu_dev = get_cpu_device(0);
-       if (!cpu_dev) {
-               pr_err("failed to get cpu0 device\n");
-               return -ENODEV;
-       }
-       cpu_clk = clk_get(cpu_dev, NULL);
-       ret = PTR_ERR_OR_ZERO(cpu_clk);
-       if (ret) {
-               /*
-                * If cpu's clk node is present, but clock is not yet
-                * registered, we should try defering probe.
-                */
-               if (ret == -EPROBE_DEFER)
-                       dev_dbg(cpu_dev, "clock not ready, retry\n");
-               else
-                       dev_err(cpu_dev, "failed to get clock: %d\n", ret);
-               return ret;
-       }
-       clk_put(cpu_clk);
-       ret = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL);
-       if (ret)
-               return ret;
-       name = find_supply_name(cpu_dev);
-       /* Platform doesn't require regulator */
-       if (!name)
-               return 0;
-       cpu_reg = regulator_get_optional(cpu_dev, name);
-       ret = PTR_ERR_OR_ZERO(cpu_reg);
-       if (ret) {
-               /*
-                * If cpu's regulator supply node is present, but regulator is
-                * not yet registered, we should try defering probe.
-                */
-               if (ret == -EPROBE_DEFER)
-                       dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n");
-               else
-                       dev_dbg(cpu_dev, "no regulator for cpu0: %d\n", ret);
-               return ret;
-       }
-       regulator_put(cpu_reg);
-       return 0;
- }
  static int cpufreq_init(struct cpufreq_policy *policy)
  {
        struct cpufreq_frequency_table *freq_table;
-       struct opp_table *opp_table = NULL;
        struct private_data *priv;
        struct device *cpu_dev;
        struct clk *cpu_clk;
        unsigned int transition_latency;
-       bool fallback = false;
-       const char *name;
        int ret;
  
-       cpu_dev = get_cpu_device(policy->cpu);
-       if (!cpu_dev) {
-               pr_err("failed to get cpu%d device\n", policy->cpu);
+       priv = cpufreq_dt_find_data(policy->cpu);
+       if (!priv) {
+               pr_err("failed to find data for cpu%d\n", policy->cpu);
                return -ENODEV;
        }
  
+       cpu_dev = priv->cpu_dev;
+       cpumask_copy(policy->cpus, priv->cpus);
        cpu_clk = clk_get(cpu_dev, NULL);
        if (IS_ERR(cpu_clk)) {
                ret = PTR_ERR(cpu_clk);
                return ret;
        }
  
-       /* Get OPP-sharing information from "operating-points-v2" bindings */
-       ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, policy->cpus);
-       if (ret) {
-               if (ret != -ENOENT)
-                       goto out_put_clk;
-               /*
-                * operating-points-v2 not supported, fallback to old method of
-                * finding shared-OPPs for backward compatibility if the
-                * platform hasn't set sharing CPUs.
-                */
-               if (dev_pm_opp_get_sharing_cpus(cpu_dev, policy->cpus))
-                       fallback = true;
-       }
-       /*
-        * OPP layer will be taking care of regulators now, but it needs to know
-        * the name of the regulator first.
-        */
-       name = find_supply_name(cpu_dev);
-       if (name) {
-               opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
-               if (IS_ERR(opp_table)) {
-                       ret = PTR_ERR(opp_table);
-                       dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
-                               policy->cpu, ret);
-                       goto out_put_clk;
-               }
-       }
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv) {
-               ret = -ENOMEM;
-               goto out_put_regulator;
-       }
-       priv->reg_name = name;
-       priv->opp_table = opp_table;
        /*
         * Initialize OPP tables for all policy->cpus. They will be shared by
         * all CPUs which have marked their CPUs shared with OPP bindings.
         */
        ret = dev_pm_opp_get_opp_count(cpu_dev);
        if (ret <= 0) {
-               dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
-               ret = -EPROBE_DEFER;
+               dev_err(cpu_dev, "OPP table can't be empty\n");
+               ret = -ENODEV;
                goto out_free_opp;
        }
  
-       if (fallback) {
-               cpumask_setall(policy->cpus);
-               /*
-                * OPP tables are initialized only for policy->cpu, do it for
-                * others as well.
-                */
-               ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
-               if (ret)
-                       dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
-                               __func__, ret);
-       }
        ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
        if (ret) {
                dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
                goto out_free_opp;
        }
  
-       priv->cpu_dev = cpu_dev;
        policy->driver_data = priv;
        policy->clk = cpu_clk;
        policy->freq_table = freq_table;
@@@ -280,11 -194,6 +186,6 @@@ out_free_cpufreq_table
  out_free_opp:
        if (priv->have_static_opps)
                dev_pm_opp_of_cpumask_remove_table(policy->cpus);
-       kfree(priv);
- out_put_regulator:
-       if (name)
-               dev_pm_opp_put_regulators(opp_table);
- out_put_clk:
        clk_put(cpu_clk);
  
        return ret;
@@@ -312,12 -221,7 +213,7 @@@ static int cpufreq_exit(struct cpufreq_
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
        if (priv->have_static_opps)
                dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
-       if (priv->reg_name)
-               dev_pm_opp_put_regulators(priv->opp_table);
        clk_put(policy->clk);
-       kfree(priv);
        return 0;
  }
  
@@@ -336,21 -240,119 +232,119 @@@ static struct cpufreq_driver dt_cpufreq
        .suspend = cpufreq_generic_suspend,
  };
  
- static int dt_cpufreq_probe(struct platform_device *pdev)
+ static int dt_cpufreq_early_init(struct device *dev, int cpu)
  {
-       struct cpufreq_dt_platform_data *data = dev_get_platdata(&pdev->dev);
+       struct private_data *priv;
+       struct device *cpu_dev;
+       const char *reg_name;
        int ret;
  
+       /* Check if this CPU is already covered by some other policy */
+       if (cpufreq_dt_find_data(cpu))
+               return 0;
+       cpu_dev = get_cpu_device(cpu);
+       if (!cpu_dev)
+               return -EPROBE_DEFER;
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+       if (!alloc_cpumask_var(&priv->cpus, GFP_KERNEL))
+               return -ENOMEM;
+       priv->cpu_dev = cpu_dev;
+       /* Try to get OPP table early to ensure resources are available */
+       priv->opp_table = dev_pm_opp_get_opp_table(cpu_dev);
+       if (IS_ERR(priv->opp_table)) {
+               ret = PTR_ERR(priv->opp_table);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(cpu_dev, "failed to get OPP table: %d\n", ret);
+               goto free_cpumask;
+       }
        /*
-        * All per-cluster (CPUs sharing clock/voltages) initialization is done
-        * from ->init(). In probe(), we just need to make sure that clk and
-        * regulators are available. Else defer probe and retry.
-        *
-        * FIXME: Is checking this only for CPU0 sufficient ?
+        * OPP layer will be taking care of regulators now, but it needs to know
+        * the name of the regulator first.
         */
-       ret = resources_available();
-       if (ret)
-               return ret;
+       reg_name = find_supply_name(cpu_dev);
+       if (reg_name) {
+               priv->reg_opp_table = dev_pm_opp_set_regulators(cpu_dev,
+                                                               &reg_name, 1);
+               if (IS_ERR(priv->reg_opp_table)) {
+                       ret = PTR_ERR(priv->reg_opp_table);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(cpu_dev, "failed to set regulators: %d\n",
+                                       ret);
+                       goto put_table;
+               }
+       }
+       /* Find OPP sharing information so we can fill pri->cpus here */
+       /* Get OPP-sharing information from "operating-points-v2" bindings */
+       ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->cpus);
+       if (ret) {
+               if (ret != -ENOENT)
+                       goto put_reg;
+               /*
+                * operating-points-v2 not supported, fallback to all CPUs share
+                * OPP for backward compatibility if the platform hasn't set
+                * sharing CPUs.
+                */
+               if (dev_pm_opp_get_sharing_cpus(cpu_dev, priv->cpus)) {
+                       cpumask_setall(priv->cpus);
+                       /*
+                        * OPP tables are initialized only for cpu, do it for
+                        * others as well.
+                        */
+                       ret = dev_pm_opp_set_sharing_cpus(cpu_dev, priv->cpus);
+                       if (ret)
+                               dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
+                                       __func__, ret);
+               }
+       }
+       list_add(&priv->node, &priv_list);
+       return 0;
+ put_reg:
+       if (priv->reg_opp_table)
+               dev_pm_opp_put_regulators(priv->reg_opp_table);
+ put_table:
+       dev_pm_opp_put_opp_table(priv->opp_table);
+ free_cpumask:
+       free_cpumask_var(priv->cpus);
+       return ret;
+ }
+ static void dt_cpufreq_release(void)
+ {
+       struct private_data *priv, *tmp;
+       list_for_each_entry_safe(priv, tmp, &priv_list, node) {
+               if (priv->reg_opp_table)
+                       dev_pm_opp_put_regulators(priv->reg_opp_table);
+               dev_pm_opp_put_opp_table(priv->opp_table);
+               free_cpumask_var(priv->cpus);
+               list_del(&priv->node);
+       }
+ }
+ static int dt_cpufreq_probe(struct platform_device *pdev)
+ {
+       struct cpufreq_dt_platform_data *data = dev_get_platdata(&pdev->dev);
+       int ret, cpu;
+       /* Request resources early so we can return in case of -EPROBE_DEFER */
+       for_each_possible_cpu(cpu) {
+               ret = dt_cpufreq_early_init(&pdev->dev, cpu);
+               if (ret)
+                       goto err;
+       }
  
        if (data) {
                if (data->have_governor_per_policy)
        }
  
        ret = cpufreq_register_driver(&dt_cpufreq_driver);
-       if (ret)
+       if (ret) {
                dev_err(&pdev->dev, "failed register driver: %d\n", ret);
+               goto err;
+       }
  
+       return 0;
+ err:
+       dt_cpufreq_release();
        return ret;
  }
  
  static int dt_cpufreq_remove(struct platform_device *pdev)
  {
        cpufreq_unregister_driver(&dt_cpufreq_driver);
+       dt_cpufreq_release();
        return 0;
  }
  
  #define LUT_L_VAL                     GENMASK(7, 0)
  #define LUT_CORE_COUNT                        GENMASK(18, 16)
  #define LUT_VOLT                      GENMASK(11, 0)
- #define LUT_ROW_SIZE                  32
  #define CLK_HW_DIV                    2
  #define LUT_TURBO_IND                 1
  
- /* Register offsets */
- #define REG_ENABLE                    0x0
- #define REG_FREQ_LUT                  0x110
- #define REG_VOLT_LUT                  0x114
- #define REG_PERF_STATE                        0x920
+ struct qcom_cpufreq_soc_data {
+       u32 reg_enable;
+       u32 reg_freq_lut;
+       u32 reg_volt_lut;
+       u32 reg_perf_state;
+       u8 lut_row_size;
+ };
+ struct qcom_cpufreq_data {
+       void __iomem *base;
+       const struct qcom_cpufreq_soc_data *soc_data;
+ };
  
  static unsigned long cpu_hw_rate, xo_rate;
- static struct platform_device *global_pdev;
  static bool icc_scaling_enabled;
  
  static int qcom_cpufreq_set_bw(struct cpufreq_policy *policy,
@@@ -77,20 -82,24 +82,22 @@@ static int qcom_cpufreq_update_opp(stru
  static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
                                        unsigned int index)
  {
-       void __iomem *perf_state_reg = policy->driver_data;
+       struct qcom_cpufreq_data *data = policy->driver_data;
+       const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
        unsigned long freq = policy->freq_table[index].frequency;
  
-       writel_relaxed(index, perf_state_reg);
+       writel_relaxed(index, data->base + soc_data->reg_perf_state);
  
        if (icc_scaling_enabled)
                qcom_cpufreq_set_bw(policy, freq);
  
 -      arch_set_freq_scale(policy->related_cpus, freq,
 -                          policy->cpuinfo.max_freq);
        return 0;
  }
  
  static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
  {
-       void __iomem *perf_state_reg;
+       struct qcom_cpufreq_data *data;
+       const struct qcom_cpufreq_soc_data *soc_data;
        struct cpufreq_policy *policy;
        unsigned int index;
  
        if (!policy)
                return 0;
  
-       perf_state_reg = policy->driver_data;
+       data = policy->driver_data;
+       soc_data = data->soc_data;
  
-       index = readl_relaxed(perf_state_reg);
+       index = readl_relaxed(data->base + soc_data->reg_perf_state);
        index = min(index, LUT_MAX_ENTRIES - 1);
  
        return policy->freq_table[index].frequency;
  static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy,
                                                unsigned int target_freq)
  {
-       void __iomem *perf_state_reg = policy->driver_data;
+       struct qcom_cpufreq_data *data = policy->driver_data;
+       const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
        unsigned int index;
 -      unsigned long freq;
  
        index = policy->cached_resolved_idx;
-       writel_relaxed(index, perf_state_reg);
+       writel_relaxed(index, data->base + soc_data->reg_perf_state);
  
 -      freq = policy->freq_table[index].frequency;
 -      arch_set_freq_scale(policy->related_cpus, freq,
 -                          policy->cpuinfo.max_freq);
 -
 -      return freq;
 +      return policy->freq_table[index].frequency;
  }
  
  static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
-                                   struct cpufreq_policy *policy,
-                                   void __iomem *base)
+                                   struct cpufreq_policy *policy)
  {
        u32 data, src, lval, i, core_count, prev_freq = 0, freq;
        u32 volt;
        struct dev_pm_opp *opp;
        unsigned long rate;
        int ret;
+       struct qcom_cpufreq_data *drv_data = policy->driver_data;
+       const struct qcom_cpufreq_soc_data *soc_data = drv_data->soc_data;
  
        table = kcalloc(LUT_MAX_ENTRIES + 1, sizeof(*table), GFP_KERNEL);
        if (!table)
        }
  
        for (i = 0; i < LUT_MAX_ENTRIES; i++) {
-               data = readl_relaxed(base + REG_FREQ_LUT +
-                                     i * LUT_ROW_SIZE);
+               data = readl_relaxed(drv_data->base + soc_data->reg_freq_lut +
+                                     i * soc_data->lut_row_size);
                src = FIELD_GET(LUT_SRC, data);
                lval = FIELD_GET(LUT_L_VAL, data);
                core_count = FIELD_GET(LUT_CORE_COUNT, data);
  
-               data = readl_relaxed(base + REG_VOLT_LUT +
-                                     i * LUT_ROW_SIZE);
+               data = readl_relaxed(drv_data->base + soc_data->reg_volt_lut +
+                                     i * soc_data->lut_row_size);
                volt = FIELD_GET(LUT_VOLT, data) * 1000;
  
                if (src)
                        freq = cpu_hw_rate / 1000;
  
                if (freq != prev_freq && core_count != LUT_TURBO_IND) {
-                       table[i].frequency = freq;
-                       qcom_cpufreq_update_opp(cpu_dev, freq, volt);
-                       dev_dbg(cpu_dev, "index=%d freq=%d, core_count %d\n", i,
+                       if (!qcom_cpufreq_update_opp(cpu_dev, freq, volt)) {
+                               table[i].frequency = freq;
+                               dev_dbg(cpu_dev, "index=%d freq=%d, core_count %d\n", i,
                                freq, core_count);
+                       } else {
+                               dev_warn(cpu_dev, "failed to update OPP for freq=%d\n", freq);
+                               table[i].frequency = CPUFREQ_ENTRY_INVALID;
+                       }
                } else if (core_count == LUT_TURBO_IND) {
                        table[i].frequency = CPUFREQ_ENTRY_INVALID;
                }
                         * as the boost frequency
                         */
                        if (prev->frequency == CPUFREQ_ENTRY_INVALID) {
-                               prev->frequency = prev_freq;
-                               prev->flags = CPUFREQ_BOOST_FREQ;
-                               qcom_cpufreq_update_opp(cpu_dev, prev_freq, volt);
+                               if (!qcom_cpufreq_update_opp(cpu_dev, prev_freq, volt)) {
+                                       prev->frequency = prev_freq;
+                                       prev->flags = CPUFREQ_BOOST_FREQ;
+                               } else {
+                                       dev_warn(cpu_dev, "failed to update OPP for freq=%d\n",
+                                                freq);
+                               }
                        }
  
                        break;
@@@ -231,14 -257,38 +250,38 @@@ static void qcom_get_related_cpus(int i
        }
  }
  
+ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
+       .reg_enable = 0x0,
+       .reg_freq_lut = 0x110,
+       .reg_volt_lut = 0x114,
+       .reg_perf_state = 0x920,
+       .lut_row_size = 32,
+ };
+ static const struct qcom_cpufreq_soc_data epss_soc_data = {
+       .reg_enable = 0x0,
+       .reg_freq_lut = 0x100,
+       .reg_volt_lut = 0x200,
+       .reg_perf_state = 0x320,
+       .lut_row_size = 4,
+ };
+ static const struct of_device_id qcom_cpufreq_hw_match[] = {
+       { .compatible = "qcom,cpufreq-hw", .data = &qcom_soc_data },
+       { .compatible = "qcom,cpufreq-epss", .data = &epss_soc_data },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, qcom_cpufreq_hw_match);
  static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
  {
-       struct device *dev = &global_pdev->dev;
+       struct platform_device *pdev = cpufreq_get_driver_data();
+       struct device *dev = &pdev->dev;
        struct of_phandle_args args;
        struct device_node *cpu_np;
        struct device *cpu_dev;
-       struct resource *res;
        void __iomem *base;
+       struct qcom_cpufreq_data *data;
        int ret, index;
  
        cpu_dev = get_cpu_device(policy->cpu);
  
        index = args.args[0];
  
-       res = platform_get_resource(global_pdev, IORESOURCE_MEM, index);
-       if (!res)
-               return -ENODEV;
+       base = devm_platform_ioremap_resource(pdev, index);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
  
-       base = devm_ioremap(dev, res->start, resource_size(res));
-       if (!base)
-               return -ENOMEM;
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               ret = -ENOMEM;
+               goto error;
+       }
+       data->soc_data = of_device_get_match_data(&pdev->dev);
+       data->base = base;
  
        /* HW should be in enabled state to proceed */
-       if (!(readl_relaxed(base + REG_ENABLE) & 0x1)) {
+       if (!(readl_relaxed(base + data->soc_data->reg_enable) & 0x1)) {
                dev_err(dev, "Domain-%d cpufreq hardware not enabled\n", index);
                ret = -ENODEV;
                goto error;
                goto error;
        }
  
-       policy->driver_data = base + REG_PERF_STATE;
+       policy->driver_data = data;
  
-       ret = qcom_cpufreq_hw_read_lut(cpu_dev, policy, base);
+       ret = qcom_cpufreq_hw_read_lut(cpu_dev, policy);
        if (ret) {
                dev_err(dev, "Domain-%d failed to read LUT\n", index);
                goto error;
@@@ -308,12 -363,13 +356,13 @@@ error
  static int qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
  {
        struct device *cpu_dev = get_cpu_device(policy->cpu);
-       void __iomem *base = policy->driver_data - REG_PERF_STATE;
+       struct qcom_cpufreq_data *data = policy->driver_data;
+       struct platform_device *pdev = cpufreq_get_driver_data();
  
        dev_pm_opp_remove_all_dynamic(cpu_dev);
        dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
        kfree(policy->freq_table);
-       devm_iounmap(&global_pdev->dev, base);
+       devm_iounmap(&pdev->dev, data->base);
  
        return 0;
  }
@@@ -358,7 -414,7 +407,7 @@@ static int qcom_cpufreq_hw_driver_probe
        cpu_hw_rate = clk_get_rate(clk) / CLK_HW_DIV;
        clk_put(clk);
  
-       global_pdev = pdev;
+       cpufreq_qcom_hw_driver.driver_data = pdev;
  
        /* Check for optional interconnect paths on CPU0 */
        cpu_dev = get_cpu_device(0);
@@@ -383,12 -439,6 +432,6 @@@ static int qcom_cpufreq_hw_driver_remov
        return cpufreq_unregister_driver(&cpufreq_qcom_hw_driver);
  }
  
- static const struct of_device_id qcom_cpufreq_hw_match[] = {
-       { .compatible = "qcom,cpufreq-hw" },
-       {}
- };
- MODULE_DEVICE_TABLE(of, qcom_cpufreq_hw_match);
  static struct platform_driver qcom_cpufreq_hw_driver = {
        .probe = qcom_cpufreq_hw_driver_probe,
        .remove = qcom_cpufreq_hw_driver_remove,
diff --combined drivers/opp/core.c
@@@ -893,10 -893,8 +893,10 @@@ int dev_pm_opp_set_rate(struct device *
                 * have OPP table for the device, while others don't and
                 * opp_set_rate() just needs to behave like clk_set_rate().
                 */
 -              if (!_get_opp_count(opp_table))
 -                      return 0;
 +              if (!_get_opp_count(opp_table)) {
 +                      ret = 0;
 +                      goto put_opp_table;
 +              }
  
                if (!opp_table->required_opp_tables && !opp_table->regulators &&
                    !opp_table->paths) {
  
                ret = _set_opp_bw(opp_table, NULL, dev, true);
                if (ret)
 -                      return ret;
 +                      goto put_opp_table;
  
                if (opp_table->regulator_enabled) {
                        regulator_disable(opp_table->regulators[0]);
  
        /* Return early if nothing to do */
        if (old_freq == freq) {
 -              dev_dbg(dev, "%s: old/new frequencies (%lu Hz) are same, nothing to do\n",
 -                      __func__, freq);
 -              ret = 0;
 -              goto put_opp_table;
 +              if (!opp_table->required_opp_tables && !opp_table->regulators &&
 +                  !opp_table->paths) {
 +                      dev_dbg(dev, "%s: old/new frequencies (%lu Hz) are same, nothing to do\n",
 +                              __func__, freq);
 +                      ret = 0;
 +                      goto put_opp_table;
 +              }
        }
  
        /*
@@@ -1068,7 -1063,7 +1068,7 @@@ static struct opp_table *_allocate_opp_
         */
        opp_table = kzalloc(sizeof(*opp_table), GFP_KERNEL);
        if (!opp_table)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
  
        mutex_init(&opp_table->lock);
        mutex_init(&opp_table->genpd_virt_dev_lock);
  
        opp_dev = _add_opp_dev(dev, opp_table);
        if (!opp_dev) {
-               kfree(opp_table);
-               return NULL;
+               ret = -ENOMEM;
+               goto err;
        }
  
        _of_init_opp_table(opp_table, dev, index);
        opp_table->clk = clk_get(dev, NULL);
        if (IS_ERR(opp_table->clk)) {
                ret = PTR_ERR(opp_table->clk);
-               if (ret != -EPROBE_DEFER)
-                       dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__,
-                               ret);
+               if (ret == -EPROBE_DEFER)
+                       goto err;
+               dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__, ret);
        }
  
        /* Find interconnect path(s) for the device */
        ret = dev_pm_opp_of_find_icc_paths(dev, opp_table);
-       if (ret)
+       if (ret) {
+               if (ret == -EPROBE_DEFER)
+                       goto err;
                dev_warn(dev, "%s: Error finding interconnect paths: %d\n",
                         __func__, ret);
+       }
  
        BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
        INIT_LIST_HEAD(&opp_table->opp_list);
        /* Secure the device table modification */
        list_add(&opp_table->node, &opp_tables);
        return opp_table;
+ err:
+       kfree(opp_table);
+       return ERR_PTR(ret);
  }
  
  void _get_opp_table_kref(struct opp_table *opp_table)
@@@ -1129,7 -1133,7 +1138,7 @@@ static struct opp_table *_opp_get_opp_t
        if (opp_table) {
                if (!_add_opp_dev_unlocked(dev, opp_table)) {
                        dev_pm_opp_put_opp_table(opp_table);
-                       opp_table = NULL;
+                       opp_table = ERR_PTR(-ENOMEM);
                }
                goto unlock;
        }
@@@ -1581,8 -1585,8 +1590,8 @@@ struct opp_table *dev_pm_opp_set_suppor
        struct opp_table *opp_table;
  
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
  
        /* Make sure there are no concurrent readers while updating opp_table */
        WARN_ON(!list_empty(&opp_table->opp_list));
@@@ -1640,8 -1644,8 +1649,8 @@@ struct opp_table *dev_pm_opp_set_prop_n
        struct opp_table *opp_table;
  
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
  
        /* Make sure there are no concurrent readers while updating opp_table */
        WARN_ON(!list_empty(&opp_table->opp_list));
@@@ -1733,8 -1737,8 +1742,8 @@@ struct opp_table *dev_pm_opp_set_regula
        int ret, i;
  
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
  
        /* This should be called before OPPs are initialized */
        if (WARN_ON(!list_empty(&opp_table->opp_list))) {
@@@ -1843,8 -1847,8 +1852,8 @@@ struct opp_table *dev_pm_opp_set_clknam
        int ret;
  
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
  
        /* This should be called before OPPs are initialized */
        if (WARN_ON(!list_empty(&opp_table->opp_list))) {
@@@ -1911,8 -1915,8 +1920,8 @@@ struct opp_table *dev_pm_opp_register_s
                return ERR_PTR(-EINVAL);
  
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (!IS_ERR(opp_table))
+               return opp_table;
  
        /* This should be called before OPPs are initialized */
        if (WARN_ON(!list_empty(&opp_table->opp_list))) {
@@@ -1992,8 -1996,8 +2001,8 @@@ struct opp_table *dev_pm_opp_attach_gen
        const char **name = names;
  
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(opp_table))
+               return opp_table;
  
        /*
         * If the genpd's OPP table isn't already initialized, parsing of the
@@@ -2163,8 -2167,8 +2172,8 @@@ int dev_pm_opp_add(struct device *dev, 
        int ret;
  
        opp_table = dev_pm_opp_get_opp_table(dev);
-       if (!opp_table)
-               return -ENOMEM;
+       if (IS_ERR(opp_table))
+               return PTR_ERR(opp_table);
  
        /* Fix regulator count for dynamic OPPs */
        opp_table->regulator_count = 1;