diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-06-09 11:22:22 -0400 |
---|---|---|
committer | Liam Girdwood <lrg@slimlogic.co.uk> | 2011-06-09 14:14:34 -0400 |
commit | 3801b86aa482d26a8ae460f67fca29e016491a86 (patch) | |
tree | ba3928efe63efb571356d33427de6cdffa1d6c76 /drivers/regulator | |
parent | e0eaedefda8e14ed3f445f382c568c5d69e4223f (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.c | 101 |
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 | ||
84 | static int _regulator_is_enabled(struct regulator_dev *rdev); | 84 | static int _regulator_is_enabled(struct regulator_dev *rdev); |
85 | static int _regulator_disable(struct regulator_dev *rdev, | 85 | static int _regulator_disable(struct regulator_dev *rdev); |
86 | struct regulator_dev **supply_rdev_ptr); | ||
87 | static int _regulator_get_voltage(struct regulator_dev *rdev); | 86 | static int _regulator_get_voltage(struct regulator_dev *rdev); |
88 | static int _regulator_get_current_limit(struct regulator_dev *rdev); | 87 | static int _regulator_get_current_limit(struct regulator_dev *rdev); |
89 | static unsigned int _regulator_get_mode(struct regulator_dev *rdev); | 88 | static 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); |
92 | static int _regulator_do_set_voltage(struct regulator_dev *rdev, | 91 | static int _regulator_do_set_voltage(struct regulator_dev *rdev, |
93 | int min_uV, int max_uV); | 92 | int min_uV, int max_uV); |
93 | static struct regulator *create_regulator(struct regulator_dev *rdev, | ||
94 | struct device *dev, | ||
95 | const char *supply_name); | ||
94 | 96 | ||
95 | static const char *rdev_get_name(struct regulator_dev *rdev) | 97 | static 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 | */ |
932 | static int set_supply(struct regulator_dev *rdev, | 934 | static 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; |
946 | out: | ||
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 | } |
1398 | EXPORT_SYMBOL_GPL(regulator_enable); | 1396 | EXPORT_SYMBOL_GPL(regulator_enable); |
1399 | 1397 | ||
1400 | /* locks held by regulator_disable() */ | 1398 | /* locks held by regulator_disable() */ |
1401 | static int _regulator_disable(struct regulator_dev *rdev, | 1399 | static 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, | |||
1460 | int regulator_disable(struct regulator *regulator) | 1454 | int 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 | } |
1481 | EXPORT_SYMBOL_GPL(regulator_disable); | 1468 | EXPORT_SYMBOL_GPL(regulator_disable); |
1482 | 1469 | ||
1483 | /* locks held by regulator_force_disable() */ | 1470 | /* locks held by regulator_force_disable() */ |
1484 | static int _regulator_force_disable(struct regulator_dev *rdev, | 1471 | static 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, | |||
1518 | int regulator_force_disable(struct regulator *regulator) | 1500 | int 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); | |||
2208 | static void _notifier_call_chain(struct regulator_dev *rdev, | 2190 | static 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(®ulator_list_mutex); | 2701 | mutex_unlock(®ulator_list_mutex); |