blob: 25dcddbd5e5c7f1bec3fb761b5dcf314aa6e2bcf [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
24void init_clock_details(void)
25{
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
29
Amit Arora6e774cd2010-10-28 11:31:24 +053030 if (path)
31 strcpy(clk_dir_path, path);
32 else {
33 fprintf(stderr, "powerdebug: Unable to locate debugfs mount"
34 " point. Mount debugfs and try again..\n");
35 exit(1);
36 }
37 sprintf(clk_dir_path, "%s/clock", clk_dir_path);
Amit Arora97006e52010-10-28 11:56:08 +053038 //strcpy(clk_dir_path, "/debug/clock"); // Hardcoded for testing..
Amit Arora6e774cd2010-10-28 11:31:24 +053039 if (stat(clk_dir_path, &buf)) {
40 fprintf(stderr, "powerdebug: Unable to find clock tree"
41 " information at %s. Exiting..\n", clk_dir_path);
42 exit(1);
43 }
44 strcpy(clk_name, "");
Amit Arora24ed7d12010-09-14 12:12:58 +053045}
Amit Arora728e0c92010-09-14 12:06:09 +053046
47int get_int_from(char *file)
48{
Amit Arora6e774cd2010-10-28 11:31:24 +053049 FILE *filep;
50 char result[NAME_MAX];
51 int ret;
Amit Arora728e0c92010-09-14 12:06:09 +053052
Amit Arora6e774cd2010-10-28 11:31:24 +053053 filep = fopen(file, "r");
Amit Arora728e0c92010-09-14 12:06:09 +053054
Amit Arora6e774cd2010-10-28 11:31:24 +053055 if (!filep)
56 return -1; //TBD : What should we return on failure, here ?
Amit Arora728e0c92010-09-14 12:06:09 +053057
Amit Arora6e774cd2010-10-28 11:31:24 +053058 ret = fscanf(filep, "%s", result);
59 fclose(filep);
Amit Arora728e0c92010-09-14 12:06:09 +053060
Amit Arora6e774cd2010-10-28 11:31:24 +053061 return atoi(result);
Amit Arora728e0c92010-09-14 12:06:09 +053062}
63
Amit Arora24ed7d12010-09-14 12:12:58 +053064int read_and_print_clock_info(int verbose, int hrow, int selected)
65{
Amit Aroraac4e8652010-11-09 11:16:53 +053066 if (!old_clock_line_no)
67 read_clock_info(clk_dir_path);
Amit Arora29cb7572010-10-05 17:40:29 +053068
Amit Arora031263a2010-11-09 11:12:41 +053069 if (!clocks_info->num_children) {
70 fprintf(stderr, "powerdebug: No clocks found. Exiting..\n");
71 exit(1);
Amit Arora6e774cd2010-10-28 11:31:24 +053072 }
Amit Arora728e0c92010-09-14 12:06:09 +053073
Amit Aroraac4e8652010-11-09 11:16:53 +053074 print_clock_info(verbose, hrow, selected);
75 //destroy_clocks_info();
76 hrow = (hrow < old_clock_line_no) ? hrow : old_clock_line_no - 1;
77
78 return hrow;
79}
80
81void print_clock_info(int verbose, int hrow, int selected)
82{
83 int i, count = 0;
84
85 (void)verbose;
86
87 print_clock_header();
Amit Arora728e0c92010-09-14 12:06:09 +053088
Amit Arora031263a2010-11-09 11:12:41 +053089 for (i = 0; i < clocks_info->num_children; i++)
Amit Aroraac4e8652010-11-09 11:16:53 +053090 add_clock_details_recur(clocks_info->children[i],
91 hrow, selected);
Amit Arora031263a2010-11-09 11:12:41 +053092
93 while (clock_lines[count] && strcmp(clock_lines[count], "")) {
Amit Aroraac4e8652010-11-09 11:16:53 +053094 print_one_clock(count, clock_lines[count], bold[count],
95 (hrow == count));
Amit Arora031263a2010-11-09 11:12:41 +053096 count++;
97 }
98
Amit Aroraac4e8652010-11-09 11:16:53 +053099 old_clock_line_no = clock_line_no;
Amit Arora031263a2010-11-09 11:12:41 +0530100 clock_line_no = 0;
Amit Arora031263a2010-11-09 11:12:41 +0530101}
102
Amit Aroraac4e8652010-11-09 11:16:53 +0530103void prepare_name_str(char *namestr, struct clock_info *clock)
104{
105 int i;
106
107 strcpy(namestr, "");
108 if (clock->level > 1)
109 for (i = 0; i < (clock->level - 1); i++)
110 strcat(namestr, " ");
111 strcat(namestr, clock->name);
112}
113
114void add_clock_details_recur(struct clock_info *clock, int hrow, int selected)
Amit Arora031263a2010-11-09 11:12:41 +0530115{
116 int i;
117 char *unit = " Hz";
118 char rate_str[64];
Amit Aroraac4e8652010-11-09 11:16:53 +0530119 char name_str[256];
Amit Arora031263a2010-11-09 11:12:41 +0530120 double drate = (double)clock->rate;
121
122 if (drate > 1000 && drate < 1000000) {
123 unit = "KHz";
124 drate /= 1000;
125 }
126 if (drate > 1000000) {
127 unit = "MHz";
128 drate /= 1000000;
129 }
130 if (clock->usecount)
131 bold[clock_line_no] = 1;
132 else
133 bold[clock_line_no] = 0;
134
135 sprintf(rate_str, "%.2f %s", drate, unit);
Amit Aroraac4e8652010-11-09 11:16:53 +0530136 prepare_name_str(name_str, clock);
137 sprintf(clock_lines[clock_line_no++], "%-55s %-4d %-12s %-12d %-12d",
138 name_str, clock->flags, rate_str, clock->usecount,
139 clock->num_children);
140
141 if (selected && (hrow == (clock_line_no - 1))) {
142 if (clock->expanded)
143 collapse_all_subclocks(clock);
144 else
145 clock->expanded = 1;
146 selected = 0;
147 }
Amit Arora031263a2010-11-09 11:12:41 +0530148
149 if (clock->expanded && clock->num_children)
150 for (i = 0; i < clock->num_children; i++)
Amit Aroraac4e8652010-11-09 11:16:53 +0530151 add_clock_details_recur(clock->children[i],
152 hrow, selected);
Amit Arora031263a2010-11-09 11:12:41 +0530153 strcpy(clock_lines[clock_line_no], "");
154}
155
Amit Aroraac4e8652010-11-09 11:16:53 +0530156void collapse_all_subclocks(struct clock_info *clock)
157{
158 int i;
159
160 clock->expanded = 0;
161 if (clock->num_children)
162 for (i = 0; i < clock->num_children; i++)
163 collapse_all_subclocks(clock->children[i]);
164}
165
Amit Arora031263a2010-11-09 11:12:41 +0530166void destroy_clocks_info(void)
167{
168 int i;
169
170 if (clocks_info->num_children) {
171 for (i = (clocks_info->num_children - 1); i >= 0 ; i--) {
172 destroy_clocks_info_recur(clocks_info->children[i]);
173 if (!i) {
174 free(clocks_info->children);
175 clocks_info->children = NULL;
176 }
177 }
178 }
179 free(clocks_info);
180 clocks_info = NULL;
181}
182
183void destroy_clocks_info_recur(struct clock_info *clock)
184{
185 int i;
186
187 if (clock && clock->num_children) {
188 for (i = (clock->num_children - 1); i >= 0; i--) {
189 fflush(stdin);
190 destroy_clocks_info_recur(clock->children[i]);
191 if (!i) {
Amit Arora031263a2010-11-09 11:12:41 +0530192 free(clock->children);
193 clock->children = NULL;
194 clock->num_children = 0;
195 }
196 }
197 }
Amit Arora728e0c92010-09-14 12:06:09 +0530198}
Amit Arora0e512722010-10-01 12:24:16 +0530199
Amit Aroraac4e8652010-11-09 11:16:53 +0530200void read_and_dump_clock_info(int verbose)
Amit Arora0e512722010-10-01 12:24:16 +0530201{
Amit Arora6e774cd2010-10-28 11:31:24 +0530202 (void)verbose;
203 printf("Clock Tree :\n");
204 printf("**********\n");
205 read_clock_info(clk_dir_path);
Amit Aroraac4e8652010-11-09 11:16:53 +0530206 dump_clock_info(clocks_info, 1, 1);
Amit Arora0e512722010-10-01 12:24:16 +0530207}
208
Amit Aroraeb6cba92010-10-25 16:03:21 +0530209void read_clock_info(char *clkpath)
Amit Arora0e512722010-10-01 12:24:16 +0530210{
Amit Arora6e774cd2010-10-28 11:31:24 +0530211 DIR *dir;
212 struct dirent *item;
213 char filename[NAME_MAX], clockname[NAME_MAX];
214 struct clock_info *child;
215 struct clock_info *cur;
Amit Arora0e512722010-10-01 12:24:16 +0530216
Amit Arora6e774cd2010-10-28 11:31:24 +0530217 dir = opendir(clkpath);
218 if (!dir)
219 return;
Amit Arora0e512722010-10-01 12:24:16 +0530220
Amit Arora6e774cd2010-10-28 11:31:24 +0530221 clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info));
222 memset(clocks_info, 0, sizeof(clocks_info));
223 strcpy(clocks_info->name, "/");
Amit Aroraac4e8652010-11-09 11:16:53 +0530224 clocks_info->level = 0;
Amit Arora0e512722010-10-01 12:24:16 +0530225
Amit Arora6e774cd2010-10-28 11:31:24 +0530226 while ((item = readdir(dir))) {
227 /* skip hidden dirs except ".." */
228 if (item->d_name[0] == '.')
229 continue;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530230
Amit Arora6e774cd2010-10-28 11:31:24 +0530231 strcpy(clockname, item->d_name);
232 sprintf(filename, "%s/%s", clkpath, item->d_name);
233 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
Amit Aroraac4e8652010-11-09 11:16:53 +0530234 memset(cur, 0, sizeof(struct clock_info));
Amit Arora6e774cd2010-10-28 11:31:24 +0530235 strcpy(cur->name, clockname);
236 cur->parent = clocks_info;
Amit Arora031263a2010-11-09 11:12:41 +0530237 cur->num_children = 0;
238 cur->expanded = 0;
Amit Aroraac4e8652010-11-09 11:16:53 +0530239 cur->level = 1;
Amit Arora6e774cd2010-10-28 11:31:24 +0530240 insert_children(&clocks_info, cur);
241 child = read_clock_info_recur(filename, 2, cur);
242 }
243 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530244}
245
246struct clock_info *read_clock_info_recur(char *clkpath, int level,
Amit Arora6e774cd2010-10-28 11:31:24 +0530247 struct clock_info *parent)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530248{
Amit Arora6e774cd2010-10-28 11:31:24 +0530249 int ret = 0;
250 DIR *dir;
251 char filename[PATH_MAX];
252 struct dirent *item;
253 struct clock_info *cur = NULL;
254 struct stat buf;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530255
Amit Arora6e774cd2010-10-28 11:31:24 +0530256 dir = opendir(clkpath);
257 if (!dir)
258 return NULL;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530259
Amit Arora6e774cd2010-10-28 11:31:24 +0530260 while ((item = readdir(dir))) {
261 struct clock_info *child;
262 /* skip hidden dirs except ".." */
263 if (item->d_name[0] == '.' )
264 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530265
Amit Arora6e774cd2010-10-28 11:31:24 +0530266 sprintf(filename, "%s/%s", clkpath, item->d_name);
Amit Arora0e512722010-10-01 12:24:16 +0530267
Amit Arora6e774cd2010-10-28 11:31:24 +0530268 ret = stat(filename, &buf);
Amit Arora0e512722010-10-01 12:24:16 +0530269
Amit Arora6e774cd2010-10-28 11:31:24 +0530270 if (ret < 0) {
271 printf("Error doing a stat on %s\n", filename);
272 exit(1);
273 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530274
Amit Arora6e774cd2010-10-28 11:31:24 +0530275 if (S_ISREG(buf.st_mode)) {
276 if (!strcmp(item->d_name, "flags"))
277 parent->flags = get_int_from(filename);
278 if (!strcmp(item->d_name, "rate"))
279 parent->rate = get_int_from(filename);
280 if (!strcmp(item->d_name, "usecount"))
281 parent->usecount = get_int_from(filename);
282 continue;
283 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530284
Amit Arora6e774cd2010-10-28 11:31:24 +0530285 if (!S_ISDIR(buf.st_mode))
286 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530287
Amit Arora6e774cd2010-10-28 11:31:24 +0530288 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
289 memset(cur, 0, sizeof(cur));
290 strcpy(cur->name, item->d_name);
291 cur->children = NULL;
292 cur->parent = NULL;
293 cur->num_children = 0;
Amit Arora031263a2010-11-09 11:12:41 +0530294 cur->expanded = 0;
Amit Aroraac4e8652010-11-09 11:16:53 +0530295 cur->level = level;
Amit Arora6e774cd2010-10-28 11:31:24 +0530296 child = read_clock_info_recur(filename, level + 1, cur);
Amit Arora6e774cd2010-10-28 11:31:24 +0530297 insert_children(&parent, cur);
298 cur->parent = parent;
299 }
300 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530301
Amit Arora6e774cd2010-10-28 11:31:24 +0530302 return cur;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530303}
304
305void insert_children(struct clock_info **parent, struct clock_info *clk)
306{
Amit Arora031263a2010-11-09 11:12:41 +0530307 if (!(*parent)->num_children || (*parent)->children == NULL) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530308 (*parent)->children = (struct clock_info **)
309 malloc(sizeof(struct clock_info *)*2);
310 (*parent)->num_children = 0;
311 } else
312 (*parent)->children = (struct clock_info **)
313 realloc((*parent)->children,
314 sizeof(struct clock_info *) *
315 ((*parent)->num_children + 2));
316 if ((*parent)->num_children > 0)
317 (*parent)->children[(*parent)->num_children - 1]->last_child
318 = 0;
319 clk->last_child = 1;
320 (*parent)->children[(*parent)->num_children] = clk;
321 (*parent)->children[(*parent)->num_children + 1] = NULL;
322 (*parent)->num_children++;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530323}
324
325
Amit Aroraac4e8652010-11-09 11:16:53 +0530326void dump_clock_info(struct clock_info *clk, int level, int bmp)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530327{
Amit Arora6e774cd2010-10-28 11:31:24 +0530328 int i, j;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530329
Amit Arora6e774cd2010-10-28 11:31:24 +0530330 if (!clk)
331 return;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530332
Amit Arora6e774cd2010-10-28 11:31:24 +0530333 for (i = 1, j = 0; i < level; i++, j = (i - 1)) {
334 if (i == (level - 1)) {
335 if (clk->last_child)
336 printf("`-- ");
337 else
338 printf("|-- ");
339 } else {
340 if ((1<<j) & bmp)
341 printf("| ");
342 else
343 printf(" ");
344 }
345 }
Amit Arora031263a2010-11-09 11:12:41 +0530346
Amit Arora6e774cd2010-10-28 11:31:24 +0530347 if (clk == clocks_info)
348 printf("%s\n", clk->name);
349 else {
350 char *unit = "Hz";
351 double drate = (double)clk->rate;
352
353 if (drate > 1000 && drate < 1000000) {
354 unit = "KHz";
355 drate /= 1000;
356 }
357 if (drate > 1000000) {
358 unit = "MHz";
359 drate /= 1000000;
360 }
361 printf("%s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
362 clk->name, clk->flags, clk->usecount, drate, unit);
Amit Arora6e774cd2010-10-28 11:31:24 +0530363 }
364 if (clk->children) {
365 int tbmp = bmp;
366 int xbmp = -1;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530367
Amit Arora6e774cd2010-10-28 11:31:24 +0530368 if (clk->last_child) {
369 xbmp ^= 1 << (level - 2);
370
371 xbmp = tbmp & xbmp;
372 } else
373 xbmp = bmp;
374 for (i = 0; i < clk->num_children; i++) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530375 tbmp = xbmp | (1 << level);
Amit Aroraac4e8652010-11-09 11:16:53 +0530376 dump_clock_info(clk->children[i], level + 1, tbmp);
Amit Arora6e774cd2010-10-28 11:31:24 +0530377 }
378 }
Amit Arora0e512722010-10-01 12:24:16 +0530379}
Amit Aroraed3e5652010-10-27 12:02:53 +0530380
381char *debugfs_locate_mpoint(void)
382{
383 int ret;
384 FILE *filep;
385 char **path;
386 char fsname[64];
387 struct statfs sfs;
388
389 path = likely_mpoints;
390 while (*path) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530391 ret = statfs(*path, &sfs);
392 if (ret >= 0 && sfs.f_type == (long)DEBUGFS_MAGIC)
Amit Aroraed3e5652010-10-27 12:02:53 +0530393 return *path;
394 path++;
395 }
396
397 filep = fopen("/proc/mounts", "r");
398 if (filep == NULL) {
399 fprintf(stderr, "powerdebug: Error opening /proc/mounts.");
Amit Arora6e774cd2010-10-28 11:31:24 +0530400 exit(1);
401 }
Amit Aroraed3e5652010-10-27 12:02:53 +0530402
403 while (fscanf(filep, "%*s %s %s %*s %*d %*d\n",
404 debugfs_mntpoint, fsname) == 2)
405 if (!strcmp(fsname, "debugfs"))
406 break;
407 fclose(filep);
408
409 if (strcmp(fsname, "debugfs"))
410 return NULL;
411
412 return debugfs_mntpoint;
413}