aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Stübner <heiko@sntech.de>2015-04-07 10:16:39 -0400
committerMark Brown <broonie@kernel.org>2015-04-10 10:46:28 -0400
commit7c225ec90c368a474daa9803922f4b7d6fe6d5c8 (patch)
tree0c42e3095d5c14b8707a1bed1d12cc9aec1c73a7
parenta9eaa8130707d4013fb109b80323489c0d0111ac (diff)
regulator: add a summary tree in debugfs
On modern systems the regulator hierarchy can get quite long and nested with regulators supplying other regulators. In some cases when debugging it might be nice to get a tree of these regulators, their consumers and the regulation constraints in one go. To achieve this add a regulator_summary sysfs node, similar to clk_summary in the common clock framework, that walks the regulator list and creates a tree out of the regulators, their consumers and core per-regulator settings. On a rk3288-firefly the regulator_summary would for example look something like: regulator use open bypass value min max ----------------------------------------------------------------------- vcc_sys 0 12 0 5000mV 5000mV 5000mV vcc_lan 1 1 0 3300mV 3300mV 3300mV ff290000.ethernet 0mV 0mV vcca_33 0 0 0 3300mV 3300mV 3300mV vcca_18 0 0 0 1800mV 1800mV 1800mV vdd10_lcd 0 0 0 1000mV 1000mV 1000mV vccio_sd 0 0 0 3300mV 3300mV 3300mV vcc_20 0 3 0 2000mV 2000mV 2000mV vcc18_lcd 0 0 0 1800mV 1800mV 1800mV vcc_18 0 2 0 1800mV 1800mV 1800mV ff100000.saradc 0mV 0mV ff0d0000.dwmmc 1650mV 1950mV vdd_10 0 0 0 1000mV 1000mV 1000mV vdd_log 0 0 0 1100mV 1100mV 1100mV vcc_io 0 3 0 3300mV 3300mV 3300mV ff0f0000.dwmmc 3300mV 3400mV vcc_flash 1 1 0 1800mV 1800mV 1800mV ff0f0000.dwmmc 1700mV 1950mV vcc_sd 1 1 0 3300mV 3300mV 3300mV ff0c0000.dwmmc 3300mV 3400mV vcc_ddr 0 0 0 1200mV 1200mV 1200mV vdd_gpu 0 0 0 1000mV 850mV 1350mV vdd_cpu 0 1 0 900mV 850mV 1350mV cpu0 900mV 900mV vcc_5v 0 2 0 5000mV 5000mV 5000mV vcc_otg_5v 0 0 0 5000mV 5000mV 5000mV vcc_host_5v 0 0 0 5000mV 5000mV 5000mV regulator-dummy 0 0 0 0mV 0mV 0mV Signed-off-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/regulator/core.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index cc242aa368ef..5aae1bd61151 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3954,6 +3954,124 @@ static const struct file_operations supply_map_fops = {
3954#endif 3954#endif
3955}; 3955};
3956 3956
3957#ifdef CONFIG_DEBUG_FS
3958static void regulator_summary_show_subtree(struct seq_file *s,
3959 struct regulator_dev *rdev,
3960 int level)
3961{
3962 struct list_head *list = s->private;
3963 struct regulator_dev *child;
3964 struct regulation_constraints *c;
3965 struct regulator *consumer;
3966
3967 if (!rdev)
3968 return;
3969
3970 mutex_lock(&rdev->mutex);
3971
3972 seq_printf(s, "%*s%-*s %3d %4d %6d ",
3973 level * 3 + 1, "",
3974 30 - level * 3, rdev_get_name(rdev),
3975 rdev->use_count, rdev->open_count, rdev->bypass_count);
3976
3977 switch (rdev->desc->type) {
3978 case REGULATOR_VOLTAGE:
3979 seq_printf(s, "%5dmV ",
3980 _regulator_get_voltage(rdev) / 1000);
3981 break;
3982 case REGULATOR_CURRENT:
3983 seq_printf(s, "%5dmA ",
3984 _regulator_get_current_limit(rdev) / 1000);
3985 break;
3986 }
3987
3988 c = rdev->constraints;
3989 if (c) {
3990 switch (rdev->desc->type) {
3991 case REGULATOR_VOLTAGE:
3992 seq_printf(s, "%5dmV %5dmV ",
3993 c->min_uV / 1000, c->max_uV / 1000);
3994 break;
3995 case REGULATOR_CURRENT:
3996 seq_printf(s, "%5dmA %5dmA ",
3997 c->min_uA / 1000, c->max_uA / 1000);
3998 break;
3999 }
4000 }
4001
4002 seq_puts(s, "\n");
4003
4004 list_for_each_entry(consumer, &rdev->consumer_list, list) {
4005 if (consumer->dev->class == &regulator_class)
4006 continue;
4007
4008 seq_printf(s, "%*s%-*s ",
4009 (level + 1) * 3 + 1, "",
4010 30 - (level + 1) * 3, dev_name(consumer->dev));
4011
4012 switch (rdev->desc->type) {
4013 case REGULATOR_VOLTAGE:
4014 seq_printf(s, "%29dmV %5dmV",
4015 consumer->min_uV / 1000,
4016 consumer->max_uV / 1000);
4017 break;
4018 case REGULATOR_CURRENT:
4019 seq_printf(s, "%37dmA",
4020 regulator_get_current_limit(consumer) / 1000);
4021 break;
4022 }
4023
4024 seq_puts(s, "\n");
4025 }
4026
4027 mutex_unlock(&rdev->mutex);
4028
4029 list_for_each_entry(child, list, list) {
4030 /* handle only non-root regulators supplied by current rdev */
4031 if (!child->supply || child->supply->rdev != rdev)
4032 continue;
4033
4034 regulator_summary_show_subtree(s, child, level + 1);
4035 }
4036}
4037
4038static int regulator_summary_show(struct seq_file *s, void *data)
4039{
4040 struct list_head *list = s->private;
4041 struct regulator_dev *rdev;
4042
4043 seq_puts(s, " regulator use open bypass value min max\n");
4044 seq_puts(s, "-----------------------------------------------------------------------\n");
4045
4046 mutex_lock(&regulator_list_mutex);
4047
4048 list_for_each_entry(rdev, list, list) {
4049 if (rdev->supply)
4050 continue;
4051
4052 regulator_summary_show_subtree(s, rdev, 0);
4053 }
4054
4055 mutex_unlock(&regulator_list_mutex);
4056
4057 return 0;
4058}
4059
4060static int regulator_summary_open(struct inode *inode, struct file *file)
4061{
4062 return single_open(file, regulator_summary_show, inode->i_private);
4063}
4064#endif
4065
4066static const struct file_operations regulator_summary_fops = {
4067#ifdef CONFIG_DEBUG_FS
4068 .open = regulator_summary_open,
4069 .read = seq_read,
4070 .llseek = seq_lseek,
4071 .release = single_release,
4072#endif
4073};
4074
3957static int __init regulator_init(void) 4075static int __init regulator_init(void)
3958{ 4076{
3959 int ret; 4077 int ret;
@@ -3967,6 +4085,9 @@ static int __init regulator_init(void)
3967 debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4085 debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
3968 &supply_map_fops); 4086 &supply_map_fops);
3969 4087
4088 debugfs_create_file("regulator_summary", 0444, debugfs_root,
4089 &regulator_list, &regulator_summary_fops);
4090
3970 regulator_dummy_init(); 4091 regulator_dummy_init();
3971 4092
3972 return ret; 4093 return ret;