Commit 57def856 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-opp'

* pm-opp:
  PM / OPP: Don't WARN on multiple calls to dev_pm_opp_set_regulators()
  PM / OPP: Allow platform specific custom set_opp() callbacks
  PM / OPP: Separate out _generic_set_opp()
  PM / OPP: Add infrastructure to manage multiple regulators
  PM / OPP: Pass struct dev_pm_opp_supply to _set_opp_voltage()
  PM / OPP: Manage supply's voltage/current in a separate structure
  PM / OPP: Don't use OPP structure outside of rcu protected section
  PM / OPP: Reword binding supporting multiple regulators per device
  PM / OPP: Fix incorrect cpu-supply property in binding
  PM / OPP: Pass opp_table to dev_pm_opp_put_regulator()
  PM / OPP: fix debug/error messages in dev_pm_opp_of_get_sharing_cpus()
  PM / OPP: make _of_get_opp_desc_node() a static function
parents 852b7fa2 e231f8d7
Loading
Loading
Loading
Loading
+19 −8
Original line number Original line Diff line number Diff line
@@ -86,8 +86,14 @@ Optional properties:
  Single entry is for target voltage and three entries are for <target min max>
  Single entry is for target voltage and three entries are for <target min max>
  voltages.
  voltages.


  Entries for multiple regulators must be present in the same order as
  Entries for multiple regulators shall be provided in the same field separated
  regulators are specified in device's DT node.
  by angular brackets <>. The OPP binding doesn't provide any provisions to
  relate the values to their power supplies or the order in which the supplies
  need to be configured and that is left for the implementation specific
  binding.

  Entries for all regulators shall be of the same size, i.e. either all use a
  single value or triplets.


- opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to
- opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to
  the above opp-microvolt property, but allows multiple voltage ranges to be
  the above opp-microvolt property, but allows multiple voltage ranges to be
@@ -104,10 +110,13 @@ Optional properties:


  Should only be set if opp-microvolt is set for the OPP.
  Should only be set if opp-microvolt is set for the OPP.


  Entries for multiple regulators must be present in the same order as
  Entries for multiple regulators shall be provided in the same field separated
  regulators are specified in device's DT node. If this property isn't required
  by angular brackets <>. If current values aren't required for a regulator,
  for few regulators, then this should be marked as zero for them. If it isn't
  then it shall be filled with 0. If current values aren't required for any of
  required for any regulator, then this property need not be present.
  the regulators, then this field is not required. The OPP binding doesn't
  provide any provisions to relate the values to their power supplies or the
  order in which the supplies need to be configured and that is left for the
  implementation specific binding.


- opp-microamp-<name>: Named opp-microamp property. Similar to
- opp-microamp-<name>: Named opp-microamp property. Similar to
  opp-microvolt-<name> property, but for microamp instead.
  opp-microvolt-<name> property, but for microamp instead.
@@ -386,10 +395,12 @@ Example 4: Handling multiple regulators
/ {
/ {
	cpus {
	cpus {
		cpu@0 {
		cpu@0 {
			compatible = "arm,cortex-a7";
			compatible = "vendor,cpu-type";
			...
			...


			cpu-supply = <&cpu_supply0>, <&cpu_supply1>, <&cpu_supply2>;
			vcc0-supply = <&cpu_supply0>;
			vcc1-supply = <&cpu_supply1>;
			vcc2-supply = <&cpu_supply2>;
			operating-points-v2 = <&cpu0_opp_table>;
			operating-points-v2 = <&cpu0_opp_table>;
		};
		};
	};
	};
+397 −124

File changed.

Preview size limit exceeded, changes collapsed.

+42 −10
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/limits.h>
#include <linux/limits.h>
#include <linux/slab.h>


#include "opp.h"
#include "opp.h"


@@ -34,6 +35,46 @@ void opp_debug_remove_one(struct dev_pm_opp *opp)
	debugfs_remove_recursive(opp->dentry);
	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)
int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
{
{
	struct dentry *pdentry = opp_table->dentry;
	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))
	if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate))
		return -ENOMEM;
		return -ENOMEM;


	if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->u_volt))
	if (!opp_debug_create_supplies(opp, opp_table, d))
		return -ENOMEM;

	if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->u_volt_min))
		return -ENOMEM;

	if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->u_volt_max))
		return -ENOMEM;

	if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->u_amp))
		return -ENOMEM;
		return -ENOMEM;


	if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
	if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
