Hi, On 10/20/2016 03:44 AM, Viresh Kumar wrote:
This patch adds infrastructure to manage multiple regulators and updates the only user (cpufreq-dt) of dev_pm_opp_set{put}_regulator().
This is preparatory work for adding full support for devices with multiple regulators.
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org
drivers/base/power/opp/core.c | 220 ++++++++++++++++++++++++++------------- drivers/base/power/opp/debugfs.c | 48 +++++++-- drivers/base/power/opp/of.c | 102 +++++++++++++----- drivers/base/power/opp/opp.h | 10 +- drivers/cpufreq/cpufreq-dt.c | 9 +- include/linux/pm_opp.h | 8 +- 6 files changed, 276 insertions(+), 121 deletions(-)
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 37fad2eb0f47..45c70ce07864 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -93,6 +93,8 @@ struct opp_table *_find_opp_table(struct device *dev)
- Return: voltage in micro volt corresponding to the opp, else
 - return 0
 
- This is useful only for devices with single power supply.
 
- Locking: This function must be called under rcu_read_lock(). opp is a rcu
 - protected pointer. This means that opp which could have been fetched by
 - opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
 @@ -112,7 +114,7 @@ unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) if (IS_ERR_OR_NULL(tmp_opp)) pr_err("%s: Invalid parameters\n", __func__); else
v = tmp_opp->supply.u_volt;
v = tmp_opp->supplies[0].u_volt;return v;
} @@ -222,10 +224,10 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) { struct opp_table *opp_table; struct dev_pm_opp *opp;
- struct regulator *reg;
 
- struct regulator *reg, **regulators; unsigned long latency_ns = 0;
 
- unsigned long min_uV = ~0, max_uV = 0;
 - int ret;
 
unsigned long *min_uV, *max_uV;
int ret, size, i, count;
rcu_read_lock();
@@ -235,21 +237,44 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) return 0; }
- reg = opp_table->regulator;
 - if (IS_ERR(reg)) {
 
- count = opp_table->regulator_count;
 - if (!count) { /* Regulator may not be required for device */ rcu_read_unlock(); return 0; }
 
- list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
 if (!opp->available)continue;
- size = count * sizeof(*regulators);
 - regulators = kmemdup(opp_table->regulators, size, GFP_KERNEL);
 - if (!regulators) {
 rcu_read_unlock();return 0;- }
 - min_uV = kmalloc(count * (sizeof(*min_uV) + sizeof(*max_uV)),
 GFP_KERNEL);- if (!min_uV) {
 kfree(regulators);rcu_read_unlock();return 0;- }
 - max_uV = min_uV + count;
 - for (i = 0; i < count; i++) {
 min_uV[i] = ~0;max_uV[i] = 0;list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {if (!opp->available)continue;
if (opp->supply.u_volt_min < min_uV)min_uV = opp->supply.u_volt_min;if (opp->supply.u_volt_max > max_uV)max_uV = opp->supply.u_volt_max;
if (opp->supplies[i].u_volt_min < min_uV[i])min_uV[i] = opp->supplies[i].u_volt_min;if (opp->supplies[i].u_volt_max > max_uV[i])max_uV[i] = opp->supplies[i].u_volt_max;}}
rcu_read_unlock();
@@ -258,9 +283,14 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev) * The caller needs to ensure that opp_table (and hence the regulator) * isn't freed, while we are executing this routine. */
- ret = regulator_set_voltage_time(reg, min_uV, max_uV);
 - if (ret > 0)
 latency_ns = ret * 1000;
for (i = 0; reg = regulators[i], i < count; i++) {
ret = regulator_set_voltage_time(reg, min_uV[i], max_uV[i]);if (ret > 0)latency_ns += ret * 1000;}
kfree(min_uV);
kfree(regulators);
return latency_ns;
} @@ -580,7 +610,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) { struct opp_table *opp_table; struct dev_pm_opp *old_opp, *opp;
- struct regulator *reg;
 
- struct regulator *reg = ERR_PTR(-ENXIO); struct clk *clk; unsigned long freq, old_freq; struct dev_pm_opp_supply old_supply, new_supply;
 @@ -633,14 +663,23 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) return ret; }
- if (opp_table->regulators) {
 /* This function only supports single regulator per device */if (WARN_ON(opp_table->regulator_count > 1)) {dev_err(dev, "multiple regulators not supported\n");rcu_read_unlock();return -EINVAL;}reg = opp_table->regulators[0];- }
 - if (IS_ERR(old_opp)) old_supply.u_volt = 0; else
 
