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

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

Merge branches 'pm-core', 'pm-opp' and 'pm-qos'

* pm-core:
  PM / sysfs: Constify attribute groups
  PM: Constify info string used in messages
  PM: Constify returned PM event name
  PM / wakeirq: Convert to SRCU

* pm-opp:
  PM / OPP: Add dev_pm_opp_{set|put}_clkname()
  PM / OPP: Use - instead of @ for DT entries
  PM / OPP: Don't create debugfs "supply-0" directory unnecessarily
  PM / OPP: opp-microvolt is not optional if regulators are set
  PM / OPP: Don't create copy of regulators unnecessarily
  PM / OPP: Reorganize _generic_set_opp_regulator()

* pm-qos:
  PM / QoS: constify *_attribute_group.
Loading
Loading
Loading
Loading
+19 −19
Original line number Diff line number Diff line
@@ -186,20 +186,20 @@ Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
		compatible = "operating-points-v2";
		opp-shared;

		opp@1000000000 {
		opp-1000000000 {
			opp-hz = /bits/ 64 <1000000000>;
			opp-microvolt = <975000 970000 985000>;
			opp-microamp = <70000>;
			clock-latency-ns = <300000>;
			opp-suspend;
		};
		opp@1100000000 {
		opp-1100000000 {
			opp-hz = /bits/ 64 <1100000000>;
			opp-microvolt = <1000000 980000 1010000>;
			opp-microamp = <80000>;
			clock-latency-ns = <310000>;
		};
		opp@1200000000 {
		opp-1200000000 {
			opp-hz = /bits/ 64 <1200000000>;
			opp-microvolt = <1025000>;
			clock-latency-ns = <290000>;
@@ -265,20 +265,20 @@ independently.
		 * independently.
		 */

		opp@1000000000 {
		opp-1000000000 {
			opp-hz = /bits/ 64 <1000000000>;
			opp-microvolt = <975000 970000 985000>;
			opp-microamp = <70000>;
			clock-latency-ns = <300000>;
			opp-suspend;
		};
		opp@1100000000 {
		opp-1100000000 {
			opp-hz = /bits/ 64 <1100000000>;
			opp-microvolt = <1000000 980000 1010000>;
			opp-microamp = <80000>;
			clock-latency-ns = <310000>;
		};
		opp@1200000000 {
		opp-1200000000 {
			opp-hz = /bits/ 64 <1200000000>;
			opp-microvolt = <1025000>;
			opp-microamp = <90000;
@@ -341,20 +341,20 @@ DVFS state together.
		compatible = "operating-points-v2";
		opp-shared;

		opp@1000000000 {
		opp-1000000000 {
			opp-hz = /bits/ 64 <1000000000>;
			opp-microvolt = <975000 970000 985000>;
			opp-microamp = <70000>;
			clock-latency-ns = <300000>;
			opp-suspend;
		};
		opp@1100000000 {
		opp-1100000000 {
			opp-hz = /bits/ 64 <1100000000>;
			opp-microvolt = <1000000 980000 1010000>;
			opp-microamp = <80000>;
			clock-latency-ns = <310000>;
		};
		opp@1200000000 {
		opp-1200000000 {
			opp-hz = /bits/ 64 <1200000000>;
			opp-microvolt = <1025000>;
			opp-microamp = <90000>;
@@ -367,20 +367,20 @@ DVFS state together.
		compatible = "operating-points-v2";
		opp-shared;

		opp@1300000000 {
		opp-1300000000 {
			opp-hz = /bits/ 64 <1300000000>;
			opp-microvolt = <1050000 1045000 1055000>;
			opp-microamp = <95000>;
			clock-latency-ns = <400000>;
			opp-suspend;
		};
		opp@1400000000 {
		opp-1400000000 {
			opp-hz = /bits/ 64 <1400000000>;
			opp-microvolt = <1075000>;
			opp-microamp = <100000>;
			clock-latency-ns = <400000>;
		};
		opp@1500000000 {
		opp-1500000000 {
			opp-hz = /bits/ 64 <1500000000>;
			opp-microvolt = <1100000 1010000 1110000>;
			opp-microamp = <95000>;
@@ -409,7 +409,7 @@ Example 4: Handling multiple regulators
		compatible = "operating-points-v2";
		opp-shared;

		opp@1000000000 {
		opp-1000000000 {
			opp-hz = /bits/ 64 <1000000000>;
			opp-microvolt = <970000>, /* Supply 0 */
					<960000>, /* Supply 1 */
@@ -422,7 +422,7 @@ Example 4: Handling multiple regulators

		/* OR */

		opp@1000000000 {
		opp-1000000000 {
			opp-hz = /bits/ 64 <1000000000>;
			opp-microvolt = <975000 970000 985000>, /* Supply 0 */
					<965000 960000 975000>, /* Supply 1 */
@@ -435,7 +435,7 @@ Example 4: Handling multiple regulators

		/* OR */

		opp@1000000000 {
		opp-1000000000 {
			opp-hz = /bits/ 64 <1000000000>;
			opp-microvolt = <975000 970000 985000>, /* Supply 0 */
					<965000 960000 975000>, /* Supply 1 */
@@ -467,7 +467,7 @@ Example 5: opp-supported-hw
		status = "okay";
		opp-shared;

		opp@600000000 {
		opp-600000000 {
			/*
			 * Supports all substrate and process versions for 0xF
			 * cuts, i.e. only first four cuts.
@@ -478,7 +478,7 @@ Example 5: opp-supported-hw
			...
		};

		opp@800000000 {
		opp-800000000 {
			/*
			 * Supports:
			 * - cuts: only one, 6th cut (represented by 6th bit).
@@ -510,7 +510,7 @@ Example 6: opp-microvolt-<name>, opp-microamp-<name>:
		compatible = "operating-points-v2";
		opp-shared;

		opp@1000000000 {
		opp-1000000000 {
			opp-hz = /bits/ 64 <1000000000>;
			opp-microvolt-slow = <915000 900000 925000>;
			opp-microvolt-fast = <975000 970000 985000>;
@@ -518,7 +518,7 @@ Example 6: opp-microvolt-<name>, opp-microamp-<name>:
			opp-microamp-fast =  <71000>;
		};

		opp@1200000000 {
		opp-1200000000 {
			opp-hz = /bits/ 64 <1200000000>;
			opp-microvolt-slow = <915000 900000 925000>, /* Supply vcc0 */
					      <925000 910000 935000>; /* Supply vcc1 */
+16 −14
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ static pm_message_t pm_transition;

static int async_error;

static char *pm_verb(int event)
static const char *pm_verb(int event)
{
	switch (event) {
	case PM_EVENT_SUSPEND:
@@ -208,7 +208,8 @@ static ktime_t initcall_debug_start(struct device *dev)
}

static void initcall_debug_report(struct device *dev, ktime_t calltime,
				  int error, pm_message_t state, char *info)
				  int error, pm_message_t state,
				  const char *info)
{
	ktime_t rettime;
	s64 nsecs;
@@ -403,21 +404,22 @@ static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t stat
	return NULL;
}

static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
static void pm_dev_dbg(struct device *dev, pm_message_t state, const char *info)
{
	dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
		((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
		", may wakeup" : "");
}

static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
static void pm_dev_err(struct device *dev, pm_message_t state, const char *info,
			int error)
{
	printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
		dev_name(dev), pm_verb(state.event), info, error);
}

static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
static void dpm_show_time(ktime_t starttime, pm_message_t state,
			  const char *info)
{
	ktime_t calltime;
	u64 usecs64;
@@ -435,7 +437,7 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
}

static int dpm_run_callback(pm_callback_t cb, struct device *dev,
			    pm_message_t state, char *info)
			    pm_message_t state, const char *info)
{
	ktime_t calltime;
	int error;
@@ -535,7 +537,7 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)
static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
{
	pm_callback_t callback = NULL;
	char *info = NULL;
	const char *info = NULL;
	int error = 0;

	TRACE_DEVICE(dev);
@@ -665,7 +667,7 @@ void dpm_resume_noirq(pm_message_t state)
static int device_resume_early(struct device *dev, pm_message_t state, bool async)
{
	pm_callback_t callback = NULL;
	char *info = NULL;
	const char *info = NULL;
	int error = 0;

	TRACE_DEVICE(dev);
@@ -793,7 +795,7 @@ EXPORT_SYMBOL_GPL(dpm_resume_start);
static int device_resume(struct device *dev, pm_message_t state, bool async)
{
	pm_callback_t callback = NULL;
	char *info = NULL;
	const char *info = NULL;
	int error = 0;
	DECLARE_DPM_WATCHDOG_ON_STACK(wd);

@@ -955,7 +957,7 @@ void dpm_resume(pm_message_t state)
static void device_complete(struct device *dev, pm_message_t state)
{
	void (*callback)(struct device *) = NULL;
	char *info = NULL;
	const char *info = NULL;

	if (dev->power.syscore)
		return;
@@ -1080,7 +1082,7 @@ static pm_message_t resume_event(pm_message_t sleep_state)
static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
{
	pm_callback_t callback = NULL;
	char *info = NULL;
	const char *info = NULL;
	int error = 0;

	TRACE_DEVICE(dev);
@@ -1225,7 +1227,7 @@ int dpm_suspend_noirq(pm_message_t state)
static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
{
	pm_callback_t callback = NULL;
	char *info = NULL;
	const char *info = NULL;
	int error = 0;

	TRACE_DEVICE(dev);
@@ -1384,7 +1386,7 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end);
 */
static int legacy_suspend(struct device *dev, pm_message_t state,
			  int (*cb)(struct device *dev, pm_message_t state),
			  char *info)
			  const char *info)
{
	int error;
	ktime_t calltime;
@@ -1426,7 +1428,7 @@ static void dpm_clear_suppliers_direct_complete(struct device *dev)
static int __device_suspend(struct device *dev, pm_message_t state, bool async)
{
	pm_callback_t callback = NULL;
	char *info = NULL;
	const char *info = NULL;
	int error = 0;
	DECLARE_DPM_WATCHDOG_ON_STACK(wd);

+104 −50
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ 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, **regulators;
	struct regulator *reg;
	unsigned long latency_ns = 0;
	int ret, i, count;
	struct {
@@ -198,15 +198,9 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
	if (!count)
		goto put_opp_table;

	regulators = kmalloc_array(count, sizeof(*regulators), GFP_KERNEL);
	if (!regulators)
		goto put_opp_table;

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

	memcpy(regulators, opp_table->regulators, count * sizeof(*regulators));
		goto put_opp_table;

	mutex_lock(&opp_table->lock);

@@ -232,15 +226,13 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
	 * isn't freed, while we are executing this routine.
	 */
	for (i = 0; i < count; i++) {
		reg = regulators[i];
		reg = opp_table->regulators[i];
		ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max);
		if (ret > 0)
			latency_ns += ret * 1000;
	}

	kfree(uV);
free_regulators:
	kfree(regulators);
put_opp_table:
	dev_pm_opp_put_opp_table(opp_table);

@@ -543,17 +535,18 @@ _generic_set_opp_clk_only(struct device *dev, struct clk *clk,
	return ret;
}

static int _generic_set_opp(struct dev_pm_set_opp_data *data)
static int _generic_set_opp_regulator(const struct opp_table *opp_table,
				      struct device *dev,
				      unsigned long old_freq,
				      unsigned long freq,
				      struct dev_pm_opp_supply *old_supply,
				      struct dev_pm_opp_supply *new_supply)
{
	struct dev_pm_opp_supply *old_supply = data->old_opp.supplies;
	struct dev_pm_opp_supply *new_supply = data->new_opp.supplies;
	unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
	struct regulator *reg = data->regulators[0];
	struct device *dev= data->dev;
	struct regulator *reg = opp_table->regulators[0];
	int ret;

	/* This function only supports single regulator per device */
	if (WARN_ON(data->regulator_count > 1)) {
	if (WARN_ON(opp_table->regulator_count > 1)) {
		dev_err(dev, "multiple regulators are not supported\n");
		return -EINVAL;
	}
@@ -566,7 +559,7 @@ static int _generic_set_opp(struct dev_pm_set_opp_data *data)
	}

	/* Change frequency */
	ret = _generic_set_opp_clk_only(dev, data->clk, old_freq, freq);
	ret = _generic_set_opp_clk_only(dev, opp_table->clk, old_freq, freq);
	if (ret)
		goto restore_voltage;

@@ -580,12 +573,12 @@ static int _generic_set_opp(struct dev_pm_set_opp_data *data)
	return 0;

restore_freq:
	if (_generic_set_opp_clk_only(dev, data->clk, freq, old_freq))
	if (_generic_set_opp_clk_only(dev, opp_table->clk, freq, old_freq))
		dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
			__func__, old_freq);
restore_voltage:
	/* This shouldn't harm even if the voltages weren't updated earlier */
	if (old_supply->u_volt)
	if (old_supply)
		_set_opp_voltage(dev, reg, old_supply);

	return ret;
@@ -603,10 +596,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
{
	struct opp_table *opp_table;
	unsigned long freq, old_freq;
	int (*set_opp)(struct dev_pm_set_opp_data *data);
	struct dev_pm_opp *old_opp, *opp;
	struct regulator **regulators;
	struct dev_pm_set_opp_data *data;
	struct clk *clk;
	int ret, size;

@@ -661,21 +651,18 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
	dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", __func__,
		old_freq, freq);

	regulators = opp_table->regulators;

	/* Only frequency scaling */
	if (!regulators) {
	if (!opp_table->regulators) {
		ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq);
		goto put_opps;
	}

	if (opp_table->set_opp)
		set_opp = opp_table->set_opp;
	else
		set_opp = _generic_set_opp;
	} else if (!opp_table->set_opp) {
		ret = _generic_set_opp_regulator(opp_table, dev, old_freq, freq,
						 IS_ERR(old_opp) ? NULL : old_opp->supplies,
						 opp->supplies);
	} else {
		struct dev_pm_set_opp_data *data;

		data = opp_table->set_opp_data;
	data->regulators = regulators;
		data->regulators = opp_table->regulators;
		data->regulator_count = opp_table->regulator_count;
		data->clk = clk;
		data->dev = dev;
@@ -690,9 +677,9 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
		data->new_opp.rate = freq;
		memcpy(data->new_opp.supplies, opp->supplies, size);

	ret = set_opp(data);
		ret = opp_table->set_opp(data);
	}

put_opps:
	dev_pm_opp_put(opp);
put_old_opp:
	if (!IS_ERR(old_opp))
@@ -1375,6 +1362,73 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators);

/**
 * dev_pm_opp_set_clkname() - Set clk name for the device
 * @dev: Device for which clk name is being set.
 * @name: Clk name.
 *
 * In order to support OPP switching, OPP layer needs to get pointer to the
 * clock for the device. Simple cases work fine without using this routine (i.e.
 * by passing connection-id as NULL), but for a device with multiple clocks
 * available, the OPP core needs to know the exact name of the clk to use.
 *
 * This must be called before any OPPs are initialized for the device.
 */
struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name)
{
	struct opp_table *opp_table;
	int ret;

	opp_table = dev_pm_opp_get_opp_table(dev);
	if (!opp_table)
		return ERR_PTR(-ENOMEM);

	/* This should be called before OPPs are initialized */
	if (WARN_ON(!list_empty(&opp_table->opp_list))) {
		ret = -EBUSY;
		goto err;
	}

	/* Already have default clk set, free it */
	if (!IS_ERR(opp_table->clk))
		clk_put(opp_table->clk);

	/* Find clk for the device */
	opp_table->clk = clk_get(dev, name);
	if (IS_ERR(opp_table->clk)) {
		ret = PTR_ERR(opp_table->clk);
		if (ret != -EPROBE_DEFER) {
			dev_err(dev, "%s: Couldn't find clock: %d\n", __func__,
				ret);
		}
		goto err;
	}

	return opp_table;

err:
	dev_pm_opp_put_opp_table(opp_table);

	return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_set_clkname);

/**
 * dev_pm_opp_put_clkname() - Releases resources blocked for clk.
 * @opp_table: OPP table returned from dev_pm_opp_set_clkname().
 */
void dev_pm_opp_put_clkname(struct opp_table *opp_table)
{
	/* Make sure there are no concurrent readers while updating opp_table */
	WARN_ON(!list_empty(&opp_table->opp_list));

	clk_put(opp_table->clk);
	opp_table->clk = ERR_PTR(-EINVAL);

	dev_pm_opp_put_opp_table(opp_table);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_put_clkname);

/**
 * dev_pm_opp_register_set_opp_helper() - Register custom set OPP helper
 * @dev: Device for which the helper is getting registered.
+3 −4
Original line number Diff line number Diff line
@@ -40,11 +40,10 @@ static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
				      struct dentry *pdentry)
{
	struct dentry *d;
	int i = 0;
	int i;
	char *name;

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

		/* Create per-opp directory */
@@ -70,7 +69,7 @@ static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
		if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
					  &opp->supplies[i].u_amp))
			return false;
	} while (++i < opp_table->regulator_count);
	}

	return true;
}
+8 −2
Original line number Diff line number Diff line
@@ -131,8 +131,14 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
		prop = of_find_property(opp->np, name, NULL);

		/* Missing property isn't a problem, but an invalid entry is */
		if (!prop)
		if (!prop) {
			if (!opp_table->regulator_count)
				return 0;

			dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
				__func__);
			return -EINVAL;
		}
	}

	vcount = of_property_count_u32_elems(opp->np, name);
Loading