+78 −33

File changed.

Preview size limit exceeded, changes collapsed.

+12 −11
Original line number Original line Diff line number Diff line
@@ -61,10 +61,7 @@ extern struct list_head opp_tables;
 * @turbo:	true if turbo (boost) OPP
 * @turbo:	true if turbo (boost) OPP
 * @suspend:	true if suspend OPP
 * @suspend:	true if suspend OPP
 * @rate:	Frequency in hertz
 * @rate:	Frequency in hertz
 * @u_volt:	Target voltage in microvolts corresponding to this OPP
 * @supplies:	Power supplies voltage/current values
 * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
 * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
 * @u_amp:	Maximum current drawn by the device in microamperes
 * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
 * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
 *		frequency from any other OPP's frequency.
 *		frequency from any other OPP's frequency.
 * @opp_table:	points back to the opp_table struct this opp belongs to
 * @opp_table:	points back to the opp_table struct this opp belongs to
@@ -83,10 +80,8 @@ struct dev_pm_opp {
	bool suspend;
	bool suspend;
	unsigned long rate;
	unsigned long rate;


	unsigned long u_volt;
	struct dev_pm_opp_supply *supplies;
	unsigned long u_volt_min;

	unsigned long u_volt_max;
	unsigned long u_amp;
	unsigned long clock_latency_ns;
	unsigned long clock_latency_ns;


	struct opp_table *opp_table;
	struct opp_table *opp_table;
@@ -144,7 +139,10 @@ enum opp_table_access {
 * @supported_hw_count: Number of elements in supported_hw array.
 * @supported_hw_count: Number of elements in supported_hw array.
 * @prop_name: A name to postfix to many DT properties, while parsing them.
 * @prop_name: A name to postfix to many DT properties, while parsing them.
 * @clk: Device's clock handle
 * @clk: Device's clock handle
 * @regulator: Supply regulator
 * @regulators: Supply regulators
 * @regulator_count: Number of power supply regulators
 * @set_opp: Platform specific set_opp callback
 * @set_opp_data: Data to be passed to set_opp callback
 * @dentry:	debugfs dentry pointer of the real device directory (not links).
 * @dentry:	debugfs dentry pointer of the real device directory (not links).
 * @dentry_name: Name of the real dentry.
 * @dentry_name: Name of the real dentry.
 *
 *
@@ -179,7 +177,11 @@ struct opp_table {
	unsigned int supported_hw_count;
	unsigned int supported_hw_count;
	const char *prop_name;
	const char *prop_name;
	struct clk *clk;
	struct clk *clk;
	struct regulator *regulator;
	struct regulator **regulators;
	unsigned int regulator_count;

	int (*set_opp)(struct dev_pm_set_opp_data *data);
	struct dev_pm_set_opp_data *set_opp_data;


#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
	struct dentry *dentry;
	struct dentry *dentry;
@@ -190,7 +192,6 @@ struct opp_table {
/* Routines internal to opp core */
/* Routines internal to opp core */
struct opp_table *_find_opp_table(struct device *dev);
struct opp_table *_find_opp_table(struct device *dev);
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
struct device_node *_of_get_opp_desc_node(struct device *dev);
void _dev_pm_opp_remove_table(struct device *dev, bool remove_all);
void _dev_pm_opp_remove_table(struct device *dev, bool remove_all);
struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table);
struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
Loading