aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-09 11:22:22 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2011-06-09 14:14:34 -0400
commit3801b86aa482d26a8ae460f67fca29e016491a86 (patch)
treeba3928efe63efb571356d33427de6cdffa1d6c76 /drivers/regulator
parente0eaedefda8e14ed3f445f382c568c5d69e4223f (diff)
regulator: Refactor supply implementation to work as regular consumers
Currently the regulator supply implementation is somewhat complex and fragile as it doesn't look like standard consumers but is instead a parallel implementation. This causes issues with locking and reference counting. Move the implementation over to using standard consumers to address this. Rather than only notifying the supply on the first enable/disable we do so every time the regulator is enabled or disabled, simplifying locking as we don't need to hold a lock on the consumer we are about to enable. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c101
1 files changed, 36 insertions, 65 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e3b67ee48b23..f0cc3983ffee 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -82,8 +82,7 @@ struct regulator {
82}; 82};
83 83
84static int _regulator_is_enabled(struct regulator_dev *rdev); 84static int _regulator_is_enabled(struct regulator_dev *rdev);
85static int _regulator_disable(struct regulator_dev *rdev, 85static int _regulator_disable(struct regulator_dev *rdev);
86 struct regulator_dev **supply_rdev_ptr);
87static int _regulator_get_voltage(struct regulator_dev *rdev); 86static int _regulator_get_voltage(struct regulator_dev *rdev);
88static int _regulator_get_current_limit(struct regulator_dev *rdev); 87static int _regulator_get_current_limit(struct regulator_dev *rdev);
89static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 88static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
@@ -91,6 +90,9 @@ static void _notifier_call_chain(struct regulator_dev *rdev,
91 unsigned long event, void *data); 90 unsigned long event, void *data);
92static int _regulator_do_set_voltage(struct regulator_dev *rdev, 91static int _regulator_do_set_voltage(struct regulator_dev *rdev,
93 int min_uV, int max_uV); 92 int min_uV, int max_uV);
93static struct regulator *create_regulator(struct regulator_dev *rdev,
94 struct device *dev,
95 const char *supply_name);
94 96
95static const char *rdev_get_name(struct regulator_dev *rdev) 97static const char *rdev_get_name(struct regulator_dev *rdev)
96{ 98{
@@ -930,21 +932,20 @@ out:
930 * core if it's child is enabled. 932 * core if it's child is enabled.
931 */ 933 */
932static int set_supply(struct regulator_dev *rdev, 934static int set_supply(struct regulator_dev *rdev,
933 struct regulator_dev *supply_rdev) 935 struct regulator_dev *supply_rdev)
934{ 936{
935 int err; 937 int err;
936 938
937 err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj, 939 rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
938 "supply"); 940
939 if (err) { 941 rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
940 rdev_err(rdev, "could not add device link %s err %d\n", 942 if (IS_ERR(rdev->supply)) {
941 supply_rdev->dev.kobj.name, err); 943 err = PTR_ERR(rdev->supply);
942 goto out; 944 rdev->supply = NULL;
945 return err;
943 } 946 }
944 rdev->supply = supply_rdev; 947
945 list_add(&rdev->slist, &supply_rdev->supply_list); 948 return 0;
946out:
947 return err;
948} 949}
949 950
950/** 951/**
@@ -1303,19 +1304,6 @@ static int _regulator_enable(struct regulator_dev *rdev)
1303{ 1304{
1304 int ret, delay; 1305 int ret, delay;
1305 1306
1306 if (rdev->use_count == 0) {
1307 /* do we need to enable the supply regulator first */
1308 if (rdev->supply) {
1309 mutex_lock(&rdev->supply->mutex);
1310 ret = _regulator_enable(rdev->supply);
1311 mutex_unlock(&rdev->supply->mutex);
1312 if (ret < 0) {
1313 rdev_err(rdev, "failed to enable: %d\n", ret);
1314 return ret;
1315 }
1316 }
1317 }
1318
1319 /* check voltage and requested load before enabling */ 1307 /* check voltage and requested load before enabling */
1320 if (rdev->constraints && 1308 if (rdev->constraints &&
1321 (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1309 (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
@@ -1390,19 +1378,27 @@ int regulator_enable(struct regulator *regulator)
1390 struct regulator_dev *rdev = regulator->rdev; 1378 struct regulator_dev *rdev = regulator->rdev;
1391 int ret = 0; 1379 int ret = 0;
1392 1380
1381 if (rdev->supply) {
1382 ret = regulator_enable(rdev->supply);
1383 if (ret != 0)
1384 return ret;
1385 }
1386
1393 mutex_lock(&rdev->mutex); 1387 mutex_lock(&rdev->mutex);
1394 ret = _regulator_enable(rdev); 1388 ret = _regulator_enable(rdev);
1395 mutex_unlock(&rdev->mutex); 1389 mutex_unlock(&rdev->mutex);
1390
1391 if (ret != 0)
1392 regulator_disable(rdev->supply);
1393
1396 return ret; 1394 return ret;
1397} 1395}
1398EXPORT_SYMBOL_GPL(regulator_enable); 1396EXPORT_SYMBOL_GPL(regulator_enable);
1399 1397
1400/* locks held by regulator_disable() */ 1398/* locks held by regulator_disable() */
1401static int _regulator_disable(struct regulator_dev *rdev, 1399static int _regulator_disable(struct regulator_dev *rdev)
1402 struct regulator_dev **supply_rdev_ptr)
1403{ 1400{
1404 int ret = 0; 1401 int ret = 0;
1405 *supply_rdev_ptr = NULL;
1406 1402
1407 if (WARN(rdev->use_count <= 0, 1403 if (WARN(rdev->use_count <= 0,
1408 "unbalanced disables for %s\n", rdev_get_name(rdev))) 1404 "unbalanced disables for %s\n", rdev_get_name(rdev)))
@@ -1429,9 +1425,6 @@ static int _regulator_disable(struct regulator_dev *rdev,
1429 NULL); 1425 NULL);
1430 } 1426 }
1431 1427
1432 /* decrease our supplies ref count and disable if required */
1433 *supply_rdev_ptr = rdev->supply;
1434
1435 rdev->use_count = 0; 1428 rdev->use_count = 0;
1436 } else if (rdev->use_count > 1) { 1429 } else if (rdev->use_count > 1) {
1437 1430
@@ -1442,6 +1435,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
1442 1435
1443 rdev->use_count--; 1436 rdev->use_count--;
1444 } 1437 }
1438
1445 return ret; 1439 return ret;
1446} 1440}
1447 1441
@@ -1460,29 +1454,21 @@ static int _regulator_disable(struct regulator_dev *rdev,
1460int regulator_disable(struct regulator *regulator) 1454int regulator_disable(struct regulator *regulator)
1461{ 1455{
1462 struct regulator_dev *rdev = regulator->rdev; 1456 struct regulator_dev *rdev = regulator->rdev;
1463 struct regulator_dev *supply_rdev = NULL;
1464 int ret = 0; 1457 int ret = 0;
1465 1458
1466 mutex_lock(&rdev->mutex); 1459 mutex_lock(&rdev->mutex);
1467 ret = _regulator_disable(rdev, &supply_rdev); 1460 ret = _regulator_disable(rdev);
1468 mutex_unlock(&rdev->mutex); 1461 mutex_unlock(&rdev->mutex);
1469 1462
1470 /* decrease our supplies ref count and disable if required */ 1463 if (ret == 0 && rdev->supply)
1471 while (supply_rdev != NULL) { 1464 regulator_disable(rdev->supply);
1472 rdev = supply_rdev;
1473
1474 mutex_lock(&rdev->mutex);
1475 _regulator_disable(rdev, &supply_rdev);
1476 mutex_unlock(&rdev->mutex);
1477 }
1478 1465
1479 return ret; 1466 return ret;
1480} 1467}
1481EXPORT_SYMBOL_GPL(regulator_disable); 1468EXPORT_SYMBOL_GPL(regulator_disable);
1482 1469
1483/* locks held by regulator_force_disable() */ 1470/* locks held by regulator_force_disable() */
1484static int _regulator_force_disable(struct regulator_dev *rdev, 1471static int _regulator_force_disable(struct regulator_dev *rdev)
1485 struct regulator_dev **supply_rdev_ptr)
1486{ 1472{
1487 int ret = 0; 1473 int ret = 0;
1488 1474
@@ -1499,10 +1485,6 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
1499 REGULATOR_EVENT_DISABLE, NULL); 1485 REGULATOR_EVENT_DISABLE, NULL);
1500 } 1486 }
1501 1487
1502 /* decrease our supplies ref count and disable if required */
1503 *supply_rdev_ptr = rdev->supply;
1504
1505 rdev->use_count = 0;
1506 return ret; 1488 return ret;
1507} 1489}
1508 1490
@@ -1518,16 +1500,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
1518int regulator_force_disable(struct regulator *regulator) 1500int regulator_force_disable(struct regulator *regulator)
1519{ 1501{
1520 struct regulator_dev *rdev = regulator->rdev; 1502 struct regulator_dev *rdev = regulator->rdev;
1521 struct regulator_dev *supply_rdev = NULL;
1522 int ret; 1503 int ret;
1523 1504
1524 mutex_lock(&rdev->mutex); 1505 mutex_lock(&rdev->mutex);
1525 regulator->uA_load = 0; 1506 regulator->uA_load = 0;
1526 ret = _regulator_force_disable(rdev, &supply_rdev); 1507 ret = _regulator_force_disable(regulator->rdev);
1527 mutex_unlock(&rdev->mutex); 1508 mutex_unlock(&rdev->mutex);
1528 1509
1529 if (supply_rdev) 1510 if (rdev->supply)
1530 regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev))); 1511 while (rdev->open_count--)
1512 regulator_disable(rdev->supply);
1531 1513
1532 return ret; 1514 return ret;
1533} 1515}
@@ -2138,7 +2120,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
2138 /* get input voltage */ 2120 /* get input voltage */
2139 input_uV = 0; 2121 input_uV = 0;
2140 if (rdev->supply) 2122 if (rdev->supply)
2141 input_uV = _regulator_get_voltage(rdev->supply); 2123 input_uV = regulator_get_voltage(rdev->supply);
2142 if (input_uV <= 0) 2124 if (input_uV <= 0)
2143 input_uV = rdev->constraints->input_uV; 2125 input_uV = rdev->constraints->input_uV;
2144 if (input_uV <= 0) { 2126 if (input_uV <= 0) {
@@ -2208,17 +2190,8 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
2208static void _notifier_call_chain(struct regulator_dev *rdev, 2190static void _notifier_call_chain(struct regulator_dev *rdev,
2209 unsigned long event, void *data) 2191 unsigned long event, void *data)
2210{ 2192{
2211 struct regulator_dev *_rdev;
2212
2213 /* call rdev chain first */ 2193 /* call rdev chain first */
2214 blocking_notifier_call_chain(&rdev->notifier, event, NULL); 2194 blocking_notifier_call_chain(&rdev->notifier, event, NULL);
2215
2216 /* now notify regulator we supply */
2217 list_for_each_entry(_rdev, &rdev->supply_list, slist) {
2218 mutex_lock(&_rdev->mutex);
2219 _notifier_call_chain(_rdev, event, data);
2220 mutex_unlock(&_rdev->mutex);
2221 }
2222} 2195}
2223 2196
2224/** 2197/**
@@ -2610,9 +2583,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2610 rdev->owner = regulator_desc->owner; 2583 rdev->owner = regulator_desc->owner;
2611 rdev->desc = regulator_desc; 2584 rdev->desc = regulator_desc;
2612 INIT_LIST_HEAD(&rdev->consumer_list); 2585 INIT_LIST_HEAD(&rdev->consumer_list);
2613 INIT_LIST_HEAD(&rdev->supply_list);
2614 INIT_LIST_HEAD(&rdev->list); 2586 INIT_LIST_HEAD(&rdev->list);
2615 INIT_LIST_HEAD(&rdev->slist);
2616 BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 2587 BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
2617 2588
2618 /* preform any regulator specific init */ 2589 /* preform any regulator specific init */
@@ -2724,7 +2695,7 @@ void regulator_unregister(struct regulator_dev *rdev)
2724 unset_regulator_supplies(rdev); 2695 unset_regulator_supplies(rdev);
2725 list_del(&rdev->list); 2696 list_del(&rdev->list);
2726 if (rdev->supply) 2697 if (rdev->supply)
2727 sysfs_remove_link(&rdev->dev.kobj, "supply"); 2698 regulator_put(rdev->supply);
2728 device_unregister(&rdev->dev); 2699 device_unregister(&rdev->dev);
2729 kfree(rdev->constraints); 2700 kfree(rdev->constraints);
2730 mutex_unlock(&regulator_list_mutex); 2701 mutex_unlock(&regulator_list_mutex);