memcpy(&old_supply, &old_opp->supply, sizeof(old_supply));
memcpy(&old_supply, old_opp->supplies, sizeof(old_supply));
- memcpy(&new_supply, &opp->supply, sizeof(new_supply));
 - reg = opp_table->regulator;
 
memcpy(&new_supply, opp->supplies, sizeof(new_supply));
rcu_read_unlock();
@@ -764,9 +803,6 @@ static struct opp_table *_add_opp_table(struct device *dev)
_of_init_opp_table(opp_table, dev);
- /* Set regulator to a non-NULL error value */
 - opp_table->regulator = ERR_PTR(-ENXIO);
 - /* Find clk for the device */ opp_table->clk = clk_get(dev, NULL); if (IS_ERR(opp_table->clk)) {
 @@ -815,7 +851,7 @@ static void _remove_opp_table(struct opp_table *opp_table) if (opp_table->prop_name) return;
- if (!IS_ERR(opp_table->regulator))
 
if (opp_table->regulators) return;
/* Release clk */
@@ -924,35 +960,49 @@ struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table) { struct dev_pm_opp *opp;
- int count, supply_size;
 - struct opp_table *table;
 
- /* allocate new OPP node */
 - opp = kzalloc(sizeof(*opp), GFP_KERNEL);
 - if (!opp)
 
- table = _add_opp_table(dev);
 - if (!table) return NULL;
 
- INIT_LIST_HEAD(&opp->node);
 
- /* Allocate space for at least one supply */
 - count = table->regulator_count ? table->regulator_count : 1;
 - supply_size = sizeof(*opp->supplies) * count;
 
- *opp_table = _add_opp_table(dev);
 - if (!*opp_table) {
 kfree(opp);
/* allocate new OPP node + and supplies structures */
opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL);
if (!opp) {
kfree(table);return NULL; }
opp->supplies = (struct dev_pm_opp_supply *)(opp + 1);
INIT_LIST_HEAD(&opp->node);
*opp_table = table;
return opp;
}
static bool _opp_supported_by_regulators(struct dev_pm_opp *opp, struct opp_table *opp_table) {
- struct regulator *reg = opp_table->regulator;
 - if (!IS_ERR(reg) &&
 !regulator_is_supported_voltage(reg, opp->supply.u_volt_min,opp->supply.u_volt_max)) {pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",__func__, opp->supply.u_volt_min,opp->supply.u_volt_max);return false;
struct regulator *reg;
int i;
for (i = 0; i < opp_table->regulator_count; i++) {
reg = opp_table->regulators[i];if (!regulator_is_supported_voltage(reg,opp->supplies[i].u_volt_min,opp->supplies[i].u_volt_max)) {pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",__func__, opp->supplies[i].u_volt_min,opp->supplies[i].u_volt_max);return false;}}
return true;
@@ -984,12 +1034,13 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
/* Duplicate OPPs */ dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
__func__, opp->rate, opp->supply.u_volt,opp->available, new_opp->rate, new_opp->supply.u_volt,new_opp->available);
__func__, opp->rate, opp->supplies[0].u_volt,opp->available, new_opp->rate,new_opp->supplies[0].u_volt, new_opp->available);/* Should we compare voltages for all regulators here ? */return opp->available &&
new_opp->supply.u_volt == opp->supply.u_volt ? 0 : -EEXIST;
new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? 0 : -EEXIST;}
new_opp->opp_table = opp_table;
@@ -1056,9 +1107,9 @@ int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt, /* populate the opp table */ new_opp->rate = freq; tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
- new_opp->supply.u_volt = u_volt;
 - new_opp->supply.u_volt_min = u_volt - tol;
 - new_opp->supply.u_volt_max = u_volt + tol;
 
- new_opp->supplies[0].u_volt = u_volt;
 - new_opp->supplies[0].u_volt_min = u_volt - tol;
 - new_opp->supplies[0].u_volt_max = u_volt + tol; new_opp->available = true; new_opp->dynamic = dynamic;
 @@ -1303,12 +1354,14 @@ void dev_pm_opp_put_prop_name(struct device *dev) EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
/**
- dev_pm_opp_set_regulator() - Set regulator name for the device
 
- dev_pm_opp_set_regulators() - Set regulator names for the device
 - @dev: Device for which regulator name is being set.
 
- @name: Name of the regulator.
 
- @names: Array of pointers to the names of the regulator.
 
- @count: Number of regulators.
 - In order to support OPP switching, OPP layer needs to know the name of the
 
- device's regulator, as the core would be required to switch voltages as well.
 
- device's regulators, as the core would be required to switch voltages as
 
- well.
 - This must be called before any OPPs are initialized for the device.
 @@ -1318,11 +1371,12 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
- that this function is *NOT* called under RCU protection or in contexts where
 - mutex cannot be locked.
 */ -int dev_pm_opp_set_regulator(struct device *dev, const char *name) +int dev_pm_opp_set_regulators(struct device *dev, const char *names[],
unsigned int count){ struct opp_table *opp_table; struct regulator *reg;
- int ret;
 
int ret, i;
mutex_lock(&opp_table_lock);
@@ -1338,26 +1392,43 @@ int dev_pm_opp_set_regulator(struct device *dev, const char *name) goto err; }
- /* Already have a regulator set */
 - if (WARN_ON(!IS_ERR(opp_table->regulator))) {
 
- /* Already have regulators set */
 - if (WARN_ON(opp_table->regulators)) { ret = -EBUSY; goto err; }
 
- /* Allocate the regulator */
 - reg = regulator_get_optional(dev, name);
 - if (IS_ERR(reg)) {
 ret = PTR_ERR(reg);if (ret != -EPROBE_DEFER)dev_err(dev, "%s: no regulator (%s) found: %d\n",__func__, name, ret);
- opp_table->regulators = kmalloc_array(count,
 sizeof(*opp_table->regulators),GFP_KERNEL);- if (!opp_table->regulators) goto err;
 - for (i = 0; i < count; i++) {
 reg = regulator_get_optional(dev, names[i]);pr_info("%s: %d: %p: %s\n", __func__, __LINE__, reg, names[i]);
Think this is leftover debug msg?
if (IS_ERR(reg)) {ret = PTR_ERR(reg);if (ret != -EPROBE_DEFER)dev_err(dev, "%s: regulator (%s) not found: %d\n",__func__, names[i], ret);goto free_regulators;} }opp_table->regulators[i] = reg;
- opp_table->regulator = reg;
 
opp_table->regulator_count = count;
mutex_unlock(&opp_table_lock); return 0;
+free_regulators:
- while (i != 0)
 regulator_put(opp_table->regulators[--i]);- kfree(opp_table->regulators);
 - opp_table->regulators = NULL;
 err: _remove_opp_table(opp_table); unlock: @@ -1365,11 +1436,11 @@ int dev_pm_opp_set_regulator(struct device *dev, const char *name)
return ret; } -EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator); +EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulators);
/**
- dev_pm_opp_put_regulator() - Releases resources blocked for regulator
 
- @dev: Device for which regulator was set.
 
- dev_pm_opp_put_regulators() - Releases resources blocked for regulators
 
- @dev: Device for which regulators were set.
 - Locking: The internal opp_table and opp structures are RCU protected.
 - Hence this function internally uses RCU updater strategy with mutex locks
 @@ -1377,9 +1448,10 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator);
- that this function is *NOT* called under RCU protection or in contexts where
 - mutex cannot be locked.
 */ -void dev_pm_opp_put_regulator(struct device *dev) +void dev_pm_opp_put_regulators(struct device *dev) { struct opp_table *opp_table;
int i;
mutex_lock(&opp_table_lock);
@@ -1391,16 +1463,20 @@ void dev_pm_opp_put_regulator(struct device *dev) goto unlock; }
- if (IS_ERR(opp_table->regulator)) {
 dev_err(dev, "%s: Doesn't have regulator set\n", __func__);
if (!opp_table->regulators) {
dev_err(dev, "%s: Doesn't have regulators set\n", __func__);goto unlock; }
/* Make sure there are no concurrent readers while updating opp_table */ WARN_ON(!list_empty(&opp_table->opp_list));
- regulator_put(opp_table->regulator);
 - opp_table->regulator = ERR_PTR(-ENXIO);
 
for (i = opp_table->regulator_count - 1; i >= 0; i--)
regulator_put(opp_table->regulators[i]);kfree(opp_table->regulators);
opp_table->regulators = NULL;
opp_table->regulator_count = 0;
/* Try freeing opp_table if this was the last blocking resource */ _remove_opp_table(opp_table);
@@ -1408,7 +1484,7 @@ void dev_pm_opp_put_regulator(struct device *dev) unlock: mutex_unlock(&opp_table_lock); } -EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator); +EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators);
/**
- dev_pm_opp_add() - Add an OPP table from a table definitions
 diff --git a/drivers/base/power/opp/debugfs.c b/drivers/base/power/opp/debugfs.c index c897676ca35f..cb5e5fde3d39 100644 --- a/drivers/base/power/opp/debugfs.c +++ b/drivers/base/power/opp/debugfs.c @@ -34,6 +34,43 @@ void opp_debug_remove_one(struct dev_pm_opp *opp) debugfs_remove_recursive(opp->dentry); }
+static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
struct opp_table *opp_table,struct dentry *pdentry)+{
- struct dentry *d;
 - int i = 0;
 - char name[] = "supply-X"; /* support only 0-9 supplies */
 - /* Always create at least supply-0 directory */
 - do {
 name[7] = i + '0';/* Create per-opp directory */d = debugfs_create_dir(name, pdentry);if (!d)return false;if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d,&opp->supplies[i].u_volt))return false;if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d,&opp->supplies[i].u_volt_min))return false;if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d,&opp->supplies[i].u_volt_max))return false;if (!debugfs_create_ulong("u_amp", S_IRUGO, d,&opp->supplies[i].u_amp))return false;- } while (++i < opp_table->regulator_count);
 - return true;
 +}
