blob: e20553e803ad624da1c787a8c3e0d3a8f883a3cd [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 Aroraac4e8652010-11-09 11:16:53 +0530235void read_and_dump_clock_info(int verbose)
Amit Arora0e512722010-10-01 12:24:16 +0530236{
Amit Arora6e774cd2010-10-28 11:31:24 +0530237 (void)verbose;
238 printf("Clock Tree :\n");
239 printf("**********\n");
240 read_clock_info(clk_dir_path);
Amit Aroraac4e8652010-11-09 11:16:53 +0530241 dump_clock_info(clocks_info, 1, 1);
Amit Arora0e512722010-10-01 12:24:16 +0530242}
243
Amit Aroraeb6cba92010-10-25 16:03:21 +0530244void read_clock_info(char *clkpath)
Amit Arora0e512722010-10-01 12:24:16 +0530245{
Amit Arora6e774cd2010-10-28 11:31:24 +0530246 DIR *dir;
247 struct dirent *item;
248 char filename[NAME_MAX], clockname[NAME_MAX];
249 struct clock_info *child;
250 struct clock_info *cur;
Amit Arora0e512722010-10-01 12:24:16 +0530251
Amit Arora6e774cd2010-10-28 11:31:24 +0530252 dir = opendir(clkpath);
253 if (!dir)
254 return;
Amit Arora0e512722010-10-01 12:24:16 +0530255
Amit Arora6e774cd2010-10-28 11:31:24 +0530256 clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info));
257 memset(clocks_info, 0, sizeof(clocks_info));
258 strcpy(clocks_info->name, "/");
Amit Aroraac4e8652010-11-09 11:16:53 +0530259 clocks_info->level = 0;
Amit Arora0e512722010-10-01 12:24:16 +0530260
Amit Arora6e774cd2010-10-28 11:31:24 +0530261 while ((item = readdir(dir))) {
262 /* skip hidden dirs except ".." */
263 if (item->d_name[0] == '.')
264 continue;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530265
Amit Arora6e774cd2010-10-28 11:31:24 +0530266 strcpy(clockname, item->d_name);
267 sprintf(filename, "%s/%s", clkpath, item->d_name);
268 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
Amit Aroraac4e8652010-11-09 11:16:53 +0530269 memset(cur, 0, sizeof(struct clock_info));
Amit Arora6e774cd2010-10-28 11:31:24 +0530270 strcpy(cur->name, clockname);
271 cur->parent = clocks_info;
Amit Arora031263a2010-11-09 11:12:41 +0530272 cur->num_children = 0;
273 cur->expanded = 0;
Amit Aroraac4e8652010-11-09 11:16:53 +0530274 cur->level = 1;
Amit Arora6e774cd2010-10-28 11:31:24 +0530275 insert_children(&clocks_info, cur);
276 child = read_clock_info_recur(filename, 2, cur);
277 }
278 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530279}
280
281struct clock_info *read_clock_info_recur(char *clkpath, int level,
Amit Arora6e774cd2010-10-28 11:31:24 +0530282 struct clock_info *parent)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530283{
Amit Arora6e774cd2010-10-28 11:31:24 +0530284 int ret = 0;
285 DIR *dir;
286 char filename[PATH_MAX];
287 struct dirent *item;
288 struct clock_info *cur = NULL;
289 struct stat buf;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530290
Amit Arora6e774cd2010-10-28 11:31:24 +0530291 dir = opendir(clkpath);
292 if (!dir)
293 return NULL;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530294
Amit Arora6e774cd2010-10-28 11:31:24 +0530295 while ((item = readdir(dir))) {
296 struct clock_info *child;
297 /* skip hidden dirs except ".." */
298 if (item->d_name[0] == '.' )
299 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530300
Amit Arora6e774cd2010-10-28 11:31:24 +0530301 sprintf(filename, "%s/%s", clkpath, item->d_name);
Amit Arora0e512722010-10-01 12:24:16 +0530302
Amit Arora6e774cd2010-10-28 11:31:24 +0530303 ret = stat(filename, &buf);
Amit Arora0e512722010-10-01 12:24:16 +0530304
Amit Arora6e774cd2010-10-28 11:31:24 +0530305 if (ret < 0) {
306 printf("Error doing a stat on %s\n", filename);
307 exit(1);
308 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530309
Amit Arora6e774cd2010-10-28 11:31:24 +0530310 if (S_ISREG(buf.st_mode)) {
311 if (!strcmp(item->d_name, "flags"))
312 parent->flags = get_int_from(filename);
313 if (!strcmp(item->d_name, "rate"))
314 parent->rate = get_int_from(filename);
315 if (!strcmp(item->d_name, "usecount"))
316 parent->usecount = get_int_from(filename);
317 continue;
318 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530319
Amit Arora6e774cd2010-10-28 11:31:24 +0530320 if (!S_ISDIR(buf.st_mode))
321 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530322
Amit Arora6e774cd2010-10-28 11:31:24 +0530323 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
324 memset(cur, 0, sizeof(cur));
325 strcpy(cur->name, item->d_name);
326 cur->children = NULL;
327 cur->parent = NULL;
328 cur->num_children = 0;
Amit Arora031263a2010-11-09 11:12:41 +0530329 cur->expanded = 0;
Amit Aroraac4e8652010-11-09 11:16:53 +0530330 cur->level = level;
Amit Arora6e774cd2010-10-28 11:31:24 +0530331 child = read_clock_info_recur(filename, level + 1, cur);
Amit Arora6e774cd2010-10-28 11:31:24 +0530332 insert_children(&parent, cur);
333 cur->parent = parent;
334 }
335 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530336
Amit Arora6e774cd2010-10-28 11:31:24 +0530337 return cur;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530338}
339
340void insert_children(struct clock_info **parent, struct clock_info *clk)
341{
Amit Arora031263a2010-11-09 11:12:41 +0530342 if (!(*parent)->num_children || (*parent)->children == NULL) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530343 (*parent)->children = (struct clock_info **)
344 malloc(sizeof(struct clock_info *)*2);
345 (*parent)->num_children = 0;
346 } else
347 (*parent)->children = (struct clock_info **)
348 realloc((*parent)->children,
349 sizeof(struct clock_info *) *
350 ((*parent)->num_children + 2));
351 if ((*parent)->num_children > 0)
352 (*parent)->children[(*parent)->num_children - 1]->last_child
353 = 0;
354 clk->last_child = 1;
355 (*parent)->children[(*parent)->num_children] = clk;
356 (*parent)->children[(*parent)->num_children + 1] = NULL;
357 (*parent)->num_children++;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530358}
359
360
Amit Aroraac4e8652010-11-09 11:16:53 +0530361void dump_clock_info(struct clock_info *clk, int level, int bmp)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530362{
Amit Arora6e774cd2010-10-28 11:31:24 +0530363 int i, j;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530364
Amit Arora6e774cd2010-10-28 11:31:24 +0530365 if (!clk)
366 return;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530367
Amit Arora6e774cd2010-10-28 11:31:24 +0530368 for (i = 1, j = 0; i < level; i++, j = (i - 1)) {
369 if (i == (level - 1)) {
370 if (clk->last_child)
371 printf("`-- ");
372 else
373 printf("|-- ");
374 } else {
375 if ((1<<j) & bmp)
376 printf("| ");
377 else
378 printf(" ");
379 }
380 }
Amit Arora031263a2010-11-09 11:12:41 +0530381
Amit Arora6e774cd2010-10-28 11:31:24 +0530382 if (clk == clocks_info)
383 printf("%s\n", clk->name);
384 else {
385 char *unit = "Hz";
386 double drate = (double)clk->rate;
387
388 if (drate > 1000 && drate < 1000000) {
389 unit = "KHz";
390 drate /= 1000;
391 }
392 if (drate > 1000000) {
393 unit = "MHz";
394 drate /= 1000000;
395 }
396 printf("%s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
397 clk->name, clk->flags, clk->usecount, drate, unit);
Amit Arora6e774cd2010-10-28 11:31:24 +0530398 }
399 if (clk->children) {
400 int tbmp = bmp;
401 int xbmp = -1;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530402
Amit Arora6e774cd2010-10-28 11:31:24 +0530403 if (clk->last_child) {
404 xbmp ^= 1 << (level - 2);
405
406 xbmp = tbmp & xbmp;
407 } else
408 xbmp = bmp;
409 for (i = 0; i < clk->num_children; i++) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530410 tbmp = xbmp | (1 << level);
Amit Aroraac4e8652010-11-09 11:16:53 +0530411 dump_clock_info(clk->children[i], level + 1, tbmp);
Amit Arora6e774cd2010-10-28 11:31:24 +0530412 }
413 }
Amit Arora0e512722010-10-01 12:24:16 +0530414}
Amit Aroraed3e5652010-10-27 12:02:53 +0530415
416char *debugfs_locate_mpoint(void)
417{
418 int ret;
419 FILE *filep;
420 char **path;
421 char fsname[64];
422 struct statfs sfs;
423
424 path = likely_mpoints;
425 while (*path) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530426 ret = statfs(*path, &sfs);
427 if (ret >= 0 && sfs.f_type == (long)DEBUGFS_MAGIC)
Amit Aroraed3e5652010-10-27 12:02:53 +0530428 return *path;
429 path++;
430 }
431
432 filep = fopen("/proc/mounts", "r");
433 if (filep == NULL) {
434 fprintf(stderr, "powerdebug: Error opening /proc/mounts.");
Amit Arora6e774cd2010-10-28 11:31:24 +0530435 exit(1);
436 }
Amit Aroraed3e5652010-10-27 12:02:53 +0530437
438 while (fscanf(filep, "%*s %s %s %*s %*d %*d\n",
439 debugfs_mntpoint, fsname) == 2)
440 if (!strcmp(fsname, "debugfs"))
441 break;
442 fclose(filep);
443
444 if (strcmp(fsname, "debugfs"))
445 return NULL;
446
447 return debugfs_mntpoint;
448}