Messages in this thread Patch in this message | | | From | Heiko Stübner <> | Subject | [PATCH] regulator: add a data summary tree in debugfs | Date | Mon, 06 Apr 2015 02:04:47 +0200 |
| |
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
Signed-off-by: Heiko Stuebner <heiko@sntech.de> --- drivers/regulator/core.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a4a8a6d..950fe22 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3936,6 +3936,116 @@ static const struct file_operations supply_map_fops = { #endif }; +#ifdef CONFIG_DEBUG_FS +static void regulator_summary_show_subtree(struct seq_file *s, + struct regulator_dev *rdev, + int level) +{ + struct list_head *list = s->private; + struct regulator_dev *child; + struct regulation_constraints *c; + struct regulator *consumer; + + if (!rdev) + return; + + mutex_lock(&rdev->mutex); + + seq_printf(s, "%*s%-*s %3d,%4d,%6d ", + level * 3 + 1, "", + 30 - level * 3, rdev_get_name(rdev), + rdev->use_count, rdev->open_count, rdev->bypass_count); + + switch (rdev->desc->type) { + case REGULATOR_VOLTAGE: + seq_printf(s, "%8dmV ", + _regulator_get_voltage(rdev) / 1000); + break; + case REGULATOR_CURRENT: + seq_printf(s, "%8dmA ", + _regulator_get_current_limit(rdev) / 1000); + break; + } + + c = rdev->constraints; + if (c) { + switch (rdev->desc->type) { + case REGULATOR_VOLTAGE: + seq_printf(s, "%8dmV %8dmV ", + c->min_uV / 1000, c->max_uV / 1000); + break; + case REGULATOR_CURRENT: + seq_printf(s, "%8dmA %8dmA ", + c->min_uA / 1000, c->max_uA / 1000); + break; + } + } + + seq_puts(s, "\n"); + + list_for_each_entry(consumer, &rdev->consumer_list, list) { + if (consumer->dev->class == ®ulator_class) + continue; + + seq_printf(s, "%*s%-*s ", + (level + 1) * 3 + 1, "", + 30 - (level + 1) * 3, dev_name(consumer->dev)); + + if (rdev->desc->type == REGULATOR_VOLTAGE) + seq_printf(s, "%35dmV %8dmV", + consumer->min_uV / 1000, + consumer->max_uV / 1000); + + seq_puts(s, "\n"); + } + + mutex_unlock(&rdev->mutex); + + list_for_each_entry(child, list, list) { + if (!child->supply || child->supply->rdev != rdev) + continue; + + regulator_summary_show_subtree(s, child, level + 1); + } +} + +static int regulator_summary_show(struct seq_file *s, void *data) +{ + struct list_head *list = s->private; + struct regulator_dev *rdev; + + seq_puts(s, " regulator use,open,bypass value min max\n"); + seq_puts(s, "--------------------------------------------------------------------------------\n"); + + mutex_lock(®ulator_list_mutex); + + list_for_each_entry(rdev, list, list) { + if (rdev->supply) + continue; + + regulator_summary_show_subtree(s, rdev, 0); + } + + mutex_unlock(®ulator_list_mutex); + + return 0; +} + +static int regulator_summary_open(struct inode *inode, struct file *file) +{ + return single_open(file, regulator_summary_show, inode->i_private); +} +#endif + +static const struct file_operations regulator_summary_fops = { +#ifdef CONFIG_DEBUG_FS + .open = regulator_summary_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +#endif +}; + static int __init regulator_init(void) { int ret; @@ -3949,6 +4059,9 @@ static int __init regulator_init(void) debugfs_create_file("supply_map", 0444, debugfs_root, NULL, &supply_map_fops); + debugfs_create_file("regulator_summary", 0444, debugfs_root, + ®ulator_list, ®ulator_summary_fops); + regulator_dummy_init(); return ret; -- 2.1.4
| |