blob: 4b2a11cb9857d1dbe0ad608cab46c23b727e1850 [file] [log] [blame]
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00001/*
2 * Power debug tool (powerdebug)
Amit Arora728e0c92010-09-14 12:06:09 +05303 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00004 * Copyright (C) 2016, Linaro Limited.
Amit Arora728e0c92010-09-14 12:06:09 +05305 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00006 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
Amit Arora728e0c92010-09-14 12:06:09 +053010 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +000011 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020015 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +000016 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020019 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +000020 */
Amit Arora728e0c92010-09-14 12:06:09 +053021
Daniel Lezcano141c0482011-06-08 23:30:00 +020022#ifndef _GNU_SOURCE
23#define _GNU_SOURCE
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010024#include <stdio.h>
Daniel Lezcano141c0482011-06-08 23:30:00 +020025#undef _GNU_SOURCE
26#endif
Daniel Lezcano15627482011-06-15 15:45:12 +020027#include <string.h>
28#include <stdbool.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <sys/param.h>
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010032#include <mntent.h>
Daniel Lezcanoef323192011-03-26 22:06:20 +010033#include <sys/stat.h>
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010034
Amit Arora728e0c92010-09-14 12:06:09 +053035#include "powerdebug.h"
Daniel Lezcanob301b082011-06-15 15:45:12 +020036#include "display.h"
Daniel Lezcanoc193b602011-06-08 23:30:00 +020037#include "tree.h"
Daniel Lezcano88b38e32011-06-15 15:45:12 +020038#include "utils.h"
Amit Arora24ed7d12010-09-14 12:12:58 +053039
Shaojie Sun73e5d972013-08-21 17:04:34 +080040#ifndef uint
41#define uint unsigned int
42#endif
43
44
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020045struct clock_info {
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020046 int flags;
Shaojie Sun73e5d972013-08-21 17:04:34 +080047 uint rate;
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020048 int usecount;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020049 bool expanded;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +020050 char *prefix;
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +053051 int preparecount;
52 int enablecount;
53 int notifiercount;
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020054} *clocks_info;
55
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +053056enum clock_fw_type{
57 CCF, /* common clock framework */
58 OCF, /* old clock framework */
59 MAX,
60};
61
Daniel Lezcano9d5431c2011-06-08 23:30:00 +020062static struct tree *clock_tree = NULL;
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +053063static int clock_fw;
Daniel Lezcanoc193b602011-06-08 23:30:00 +020064
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010065static int locate_debugfs(char *clk_path)
66{
Nishanth Menona14971b2011-09-20 11:31:17 +020067 strcpy(clk_path, "/sys/kernel/debug");
68 return 0;
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010069}
70
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020071static struct clock_info *clock_alloc(void)
Amit Arora24ed7d12010-09-14 12:12:58 +053072{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020073 struct clock_info *ci;
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010074
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020075 ci = malloc(sizeof(*ci));
76 if (ci)
77 memset(ci, 0, sizeof(*ci));
Daniel Lezcanoc5a65bf2011-03-26 22:06:11 +010078
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020079 return ci;
Amit Arora24ed7d12010-09-14 12:12:58 +053080}
Amit Arora728e0c92010-09-14 12:06:09 +053081
Shaojie Sun2489bc72013-08-21 17:27:33 +080082static inline bool is_hex_clock(uint rate)
83{
84 return rate%10;
85}
86
Shaojie Sun73e5d972013-08-21 17:04:34 +080087static inline const char *clock_rate(uint *rate)
Daniel Lezcanoc6718332011-03-23 14:37:39 +010088{
Shaojie Sun2489bc72013-08-21 17:27:33 +080089 uint r, mod;
90 bool is_hex = is_hex_clock(*rate);
Daniel Lezcanoc6718332011-03-23 14:37:39 +010091
Daniel Lezcanoafe62252011-06-08 23:30:00 +020092 /* GHZ */
Shaojie Sun2489bc72013-08-21 17:27:33 +080093 if (is_hex) {
94 r = *rate >> 30;
95 mod = *rate&((1<<30)-1);
96 } else {
97 r = *rate / 1000000000;
98 mod = *rate % 1000000000;
99 }
100 if (r && !mod) {
101 *rate = r;
102 return "GHZ";
103 }
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100104
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200105 /* MHZ */
Shaojie Sun2489bc72013-08-21 17:27:33 +0800106 if (is_hex) {
107 r = *rate >> 20;
108 mod = *rate&((1<<20)-1);
109 } else {
110 r = *rate / 1000000;
111 mod = *rate % 1000000;
112 }
113 if (r && !mod) {
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200114 *rate = r;
115 return "MHZ";
116 }
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100117
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200118 /* KHZ */
Shaojie Sun2489bc72013-08-21 17:27:33 +0800119 if (is_hex) {
120 r = *rate >> 10;
121 mod = *rate&((1<<10)-1);
122 } else {
123 r = *rate / 1000;
124 mod = *rate % 1000;
125 }
126 if (r && !mod) {
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200127 *rate = r;
128 return "KHZ";
129 }
130
131 return "";
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100132}
133
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200134static int dump_clock_cb(struct tree *t, void *data)
Daniel Lezcanoef323192011-03-26 22:06:20 +0100135{
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200136 struct clock_info *clk = t->private;
137 struct clock_info *pclk;
138 const char *unit;
139 int ret = 0;
Shaojie Sun73e5d972013-08-21 17:04:34 +0800140 uint rate = clk->rate;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100141
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200142 if (!t->parent) {
143 printf("/\n");
144 clk->prefix = "";
145 return 0;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100146 }
147
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200148 pclk = t->parent->private;
149
150 if (!clk->prefix)
151 ret = asprintf(&clk->prefix, "%s%s%s", pclk->prefix,
152 t->depth > 1 ? " ": "", t->next ? "|" : " ");
153 if (ret < 0)
154 return -1;
155
156 unit = clock_rate(&rate);
157
Shaojie Sun73e5d972013-08-21 17:04:34 +0800158 printf("%s%s-- %s (flags:0x%x, usecount:%d, rate: %u %s)\n",
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200159 clk->prefix, !t->next ? "`" : "", t->name, clk->flags,
160 clk->usecount, rate, unit);
161
162 return 0;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100163}
164
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200165int dump_clock_info(void)
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100166{
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200167 return tree_for_each(clock_tree, dump_clock_cb, NULL);
168}
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100169
Daniel Lezcano3e38e0f2011-06-08 23:30:00 +0200170static int dump_all_parents(char *clkarg)
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200171{
172 struct tree *tree;
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100173
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200174 tree = tree_find(clock_tree, clkarg);
175 if (!tree) {
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100176 printf("Clock NOT found!\n");
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200177 return -1;
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100178 }
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200179
180 return tree_for_each_parent(tree, dump_clock_cb, NULL);
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100181}
182
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200183static inline int read_clock_cb(struct tree *t, void *data)
Daniel Lezcanoef323192011-03-26 22:06:20 +0100184{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200185 struct clock_info *clk = t->private;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100186
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530187 if(clock_fw == CCF) {
188 file_read_value(t->path, "clk_flags", "%x", &clk->flags);
Shaojie Sun73e5d972013-08-21 17:04:34 +0800189 file_read_value(t->path, "clk_rate", "%u", &clk->rate);
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530190 file_read_value(t->path, "clk_prepare_count", "%d", &clk->preparecount);
191 file_read_value(t->path, "clk_enable_count", "%d", &clk->enablecount);
192 file_read_value(t->path, "clk_notifier_count", "%d", &clk->notifiercount);
193 }
194 else {
195 file_read_value(t->path, "flags", "%x", &clk->flags);
Shaojie Sun73e5d972013-08-21 17:04:34 +0800196 file_read_value(t->path, "rate", "%u", &clk->rate);
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530197 file_read_value(t->path, "usecount", "%d", &clk->usecount);
198 }
Amit Arora3bc8c922010-11-16 11:27:38 +0530199
200 return 0;
201}
202
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200203static int read_clock_info(struct tree *tree)
Amit Aroraac4e8652010-11-09 11:16:53 +0530204{
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200205 return tree_for_each(tree, read_clock_cb, NULL);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200206}
207
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200208static int fill_clock_cb(struct tree *t, void *data)
209{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200210 struct clock_info *clk;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200211
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200212 clk = clock_alloc();
213 if (!clk)
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200214 return -1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200215 t->private = clk;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200216
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200217 /* we skip the root node but we set it expanded for its children */
218 if (!t->parent) {
219 clk->expanded = true;
220 return 0;
221 }
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200222
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200223 return read_clock_cb(t, data);
224}
225
226static int fill_clock_tree(void)
227{
228 return tree_for_each(clock_tree, fill_clock_cb, NULL);
229}
230
231static int is_collapsed(struct tree *t, void *data)
232{
233 struct clock_info *clk = t->private;
234
235 if (!clk->expanded)
236 return 1;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200237
238 return 0;
239}
240
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200241static char *clock_line(struct tree *t)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530242{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200243 struct clock_info *clk;
Shaojie Sun73e5d972013-08-21 17:04:34 +0800244 uint rate;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200245 const char *clkunit;
246 char *clkrate, *clkname, *clkline = NULL;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200247
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200248 clk = t->private;
249 rate = clk->rate;
250 clkunit = clock_rate(&rate);
251
252 if (asprintf(&clkname, "%*s%s", (t->depth - 1) * 2, "", t->name) < 0)
253 return NULL;
254
255 if (asprintf(&clkrate, "%d%s", rate, clkunit) < 0)
256 goto free_clkname;
257
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530258 if(clock_fw == CCF) {
259 if (asprintf(&clkline, "%-35s 0x%-8x %-12s %-10d %-11d %-15d %-14d %-10d",
260 clkname, clk->flags, clkrate, clk->usecount, t->nrchild,
261 clk->preparecount, clk->enablecount, clk->notifiercount) < 0)
262 goto free_clkrate;
263 }
264 else {
265 if (asprintf(&clkline, "%-55s 0x%-16x %-12s %-9d %-8d",
266 clkname, clk->flags, clkrate, clk->usecount, t->nrchild) < 0)
267 goto free_clkrate;
268 }
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200269
270free_clkrate:
271 free(clkrate);
272free_clkname:
273 free(clkname);
274
275 return clkline;
276}
277
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200278static int _clock_print_info_cb(struct tree *t, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200279{
280 struct clock_info *clock = t->private;
281 int *line = data;
282 char *buffer;
283
Daniel Lezcano73b40022011-06-21 00:57:08 +0200284 /* we skip the root node of the tree */
285 if (!t->parent)
286 return 0;
287
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200288 buffer = clock_line(t);
289 if (!buffer)
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200290 return -1;
291
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200292 display_print_line(CLOCK, *line, buffer, clock->usecount, t);
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200293
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200294 (*line)++;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200295
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200296 free(buffer);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200297
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200298 return 0;
299}
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200300
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200301static int clock_print_info_cb(struct tree *t, void *data)
302{
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200303 /* we skip the root node of the tree */
304 if (!t->parent)
305 return 0;
306
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200307 /* show the clock when *all* its parent is expanded */
308 if (tree_for_each_parent(t->parent, is_collapsed, NULL))
309 return 0;
310
311 return _clock_print_info_cb(t, data);
312}
313
Daniel Lezcanofa453332011-06-21 00:57:08 +0200314static int clock_print_header(void)
315{
316 char *buf;
317 int ret;
318
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530319 if(clock_fw == CCF) {
320 if (asprintf(&buf, "%-35s %-10s %-12s %-10s %-11s %-15s %-14s %-14s",
321 "Name", "Flags", "Rate", "Usecount", "Children", "Prepare_Count",
322 "Enable_Count", "Notifier_Count") < 0)
323 return -1;
324 }
325 else {
326 if (asprintf(&buf, "%-55s %-16s %-12s %-9s %-8s",
Daniel Lezcanofa453332011-06-21 00:57:08 +0200327 "Name", "Flags", "Rate", "Usecount", "Children") < 0)
328 return -1;
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530329 }
Daniel Lezcanofa453332011-06-21 00:57:08 +0200330
Daniel Lezcano372ffba2011-06-21 00:57:08 +0200331 ret = display_column_name(buf);
Daniel Lezcanofa453332011-06-21 00:57:08 +0200332
333 free(buf);
334
335 return ret;
336}
337
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200338static int clock_print_info(struct tree *tree)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200339{
340 int ret, line = 0;
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200341
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200342 display_reset_cursor(CLOCK);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200343
Daniel Lezcanofa453332011-06-21 00:57:08 +0200344 clock_print_header();
345
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200346 ret = tree_for_each(tree, clock_print_info_cb, &line);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200347
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200348 display_refresh_pad(CLOCK);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200349
350 return ret;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200351}
352
Daniel Lezcano73b40022011-06-21 00:57:08 +0200353static int clock_select(void)
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200354{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200355 struct tree *t = display_get_row_data(CLOCK);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200356 struct clock_info *clk = t->private;
357
358 clk->expanded = !clk->expanded;
359
360 return 0;
361}
362
Daniel Lezcanod42d7ad2016-02-22 15:02:57 +0100363static int clock_info_load(void)
364{
365 char clk_dir_path[MAX+1][PATH_MAX];
366
367 if (clock_tree)
368 return 0;
369
370 if (locate_debugfs(clk_dir_path[CCF]) || locate_debugfs(clk_dir_path[OCF]))
371 return -1;
372
373 sprintf(clk_dir_path[CCF], "%s/clk", clk_dir_path[CCF]);
374 sprintf(clk_dir_path[OCF], "%s/clock", clk_dir_path[OCF]);
375 if (!access(clk_dir_path[CCF], F_OK)) {
376 clock_fw = CCF;
377 strcpy(clk_dir_path[MAX],clk_dir_path[CCF]);
378 }
379 else if(!access(clk_dir_path[OCF], F_OK)) {
380 clock_fw = OCF;
381 strcpy(clk_dir_path[MAX],clk_dir_path[OCF]);
382 }
383 else
384 return -1;
385
386 clock_tree = tree_load(clk_dir_path[MAX], NULL, false);
387 if (!clock_tree)
388 return -1;
389
390 if (fill_clock_tree())
391 return -1;
392
393 return 0;
394}
395
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200396/*
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200397 * Read the clock information and fill the tree with the information
398 * found in the files. Then print the result to the text based interface
399 * Return 0 on success, < 0 otherwise
400 */
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200401static int clock_display(bool refresh)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200402{
Daniel Lezcanod42d7ad2016-02-22 15:02:57 +0100403 if (clock_info_load()) {
404 display_print_error(CLOCK, 0, "Failed to read clock info");
405 return 0; /* we don't want this to be a critical error */
406 }
407
408
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200409 if (refresh && read_clock_info(clock_tree))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200410 return -1;
411
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200412 return clock_print_info(clock_tree);
413}
414
Daniel Lezcano73b40022011-06-21 00:57:08 +0200415static int clock_find(const char *name)
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200416{
417 struct tree **ptree = NULL;
418 int i, nr, line = 0, ret = 0;
419
420 nr = tree_finds(clock_tree, name, &ptree);
421
422 display_reset_cursor(CLOCK);
423
424 for (i = 0; i < nr; i++) {
425
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200426 ret = _clock_print_info_cb(ptree[i], &line);
427 if (ret)
428 break;
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200429
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200430 }
431
432 display_refresh_pad(CLOCK);
433
434 free(ptree);
435
436 return ret;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200437}
438
Daniel Lezcano73b40022011-06-21 00:57:08 +0200439static int clock_selectf(void)
440{
441 struct tree *t = display_get_row_data(CLOCK);
442 int line = 0;
443
444 display_reset_cursor(CLOCK);
445
446 if (tree_for_each_parent(t, _clock_print_info_cb, &line))
447 return -1;
448
449 return display_refresh_pad(CLOCK);
450}
451
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200452/*
453 * Read the clock information and fill the tree with the information
454 * found in the files. Then dump to stdout a formatted result.
455 * @clk : a name for a specific clock we want to show
456 * Return 0 on success, < 0 otherwise
457 */
Daniel Lezcano597892a2011-06-15 15:45:12 +0200458int clock_dump(char *clk)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200459{
460 int ret;
461
Thara Gopinathd78818c2017-07-14 13:15:45 -0400462 if (!clock_tree) {
463 if (clock_info_load())
464 return -1;
465 } else {
466 if (read_clock_info(clock_tree))
467 return -1;
468 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530469
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200470 if (clk) {
471 printf("\nParents for \"%s\" Clock :\n\n", clk);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200472 ret = dump_all_parents(clk);
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200473 printf("\n\n");
474 } else {
475 printf("\nClock Tree :\n");
476 printf("**********\n");
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200477 ret = dump_clock_info();
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200478 printf("\n\n");
479 }
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200480
481 return ret;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200482}
Daniel Lezcanob301b082011-06-15 15:45:12 +0200483
484static struct display_ops clock_ops = {
485 .display = clock_display,
Daniel Lezcano73b40022011-06-21 00:57:08 +0200486 .select = clock_select,
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200487 .find = clock_find,
Daniel Lezcano73b40022011-06-21 00:57:08 +0200488 .selectf = clock_selectf,
Daniel Lezcanob301b082011-06-15 15:45:12 +0200489};
490
491/*
492 * Initialize the clock framework
493 */
Daniel Lezcanob4eec7e2016-02-18 16:44:55 +0000494int clock_init(struct powerdebug_options *options)
Daniel Lezcanob301b082011-06-15 15:45:12 +0200495{
Daniel Lezcanob4eec7e2016-02-18 16:44:55 +0000496 if (!(options->flags & CLOCK_OPTION))
497 return 0;
498
Daniel Lezcanocaafece2011-06-27 22:59:17 +0200499 return display_register(CLOCK, &clock_ops);
Daniel Lezcanob301b082011-06-15 15:45:12 +0200500}