blob: d70d4802a4d023fa121105fe453b4f31f622955c [file] [log] [blame]
Amit Arora728e0c92010-09-14 12:06:09 +05301/*******************************************************************************
Amit Kucheriac0e17fc2011-01-17 09:35:52 +02002 * Copyright (C) 2010, Linaro Limited.
Amit Arora728e0c92010-09-14 12:06:09 +05303 *
4 * This file is part of PowerDebug.
5 *
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors:
12 * Amit Arora <amit.arora@linaro.org> (IBM Corporation)
13 * - initial API and implementation
14 *******************************************************************************/
15
Daniel Lezcano141c0482011-06-08 23:30:00 +020016#ifndef _GNU_SOURCE
17#define _GNU_SOURCE
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010018#include <stdio.h>
Daniel Lezcano141c0482011-06-08 23:30:00 +020019#undef _GNU_SOURCE
20#endif
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010021#include <mntent.h>
Daniel Lezcanoef323192011-03-26 22:06:20 +010022#include <sys/stat.h>
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010023
Amit Arora728e0c92010-09-14 12:06:09 +053024#include "powerdebug.h"
Amit Aroraed3e5652010-10-27 12:02:53 +053025#include "clocks.h"
Daniel Lezcanoc193b602011-06-08 23:30:00 +020026#include "tree.h"
Amit Arora24ed7d12010-09-14 12:12:58 +053027
Daniel Lezcanoef323192011-03-26 22:06:20 +010028#define MAX_LINES 120
29
Amit Arora24ed7d12010-09-14 12:12:58 +053030static char clk_dir_path[PATH_MAX];
Amit Aroraac4e8652010-11-09 11:16:53 +053031static int bold[MAX_LINES];
Daniel Lezcanoef323192011-03-26 22:06:20 +010032static char clock_lines[MAX_LINES][128];
33static int clock_line_no;
34static int old_clock_line_no;
Amit Arora24ed7d12010-09-14 12:12:58 +053035
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020036struct clock_info {
37 char name[NAME_MAX];
38 int flags;
39 int rate;
40 int usecount;
41 int num_children;
42 int last_child;
43 int expanded;
44 int level;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +020045 char *prefix;
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020046 struct clock_info *parent;
47 struct clock_info **children;
48} *clocks_info;
49
Daniel Lezcano9d5431c2011-06-08 23:30:00 +020050static struct tree *clock_tree = NULL;
Daniel Lezcanoc193b602011-06-08 23:30:00 +020051
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010052static int locate_debugfs(char *clk_path)
53{
54 const char *mtab = "/proc/mounts";
55 struct mntent *mntent;
56 int ret = -1;
57 FILE *file = NULL;
58
59 file = setmntent(mtab, "r");
60 if (!file)
61 return -1;
62
63 while ((mntent = getmntent(file))) {
64
65 if (strcmp(mntent->mnt_type, "debugfs"))
66 continue;
67
68 strcpy(clk_path, mntent->mnt_dir);
69 ret = 0;
70 break;
71 }
72
73 fclose(file);
74 return ret;
75}
76
Daniel Lezcanof0e06652011-03-26 22:06:19 +010077int clock_init(void)
Amit Arora24ed7d12010-09-14 12:12:58 +053078{
Daniel Lezcanof0e06652011-03-26 22:06:19 +010079 if (locate_debugfs(clk_dir_path))
80 return -1;
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010081
Amit Arora6e774cd2010-10-28 11:31:24 +053082 sprintf(clk_dir_path, "%s/clock", clk_dir_path);
Daniel Lezcanoc5a65bf2011-03-26 22:06:11 +010083
Daniel Lezcanoc193b602011-06-08 23:30:00 +020084 clock_tree = tree_load(clk_dir_path, NULL);
85 if (!clock_tree)
86 return -1;
87
Daniel Lezcanof0e06652011-03-26 22:06:19 +010088 return access(clk_dir_path, F_OK);
Amit Arora24ed7d12010-09-14 12:12:58 +053089}
Amit Arora728e0c92010-09-14 12:06:09 +053090
Daniel Lezcano141c0482011-06-08 23:30:00 +020091/*
92 * This functions is a helper to read a specific file content and store
93 * the content inside a variable pointer passed as parameter, the format
94 * parameter gives the variable type to be read from the file.
95 *
96 * @path : directory path containing the file
97 * @name : name of the file to be read
98 * @format : the format of the format
99 * @value : a pointer to a variable to store the content of the file
100 * Returns 0 on success, -1 otherwise
101 */
102int file_read_value(const char *path, const char *name,
103 const char *format, void *value)
104{
105 FILE *file;
106 char *rpath;
107 int ret;
108
109 ret = asprintf(&rpath, "%s/%s", path, name);
110 if (ret < 0)
111 return ret;
112
113 file = fopen(rpath, "r");
114 if (!file) {
115 ret = -1;
116 goto out_free;
117 }
118
119 ret = fscanf(file, format, value) == EOF ? -1 : 0;
120
121 fclose(file);
122out_free:
123 free(rpath);
124 return ret;
125}
126
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200127static int file_read_from_format(const char *file, int *value,
128 const char *format)
Amit Arora728e0c92010-09-14 12:06:09 +0530129{
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100130 FILE *f;
Amit Arora6e774cd2010-10-28 11:31:24 +0530131 int ret;
Amit Arora728e0c92010-09-14 12:06:09 +0530132
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100133 f = fopen(file, "r");
134 if (!f)
135 return -1;
136 ret = fscanf(f, format, value);
137 fclose(f);
Amit Arora728e0c92010-09-14 12:06:09 +0530138
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100139 return !ret ? -1 : 0;
140}
Amit Arora728e0c92010-09-14 12:06:09 +0530141
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200142static inline int file_read_int(const char *file, int *value)
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100143{
144 return file_read_from_format(file, value, "%d");
145}
Amit Arora728e0c92010-09-14 12:06:09 +0530146
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200147static inline int file_read_hex(const char *file, int *value)
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100148{
149 return file_read_from_format(file, value, "%x");
Amit Arora728e0c92010-09-14 12:06:09 +0530150}
151
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200152static inline const char *clock_rate(int *rate)
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100153{
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200154 int r;
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100155
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200156 /* GHZ */
157 r = *rate >> 30;
158 if (r) {
159 *rate = r;
160 return "GHZ";
161 }
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100162
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200163 /* MHZ */
164 r = *rate >> 20;
165 if (r) {
166 *rate = r;
167 return "MHZ";
168 }
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100169
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200170 /* KHZ */
171 r = *rate >> 10;
172 if (r) {
173 *rate = r;
174 return "KHZ";
175 }
176
177 return "";
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100178}
179
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200180static int dump_clock_cb(struct tree *t, void *data)
Daniel Lezcanoef323192011-03-26 22:06:20 +0100181{
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200182 struct clock_info *clk = t->private;
183 struct clock_info *pclk;
184 const char *unit;
185 int ret = 0;
186 int rate = clk->rate;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100187
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200188 if (!t->parent) {
189 printf("/\n");
190 clk->prefix = "";
191 return 0;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100192 }
193
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200194 pclk = t->parent->private;
195
196 if (!clk->prefix)
197 ret = asprintf(&clk->prefix, "%s%s%s", pclk->prefix,
198 t->depth > 1 ? " ": "", t->next ? "|" : " ");
199 if (ret < 0)
200 return -1;
201
202 unit = clock_rate(&rate);
203
204 printf("%s%s-- %s (flags:0x%x, usecount:%d, rate: %d %s)\n",
205 clk->prefix, !t->next ? "`" : "", t->name, clk->flags,
206 clk->usecount, rate, unit);
207
208 return 0;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100209}
210
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200211int dump_clock_info(void)
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100212{
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200213 return tree_for_each(clock_tree, dump_clock_cb, NULL);
214}
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100215
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200216static int dump_all_parents(char *clkarg, bool dump)
217{
218 struct tree *tree;
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100219
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200220 tree = tree_find(clock_tree, clkarg);
221 if (!tree) {
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100222 printf("Clock NOT found!\n");
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200223 return -1;
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100224 }
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200225
226 return tree_for_each_parent(tree, dump_clock_cb, NULL);
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100227}
228
Daniel Lezcano897f7332011-03-26 22:06:06 +0100229void find_parents_for_clock(char *clkname, int complete)
Amit Arora3bd79162010-12-01 13:51:42 +0530230{
231 char name[256];
232
233 name[0] = '\0';
234 if (!complete) {
235 char str[256];
236
237 strcat(name, clkname);
238 sprintf(str, "Enter Clock Name : %s\n", name);
239 print_one_clock(2, str, 1, 0);
240 return;
241 }
242 sprintf(name, "Parents for \"%s\" Clock : \n", clkname);
243 print_one_clock(0, name, 1, 1);
Daniel Lezcano897f7332011-03-26 22:06:06 +0100244 dump_all_parents(clkname, false);
Amit Kucheriaa0adae42011-01-12 10:54:23 -0600245}
Amit Arora3bd79162010-12-01 13:51:42 +0530246
Daniel Lezcanoef323192011-03-26 22:06:20 +0100247static void destroy_clocks_info_recur(struct clock_info *clock)
248{
249 int i;
250
251 if (clock && clock->num_children) {
252 for (i = (clock->num_children - 1); i >= 0; i--) {
253 fflush(stdin);
254 destroy_clocks_info_recur(clock->children[i]);
255 if (!i) {
256 free(clock->children);
257 clock->children = NULL;
258 clock->num_children = 0;
259 }
260 }
261 }
262}
263
264static void destroy_clocks_info(void)
265{
266 int i;
267
268 if (!clocks_info)
269 return;
270
271 if (clocks_info->num_children) {
272 for (i = (clocks_info->num_children - 1); i >= 0 ; i--) {
273 destroy_clocks_info_recur(clocks_info->children[i]);
274 if (!i) {
275 free(clocks_info->children);
276 clocks_info->children = NULL;
277 }
278 }
279 }
280 clocks_info->num_children = 0;
281 free(clocks_info);
282 clocks_info = NULL;
283}
284
285
Amit Arora24ed7d12010-09-14 12:12:58 +0530286int read_and_print_clock_info(int verbose, int hrow, int selected)
287{
Amit Arora3bd79162010-12-01 13:51:42 +0530288 print_one_clock(0, "Reading Clock Tree ...", 1, 1);
Amit Aroraa06a7302010-12-02 15:59:37 +0530289
290 if (!old_clock_line_no || selected == REFRESH_WINDOW) {
291 destroy_clocks_info();
Amit Aroraac4e8652010-11-09 11:16:53 +0530292 read_clock_info(clk_dir_path);
Amit Aroraa06a7302010-12-02 15:59:37 +0530293 }
Amit Arora29cb7572010-10-05 17:40:29 +0530294
Daniel Lezcano95b0dac2011-06-08 23:30:00 +0200295 if (!clocks_info || !clocks_info->num_children) {
Amit Arora031263a2010-11-09 11:12:41 +0530296 fprintf(stderr, "powerdebug: No clocks found. Exiting..\n");
297 exit(1);
Amit Arora6e774cd2010-10-28 11:31:24 +0530298 }
Amit Arora728e0c92010-09-14 12:06:09 +0530299
Amit Aroraa06a7302010-12-02 15:59:37 +0530300 if (selected == CLOCK_SELECTED)
301 selected = 1;
302 else
303 selected = 0;
304
Amit Aroraac4e8652010-11-09 11:16:53 +0530305 print_clock_info(verbose, hrow, selected);
Amit Aroraac4e8652010-11-09 11:16:53 +0530306 hrow = (hrow < old_clock_line_no) ? hrow : old_clock_line_no - 1;
307
308 return hrow;
309}
310
Daniel Lezcanoef323192011-03-26 22:06:20 +0100311static int calc_delta_screen_size(int hrow)
Amit Arora3bc8c922010-11-16 11:27:38 +0530312{
Amit Arora51d1b9c2010-11-30 13:55:15 +0530313 if (hrow >= (maxy - 3))
314 return hrow - (maxy - 4);
Amit Arora3bc8c922010-11-16 11:27:38 +0530315
316 return 0;
317}
318
Daniel Lezcanoef323192011-03-26 22:06:20 +0100319static void prepare_name_str(char *namestr, struct clock_info *clock)
Amit Aroraac4e8652010-11-09 11:16:53 +0530320{
321 int i;
322
323 strcpy(namestr, "");
324 if (clock->level > 1)
325 for (i = 0; i < (clock->level - 1); i++)
326 strcat(namestr, " ");
327 strcat(namestr, clock->name);
328}
329
Daniel Lezcanoef323192011-03-26 22:06:20 +0100330static void collapse_all_subclocks(struct clock_info *clock)
331{
332 int i;
333
334 clock->expanded = 0;
335 if (clock->num_children)
336 for (i = 0; i < clock->num_children; i++)
337 collapse_all_subclocks(clock->children[i]);
338}
339
340static void add_clock_details_recur(struct clock_info *clock,
341 int hrow, int selected)
Amit Arora031263a2010-11-09 11:12:41 +0530342{
343 int i;
344 char *unit = " Hz";
345 char rate_str[64];
Amit Aroraac4e8652010-11-09 11:16:53 +0530346 char name_str[256];
Amit Arora031263a2010-11-09 11:12:41 +0530347 double drate = (double)clock->rate;
348
349 if (drate > 1000 && drate < 1000000) {
350 unit = "KHz";
351 drate /= 1000;
352 }
353 if (drate > 1000000) {
354 unit = "MHz";
355 drate /= 1000000;
356 }
357 if (clock->usecount)
358 bold[clock_line_no] = 1;
359 else
360 bold[clock_line_no] = 0;
361
362 sprintf(rate_str, "%.2f %s", drate, unit);
Amit Aroraac4e8652010-11-09 11:16:53 +0530363 prepare_name_str(name_str, clock);
Daniel Lezcano4b669072011-05-24 15:27:49 +0200364 sprintf(clock_lines[clock_line_no++], "%-55s 0x%-4x %-12s %-12d %-12d",
Amit Aroraac4e8652010-11-09 11:16:53 +0530365 name_str, clock->flags, rate_str, clock->usecount,
366 clock->num_children);
367
368 if (selected && (hrow == (clock_line_no - 1))) {
369 if (clock->expanded)
370 collapse_all_subclocks(clock);
371 else
372 clock->expanded = 1;
373 selected = 0;
374 }
Amit Arora031263a2010-11-09 11:12:41 +0530375
376 if (clock->expanded && clock->num_children)
377 for (i = 0; i < clock->num_children; i++)
Amit Aroraac4e8652010-11-09 11:16:53 +0530378 add_clock_details_recur(clock->children[i],
379 hrow, selected);
Amit Arora031263a2010-11-09 11:12:41 +0530380 strcpy(clock_lines[clock_line_no], "");
381}
382
Daniel Lezcanoef323192011-03-26 22:06:20 +0100383void print_clock_info(int verbose, int hrow, int selected)
Amit Aroraac4e8652010-11-09 11:16:53 +0530384{
Daniel Lezcanoef323192011-03-26 22:06:20 +0100385 int i, count = 0, delta;
Amit Aroraac4e8652010-11-09 11:16:53 +0530386
Daniel Lezcanoef323192011-03-26 22:06:20 +0100387 (void)verbose;
Amit Aroraac4e8652010-11-09 11:16:53 +0530388
Daniel Lezcanoef323192011-03-26 22:06:20 +0100389 print_clock_header();
Amit Arora031263a2010-11-09 11:12:41 +0530390
Daniel Lezcanoef323192011-03-26 22:06:20 +0100391 for (i = 0; i < clocks_info->num_children; i++)
392 add_clock_details_recur(clocks_info->children[i],
393 hrow, selected);
Amit Aroraa06a7302010-12-02 15:59:37 +0530394
Daniel Lezcanoef323192011-03-26 22:06:20 +0100395 delta = calc_delta_screen_size(hrow);
396
397 while (clock_lines[count + delta] &&
398 strcmp(clock_lines[count + delta], "")) {
399 if (count < delta) {
400 count++;
401 continue;
Amit Arora031263a2010-11-09 11:12:41 +0530402 }
Daniel Lezcanoef323192011-03-26 22:06:20 +0100403 print_one_clock(count - delta, clock_lines[count + delta],
404 bold[count + delta], (hrow == (count + delta)));
405 count++;
Amit Arora031263a2010-11-09 11:12:41 +0530406 }
Amit Arora031263a2010-11-09 11:12:41 +0530407
Daniel Lezcanoef323192011-03-26 22:06:20 +0100408 old_clock_line_no = clock_line_no;
409 clock_line_no = 0;
Amit Arora728e0c92010-09-14 12:06:09 +0530410}
Amit Arora0e512722010-10-01 12:24:16 +0530411
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200412static void insert_children(struct clock_info **parent, struct clock_info *clk)
Amit Aroraf4fb8102010-11-30 13:55:50 +0530413{
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200414 if (!(*parent)->num_children || (*parent)->children == NULL) {
415 (*parent)->children = (struct clock_info **)
416 malloc(sizeof(struct clock_info *)*2);
417 (*parent)->num_children = 0;
418 } else
419 (*parent)->children = (struct clock_info **)
420 realloc((*parent)->children,
421 sizeof(struct clock_info *) *
422 ((*parent)->num_children + 2));
423 if ((*parent)->num_children > 0)
424 (*parent)->children[(*parent)->num_children - 1]->last_child
425 = 0;
426 clk->last_child = 1;
427 (*parent)->children[(*parent)->num_children] = clk;
428 (*parent)->children[(*parent)->num_children + 1] = NULL;
429 (*parent)->num_children++;
Amit Aroraf4fb8102010-11-30 13:55:50 +0530430}
431
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200432static struct clock_info *read_clock_info_recur(char *clkpath, int level,
433 struct clock_info *parent)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530434{
Amit Arora6e774cd2010-10-28 11:31:24 +0530435 int ret = 0;
436 DIR *dir;
437 char filename[PATH_MAX];
438 struct dirent *item;
439 struct clock_info *cur = NULL;
440 struct stat buf;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530441
Amit Arora6e774cd2010-10-28 11:31:24 +0530442 dir = opendir(clkpath);
443 if (!dir)
444 return NULL;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530445
Amit Arora6e774cd2010-10-28 11:31:24 +0530446 while ((item = readdir(dir))) {
447 struct clock_info *child;
448 /* skip hidden dirs except ".." */
449 if (item->d_name[0] == '.' )
450 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530451
Amit Arora6e774cd2010-10-28 11:31:24 +0530452 sprintf(filename, "%s/%s", clkpath, item->d_name);
Amit Arora0e512722010-10-01 12:24:16 +0530453
Amit Arora6e774cd2010-10-28 11:31:24 +0530454 ret = stat(filename, &buf);
Amit Arora0e512722010-10-01 12:24:16 +0530455
Amit Arora6e774cd2010-10-28 11:31:24 +0530456 if (ret < 0) {
457 printf("Error doing a stat on %s\n", filename);
458 exit(1);
459 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530460
Amit Arora6e774cd2010-10-28 11:31:24 +0530461 if (S_ISREG(buf.st_mode)) {
462 if (!strcmp(item->d_name, "flags"))
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100463 file_read_hex(filename, &parent->flags);
Amit Arora6e774cd2010-10-28 11:31:24 +0530464 if (!strcmp(item->d_name, "rate"))
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100465 file_read_int(filename, &parent->rate);
Amit Arora6e774cd2010-10-28 11:31:24 +0530466 if (!strcmp(item->d_name, "usecount"))
Daniel Lezcano2d19ae82011-03-26 22:06:09 +0100467 file_read_int(filename, &parent->usecount);
Amit Arora6e774cd2010-10-28 11:31:24 +0530468 continue;
469 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530470
Amit Arora6e774cd2010-10-28 11:31:24 +0530471 if (!S_ISDIR(buf.st_mode))
472 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530473
Amit Arora6e774cd2010-10-28 11:31:24 +0530474 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
475 memset(cur, 0, sizeof(cur));
476 strcpy(cur->name, item->d_name);
477 cur->children = NULL;
478 cur->parent = NULL;
479 cur->num_children = 0;
Amit Arora031263a2010-11-09 11:12:41 +0530480 cur->expanded = 0;
Amit Aroraac4e8652010-11-09 11:16:53 +0530481 cur->level = level;
Amit Arora6e774cd2010-10-28 11:31:24 +0530482 child = read_clock_info_recur(filename, level + 1, cur);
Amit Arora6e774cd2010-10-28 11:31:24 +0530483 insert_children(&parent, cur);
484 cur->parent = parent;
485 }
486 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530487
Amit Arora6e774cd2010-10-28 11:31:24 +0530488 return cur;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530489}
490
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200491static struct clock_info *clock_alloc(const char *name)
492{
493 struct clock_info *ci;
494
495 ci = malloc(sizeof(*ci));
496 if (ci) {
497 memset(ci, 0, sizeof(*ci));
498 strcpy(ci->name, name);
499 }
500
501 return ci;
502}
503
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200504static int fill_clock_cb(struct tree *t, void *data)
505{
506 struct clock_info *clkinfo;
507
508 clkinfo = clock_alloc(t->name);
509 if (!clkinfo)
510 return -1;
511
512 t->private = clkinfo;
513 clkinfo->level = t->depth;
514
515 file_read_value(t->path, "flags", "%x", &clkinfo->flags);
516 file_read_value(t->path, "rate", "%d", &clkinfo->rate);
517 file_read_value(t->path, "usecount", "%d", &clkinfo->usecount);
518
519 return 0;
520}
521
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200522int read_clock_info(char *clkpath)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530523{
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200524 DIR *dir;
525 struct dirent *item;
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200526 char filename[NAME_MAX];
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200527 struct clock_info *child;
528 struct clock_info *cur;
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200529 int ret = -1;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200530
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200531 if (tree_for_each(clock_tree, fill_clock_cb, NULL))
532 return -1;
533
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200534 dir = opendir(clkpath);
535 if (!dir)
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200536 return -1;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200537
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200538 clocks_info = clock_alloc("/");
539 if (!clocks_info)
540 return -1;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200541
542 while ((item = readdir(dir))) {
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200543
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200544 /* skip hidden dirs except ".." */
545 if (item->d_name[0] == '.')
546 continue;
547
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200548 sprintf(filename, "%s/%s", clkpath, item->d_name);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200549
550 cur = clock_alloc(item->d_name);
551 if (!cur)
552 goto out;
553
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200554 cur->parent = clocks_info;
555 cur->num_children = 0;
556 cur->expanded = 0;
557 cur->level = 1;
558 insert_children(&clocks_info, cur);
559 child = read_clock_info_recur(filename, 2, cur);
560 }
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200561
562 ret = 0;
563
564out:
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200565 closedir(dir);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200566
567 return ret;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200568}
569
570void read_and_dump_clock_info_one(char *clk, bool dump)
571{
572 printf("\nParents for \"%s\" Clock :\n\n", clk);
573 read_clock_info(clk_dir_path);
574 dump_all_parents(clk, dump);
575 printf("\n\n");
Amit Aroraeb6cba92010-10-25 16:03:21 +0530576}
577
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200578void read_and_dump_clock_info(int verbose)
579{
580 (void)verbose;
581 printf("\nClock Tree :\n");
582 printf("**********\n");
583 read_clock_info(clk_dir_path);
Daniel Lezcano7801c2d2011-06-08 23:30:00 +0200584 dump_clock_info();
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200585 printf("\n\n");
586}