aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-19 08:19:07 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-20 05:12:38 -0400
commit6492bc1b1a9cb21d28cde3c70d090c7648c8b0ed (patch)
tree864ac01b80bbc6e57cbd86e0938b20112d68fe4a /drivers/regulator/core.c
parent854ccbaee7e48734936690a3fd4817c57e98aaad (diff)
regulator: core: Optimise enable/disable path for always on regulators
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>
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r--drivers/regulator/core.c54
1 files changed, 40 insertions, 14 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2f0d557a910d..4b2c02c519f0 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -74,6 +74,7 @@ struct regulator_map {
74struct regulator { 74struct regulator {
75 struct device *dev; 75 struct device *dev;
76 struct list_head list; 76 struct list_head list;
77 unsigned int always_on:1;
77 int uA_load; 78 int uA_load;
78 int min_uV; 79 int min_uV;
79 int max_uV; 80 int max_uV;
@@ -155,6 +156,17 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
155 return regnode; 156 return regnode;
156} 157}
157 158
159static int _regulator_can_change_status(struct regulator_dev *rdev)
160{
161 if (!rdev->constraints)
162 return 0;
163
164 if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
165 return 1;
166 else
167 return 0;
168}
169
158/* Platform voltage constraint check */ 170/* Platform voltage constraint check */
159static int regulator_check_voltage(struct regulator_dev *rdev, 171static int regulator_check_voltage(struct regulator_dev *rdev,
160 int *min_uV, int *max_uV) 172 int *min_uV, int *max_uV)
@@ -1141,6 +1153,15 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
1141 &regulator->max_uV); 1153 &regulator->max_uV);
1142 } 1154 }
1143 1155
1156 /*
1157 * Check now if the regulator is an always on regulator - if
1158 * it is then we don't need to do nearly so much work for
1159 * enable/disable calls.
1160 */
1161 if (!_regulator_can_change_status(rdev) &&
1162 _regulator_is_enabled(rdev))
1163 regulator->always_on = true;
1164
1144 mutex_unlock(&rdev->mutex); 1165 mutex_unlock(&rdev->mutex);
1145 return regulator; 1166 return regulator;
1146link_name_err: 1167link_name_err:
@@ -1443,17 +1464,6 @@ void devm_regulator_put(struct regulator *regulator)
1443} 1464}
1444EXPORT_SYMBOL_GPL(devm_regulator_put); 1465EXPORT_SYMBOL_GPL(devm_regulator_put);
1445 1466
1446static int _regulator_can_change_status(struct regulator_dev *rdev)
1447{
1448 if (!rdev->constraints)
1449 return 0;
1450
1451 if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
1452 return 1;
1453 else
1454 return 0;
1455}
1456
1457/* locks held by regulator_enable() */ 1467/* locks held by regulator_enable() */
1458static int _regulator_enable(struct regulator_dev *rdev) 1468static int _regulator_enable(struct regulator_dev *rdev)
1459{ 1469{
@@ -1533,6 +1543,9 @@ int regulator_enable(struct regulator *regulator)
1533 struct regulator_dev *rdev = regulator->rdev; 1543 struct regulator_dev *rdev = regulator->rdev;
1534 int ret = 0; 1544 int ret = 0;
1535 1545
1546 if (regulator->always_on)
1547 return 0;
1548
1536 if (rdev->supply) { 1549 if (rdev->supply) {
1537 ret = regulator_enable(rdev->supply); 1550 ret = regulator_enable(rdev->supply);
1538 if (ret != 0) 1551 if (ret != 0)
@@ -1611,6 +1624,9 @@ int regulator_disable(struct regulator *regulator)
1611 struct regulator_dev *rdev = regulator->rdev; 1624 struct regulator_dev *rdev = regulator->rdev;
1612 int ret = 0; 1625 int ret = 0;
1613 1626
1627 if (regulator->always_on)
1628 return 0;
1629
1614 mutex_lock(&rdev->mutex); 1630 mutex_lock(&rdev->mutex);
1615 ret = _regulator_disable(rdev); 1631 ret = _regulator_disable(rdev);
1616 mutex_unlock(&rdev->mutex); 1632 mutex_unlock(&rdev->mutex);
@@ -1719,6 +1735,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
1719 struct regulator_dev *rdev = regulator->rdev; 1735 struct regulator_dev *rdev = regulator->rdev;
1720 int ret; 1736 int ret;
1721 1737
1738 if (regulator->always_on)
1739 return 0;
1740
1722 mutex_lock(&rdev->mutex); 1741 mutex_lock(&rdev->mutex);
1723 rdev->deferred_disables++; 1742 rdev->deferred_disables++;
1724 mutex_unlock(&rdev->mutex); 1743 mutex_unlock(&rdev->mutex);
@@ -1757,6 +1776,9 @@ int regulator_is_enabled(struct regulator *regulator)
1757{ 1776{
1758 int ret; 1777 int ret;
1759 1778
1779 if (regulator->always_on)
1780 return 1;
1781
1760 mutex_lock(&regulator->rdev->mutex); 1782 mutex_lock(&regulator->rdev->mutex);
1761 ret = _regulator_is_enabled(regulator->rdev); 1783 ret = _regulator_is_enabled(regulator->rdev);
1762 mutex_unlock(&regulator->rdev->mutex); 1784 mutex_unlock(&regulator->rdev->mutex);
@@ -2539,9 +2561,13 @@ int regulator_bulk_enable(int num_consumers,
2539 int i; 2561 int i;
2540 int ret = 0; 2562 int ret = 0;
2541 2563
2542 for (i = 0; i < num_consumers; i++) 2564 for (i = 0; i < num_consumers; i++) {
2543 async_schedule_domain(regulator_bulk_enable_async, 2565 if (consumers[i].consumer->always_on)
2544 &consumers[i], &async_domain); 2566 consumers[i].ret = 0;
2567 else
2568 async_schedule_domain(regulator_bulk_enable_async,
2569 &consumers[i], &async_domain);
2570 }
2545 2571
2546 async_synchronize_full_domain(&async_domain); 2572 async_synchronize_full_domain(&async_domain);
2547 2573