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; |