int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) { struct dentry *pdentry = opp_table->dentry; @@ -63,16 +100,7 @@ int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate)) return -ENOMEM;
- if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->supply.u_volt))
 return -ENOMEM;- if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->supply.u_volt_min))
 return -ENOMEM;- if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->supply.u_volt_max))
 return -ENOMEM;- if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->supply.u_amp))
 
if (!opp_debug_create_supplies(opp, opp_table, d)) return -ENOMEM;
if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index b7fcd0a1b58b..c857fb07a5bc 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/device.h> #include <linux/of.h> +#include <linux/slab.h> #include <linux/export.h>
#include "opp.h" @@ -105,12 +106,13 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
Though not in the patch there's a comment to
/* TODO: Support multiple regulators */
in the file right above the below opp_parse_supplies function that can probably be removed as part of this patch.
Otherwise this patch looks good to me.
Regards, Dave
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, struct opp_table *opp_table) {
- u32 microvolt[3] = {0};
 - u32 val;
 - int count, ret;
 
u32 *microvolt, *microamp = NULL;
int supplies, vcount, icount, ret, i, j; struct property *prop = NULL; char name[NAME_MAX];
supplies = opp_table->regulator_count ? opp_table->regulator_count : 1;
/* Search for "opp-microvolt-<name>" */ if (opp_table->prop_name) { snprintf(name, sizeof(name), "opp-microvolt-%s",
@@ -128,34 +130,29 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, return 0; }
- count = of_property_count_u32_elems(opp->np, name);
 - if (count < 0) {
 
- vcount = of_property_count_u32_elems(opp->np, name);
 - if (vcount < 0) { dev_err(dev, "%s: Invalid %s property (%d)\n",
 
__func__, name, count);return count;
__func__, name, vcount); }return vcount;
- /* There can be one or three elements here */
 - if (count != 1 && count != 3) {
 dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",__func__, name, count);
- /* There can be one or three elements per supply */
 - if (vcount != supplies && vcount != supplies * 3) {
 dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n", return -EINVAL; }__func__, name, vcount, supplies);
- ret = of_property_read_u32_array(opp->np, name, microvolt, count);
 
- microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
 - if (!microvolt)
 return -ENOMEM;- ret = of_property_read_u32_array(opp->np, name, microvolt, vcount); if (ret) { dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
 
return -EINVAL;- }
 - opp->supply.u_volt = microvolt[0];
 - if (count == 1) {
 opp->supply.u_volt_min = opp->supply.u_volt;opp->supply.u_volt_max = opp->supply.u_volt;- } else {
 opp->supply.u_volt_min = microvolt[1];opp->supply.u_volt_max = microvolt[2];
ret = -EINVAL;goto free_microvolt;}
/* Search for "opp-microamp-<name>" */
@@ -172,10 +169,59 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, prop = of_find_property(opp->np, name, NULL); }
- if (prop && !of_property_read_u32(opp->np, name, &val))
 opp->supply.u_amp = val;
- if (prop) {
 icount = of_property_count_u32_elems(opp->np, name);if (icount < 0) {dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,name, icount);ret = icount;goto free_microvolt;}
- return 0;
 
if (icount != supplies) {dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",__func__, name, icount, supplies);ret = -EINVAL;goto free_microvolt;}microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);if (!microamp) {ret = -EINVAL;goto free_microvolt;}ret = of_property_read_u32_array(opp->np, name, microamp,icount);if (ret) {dev_err(dev, "%s: error parsing %s: %d\n", __func__,name, ret);ret = -EINVAL;goto free_microamp;}- }
 - for (i = 0, j = 0; i < supplies; i++) {
 opp->supplies[i].u_volt = microvolt[j++];if (vcount == supplies) {opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;} else {opp->supplies[i].u_volt_min = microvolt[j++];opp->supplies[i].u_volt_max = microvolt[j++];}if (microamp)opp->supplies[i].u_amp = microamp[i];- }
 +free_microamp:
- kfree(microamp);
 +free_microvolt:
- kfree(microvolt);
 - return ret;
 }
/** @@ -304,8 +350,8 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n", __func__, new_opp->turbo, new_opp->rate,
new_opp->supply.u_volt, new_opp->supply.u_volt_min,new_opp->supply.u_volt_max, new_opp->clock_latency_ns);
new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns);/*
- Notify the changes in the availability of the operable
 diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index 1bda0d35c486..d3f0861f9bff 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -77,7 +77,7 @@ struct dev_pm_opp_supply {
- @turbo: true if turbo (boost) OPP
 - @suspend: true if suspend OPP
 - @rate: Frequency in hertz
 
- @supply: Power supply voltage/current values
 
- @supplies: Power supplies voltage/current values
 - @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
 frequency from any other OPP's frequency.- @opp_table: points back to the opp_table struct this opp belongs to
 @@ -96,7 +96,7 @@ struct dev_pm_opp { bool suspend; unsigned long rate;
- struct dev_pm_opp_supply supply;
 
struct dev_pm_opp_supply *supplies;
unsigned long clock_latency_ns;
@@ -155,7 +155,8 @@ enum opp_table_access {
- @supported_hw_count: Number of elements in supported_hw array.
 - @prop_name: A name to postfix to many DT properties, while parsing them.
 - @clk: Device's clock handle
 
- @regulator: Supply regulator
 
- @regulators: Supply regulators
 
- @regulator_count: Number of Power Supply regulators
 - @dentry: debugfs dentry pointer of the real device directory (not links).
 - @dentry_name: Name of the real dentry.
 @@ -190,7 +191,8 @@ struct opp_table { unsigned int supported_hw_count; const char *prop_name; struct clk *clk;
- struct regulator *regulator;
 
- struct regulator **regulators;
 - unsigned int regulator_count;
 #ifdef CONFIG_DEBUG_FS struct dentry *dentry; diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 5c07ae05d69a..15cb26118dc7 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -186,7 +186,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) */ name = find_supply_name(cpu_dev); if (name) {
ret = dev_pm_opp_set_regulator(cpu_dev, name);
const char *names[] = {name};ret = dev_pm_opp_set_regulators(cpu_dev, names, if (ret) { dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n", policy->cpu, ret);ARRAY_SIZE(names));@@ -285,7 +288,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) out_free_opp: dev_pm_opp_of_cpumask_remove_table(policy->cpus); if (name)
dev_pm_opp_put_regulator(cpu_dev);
dev_pm_opp_put_regulators(cpu_dev);out_put_clk: clk_put(cpu_clk);
@@ -300,7 +303,7 @@ static int cpufreq_exit(struct cpufreq_policy *policy) dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); if (priv->reg_name)
dev_pm_opp_put_regulator(priv->cpu_dev);
dev_pm_opp_put_regulators(priv->cpu_dev);clk_put(policy->clk); kfree(priv);
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index bca26157f5b6..0606b70a8b97 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -62,8 +62,8 @@ int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, void dev_pm_opp_put_supported_hw(struct device *dev); int dev_pm_opp_set_prop_name(struct device *dev, const char *name); void dev_pm_opp_put_prop_name(struct device *dev); -int dev_pm_opp_set_regulator(struct device *dev, const char *name); -void dev_pm_opp_put_regulator(struct device *dev); +int dev_pm_opp_set_regulators(struct device *dev, const char *names[], unsigned int count); +void dev_pm_opp_put_regulators(struct device *dev); int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask); int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask); @@ -170,12 +170,12 @@ static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
static inline void dev_pm_opp_put_prop_name(struct device *dev) {}
-static inline int dev_pm_opp_set_regulator(struct device *dev, const char *name) +static inline int dev_pm_opp_set_regulators(struct device *dev, const char *names[], unsigned int count) { return -ENOTSUPP; }
-static inline void dev_pm_opp_put_regulator(struct device *dev) {} +static inline void dev_pm_opp_put_regulators(struct device *dev) {}
static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) {