aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn.andersson@sonymobile.com>2015-03-24 21:56:05 -0400
committerMark Brown <broonie@kernel.org>2015-04-01 16:19:44 -0400
commit6261b06de565baafa590e58a531a1a5522cea0b6 (patch)
tree4bc6989348daaf4fc2c92c4f1c9976796975f2f7 /drivers/regulator
parent5c9e719691eab8c5de8b1b68fc3da9f7c4470c38 (diff)
regulator: Defer lookup of supply to regulator_get
Instead of resolving regulator supplies during registration move this to the time of a consumer retrieving a handle. The benefit is that it's possible for one driver to register regulators with internal dependencies out of order. Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c92
1 files changed, 56 insertions, 36 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index b899947d839d..a291a6b9cd44 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1316,6 +1316,54 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
1316 return NULL; 1316 return NULL;
1317} 1317}
1318 1318
1319static int regulator_resolve_supply(struct regulator_dev *rdev)
1320{
1321 struct regulator_dev *r;
1322 struct device *dev = rdev->dev.parent;
1323 int ret;
1324
1325 /* No supply to resovle? */
1326 if (!rdev->supply_name)
1327 return 0;
1328
1329 /* Supply already resolved? */
1330 if (rdev->supply)
1331 return 0;
1332
1333 r = regulator_dev_lookup(dev, rdev->supply_name, &ret);
1334 if (ret == -ENODEV) {
1335 /*
1336 * No supply was specified for this regulator and
1337 * there will never be one.
1338 */
1339 return 0;
1340 }
1341
1342 if (!r) {
1343 dev_err(dev, "Failed to resolve %s-supply for %s\n",
1344 rdev->supply_name, rdev->desc->name);
1345 return -EPROBE_DEFER;
1346 }
1347
1348 /* Recursively resolve the supply of the supply */
1349 ret = regulator_resolve_supply(r);
1350 if (ret < 0)
1351 return ret;
1352
1353 ret = set_supply(rdev, r);
1354 if (ret < 0)
1355 return ret;
1356
1357 /* Cascade always-on state to supply */
1358 if (_regulator_is_enabled(rdev)) {
1359 ret = regulator_enable(rdev->supply);
1360 if (ret < 0)
1361 return ret;
1362 }
1363
1364 return 0;
1365}
1366
1319/* Internal regulator request function */ 1367/* Internal regulator request function */
1320static struct regulator *_regulator_get(struct device *dev, const char *id, 1368static struct regulator *_regulator_get(struct device *dev, const char *id,
1321 bool exclusive, bool allow_dummy) 1369 bool exclusive, bool allow_dummy)
@@ -1385,6 +1433,12 @@ found:
1385 goto out; 1433 goto out;
1386 } 1434 }
1387 1435
1436 ret = regulator_resolve_supply(rdev);
1437 if (ret < 0) {
1438 regulator = ERR_PTR(ret);
1439 goto out;
1440 }
1441
1388 if (!try_module_get(rdev->owner)) 1442 if (!try_module_get(rdev->owner))
1389 goto out; 1443 goto out;
1390 1444
@@ -3536,7 +3590,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
3536 struct regulator_dev *rdev; 3590 struct regulator_dev *rdev;
3537 struct device *dev; 3591 struct device *dev;
3538 int ret, i; 3592 int ret, i;
3539 const char *supply = NULL;
3540 3593
3541 if (regulator_desc == NULL || cfg == NULL) 3594 if (regulator_desc == NULL || cfg == NULL)
3542 return ERR_PTR(-EINVAL); 3595 return ERR_PTR(-EINVAL);
@@ -3650,41 +3703,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
3650 goto scrub; 3703 goto scrub;
3651 3704
3652 if (init_data && init_data->supply_regulator) 3705 if (init_data && init_data->supply_regulator)
3653 supply = init_data->supply_regulator; 3706 rdev->supply_name = init_data->supply_regulator;
3654 else if (regulator_desc->supply_name) 3707 else if (regulator_desc->supply_name)
3655 supply = regulator_desc->supply_name; 3708 rdev->supply_name = regulator_desc->supply_name;
3656
3657 if (supply) {
3658 struct regulator_dev *r;
3659
3660 r = regulator_dev_lookup(dev, supply, &ret);
3661 3709
3662 if (ret == -ENODEV) {
3663 /*
3664 * No supply was specified for this regulator and
3665 * there will never be one.
3666 */
3667 ret = 0;
3668 goto add_dev;
3669 } else if (!r) {
3670 dev_err(dev, "Failed to find supply %s\n", supply);
3671 ret = -EPROBE_DEFER;
3672 goto scrub;
3673 }
3674
3675 ret = set_supply(rdev, r);
3676 if (ret < 0)
3677 goto scrub;
3678
3679 /* Enable supply if rail is enabled */
3680 if (_regulator_is_enabled(rdev)) {
3681 ret = regulator_enable(rdev->supply);
3682 if (ret < 0)
3683 goto scrub;
3684 }
3685 }
3686
3687add_dev:
3688 /* add consumers devices */ 3710 /* add consumers devices */
3689 if (init_data) { 3711 if (init_data) {
3690 for (i = 0; i < init_data->num_consumer_supplies; i++) { 3712 for (i = 0; i < init_data->num_consumer_supplies; i++) {
@@ -3711,8 +3733,6 @@ unset_supplies:
3711 unset_regulator_supplies(rdev); 3733 unset_regulator_supplies(rdev);
3712 3734
3713scrub: 3735scrub:
3714 if (rdev->supply)
3715 _regulator_put(rdev->supply);
3716 regulator_ena_gpio_free(rdev); 3736 regulator_ena_gpio_free(rdev);
3717 kfree(rdev->constraints); 3737 kfree(rdev->constraints);
3718wash: 3738wash: