blob: 4ef69371aad6706c66022f0ff9e3de9a35c251a9 [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#include <errno.h>
Amit Aroraeb6cba92010-10-25 16:03:21 +053020#include <sys/stat.h>
Amit Arora24ed7d12010-09-14 12:12:58 +053021
Amit Arora031263a2010-11-09 11:12:41 +053022//static int clk_tree_level = 1;
Amit Arora24ed7d12010-09-14 12:12:58 +053023static char clk_dir_path[PATH_MAX];
24static char highlighted_path[PATH_MAX];
25static char clk_name[NAME_MAX];
Amit Arora031263a2010-11-09 11:12:41 +053026static int bold[MAX_LINES];
Amit Arora24ed7d12010-09-14 12:12:58 +053027
28void init_clock_details(void)
29{
Amit Arora6e774cd2010-10-28 11:31:24 +053030 char *path = debugfs_locate_mpoint();
31 struct stat buf;
Amit Aroraed3e5652010-10-27 12:02:53 +053032
33
Amit Arora6e774cd2010-10-28 11:31:24 +053034 if (path)
35 strcpy(clk_dir_path, path);
36 else {
37 fprintf(stderr, "powerdebug: Unable to locate debugfs mount"
38 " point. Mount debugfs and try again..\n");
39 exit(1);
40 }
41 sprintf(clk_dir_path, "%s/clock", clk_dir_path);
Amit Arora97006e52010-10-28 11:56:08 +053042 //strcpy(clk_dir_path, "/debug/clock"); // Hardcoded for testing..
Amit Arora6e774cd2010-10-28 11:31:24 +053043 if (stat(clk_dir_path, &buf)) {
44 fprintf(stderr, "powerdebug: Unable to find clock tree"
45 " information at %s. Exiting..\n", clk_dir_path);
46 exit(1);
47 }
48 strcpy(clk_name, "");
49 strcpy(highlighted_path, "");
Amit Arora24ed7d12010-09-14 12:12:58 +053050}
Amit Arora728e0c92010-09-14 12:06:09 +053051
52int get_int_from(char *file)
53{
Amit Arora6e774cd2010-10-28 11:31:24 +053054 FILE *filep;
55 char result[NAME_MAX];
56 int ret;
Amit Arora728e0c92010-09-14 12:06:09 +053057
Amit Arora6e774cd2010-10-28 11:31:24 +053058 filep = fopen(file, "r");
Amit Arora728e0c92010-09-14 12:06:09 +053059
Amit Arora6e774cd2010-10-28 11:31:24 +053060 if (!filep)
61 return -1; //TBD : What should we return on failure, here ?
Amit Arora728e0c92010-09-14 12:06:09 +053062
Amit Arora6e774cd2010-10-28 11:31:24 +053063 ret = fscanf(filep, "%s", result);
64 fclose(filep);
Amit Arora728e0c92010-09-14 12:06:09 +053065
Amit Arora6e774cd2010-10-28 11:31:24 +053066 return atoi(result);
Amit Arora728e0c92010-09-14 12:06:09 +053067}
68
Amit Arora24ed7d12010-09-14 12:12:58 +053069int read_and_print_clock_info(int verbose, int hrow, int selected)
70{
Amit Arora031263a2010-11-09 11:12:41 +053071 int i, count = 0;
Amit Arora728e0c92010-09-14 12:06:09 +053072
Amit Arora6e774cd2010-10-28 11:31:24 +053073 (void)verbose;
Amit Arora031263a2010-11-09 11:12:41 +053074 (void)hrow;
75 (void)selected;
76 read_clock_info(clk_dir_path);
Amit Arora29cb7572010-10-05 17:40:29 +053077
Amit Arora031263a2010-11-09 11:12:41 +053078 if (!clocks_info->num_children) {
79 fprintf(stderr, "powerdebug: No clocks found. Exiting..\n");
80 exit(1);
Amit Arora6e774cd2010-10-28 11:31:24 +053081 }
Amit Arora728e0c92010-09-14 12:06:09 +053082
Amit Arora031263a2010-11-09 11:12:41 +053083 print_clock_header(1);
Amit Arora728e0c92010-09-14 12:06:09 +053084
Amit Arora031263a2010-11-09 11:12:41 +053085 for (i = 0; i < clocks_info->num_children; i++)
86 add_clock_details_recur(clocks_info->children[i]);
87
88 while (clock_lines[count] && strcmp(clock_lines[count], "")) {
89 print_one_clock(count, clock_lines[count], bold[count]);
90 count++;
91 }
92
93 clock_line_no = 0;
94 destroy_clocks_info();
95
96 return 1;
97}
98
99void add_clock_details_recur(struct clock_info *clock)
100{
101 int i;
102 char *unit = " Hz";
103 char rate_str[64];
104 double drate = (double)clock->rate;
105
106 if (drate > 1000 && drate < 1000000) {
107 unit = "KHz";
108 drate /= 1000;
109 }
110 if (drate > 1000000) {
111 unit = "MHz";
112 drate /= 1000000;
113 }
114 if (clock->usecount)
115 bold[clock_line_no] = 1;
116 else
117 bold[clock_line_no] = 0;
118
119 sprintf(rate_str, "%.2f %s", drate, unit);
120 sprintf(clock_lines[clock_line_no++], "%-55s %-4d %-12s %-12d",
121 clock->name, clock->flags, rate_str, clock->usecount);
122
123 if (clock->expanded && clock->num_children)
124 for (i = 0; i < clock->num_children; i++)
125 add_clock_details_recur(clock->children[i]);
126 strcpy(clock_lines[clock_line_no], "");
127}
128
129void destroy_clocks_info(void)
130{
131 int i;
132
133 if (clocks_info->num_children) {
134 for (i = (clocks_info->num_children - 1); i >= 0 ; i--) {
135 destroy_clocks_info_recur(clocks_info->children[i]);
136 if (!i) {
137 free(clocks_info->children);
138 clocks_info->children = NULL;
139 }
140 }
141 }
142 free(clocks_info);
143 clocks_info = NULL;
144}
145
146void destroy_clocks_info_recur(struct clock_info *clock)
147{
148 int i;
149
150 if (clock && clock->num_children) {
151 for (i = (clock->num_children - 1); i >= 0; i--) {
152 fflush(stdin);
153 destroy_clocks_info_recur(clock->children[i]);
154 if (!i) {
155 char name[128];
156
157 strcpy(name, clock->children[0]->name);
158 free(clock->children);
159 clock->children = NULL;
160 clock->num_children = 0;
161 }
162 }
163 }
Amit Arora728e0c92010-09-14 12:06:09 +0530164}
Amit Arora0e512722010-10-01 12:24:16 +0530165
166void dump_clock_info(int verbose)
167{
Amit Arora6e774cd2010-10-28 11:31:24 +0530168 (void)verbose;
169 printf("Clock Tree :\n");
170 printf("**********\n");
171 read_clock_info(clk_dir_path);
172 print_clock_info(clocks_info, 1, 1);
Amit Arora0e512722010-10-01 12:24:16 +0530173}
174
Amit Aroraeb6cba92010-10-25 16:03:21 +0530175void read_clock_info(char *clkpath)
Amit Arora0e512722010-10-01 12:24:16 +0530176{
Amit Arora6e774cd2010-10-28 11:31:24 +0530177 DIR *dir;
178 struct dirent *item;
179 char filename[NAME_MAX], clockname[NAME_MAX];
180 struct clock_info *child;
181 struct clock_info *cur;
Amit Arora0e512722010-10-01 12:24:16 +0530182
Amit Arora6e774cd2010-10-28 11:31:24 +0530183 dir = opendir(clkpath);
184 if (!dir)
185 return;
Amit Arora0e512722010-10-01 12:24:16 +0530186
Amit Arora6e774cd2010-10-28 11:31:24 +0530187 clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info));
188 memset(clocks_info, 0, sizeof(clocks_info));
189 strcpy(clocks_info->name, "/");
Amit Arora0e512722010-10-01 12:24:16 +0530190
Amit Arora6e774cd2010-10-28 11:31:24 +0530191 while ((item = readdir(dir))) {
192 /* skip hidden dirs except ".." */
193 if (item->d_name[0] == '.')
194 continue;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530195
Amit Arora6e774cd2010-10-28 11:31:24 +0530196 strcpy(clockname, item->d_name);
197 sprintf(filename, "%s/%s", clkpath, item->d_name);
198 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
199 memset(cur, 0, sizeof(cur));
200 strcpy(cur->name, clockname);
201 cur->parent = clocks_info;
Amit Arora031263a2010-11-09 11:12:41 +0530202 cur->num_children = 0;
203 cur->expanded = 0;
Amit Arora6e774cd2010-10-28 11:31:24 +0530204 insert_children(&clocks_info, cur);
205 child = read_clock_info_recur(filename, 2, cur);
206 }
207 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530208}
209
210struct clock_info *read_clock_info_recur(char *clkpath, int level,
Amit Arora6e774cd2010-10-28 11:31:24 +0530211 struct clock_info *parent)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530212{
Amit Arora6e774cd2010-10-28 11:31:24 +0530213 int ret = 0;
214 DIR *dir;
215 char filename[PATH_MAX];
216 struct dirent *item;
217 struct clock_info *cur = NULL;
218 struct stat buf;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530219
Amit Arora6e774cd2010-10-28 11:31:24 +0530220 dir = opendir(clkpath);
221 if (!dir)
222 return NULL;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530223
Amit Arora6e774cd2010-10-28 11:31:24 +0530224 while ((item = readdir(dir))) {
225 struct clock_info *child;
226 /* skip hidden dirs except ".." */
227 if (item->d_name[0] == '.' )
228 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530229
Amit Arora6e774cd2010-10-28 11:31:24 +0530230 sprintf(filename, "%s/%s", clkpath, item->d_name);
Amit Arora0e512722010-10-01 12:24:16 +0530231
Amit Arora6e774cd2010-10-28 11:31:24 +0530232 ret = stat(filename, &buf);
Amit Arora0e512722010-10-01 12:24:16 +0530233
Amit Arora6e774cd2010-10-28 11:31:24 +0530234 if (ret < 0) {
235 printf("Error doing a stat on %s\n", filename);
236 exit(1);
237 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530238
Amit Arora6e774cd2010-10-28 11:31:24 +0530239 if (S_ISREG(buf.st_mode)) {
240 if (!strcmp(item->d_name, "flags"))
241 parent->flags = get_int_from(filename);
242 if (!strcmp(item->d_name, "rate"))
243 parent->rate = get_int_from(filename);
244 if (!strcmp(item->d_name, "usecount"))
245 parent->usecount = get_int_from(filename);
246 continue;
247 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530248
Amit Arora6e774cd2010-10-28 11:31:24 +0530249 if (!S_ISDIR(buf.st_mode))
250 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530251
Amit Arora6e774cd2010-10-28 11:31:24 +0530252 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
253 memset(cur, 0, sizeof(cur));
254 strcpy(cur->name, item->d_name);
255 cur->children = NULL;
256 cur->parent = NULL;
257 cur->num_children = 0;
Amit Arora031263a2010-11-09 11:12:41 +0530258 cur->expanded = 0;
Amit Arora6e774cd2010-10-28 11:31:24 +0530259 child = read_clock_info_recur(filename, level + 1, cur);
Amit Arora6e774cd2010-10-28 11:31:24 +0530260 insert_children(&parent, cur);
261 cur->parent = parent;
262 }
263 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530264
Amit Arora6e774cd2010-10-28 11:31:24 +0530265 return cur;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530266}
267
268void insert_children(struct clock_info **parent, struct clock_info *clk)
269{
Amit Arora031263a2010-11-09 11:12:41 +0530270 if (!(*parent)->num_children || (*parent)->children == NULL) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530271 (*parent)->children = (struct clock_info **)
272 malloc(sizeof(struct clock_info *)*2);
273 (*parent)->num_children = 0;
274 } else
275 (*parent)->children = (struct clock_info **)
276 realloc((*parent)->children,
277 sizeof(struct clock_info *) *
278 ((*parent)->num_children + 2));
279 if ((*parent)->num_children > 0)
280 (*parent)->children[(*parent)->num_children - 1]->last_child
281 = 0;
282 clk->last_child = 1;
283 (*parent)->children[(*parent)->num_children] = clk;
284 (*parent)->children[(*parent)->num_children + 1] = NULL;
285 (*parent)->num_children++;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530286}
287
288
289void print_clock_info(struct clock_info *clk, int level, int bmp)
290{
Amit Arora6e774cd2010-10-28 11:31:24 +0530291 int i, j;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530292
Amit Arora6e774cd2010-10-28 11:31:24 +0530293 if (!clk)
294 return;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530295
Amit Arora6e774cd2010-10-28 11:31:24 +0530296 for (i = 1, j = 0; i < level; i++, j = (i - 1)) {
297 if (i == (level - 1)) {
298 if (clk->last_child)
299 printf("`-- ");
300 else
301 printf("|-- ");
302 } else {
303 if ((1<<j) & bmp)
304 printf("| ");
305 else
306 printf(" ");
307 }
308 }
Amit Arora031263a2010-11-09 11:12:41 +0530309
Amit Arora6e774cd2010-10-28 11:31:24 +0530310 if (clk == clocks_info)
311 printf("%s\n", clk->name);
312 else {
313 char *unit = "Hz";
314 double drate = (double)clk->rate;
315
316 if (drate > 1000 && drate < 1000000) {
317 unit = "KHz";
318 drate /= 1000;
319 }
320 if (drate > 1000000) {
321 unit = "MHz";
322 drate /= 1000000;
323 }
324 printf("%s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
325 clk->name, clk->flags, clk->usecount, drate, unit);
Amit Arora6e774cd2010-10-28 11:31:24 +0530326 }
327 if (clk->children) {
328 int tbmp = bmp;
329 int xbmp = -1;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530330
Amit Arora6e774cd2010-10-28 11:31:24 +0530331 if (clk->last_child) {
332 xbmp ^= 1 << (level - 2);
333
334 xbmp = tbmp & xbmp;
335 } else
336 xbmp = bmp;
337 for (i = 0; i < clk->num_children; i++) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530338 tbmp = xbmp | (1 << level);
339 print_clock_info(clk->children[i], level + 1, tbmp);
340 }
341 }
Amit Arora0e512722010-10-01 12:24:16 +0530342}
Amit Aroraed3e5652010-10-27 12:02:53 +0530343
344char *debugfs_locate_mpoint(void)
345{
346 int ret;
347 FILE *filep;
348 char **path;
349 char fsname[64];
350 struct statfs sfs;
351
352 path = likely_mpoints;
353 while (*path) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530354 ret = statfs(*path, &sfs);
355 if (ret >= 0 && sfs.f_type == (long)DEBUGFS_MAGIC)
Amit Aroraed3e5652010-10-27 12:02:53 +0530356 return *path;
357 path++;
358 }
359
360 filep = fopen("/proc/mounts", "r");
361 if (filep == NULL) {
362 fprintf(stderr, "powerdebug: Error opening /proc/mounts.");
Amit Arora6e774cd2010-10-28 11:31:24 +0530363 exit(1);
364 }
Amit Aroraed3e5652010-10-27 12:02:53 +0530365
366 while (fscanf(filep, "%*s %s %s %*s %*d %*d\n",
367 debugfs_mntpoint, fsname) == 2)
368 if (!strcmp(fsname, "debugfs"))
369 break;
370 fclose(filep);
371
372 if (strcmp(fsname, "debugfs"))
373 return NULL;
374
375 return debugfs_mntpoint;
376}