aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk.c
diff options
context:
space:
mode:
authorPrashant Gaikwad <pgaikwad@nvidia.com>2012-12-26 08:46:23 -0500
committerMike Turquette <mturquette@linaro.org>2013-01-11 22:49:23 -0500
commitbddca8944a7ab6699984c4b1b677261eb1c8d819 (patch)
tree6eb60ceee80c223ea3c29a0ffa044f5ac8cf0b62 /drivers/clk/clk.c
parent1af599df6bdad9ee34ae9e50efcda273e12b9d4f (diff)
clk: JSON debugfs clock tree summary
Clock information is dumped in JSON format which is easy for machines to parse. Each clock is represented as an object which has same name as clock and following properties - enable_count - prepare_count - rate Output is verified using online JSON editor. Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r--drivers/clk/clk.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8622b9de7302..593a2e42d4af 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -96,6 +96,76 @@ static const struct file_operations clk_summary_fops = {
96 .release = single_release, 96 .release = single_release,
97}; 97};
98 98
99static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
100{
101 if (!c)
102 return;
103
104 seq_printf(s, "\"%s\": { ", c->name);
105 seq_printf(s, "\"enable_count\": %d,", c->enable_count);
106 seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
107 seq_printf(s, "\"rate\": %lu", c->rate);
108}
109
110static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
111{
112 struct clk *child;
113 struct hlist_node *tmp;
114
115 if (!c)
116 return;
117
118 clk_dump_one(s, c, level);
119
120 hlist_for_each_entry(child, tmp, &c->children, child_node) {
121 seq_printf(s, ",");
122 clk_dump_subtree(s, child, level + 1);
123 }
124
125 seq_printf(s, "}");
126}
127
128static int clk_dump(struct seq_file *s, void *data)
129{
130 struct clk *c;
131 struct hlist_node *tmp;
132 bool first_node = true;
133
134 seq_printf(s, "{");
135
136 mutex_lock(&prepare_lock);
137
138 hlist_for_each_entry(c, tmp, &clk_root_list, child_node) {
139 if (!first_node)
140 seq_printf(s, ",");
141 first_node = false;
142 clk_dump_subtree(s, c, 0);
143 }
144
145 hlist_for_each_entry(c, tmp, &clk_orphan_list, child_node) {
146 seq_printf(s, ",");
147 clk_dump_subtree(s, c, 0);
148 }
149
150 mutex_unlock(&prepare_lock);
151
152 seq_printf(s, "}");
153 return 0;
154}
155
156
157static int clk_dump_open(struct inode *inode, struct file *file)
158{
159 return single_open(file, clk_dump, inode->i_private);
160}
161
162static const struct file_operations clk_dump_fops = {
163 .open = clk_dump_open,
164 .read = seq_read,
165 .llseek = seq_lseek,
166 .release = single_release,
167};
168
99/* caller must hold prepare_lock */ 169/* caller must hold prepare_lock */
100static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) 170static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
101{ 171{
@@ -241,6 +311,11 @@ static int __init clk_debug_init(void)
241 if (!d) 311 if (!d)
242 return -ENOMEM; 312 return -ENOMEM;
243 313
314 d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL,
315 &clk_dump_fops);
316 if (!d)
317 return -ENOMEM;
318
244 orphandir = debugfs_create_dir("orphans", rootdir); 319 orphandir = debugfs_create_dir("orphans", rootdir);
245 320
246 if (!orphandir) 321 if (!orphandir)