linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] regulator: core: Optimise enable/disable path for always on regulators
@ 2012-04-19 12:30 Mark Brown
  2012-04-19 18:35 ` Liam Girdwood
  0 siblings, 1 reply; 2+ messages in thread
From: Mark Brown @ 2012-04-19 12:30 UTC (permalink / raw)
  To: Liam Girdwood, Jassi Brar; +Cc: linux-kernel, Mark Brown

If a regulator is always on for any reason then cache that when the
consumer is created and use it to optimise away the need to take locks
or recurse up the supply tree when consumers do enable or disable calls.
The scheduling of asynchronous work for bulk enables is also skipped.

We don't actually check if the device physically supports control on the
basis that constraints allowing status changes on physically always on
regulators are nonsensical anyway.

This is a very common pattern in hardware - it's normal to have some
power supplies that have either no software control or are critical to
system function - so many systems should be able to benefit.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---

I've only compile tested this so far, will do so later today or
tomorrow, but I'm fairly optimistic it'll be OK so pushing out now for
review.

 drivers/regulator/core.c |   54 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index db79987..1caada2 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -75,6 +75,7 @@ struct regulator_map {
 struct regulator {
 	struct device *dev;
 	struct list_head list;
+	unsigned int always_on:1;
 	int uA_load;
 	int min_uV;
 	int max_uV;
@@ -156,6 +157,17 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
 	return regnode;
 }
 
+static int _regulator_can_change_status(struct regulator_dev *rdev)
+{
+	if (!rdev->constraints)
+		return 0;
+
+	if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
+		return 1;
+	else
+		return 0;
+}
+
 /* Platform voltage constraint check */
 static int regulator_check_voltage(struct regulator_dev *rdev,
 				   int *min_uV, int *max_uV)
@@ -1142,6 +1154,15 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
 				   &regulator->max_uV);
 	}
 
+	/*
+	 * Check now if the regulator is an always on regulator - if
+	 * it is then we don't need to do nearly so much work for
+	 * enable/disable calls.
+	 */
+	if (!_regulator_can_change_status(rdev) &&
+	    _regulator_is_enabled(rdev))
+		regulator->always_on = true;
+
 	mutex_unlock(&rdev->mutex);
 	return regulator;
 link_name_err:
@@ -1444,17 +1465,6 @@ void devm_regulator_put(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
 
-static int _regulator_can_change_status(struct regulator_dev *rdev)
-{
-	if (!rdev->constraints)
-		return 0;
-
-	if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
-		return 1;
-	else
-		return 0;
-}
-
 /* locks held by regulator_enable() */
 static int _regulator_enable(struct regulator_dev *rdev)
 {
@@ -1534,6 +1544,9 @@ int regulator_enable(struct regulator *regulator)
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret = 0;
 
+	if (regulator->always_on)
+		return 0;
+
 	if (rdev->supply) {
 		ret = regulator_enable(rdev->supply);
 		if (ret != 0)
@@ -1612,6 +1625,9 @@ int regulator_disable(struct regulator *regulator)
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret = 0;
 
+	if (regulator->always_on)
+		return 0;
+
 	mutex_lock(&rdev->mutex);
 	ret = _regulator_disable(rdev);
 	mutex_unlock(&rdev->mutex);
@@ -1720,6 +1736,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret;
 
+	if (regulator->always_on)
+		return 0;
+
 	mutex_lock(&rdev->mutex);
 	rdev->deferred_disables++;
 	mutex_unlock(&rdev->mutex);
@@ -1813,6 +1832,9 @@ int regulator_is_enabled(struct regulator *regulator)
 {
 	int ret;
 
+	if (regulator->always_on)
+		return 1;
+
 	mutex_lock(&regulator->rdev->mutex);
 	ret = _regulator_is_enabled(regulator->rdev);
 	mutex_unlock(&regulator->rdev->mutex);
@@ -2639,9 +2661,13 @@ int regulator_bulk_enable(int num_consumers,
 	int i;
 	int ret = 0;
 
-	for (i = 0; i < num_consumers; i++)
-		async_schedule_domain(regulator_bulk_enable_async,
-				      &consumers[i], &async_domain);
+	for (i = 0; i < num_consumers; i++) {
+		if (consumers[i].consumer->always_on)
+			consumers[i].ret = 0;
+		else
+			async_schedule_domain(regulator_bulk_enable_async,
+					      &consumers[i], &async_domain);
+	}
 
 	async_synchronize_full_domain(&async_domain);
 
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] regulator: core: Optimise enable/disable path for always on regulators
  2012-04-19 12:30 [PATCH] regulator: core: Optimise enable/disable path for always on regulators Mark Brown
@ 2012-04-19 18:35 ` Liam Girdwood
  0 siblings, 0 replies; 2+ messages in thread
From: Liam Girdwood @ 2012-04-19 18:35 UTC (permalink / raw)
  To: Mark Brown; +Cc: Jassi Brar, linux-kernel

On Thu, 2012-04-19 at 13:30 +0100, Mark Brown wrote:
> If a regulator is always on for any reason then cache that when the
> consumer is created and use it to optimise away the need to take locks
> or recurse up the supply tree when consumers do enable or disable calls.
> The scheduling of asynchronous work for bulk enables is also skipped.
> 
> We don't actually check if the device physically supports control on the
> basis that constraints allowing status changes on physically always on
> regulators are nonsensical anyway.
> 
> This is a very common pattern in hardware - it's normal to have some
> power supplies that have either no software control or are critical to
> system function - so many systems should be able to benefit.
> 
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> ---

Acked-by: Liam Girdwood <lrg@ti.com>


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-04-19 18:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-19 12:30 [PATCH] regulator: core: Optimise enable/disable path for always on regulators Mark Brown
2012-04-19 18:35 ` Liam Girdwood

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).