regulator: add a data summary tree in debugfs

A patch from »regulator: add a data summary tree in debugfs« in state Mainline for linux-kernel

From: Heiko Stuebner <heiko@...> Date: Sun, 22 Mar 2015 15:19:46 +0100

Commit-Message

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@...>

Patch-Comment

drivers/regulator/core.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+)

Statistics

  • 113 lines added
  • 0 lines removed

Changes

--------------------------- drivers/regulator/core.c ---------------------------
index a4a8a6d..950fe22 100644
@@ -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 == &regulator_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(&regulator_list_mutex);
+
+ list_for_each_entry(rdev, list, list) {
+ if (rdev->supply)
+ continue;
+
+ regulator_summary_show_subtree(s, rdev, 0);
+ }
+
+ mutex_unlock(&regulator_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,
+ &regulator_list, &regulator_summary_fops);
+
regulator_dummy_init();
return ret;
 
 

Recent Patches

About Us

Sed lacus. Donec lectus. Nullam pretium nibh ut turpis. Nam bibendum. In nulla tortor, elementum vel, tempor at, varius non, purus. Mauris vitae nisl nec metus placerat consectetuer.

Read More...