blob: 5cdc8d5a997ec22fd0a8bd67e1b31b3bcfadfb8c [file] [log] [blame]
Amit Arora728e0c92010-09-14 12:06:09 +05301/*******************************************************************************
2 * Copyright (C) 2010, Linaro
3 * Copyright (C) 2010, IBM Corporation
4 *
5 * This file is part of PowerDebug.
6 *
7 * All rights reserved. This program and the accompanying materials
8 * are made available under the terms of the Eclipse Public License v1.0
9 * which accompanies this distribution, and is available at
10 * http://www.eclipse.org/legal/epl-v10.html
11 *
12 * Contributors:
13 * Amit Arora <amit.arora@linaro.org> (IBM Corporation)
14 * - initial API and implementation
15 *******************************************************************************/
16
17#include "powerdebug.h"
Amit Aroraed3e5652010-10-27 12:02:53 +053018#include "clocks.h"
Amit Arora24ed7d12010-09-14 12:12:58 +053019
Amit Arora24ed7d12010-09-14 12:12:58 +053020static char clk_dir_path[PATH_MAX];
Amit Arora24ed7d12010-09-14 12:12:58 +053021static char clk_name[NAME_MAX];
Amit Aroraac4e8652010-11-09 11:16:53 +053022static int bold[MAX_LINES];
Amit Arora24ed7d12010-09-14 12:12:58 +053023
Amit Arora04f97742010-11-16 11:28:57 +053024int init_clock_details(void)
Amit Arora24ed7d12010-09-14 12:12:58 +053025{
Amit Arora6e774cd2010-10-28 11:31:24 +053026 char *path = debugfs_locate_mpoint();
27 struct stat buf;
Amit Aroraed3e5652010-10-27 12:02:53 +053028
Amit Arora6e774cd2010-10-28 11:31:24 +053029 if (path)
30 strcpy(clk_dir_path, path);
31 else {
Amit Arora81350772010-11-16 14:56:26 +053032 if (!dump) {
33 create_selectedwindow();
34 sprintf(clock_lines[0], "Unable to locate debugfs "
35 "mount point. Mount debugfs "
36 "and try again..\n");
37 print_one_clock(0, clock_lines[0], 1, 0);
38 old_clock_line_no = 1;
39 return(1);
40 } else {
41 fprintf(stderr, "powerdebug: Unable to locate debugfs "
42 "mount point. Mount debugfs and try "
43 "again..\n");
44 exit(1);
45 }
Amit Arora6e774cd2010-10-28 11:31:24 +053046 }
47 sprintf(clk_dir_path, "%s/clock", clk_dir_path);
Amit Arora59429a42010-11-16 11:30:20 +053048 //strcpy(clk_dir_path, "/debug/clock"); // Hardcoded for testing..
Amit Arora6e774cd2010-10-28 11:31:24 +053049 if (stat(clk_dir_path, &buf)) {
Amit Arora81350772010-11-16 14:56:26 +053050 if (!dump) {
51 create_selectedwindow();
52 sprintf(clock_lines[0], "Unable to find clock tree"
53 " information at %s.\n", clk_dir_path);
54 print_one_clock(0, clock_lines[0], 1, 0);
55 old_clock_line_no = 1;
56 return(1);
57 } else {
58 fprintf(stderr, "powerdebug: Unable to find clock tree"
59 " information at %s.\n", clk_dir_path);
60 exit(1);
61 }
Amit Arora6e774cd2010-10-28 11:31:24 +053062 }
63 strcpy(clk_name, "");
Amit Arora04f97742010-11-16 11:28:57 +053064 return(0);
Amit Arora24ed7d12010-09-14 12:12:58 +053065}
Amit Arora728e0c92010-09-14 12:06:09 +053066
67int get_int_from(char *file)
68{
Amit Arora6e774cd2010-10-28 11:31:24 +053069 FILE *filep;
70 char result[NAME_MAX];
71 int ret;
Amit Arora728e0c92010-09-14 12:06:09 +053072
Amit Arora6e774cd2010-10-28 11:31:24 +053073 filep = fopen(file, "r");
Amit Arora728e0c92010-09-14 12:06:09 +053074
Amit Arora6e774cd2010-10-28 11:31:24 +053075 if (!filep)
76 return -1; //TBD : What should we return on failure, here ?
Amit Arora728e0c92010-09-14 12:06:09 +053077
Amit Arora6e774cd2010-10-28 11:31:24 +053078 ret = fscanf(filep, "%s", result);
79 fclose(filep);
Amit Arora728e0c92010-09-14 12:06:09 +053080
Amit Arora6e774cd2010-10-28 11:31:24 +053081 return atoi(result);
Amit Arora728e0c92010-09-14 12:06:09 +053082}
83
Amit Arora24ed7d12010-09-14 12:12:58 +053084int read_and_print_clock_info(int verbose, int hrow, int selected)
85{
Amit Aroraac4e8652010-11-09 11:16:53 +053086 if (!old_clock_line_no)
87 read_clock_info(clk_dir_path);
Amit Arora29cb7572010-10-05 17:40:29 +053088
Amit Arora031263a2010-11-09 11:12:41 +053089 if (!clocks_info->num_children) {
90 fprintf(stderr, "powerdebug: No clocks found. Exiting..\n");
91 exit(1);
Amit Arora6e774cd2010-10-28 11:31:24 +053092 }
Amit Arora728e0c92010-09-14 12:06:09 +053093
Amit Aroraac4e8652010-11-09 11:16:53 +053094 print_clock_info(verbose, hrow, selected);
95 //destroy_clocks_info();
96 hrow = (hrow < old_clock_line_no) ? hrow : old_clock_line_no - 1;
97
98 return hrow;
99}
100
Amit Arora3bc8c922010-11-16 11:27:38 +0530101int calc_delta_screen_size(int hrow)
102{
Amit Arora51d1b9c2010-11-30 13:55:15 +0530103 if (hrow >= (maxy - 3))
104 return hrow - (maxy - 4);
Amit Arora3bc8c922010-11-16 11:27:38 +0530105
106 return 0;
107}
108
Amit Aroraac4e8652010-11-09 11:16:53 +0530109void print_clock_info(int verbose, int hrow, int selected)
110{
Amit Arora3bc8c922010-11-16 11:27:38 +0530111 int i, count = 0, delta;
Amit Aroraac4e8652010-11-09 11:16:53 +0530112
113 (void)verbose;
114
115 print_clock_header();
Amit Arora728e0c92010-09-14 12:06:09 +0530116
Amit Arora031263a2010-11-09 11:12:41 +0530117 for (i = 0; i < clocks_info->num_children; i++)
Amit Aroraac4e8652010-11-09 11:16:53 +0530118 add_clock_details_recur(clocks_info->children[i],
119 hrow, selected);
Amit Arora031263a2010-11-09 11:12:41 +0530120
Amit Arora3bc8c922010-11-16 11:27:38 +0530121 delta = calc_delta_screen_size(hrow);
122
123 while (clock_lines[count + delta] &&
124 strcmp(clock_lines[count + delta], "")) {
125 if (count < delta) {
126 count++;
127 continue;
128 }
129 print_one_clock(count - delta, clock_lines[count + delta],
130 bold[count + delta], (hrow == (count + delta)));
Amit Arora031263a2010-11-09 11:12:41 +0530131 count++;
132 }
133
Amit Aroraac4e8652010-11-09 11:16:53 +0530134 old_clock_line_no = clock_line_no;
Amit Arora031263a2010-11-09 11:12:41 +0530135 clock_line_no = 0;
Amit Arora031263a2010-11-09 11:12:41 +0530136}
137
Amit Aroraac4e8652010-11-09 11:16:53 +0530138void prepare_name_str(char *namestr, struct clock_info *clock)
139{
140 int i;
141
142 strcpy(namestr, "");
143 if (clock->level > 1)
144 for (i = 0; i < (clock->level - 1); i++)
145 strcat(namestr, " ");
146 strcat(namestr, clock->name);
147}
148
149void add_clock_details_recur(struct clock_info *clock, int hrow, int selected)
Amit Arora031263a2010-11-09 11:12:41 +0530150{
151 int i;
152 char *unit = " Hz";
153 char rate_str[64];
Amit Aroraac4e8652010-11-09 11:16:53 +0530154 char name_str[256];
Amit Arora031263a2010-11-09 11:12:41 +0530155 double drate = (double)clock->rate;
156
157 if (drate > 1000 && drate < 1000000) {
158 unit = "KHz";
159 drate /= 1000;
160 }
161 if (drate > 1000000) {
162 unit = "MHz";
163 drate /= 1000000;
164 }
165 if (clock->usecount)
166 bold[clock_line_no] = 1;
167 else
168 bold[clock_line_no] = 0;
169
170 sprintf(rate_str, "%.2f %s", drate, unit);
Amit Aroraac4e8652010-11-09 11:16:53 +0530171 prepare_name_str(name_str, clock);
172 sprintf(clock_lines[clock_line_no++], "%-55s %-4d %-12s %-12d %-12d",
173 name_str, clock->flags, rate_str, clock->usecount,
174 clock->num_children);
175
176 if (selected && (hrow == (clock_line_no - 1))) {
177 if (clock->expanded)
178 collapse_all_subclocks(clock);
179 else
180 clock->expanded = 1;
181 selected = 0;
182 }
Amit Arora031263a2010-11-09 11:12:41 +0530183
184 if (clock->expanded && clock->num_children)
185 for (i = 0; i < clock->num_children; i++)
Amit Aroraac4e8652010-11-09 11:16:53 +0530186 add_clock_details_recur(clock->children[i],
187 hrow, selected);
Amit Arora031263a2010-11-09 11:12:41 +0530188 strcpy(clock_lines[clock_line_no], "");
189}
190
Amit Aroraac4e8652010-11-09 11:16:53 +0530191void collapse_all_subclocks(struct clock_info *clock)
192{
193 int i;
194
195 clock->expanded = 0;
196 if (clock->num_children)
197 for (i = 0; i < clock->num_children; i++)
198 collapse_all_subclocks(clock->children[i]);
199}
200
Amit Arora031263a2010-11-09 11:12:41 +0530201void destroy_clocks_info(void)
202{
203 int i;
204
205 if (clocks_info->num_children) {
206 for (i = (clocks_info->num_children - 1); i >= 0 ; i--) {
207 destroy_clocks_info_recur(clocks_info->children[i]);
208 if (!i) {
209 free(clocks_info->children);
210 clocks_info->children = NULL;
211 }
212 }
213 }
214 free(clocks_info);
215 clocks_info = NULL;
216}
217
218void destroy_clocks_info_recur(struct clock_info *clock)
219{
220 int i;
221
222 if (clock && clock->num_children) {
223 for (i = (clock->num_children - 1); i >= 0; i--) {
224 fflush(stdin);
225 destroy_clocks_info_recur(clock->children[i]);
226 if (!i) {
Amit Arora031263a2010-11-09 11:12:41 +0530227 free(clock->children);
228 clock->children = NULL;
229 clock->num_children = 0;
230 }
231 }
232 }
Amit Arora728e0c92010-09-14 12:06:09 +0530233}
Amit Arora0e512722010-10-01 12:24:16 +0530234
Amit Aroraf4fb8102010-11-30 13:55:50 +0530235void read_and_dump_clock_info_one(char *clk)
236{
237 printf("Clock Tree : (clock name = %s)\n", clk);
238 printf("**********\n");
239 read_clock_info(clk_dir_path);
240 dump_all_parents(clk);
241}
242
Amit Aroraac4e8652010-11-09 11:16:53 +0530243void read_and_dump_clock_info(int verbose)
Amit Arora0e512722010-10-01 12:24:16 +0530244{
Amit Arora6e774cd2010-10-28 11:31:24 +0530245 (void)verbose;
246 printf("Clock Tree :\n");
247 printf("**********\n");
248 read_clock_info(clk_dir_path);
Amit Aroraac4e8652010-11-09 11:16:53 +0530249 dump_clock_info(clocks_info, 1, 1);
Amit Arora0e512722010-10-01 12:24:16 +0530250}
251
Amit Aroraeb6cba92010-10-25 16:03:21 +0530252void read_clock_info(char *clkpath)
Amit Arora0e512722010-10-01 12:24:16 +0530253{
Amit Arora6e774cd2010-10-28 11:31:24 +0530254 DIR *dir;
255 struct dirent *item;
256 char filename[NAME_MAX], clockname[NAME_MAX];
257 struct clock_info *child;
258 struct clock_info *cur;
Amit Arora0e512722010-10-01 12:24:16 +0530259
Amit Arora6e774cd2010-10-28 11:31:24 +0530260 dir = opendir(clkpath);
261 if (!dir)
262 return;
Amit Arora0e512722010-10-01 12:24:16 +0530263
Amit Arora6e774cd2010-10-28 11:31:24 +0530264 clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info));
265 memset(clocks_info, 0, sizeof(clocks_info));
266 strcpy(clocks_info->name, "/");
Amit Aroraac4e8652010-11-09 11:16:53 +0530267 clocks_info->level = 0;
Amit Arora0e512722010-10-01 12:24:16 +0530268
Amit Arora6e774cd2010-10-28 11:31:24 +0530269 while ((item = readdir(dir))) {
270 /* skip hidden dirs except ".." */
271 if (item->d_name[0] == '.')
272 continue;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530273
Amit Arora6e774cd2010-10-28 11:31:24 +0530274 strcpy(clockname, item->d_name);
275 sprintf(filename, "%s/%s", clkpath, item->d_name);
276 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
Amit Aroraac4e8652010-11-09 11:16:53 +0530277 memset(cur, 0, sizeof(struct clock_info));
Amit Arora6e774cd2010-10-28 11:31:24 +0530278 strcpy(cur->name, clockname);
279 cur->parent = clocks_info;
Amit Arora031263a2010-11-09 11:12:41 +0530280 cur->num_children = 0;
281 cur->expanded = 0;
Amit Aroraac4e8652010-11-09 11:16:53 +0530282 cur->level = 1;
Amit Arora6e774cd2010-10-28 11:31:24 +0530283 insert_children(&clocks_info, cur);
284 child = read_clock_info_recur(filename, 2, cur);
285 }
286 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530287}
288
289struct clock_info *read_clock_info_recur(char *clkpath, int level,
Amit Arora6e774cd2010-10-28 11:31:24 +0530290 struct clock_info *parent)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530291{
Amit Arora6e774cd2010-10-28 11:31:24 +0530292 int ret = 0;
293 DIR *dir;
294 char filename[PATH_MAX];
295 struct dirent *item;
296 struct clock_info *cur = NULL;
297 struct stat buf;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530298
Amit Arora6e774cd2010-10-28 11:31:24 +0530299 dir = opendir(clkpath);
300 if (!dir)
301 return NULL;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530302
Amit Arora6e774cd2010-10-28 11:31:24 +0530303 while ((item = readdir(dir))) {
304 struct clock_info *child;
305 /* skip hidden dirs except ".." */
306 if (item->d_name[0] == '.' )
307 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530308
Amit Arora6e774cd2010-10-28 11:31:24 +0530309 sprintf(filename, "%s/%s", clkpath, item->d_name);
Amit Arora0e512722010-10-01 12:24:16 +0530310
Amit Arora6e774cd2010-10-28 11:31:24 +0530311 ret = stat(filename, &buf);
Amit Arora0e512722010-10-01 12:24:16 +0530312
Amit Arora6e774cd2010-10-28 11:31:24 +0530313 if (ret < 0) {
314 printf("Error doing a stat on %s\n", filename);
315 exit(1);
316 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530317
Amit Arora6e774cd2010-10-28 11:31:24 +0530318 if (S_ISREG(buf.st_mode)) {
319 if (!strcmp(item->d_name, "flags"))
320 parent->flags = get_int_from(filename);
321 if (!strcmp(item->d_name, "rate"))
322 parent->rate = get_int_from(filename);
323 if (!strcmp(item->d_name, "usecount"))
324 parent->usecount = get_int_from(filename);
325 continue;
326 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530327
Amit Arora6e774cd2010-10-28 11:31:24 +0530328 if (!S_ISDIR(buf.st_mode))
329 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530330
Amit Arora6e774cd2010-10-28 11:31:24 +0530331 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
332 memset(cur, 0, sizeof(cur));
333 strcpy(cur->name, item->d_name);
334 cur->children = NULL;
335 cur->parent = NULL;
336 cur->num_children = 0;
Amit Arora031263a2010-11-09 11:12:41 +0530337 cur->expanded = 0;
Amit Aroraac4e8652010-11-09 11:16:53 +0530338 cur->level = level;
Amit Arora6e774cd2010-10-28 11:31:24 +0530339 child = read_clock_info_recur(filename, level + 1, cur);
Amit Arora6e774cd2010-10-28 11:31:24 +0530340 insert_children(&parent, cur);
341 cur->parent = parent;
342 }
343 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530344
Amit Arora6e774cd2010-10-28 11:31:24 +0530345 return cur;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530346}
347
348void insert_children(struct clock_info **parent, struct clock_info *clk)
349{
Amit Arora031263a2010-11-09 11:12:41 +0530350 if (!(*parent)->num_children || (*parent)->children == NULL) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530351 (*parent)->children = (struct clock_info **)
352 malloc(sizeof(struct clock_info *)*2);
353 (*parent)->num_children = 0;
354 } else
355 (*parent)->children = (struct clock_info **)
356 realloc((*parent)->children,
357 sizeof(struct clock_info *) *
358 ((*parent)->num_children + 2));
359 if ((*parent)->num_children > 0)
360 (*parent)->children[(*parent)->num_children - 1]->last_child
361 = 0;
362 clk->last_child = 1;
363 (*parent)->children[(*parent)->num_children] = clk;
364 (*parent)->children[(*parent)->num_children + 1] = NULL;
365 (*parent)->num_children++;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530366}
367
Amit Aroraf4fb8102010-11-30 13:55:50 +0530368void dump_parent(struct clock_info *clk)
369{
370 char *unit = "Hz";
371 double drate;
372 static char spaces[256];
373
374 if (clk && clk->parent)
375 dump_parent(clk->parent);
376
377 drate = (double)clk->rate;
378 if (drate > 1000 && drate < 1000000) {
379 unit = "KHz";
380 drate /= 1000;
381 }
382 if (drate > 1000000) {
383 unit = "MHz";
384 drate /= 1000000;
385 }
386 if (clk == clocks_info) {
387 strcpy(spaces, "");
388 printf("%s%s (flags:%d,usecount:%d,rate:%5.2f %s)\n", spaces,
389 clk->name, clk->flags, clk->usecount, drate, unit);
390 } else {
391 if (!(clk->parent == clocks_info))
392 strcat(spaces, " ");
393 printf("%s`- %s (flags:%d,usecount:%d,rate:%5.2f %s)\n", spaces,
394 clk->name, clk->flags, clk->usecount, drate, unit);
395 }
396}
397
398void dump_all_parents(char *clkarg)
399{
400 struct clock_info *clk;
401 char spaces[1024];
402
403 strcpy(spaces, "");
404
405 clk = find_clock(clocks_info, clkarg);
406
407 if (!clk)
408 printf("Clock NOT found!\n");
409 else {
410// while(clk && clk != clocks_info) {
411// printf("%s\n", clk->name);
412// strcat(spaces, " ");
413// clk = clk->parent;
414// printf("%s <-- ", spaces);
415// }
416// printf(" /\n");
417 dump_parent(clk);
418 }
419}
420
421struct clock_info *find_clock(struct clock_info *clk, char *clkarg)
422{
423 int i;
424 struct clock_info *ret = clk;
425
426 if (!strcmp(clk->name, clkarg))
427 return ret;
428
429 if (clk->children) {
430 for (i = 0; i < clk->num_children; i++) {
431 if (!strcmp(clk->children[i]->name, clkarg))
432 return clk->children[i];
433 }
434 for (i = 0; i < clk->num_children; i++) {
435 ret = find_clock(clk->children[i], clkarg);
436 if (ret)
437 return ret;
438 }
439 }
440
441 return NULL;
442}
443
Amit Aroraeb6cba92010-10-25 16:03:21 +0530444
Amit Aroraac4e8652010-11-09 11:16:53 +0530445void dump_clock_info(struct clock_info *clk, int level, int bmp)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530446{
Amit Arora6e774cd2010-10-28 11:31:24 +0530447 int i, j;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530448
Amit Arora6e774cd2010-10-28 11:31:24 +0530449 if (!clk)
450 return;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530451
Amit Arora6e774cd2010-10-28 11:31:24 +0530452 for (i = 1, j = 0; i < level; i++, j = (i - 1)) {
453 if (i == (level - 1)) {
454 if (clk->last_child)
455 printf("`-- ");
456 else
457 printf("|-- ");
458 } else {
459 if ((1<<j) & bmp)
460 printf("| ");
461 else
462 printf(" ");
463 }
464 }
Amit Arora031263a2010-11-09 11:12:41 +0530465
Amit Arora6e774cd2010-10-28 11:31:24 +0530466 if (clk == clocks_info)
467 printf("%s\n", clk->name);
468 else {
469 char *unit = "Hz";
470 double drate = (double)clk->rate;
471
472 if (drate > 1000 && drate < 1000000) {
473 unit = "KHz";
474 drate /= 1000;
475 }
476 if (drate > 1000000) {
477 unit = "MHz";
478 drate /= 1000000;
479 }
480 printf("%s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
481 clk->name, clk->flags, clk->usecount, drate, unit);
Amit Arora6e774cd2010-10-28 11:31:24 +0530482 }
483 if (clk->children) {
484 int tbmp = bmp;
485 int xbmp = -1;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530486
Amit Arora6e774cd2010-10-28 11:31:24 +0530487 if (clk->last_child) {
488 xbmp ^= 1 << (level - 2);
489
490 xbmp = tbmp & xbmp;
491 } else
492 xbmp = bmp;
493 for (i = 0; i < clk->num_children; i++) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530494 tbmp = xbmp | (1 << level);
Amit Aroraac4e8652010-11-09 11:16:53 +0530495 dump_clock_info(clk->children[i], level + 1, tbmp);
Amit Arora6e774cd2010-10-28 11:31:24 +0530496 }
497 }
Amit Arora0e512722010-10-01 12:24:16 +0530498}
Amit Aroraed3e5652010-10-27 12:02:53 +0530499
500char *debugfs_locate_mpoint(void)
501{
502 int ret;
503 FILE *filep;
504 char **path;
505 char fsname[64];
506 struct statfs sfs;
507
508 path = likely_mpoints;
509 while (*path) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530510 ret = statfs(*path, &sfs);
511 if (ret >= 0 && sfs.f_type == (long)DEBUGFS_MAGIC)
Amit Aroraed3e5652010-10-27 12:02:53 +0530512 return *path;
513 path++;
514 }
515
516 filep = fopen("/proc/mounts", "r");
517 if (filep == NULL) {
518 fprintf(stderr, "powerdebug: Error opening /proc/mounts.");
Amit Arora6e774cd2010-10-28 11:31:24 +0530519 exit(1);
520 }
Amit Aroraed3e5652010-10-27 12:02:53 +0530521
522 while (fscanf(filep, "%*s %s %s %*s %*d %*d\n",
523 debugfs_mntpoint, fsname) == 2)
524 if (!strcmp(fsname, "debugfs"))
525 break;
526 fclose(filep);
527
528 if (strcmp(fsname, "debugfs"))
529 return NULL;
530
531 return debugfs_mntpoint;
532}