Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dfbe4678 authored by Viresh Kumar's avatar Viresh Kumar Committed by Rafael J. Wysocki
Browse files

PM / OPP: Add infrastructure to manage multiple regulators



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: default avatarViresh Kumar <viresh.kumar@linaro.org>
Tested-by: default avatarDave Gerlach <d-gerlach@ti.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent ce31781a
Loading
Loading
Loading
Loading
+171 −77
Original line number Diff line number Diff line
@@ -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;
}
@@ -210,6 +212,24 @@ unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);

static int _get_regulator_count(struct device *dev)
{
	struct opp_table *opp_table;
	int count;

	rcu_read_lock();

	opp_table = _find_opp_table(dev);
	if (!IS_ERR(opp_table))
		count = opp_table->regulator_count;
	else
		count = 0;

	rcu_read_unlock();

	return count;
}

/**
 * dev_pm_opp_get_max_volt_latency() - Get max voltage latency in nanoseconds
 * @dev: device for which we do this operation
@@ -222,34 +242,51 @@ 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;
	int ret, i, count;
	struct {
		unsigned long min;
		unsigned long max;
	} *uV;

	count = _get_regulator_count(dev);

	/* Regulator may not be required for the device */
	if (!count)
		return 0;

	regulators = kmalloc_array(count, sizeof(*regulators), GFP_KERNEL);
	if (!regulators)
		return 0;

	uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL);
	if (!uV)
		goto free_regulators;

	rcu_read_lock();

	opp_table = _find_opp_table(dev);
	if (IS_ERR(opp_table)) {
		rcu_read_unlock();
		return 0;
		goto free_uV;
	}

	reg = opp_table->regulator;
	if (IS_ERR(reg)) {
		/* Regulator may not be required for device */
		rcu_read_unlock();
		return 0;
	}
	memcpy(regulators, opp_table->regulators, count * sizeof(*regulators));

	for (i = 0; i < count; i++) {
		uV[i].min = ~0;
		uV[i].max = 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 < uV[i].min)
				uV[i].min = opp->supplies[i].u_volt_min;
			if (opp->supplies[i].u_volt_max > uV[i].max)
				uV[i].max = opp->supplies[i].u_volt_max;
		}
	}

	rcu_read_unlock();
@@ -258,9 +295,16 @@ 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);
	for (i = 0; reg = regulators[i], i < count; i++) {
		ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max);
		if (ret > 0)
		latency_ns = ret * 1000;
			latency_ns += ret * 1000;
	}

free_uV:
	kfree(uV);
free_regulators:
	kfree(regulators);

	return latency_ns;
}
@@ -580,7 +624,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 +677,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 +817,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 +865,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,36 +974,51 @@ 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;
	}

	/* Put the supplies at the end of the OPP structure as an empty array */
	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;
	struct regulator *reg;
	int i;

	for (i = 0; i < opp_table->regulator_count; i++) {
		reg = opp_table->regulators[i];

	if (!IS_ERR(reg) &&
	    !regulator_is_supported_voltage(reg, opp->supply.u_volt_min,
					    opp->supply.u_volt_max)) {
		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->supply.u_volt_min,
			opp->supply.u_volt_max);
				__func__, opp->supplies[i].u_volt_min,
				opp->supplies[i].u_volt_max);
			return false;
		}
	}

	return true;
}
@@ -984,12 +1049,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 +1122,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 +1369,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 +1386,13 @@ 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.
 */
struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name)
struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
					    const char * const names[],
					    unsigned int count)
{
	struct opp_table *opp_table;
	struct regulator *reg;
	int ret;
	int ret, i;

	mutex_lock(&opp_table_lock);

@@ -1338,26 +1408,44 @@ struct opp_table *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);

	opp_table->regulators = kmalloc_array(count,
					      sizeof(*opp_table->regulators),
					      GFP_KERNEL);
	if (!opp_table->regulators) {
		ret = -ENOMEM;
		goto err;
	}

	for (i = 0; i < count; i++) {
		reg = regulator_get_optional(dev, names[i]);
		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);
		goto err;
					__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 opp_table;

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 +1453,11 @@ struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name)

	return ERR_PTR(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
 * @opp_table: OPP table returned from dev_pm_opp_set_regulator().
 * dev_pm_opp_put_regulators() - Releases resources blocked for regulator
 * @opp_table: OPP table returned from dev_pm_opp_set_regulators().
 *
 * Locking: The internal opp_table and opp structures are RCU protected.
 * Hence this function internally uses RCU updater strategy with mutex locks
@@ -1377,20 +1465,26 @@ 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 opp_table *opp_table)
void dev_pm_opp_put_regulators(struct opp_table *opp_table)
{
	int i;

	mutex_lock(&opp_table_lock);

	if (IS_ERR(opp_table->regulator)) {
		pr_err("%s: Doesn't have regulator set\n", __func__);
	if (!opp_table->regulators) {
		pr_err("%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);
@@ -1398,7 +1492,7 @@ void dev_pm_opp_put_regulator(struct opp_table *opp_table)
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
+42 −10
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/limits.h>
#include <linux/slab.h>

#include "opp.h"

@@ -34,6 +35,46 @@ 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;

	/* Always create at least supply-0 directory */
	do {
		name = kasprintf(GFP_KERNEL, "supply-%d", i);

		/* Create per-opp directory */
		d = debugfs_create_dir(name, pdentry);

		kfree(name);

		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 +104,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,
+74 −29
Original line number Diff line number Diff line
@@ -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"
@@ -101,16 +102,16 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
	return true;
}

/* TODO: Support multiple regulators */
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 +129,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",
			__func__, name, vcount, supplies);
		return -EINVAL;
	}

	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 +168,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 +349,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
+6 −4
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ extern struct list_head opp_tables;
 * @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
@@ -80,7 +80,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;

@@ -139,7 +139,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.
 *
@@ -174,7 +175,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;
+3 −3
Original line number Diff line number Diff line
@@ -188,7 +188,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
	 */
	name = find_supply_name(cpu_dev);
	if (name) {
		opp_table = dev_pm_opp_set_regulator(cpu_dev, 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",
@@ -289,7 +289,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(opp_table);
		dev_pm_opp_put_regulators(opp_table);
out_put_clk:
	clk_put(cpu_clk);

@@ -304,7 +304,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->opp_table);
		dev_pm_opp_put_regulators(priv->opp_table);

	clk_put(policy->clk);
	kfree(priv);
Loading