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

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 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>
  voltages.

  Entries for multiple regulators must be present in the same order as
  regulators are specified in device's DT node.
  Entries for multiple regulators shall be provided in the same field separated
  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
  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.

  Entries for multiple regulators must be present in the same order as
  regulators are specified in device's DT node. If this property isn't required
  for few regulators, then this should be marked as zero for them. If it isn't
  required for any regulator, then this property need not be present.
  Entries for multiple regulators shall be provided in the same field separated
  by angular brackets <>. If current values aren't required for a regulator,
  then it shall be filled with 0. If current values aren't required for any of
  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-microvolt-<name> property, but for microamp instead.
@@ -386,10 +395,12 @@ Example 4: Handling multiple regulators
/ {
	cpus {
		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>;
		};
	};
+397 −124

File changed.

Preview size limit exceeded, changes collapsed.

+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->u_volt))
		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))
	if (!opp_debug_create_supplies(opp, opp_table, d))
		return -ENOMEM;

	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 Diff line number Diff line
@@ -61,10 +61,7 @@ extern struct list_head opp_tables;
 * @turbo:	true if turbo (boost) OPP
 * @suspend:	true if suspend OPP
 * @rate:	Frequency in hertz
 * @u_volt:	Target voltage in microvolts corresponding to this OPP
 * @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
 * @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
@@ -83,10 +80,8 @@ struct dev_pm_opp {
	bool suspend;
	unsigned long rate;

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

	unsigned long clock_latency_ns;

	struct opp_table *opp_table;
@@ -144,7 +139,10 @@ 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
 * @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_name: Name of the real dentry.
 *
@@ -179,7 +177,11 @@ 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;

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

#ifdef CONFIG_DEBUG_FS
	struct dentry *dentry;
@@ -190,7 +192,6 @@ struct opp_table {
/* Routines internal to opp core */
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 device_node *_of_get_opp_desc_node(struct device *dev);
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);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
Loading