diff options
author | Mark Brown <broonie@kernel.org> | 2015-04-10 14:15:59 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-04-10 14:15:59 -0400 |
commit | 5fc31b43d59a983c47c37b7a6d327f83395609ed (patch) | |
tree | a09e68462f79fa616d08fd866764865384409b8b | |
parent | f22e6e847115abc3a0e2ad7bb18d243d42275af1 (diff) | |
parent | 498e530e50ffccb979cf5f2f2e5bbce01afe1b6e (diff) |
Merge remote-tracking branch 'regulator/topic/core' into regulator-next
-rw-r--r-- | drivers/regulator/core.c | 212 | ||||
-rw-r--r-- | include/linux/regulator/consumer.h | 2 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 1 |
3 files changed, 177 insertions, 38 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a4a8a6dc60c4..669418bc99aa 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 | ||
1319 | static 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 */ |
1320 | static struct regulator *_regulator_get(struct device *dev, const char *id, | 1368 | static 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 | ||
@@ -3499,7 +3553,18 @@ static struct class regulator_class = { | |||
3499 | 3553 | ||
3500 | static void rdev_init_debugfs(struct regulator_dev *rdev) | 3554 | static void rdev_init_debugfs(struct regulator_dev *rdev) |
3501 | { | 3555 | { |
3502 | rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); | 3556 | struct device *parent = rdev->dev.parent; |
3557 | const char *rname = rdev_get_name(rdev); | ||
3558 | char name[NAME_MAX]; | ||
3559 | |||
3560 | /* Avoid duplicate debugfs directory names */ | ||
3561 | if (parent && rname == rdev->desc->name) { | ||
3562 | snprintf(name, sizeof(name), "%s-%s", dev_name(parent), | ||
3563 | rname); | ||
3564 | rname = name; | ||
3565 | } | ||
3566 | |||
3567 | rdev->debugfs = debugfs_create_dir(rname, debugfs_root); | ||
3503 | if (!rdev->debugfs) { | 3568 | if (!rdev->debugfs) { |
3504 | rdev_warn(rdev, "Failed to create debugfs directory\n"); | 3569 | rdev_warn(rdev, "Failed to create debugfs directory\n"); |
3505 | return; | 3570 | return; |
@@ -3533,7 +3598,6 @@ regulator_register(const struct regulator_desc *regulator_desc, | |||
3533 | struct regulator_dev *rdev; | 3598 | struct regulator_dev *rdev; |
3534 | struct device *dev; | 3599 | struct device *dev; |
3535 | int ret, i; | 3600 | int ret, i; |
3536 | const char *supply = NULL; | ||
3537 | 3601 | ||
3538 | if (regulator_desc == NULL || cfg == NULL) | 3602 | if (regulator_desc == NULL || cfg == NULL) |
3539 | return ERR_PTR(-EINVAL); | 3603 | return ERR_PTR(-EINVAL); |
@@ -3641,41 +3705,10 @@ regulator_register(const struct regulator_desc *regulator_desc, | |||
3641 | goto scrub; | 3705 | goto scrub; |
3642 | 3706 | ||
3643 | if (init_data && init_data->supply_regulator) | 3707 | if (init_data && init_data->supply_regulator) |
3644 | supply = init_data->supply_regulator; | 3708 | rdev->supply_name = init_data->supply_regulator; |
3645 | else if (regulator_desc->supply_name) | 3709 | else if (regulator_desc->supply_name) |
3646 | supply = regulator_desc->supply_name; | 3710 | rdev->supply_name = regulator_desc->supply_name; |
3647 | |||
3648 | if (supply) { | ||
3649 | struct regulator_dev *r; | ||
3650 | |||
3651 | r = regulator_dev_lookup(dev, supply, &ret); | ||
3652 | 3711 | ||
3653 | if (ret == -ENODEV) { | ||
3654 | /* | ||
3655 | * No supply was specified for this regulator and | ||
3656 | * there will never be one. | ||
3657 | */ | ||
3658 | ret = 0; | ||
3659 | goto add_dev; | ||
3660 | } else if (!r) { | ||
3661 | dev_err(dev, "Failed to find supply %s\n", supply); | ||
3662 | ret = -EPROBE_DEFER; | ||
3663 | goto scrub; | ||
3664 | } | ||
3665 | |||
3666 | ret = set_supply(rdev, r); | ||
3667 | if (ret < 0) | ||
3668 | goto scrub; | ||
3669 | |||
3670 | /* Enable supply if rail is enabled */ | ||
3671 | if (_regulator_is_enabled(rdev)) { | ||
3672 | ret = regulator_enable(rdev->supply); | ||
3673 | if (ret < 0) | ||
3674 | goto scrub; | ||
3675 | } | ||
3676 | } | ||
3677 | |||
3678 | add_dev: | ||
3679 | /* add consumers devices */ | 3712 | /* add consumers devices */ |
3680 | if (init_data) { | 3713 | if (init_data) { |
3681 | for (i = 0; i < init_data->num_consumer_supplies; i++) { | 3714 | for (i = 0; i < init_data->num_consumer_supplies; i++) { |
@@ -3702,8 +3735,6 @@ unset_supplies: | |||
3702 | unset_regulator_supplies(rdev); | 3735 | unset_regulator_supplies(rdev); |
3703 | 3736 | ||
3704 | scrub: | 3737 | scrub: |
3705 | if (rdev->supply) | ||
3706 | _regulator_put(rdev->supply); | ||
3707 | regulator_ena_gpio_free(rdev); | 3738 | regulator_ena_gpio_free(rdev); |
3708 | kfree(rdev->constraints); | 3739 | kfree(rdev->constraints); |
3709 | wash: | 3740 | wash: |
@@ -3936,6 +3967,110 @@ static const struct file_operations supply_map_fops = { | |||
3936 | #endif | 3967 | #endif |
3937 | }; | 3968 | }; |
3938 | 3969 | ||
3970 | #ifdef CONFIG_DEBUG_FS | ||
3971 | static void regulator_summary_show_subtree(struct seq_file *s, | ||
3972 | struct regulator_dev *rdev, | ||
3973 | int level) | ||
3974 | { | ||
3975 | struct list_head *list = s->private; | ||
3976 | struct regulator_dev *child; | ||
3977 | struct regulation_constraints *c; | ||
3978 | struct regulator *consumer; | ||
3979 | |||
3980 | if (!rdev) | ||
3981 | return; | ||
3982 | |||
3983 | seq_printf(s, "%*s%-*s %3d %4d %6d ", | ||
3984 | level * 3 + 1, "", | ||
3985 | 30 - level * 3, rdev_get_name(rdev), | ||
3986 | rdev->use_count, rdev->open_count, rdev->bypass_count); | ||
3987 | |||
3988 | seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); | ||
3989 | seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); | ||
3990 | |||
3991 | c = rdev->constraints; | ||
3992 | if (c) { | ||
3993 | switch (rdev->desc->type) { | ||
3994 | case REGULATOR_VOLTAGE: | ||
3995 | seq_printf(s, "%5dmV %5dmV ", | ||
3996 | c->min_uV / 1000, c->max_uV / 1000); | ||
3997 | break; | ||
3998 | case REGULATOR_CURRENT: | ||
3999 | seq_printf(s, "%5dmA %5dmA ", | ||
4000 | c->min_uA / 1000, c->max_uA / 1000); | ||
4001 | break; | ||
4002 | } | ||
4003 | } | ||
4004 | |||
4005 | seq_puts(s, "\n"); | ||
4006 | |||
4007 | list_for_each_entry(consumer, &rdev->consumer_list, list) { | ||
4008 | if (consumer->dev->class == ®ulator_class) | ||
4009 | continue; | ||
4010 | |||
4011 | seq_printf(s, "%*s%-*s ", | ||
4012 | (level + 1) * 3 + 1, "", | ||
4013 | 30 - (level + 1) * 3, dev_name(consumer->dev)); | ||
4014 | |||
4015 | switch (rdev->desc->type) { | ||
4016 | case REGULATOR_VOLTAGE: | ||
4017 | seq_printf(s, "%37dmV %5dmV", | ||
4018 | consumer->min_uV / 1000, | ||
4019 | consumer->max_uV / 1000); | ||
4020 | break; | ||
4021 | case REGULATOR_CURRENT: | ||
4022 | break; | ||
4023 | } | ||
4024 | |||
4025 | seq_puts(s, "\n"); | ||
4026 | } | ||
4027 | |||
4028 | list_for_each_entry(child, list, list) { | ||
4029 | /* handle only non-root regulators supplied by current rdev */ | ||
4030 | if (!child->supply || child->supply->rdev != rdev) | ||
4031 | continue; | ||
4032 | |||
4033 | regulator_summary_show_subtree(s, child, level + 1); | ||
4034 | } | ||
4035 | } | ||
4036 | |||
4037 | static int regulator_summary_show(struct seq_file *s, void *data) | ||
4038 | { | ||
4039 | struct list_head *list = s->private; | ||
4040 | struct regulator_dev *rdev; | ||
4041 | |||
4042 | seq_puts(s, " regulator use open bypass voltage current min max\n"); | ||
4043 | seq_puts(s, "-------------------------------------------------------------------------------\n"); | ||
4044 | |||
4045 | mutex_lock(®ulator_list_mutex); | ||
4046 | |||
4047 | list_for_each_entry(rdev, list, list) { | ||
4048 | if (rdev->supply) | ||
4049 | continue; | ||
4050 | |||
4051 | regulator_summary_show_subtree(s, rdev, 0); | ||
4052 | } | ||
4053 | |||
4054 | mutex_unlock(®ulator_list_mutex); | ||
4055 | |||
4056 | return 0; | ||
4057 | } | ||
4058 | |||
4059 | static int regulator_summary_open(struct inode *inode, struct file *file) | ||
4060 | { | ||
4061 | return single_open(file, regulator_summary_show, inode->i_private); | ||
4062 | } | ||
4063 | #endif | ||
4064 | |||
4065 | static const struct file_operations regulator_summary_fops = { | ||
4066 | #ifdef CONFIG_DEBUG_FS | ||
4067 | .open = regulator_summary_open, | ||
4068 | .read = seq_read, | ||
4069 | .llseek = seq_lseek, | ||
4070 | .release = single_release, | ||
4071 | #endif | ||
4072 | }; | ||
4073 | |||
3939 | static int __init regulator_init(void) | 4074 | static int __init regulator_init(void) |
3940 | { | 4075 | { |
3941 | int ret; | 4076 | int ret; |
@@ -3949,6 +4084,9 @@ static int __init regulator_init(void) | |||
3949 | debugfs_create_file("supply_map", 0444, debugfs_root, NULL, | 4084 | debugfs_create_file("supply_map", 0444, debugfs_root, NULL, |
3950 | &supply_map_fops); | 4085 | &supply_map_fops); |
3951 | 4086 | ||
4087 | debugfs_create_file("regulator_summary", 0444, debugfs_root, | ||
4088 | ®ulator_list, ®ulator_summary_fops); | ||
4089 | |||
3952 | regulator_dummy_init(); | 4090 | regulator_dummy_init(); |
3953 | 4091 | ||
3954 | return ret; | 4092 | return ret; |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index d17e1ff7ad01..aeacd624a794 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
@@ -114,7 +114,7 @@ struct regmap; | |||
114 | #define REGULATOR_EVENT_OVER_TEMP 0x10 | 114 | #define REGULATOR_EVENT_OVER_TEMP 0x10 |
115 | #define REGULATOR_EVENT_FORCE_DISABLE 0x20 | 115 | #define REGULATOR_EVENT_FORCE_DISABLE 0x20 |
116 | #define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40 | 116 | #define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40 |
117 | #define REGULATOR_EVENT_DISABLE 0x80 | 117 | #define REGULATOR_EVENT_DISABLE 0x80 |
118 | #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100 | 118 | #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100 |
119 | #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 | 119 | #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 |
120 | #define REGULATOR_EVENT_PRE_DISABLE 0x400 | 120 | #define REGULATOR_EVENT_PRE_DISABLE 0x400 |
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 045f709cb89b..3429e81beca0 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
@@ -367,6 +367,7 @@ struct regulator_dev { | |||
367 | struct device dev; | 367 | struct device dev; |
368 | struct regulation_constraints *constraints; | 368 | struct regulation_constraints *constraints; |
369 | struct regulator *supply; /* for tree */ | 369 | struct regulator *supply; /* for tree */ |
370 | const char *supply_name; | ||
370 | struct regmap *regmap; | 371 | struct regmap *regmap; |
371 | 372 | ||
372 | struct delayed_work disable_work; | 373 | struct delayed_work disable_work; |