blob: b2c53ac6bb5950110414124078ddb36a1106dbad [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
22static int clk_tree_level = 1;
23static char clk_dir_path[PATH_MAX];
24static char highlighted_path[PATH_MAX];
25static char clk_name[NAME_MAX];
26static int gadder = 0;
27
28
29void init_clock_details(void)
30{
Amit Arora6e774cd2010-10-28 11:31:24 +053031 char *path = debugfs_locate_mpoint();
32 struct stat buf;
Amit Aroraed3e5652010-10-27 12:02:53 +053033
34
Amit Arora6e774cd2010-10-28 11:31:24 +053035 if (path)
36 strcpy(clk_dir_path, path);
37 else {
38 fprintf(stderr, "powerdebug: Unable to locate debugfs mount"
39 " point. Mount debugfs and try again..\n");
40 exit(1);
41 }
42 sprintf(clk_dir_path, "%s/clock", clk_dir_path);
Amit Arora97006e52010-10-28 11:56:08 +053043 //strcpy(clk_dir_path, "/debug/clock"); // Hardcoded for testing..
Amit Arora6e774cd2010-10-28 11:31:24 +053044 if (stat(clk_dir_path, &buf)) {
45 fprintf(stderr, "powerdebug: Unable to find clock tree"
46 " information at %s. Exiting..\n", clk_dir_path);
47 exit(1);
48 }
49 strcpy(clk_name, "");
50 strcpy(highlighted_path, "");
Amit Arora24ed7d12010-09-14 12:12:58 +053051}
Amit Arora728e0c92010-09-14 12:06:09 +053052
53int get_int_from(char *file)
54{
Amit Arora6e774cd2010-10-28 11:31:24 +053055 FILE *filep;
56 char result[NAME_MAX];
57 int ret;
Amit Arora728e0c92010-09-14 12:06:09 +053058
Amit Arora6e774cd2010-10-28 11:31:24 +053059 filep = fopen(file, "r");
Amit Arora728e0c92010-09-14 12:06:09 +053060
Amit Arora6e774cd2010-10-28 11:31:24 +053061 if (!filep)
62 return -1; //TBD : What should we return on failure, here ?
Amit Arora728e0c92010-09-14 12:06:09 +053063
Amit Arora6e774cd2010-10-28 11:31:24 +053064 ret = fscanf(filep, "%s", result);
65 fclose(filep);
Amit Arora728e0c92010-09-14 12:06:09 +053066
Amit Arora6e774cd2010-10-28 11:31:24 +053067 return atoi(result);
Amit Arora728e0c92010-09-14 12:06:09 +053068}
69
Amit Arora24ed7d12010-09-14 12:12:58 +053070int read_and_print_clock_info(int verbose, int hrow, int selected)
71{
Amit Arora6e774cd2010-10-28 11:31:24 +053072 if (selected) {
Amit Arora6e774cd2010-10-28 11:31:24 +053073 strcpy(clk_dir_path, highlighted_path);
74 hrow = 0;
75 clk_tree_level += gadder;
76 if (clk_tree_level <= 0)
77 clk_tree_level = 1;
78 }
Amit Arora24ed7d12010-09-14 12:12:58 +053079
Amit Arora6e774cd2010-10-28 11:31:24 +053080 hrow = read_and_print_clock_one_level(verbose, hrow, selected);
Amit Arora24ed7d12010-09-14 12:12:58 +053081
Amit Arora6e774cd2010-10-28 11:31:24 +053082 return hrow;
Amit Arora24ed7d12010-09-14 12:12:58 +053083}
84
85void set_hl_dir_path_to_parent(void)
86{
Amit Arora6e774cd2010-10-28 11:31:24 +053087 char *ptr;
Amit Arora24ed7d12010-09-14 12:12:58 +053088
Amit Arora6e774cd2010-10-28 11:31:24 +053089 strcpy(highlighted_path, clk_dir_path);
90 if (strcmp(clk_dir_path, "/clock/debug")) {
91 ptr = strrchr(highlighted_path, '/');
92 if (ptr)
93 ptr[0] = '\0';
94 }
Amit Arora24ed7d12010-09-14 12:12:58 +053095}
96
97int read_and_print_clock_one_level(int verbose, int hrow, int selected)
Amit Arora728e0c92010-09-14 12:06:09 +053098{
Amit Arora6e774cd2010-10-28 11:31:24 +053099 int line = 0, usecount = 0, flags = 0, rate = 0;
Amit Arora6e774cd2010-10-28 11:31:24 +0530100 DIR *dir, *subdir;
101 char filename[PATH_MAX], devpath[PATH_MAX], clockname[NAME_MAX];
102 struct dirent *item, *subitem;
Amit Arora728e0c92010-09-14 12:06:09 +0530103
Amit Arora6e774cd2010-10-28 11:31:24 +0530104 (void)verbose;
Amit Arora29cb7572010-10-05 17:40:29 +0530105
Amit Arora6e774cd2010-10-28 11:31:24 +0530106 print_clock_header(clk_tree_level);
Amit Arora728e0c92010-09-14 12:06:09 +0530107
Amit Arora6e774cd2010-10-28 11:31:24 +0530108 sprintf(filename, "%s", clk_dir_path);
Amit Arora728e0c92010-09-14 12:06:09 +0530109
Amit Arora6e774cd2010-10-28 11:31:24 +0530110 dir = opendir(filename);
111 if (!dir)
112 return 0;
Amit Arora728e0c92010-09-14 12:06:09 +0530113
Amit Arora6e774cd2010-10-28 11:31:24 +0530114 while ((item = readdir(dir))) {
115 /* skip hidden dirs except ".." */
116 if (item->d_name[0] == '.' && strcmp(item->d_name, ".."))
117 continue;
Amit Arora728e0c92010-09-14 12:06:09 +0530118
Amit Arora6e774cd2010-10-28 11:31:24 +0530119 if (selected && hrow == line && !strcmp(item->d_name, "..")) {
120 sprintf(devpath, "%s", clk_dir_path);
121 strcpy(clockname, "..");
122 } else {
123 sprintf(devpath, "%s/%s", clk_dir_path, item->d_name);
124 strcpy(clockname, item->d_name);
125 }
Amit Arora728e0c92010-09-14 12:06:09 +0530126
Amit Arora6e774cd2010-10-28 11:31:24 +0530127 subdir = opendir(devpath);
Amit Arora728e0c92010-09-14 12:06:09 +0530128
Amit Arora6e774cd2010-10-28 11:31:24 +0530129 if (!subdir)
130 continue;
Amit Arora728e0c92010-09-14 12:06:09 +0530131
Amit Arora6e774cd2010-10-28 11:31:24 +0530132 while ((subitem = readdir(subdir))) {
133 if (subitem->d_name[0] == '.') /* skip hidden files */
134 continue;
Amit Arora728e0c92010-09-14 12:06:09 +0530135
Amit Arora6e774cd2010-10-28 11:31:24 +0530136 sprintf(filename, "%s/%s", devpath, subitem->d_name);
Amit Arora728e0c92010-09-14 12:06:09 +0530137
Amit Arora6e774cd2010-10-28 11:31:24 +0530138 if (!strcmp(subitem->d_name, "flags"))
139 flags = get_int_from(filename);
Amit Arora728e0c92010-09-14 12:06:09 +0530140
Amit Arora6e774cd2010-10-28 11:31:24 +0530141 if (!strcmp(subitem->d_name, "rate"))
142 rate = get_int_from(filename);
Amit Arora728e0c92010-09-14 12:06:09 +0530143
Amit Arora6e774cd2010-10-28 11:31:24 +0530144 if (!strcmp(subitem->d_name, "usecount"))
145 usecount = get_int_from(filename);
146 }
Amit Arora24ed7d12010-09-14 12:12:58 +0530147
Amit Arora6e774cd2010-10-28 11:31:24 +0530148 if (hrow == line) {
149 if (!strcmp(clockname, "..")) {
150 if (clk_tree_level != 1) {
151 set_hl_dir_path_to_parent();
152 gadder = -1;
153 }
154 } else {
155 strcpy(highlighted_path, devpath);
156 gadder = 1;
157 }
158 }
Amit Arora24ed7d12010-09-14 12:12:58 +0530159
Amit Arora6e774cd2010-10-28 11:31:24 +0530160 print_clock_info_line(line, clockname, flags, rate, usecount,
161 (hrow == line) ? 1 : 0);
162 line++;
Amit Arora6e774cd2010-10-28 11:31:24 +0530163 closedir(subdir);
164 }
Amit Arora728e0c92010-09-14 12:06:09 +0530165
Amit Arora6e774cd2010-10-28 11:31:24 +0530166 closedir(dir);
Amit Arora728e0c92010-09-14 12:06:09 +0530167
Amit Arora6e774cd2010-10-28 11:31:24 +0530168 if (hrow >= (line - 1))
169 hrow = -1;
170 return hrow;
Amit Arora728e0c92010-09-14 12:06:09 +0530171}
Amit Arora0e512722010-10-01 12:24:16 +0530172
173void dump_clock_info(int verbose)
174{
Amit Arora6e774cd2010-10-28 11:31:24 +0530175 (void)verbose;
176 printf("Clock Tree :\n");
177 printf("**********\n");
178 read_clock_info(clk_dir_path);
179 print_clock_info(clocks_info, 1, 1);
Amit Arora0e512722010-10-01 12:24:16 +0530180}
181
Amit Aroraeb6cba92010-10-25 16:03:21 +0530182void read_clock_info(char *clkpath)
Amit Arora0e512722010-10-01 12:24:16 +0530183{
Amit Arora6e774cd2010-10-28 11:31:24 +0530184 DIR *dir;
185 struct dirent *item;
186 char filename[NAME_MAX], clockname[NAME_MAX];
187 struct clock_info *child;
188 struct clock_info *cur;
Amit Arora0e512722010-10-01 12:24:16 +0530189
Amit Arora6e774cd2010-10-28 11:31:24 +0530190 dir = opendir(clkpath);
191 if (!dir)
192 return;
Amit Arora0e512722010-10-01 12:24:16 +0530193
Amit Arora6e774cd2010-10-28 11:31:24 +0530194 clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info));
195 memset(clocks_info, 0, sizeof(clocks_info));
196 strcpy(clocks_info->name, "/");
Amit Arora0e512722010-10-01 12:24:16 +0530197
Amit Arora6e774cd2010-10-28 11:31:24 +0530198 while ((item = readdir(dir))) {
199 /* skip hidden dirs except ".." */
200 if (item->d_name[0] == '.')
201 continue;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530202
Amit Arora6e774cd2010-10-28 11:31:24 +0530203 strcpy(clockname, item->d_name);
204 sprintf(filename, "%s/%s", clkpath, item->d_name);
205 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
206 memset(cur, 0, sizeof(cur));
207 strcpy(cur->name, clockname);
208 cur->parent = clocks_info;
209 insert_children(&clocks_info, cur);
210 child = read_clock_info_recur(filename, 2, cur);
211 }
212 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530213}
214
215struct clock_info *read_clock_info_recur(char *clkpath, int level,
Amit Arora6e774cd2010-10-28 11:31:24 +0530216 struct clock_info *parent)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530217{
Amit Arora6e774cd2010-10-28 11:31:24 +0530218 int ret = 0;
219 DIR *dir;
220 char filename[PATH_MAX];
221 struct dirent *item;
222 struct clock_info *cur = NULL;
223 struct stat buf;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530224
Amit Arora6e774cd2010-10-28 11:31:24 +0530225 dir = opendir(clkpath);
226 if (!dir)
227 return NULL;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530228
Amit Arora6e774cd2010-10-28 11:31:24 +0530229 while ((item = readdir(dir))) {
230 struct clock_info *child;
231 /* skip hidden dirs except ".." */
232 if (item->d_name[0] == '.' )
233 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530234
Amit Arora6e774cd2010-10-28 11:31:24 +0530235 sprintf(filename, "%s/%s", clkpath, item->d_name);
Amit Arora0e512722010-10-01 12:24:16 +0530236
Amit Arora6e774cd2010-10-28 11:31:24 +0530237 ret = stat(filename, &buf);
Amit Arora0e512722010-10-01 12:24:16 +0530238
Amit Arora6e774cd2010-10-28 11:31:24 +0530239 if (ret < 0) {
240 printf("Error doing a stat on %s\n", filename);
241 exit(1);
242 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530243
Amit Arora6e774cd2010-10-28 11:31:24 +0530244 if (S_ISREG(buf.st_mode)) {
245 if (!strcmp(item->d_name, "flags"))
246 parent->flags = get_int_from(filename);
247 if (!strcmp(item->d_name, "rate"))
248 parent->rate = get_int_from(filename);
249 if (!strcmp(item->d_name, "usecount"))
250 parent->usecount = get_int_from(filename);
251 continue;
252 }
Amit Aroraeb6cba92010-10-25 16:03:21 +0530253
Amit Arora6e774cd2010-10-28 11:31:24 +0530254 if (!S_ISDIR(buf.st_mode))
255 continue;
Amit Arora0e512722010-10-01 12:24:16 +0530256
Amit Arora6e774cd2010-10-28 11:31:24 +0530257 cur = (struct clock_info *)malloc(sizeof(struct clock_info));
258 memset(cur, 0, sizeof(cur));
259 strcpy(cur->name, item->d_name);
260 cur->children = NULL;
261 cur->parent = NULL;
262 cur->num_children = 0;
263 child = read_clock_info_recur(filename, level + 1, cur);
Amit Arora0e512722010-10-01 12:24:16 +0530264
Amit Arora6e774cd2010-10-28 11:31:24 +0530265 insert_children(&parent, cur);
266 cur->parent = parent;
267 }
268 closedir(dir);
Amit Aroraeb6cba92010-10-25 16:03:21 +0530269
Amit Arora6e774cd2010-10-28 11:31:24 +0530270 return cur;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530271}
272
273void insert_children(struct clock_info **parent, struct clock_info *clk)
274{
Amit Arora6e774cd2010-10-28 11:31:24 +0530275 if (!(*parent)->children) {
276 (*parent)->children = (struct clock_info **)
277 malloc(sizeof(struct clock_info *)*2);
278 (*parent)->num_children = 0;
279 } else
280 (*parent)->children = (struct clock_info **)
281 realloc((*parent)->children,
282 sizeof(struct clock_info *) *
283 ((*parent)->num_children + 2));
284 if ((*parent)->num_children > 0)
285 (*parent)->children[(*parent)->num_children - 1]->last_child
286 = 0;
287 clk->last_child = 1;
288 (*parent)->children[(*parent)->num_children] = clk;
289 (*parent)->children[(*parent)->num_children + 1] = NULL;
290 (*parent)->num_children++;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530291}
292
293
294void print_clock_info(struct clock_info *clk, int level, int bmp)
295{
Amit Arora6e774cd2010-10-28 11:31:24 +0530296 int i, j;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530297
Amit Arora6e774cd2010-10-28 11:31:24 +0530298 if (!clk)
299 return;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530300
Amit Arora6e774cd2010-10-28 11:31:24 +0530301 for (i = 1, j = 0; i < level; i++, j = (i - 1)) {
302 if (i == (level - 1)) {
303 if (clk->last_child)
304 printf("`-- ");
305 else
306 printf("|-- ");
307 } else {
308 if ((1<<j) & bmp)
309 printf("| ");
310 else
311 printf(" ");
312 }
313 }
314 if (clk == clocks_info)
315 printf("%s\n", clk->name);
316 else {
317 char *unit = "Hz";
318 double drate = (double)clk->rate;
319
320 if (drate > 1000 && drate < 1000000) {
321 unit = "KHz";
322 drate /= 1000;
323 }
324 if (drate > 1000000) {
325 unit = "MHz";
326 drate /= 1000000;
327 }
328 printf("%s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
329 clk->name, clk->flags, clk->usecount, drate, unit);
Amit Arora6e774cd2010-10-28 11:31:24 +0530330 }
331 if (clk->children) {
332 int tbmp = bmp;
333 int xbmp = -1;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530334
Amit Arora6e774cd2010-10-28 11:31:24 +0530335 if (clk->last_child) {
336 xbmp ^= 1 << (level - 2);
337
338 xbmp = tbmp & xbmp;
339 } else
340 xbmp = bmp;
341 for (i = 0; i < clk->num_children; i++) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530342 tbmp = xbmp | (1 << level);
343 print_clock_info(clk->children[i], level + 1, tbmp);
344 }
345 }
Amit Arora0e512722010-10-01 12:24:16 +0530346}
Amit Aroraed3e5652010-10-27 12:02:53 +0530347
348char *debugfs_locate_mpoint(void)
349{
350 int ret;
351 FILE *filep;
352 char **path;
353 char fsname[64];
354 struct statfs sfs;
355
356 path = likely_mpoints;
357 while (*path) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530358 ret = statfs(*path, &sfs);
359 if (ret >= 0 && sfs.f_type == (long)DEBUGFS_MAGIC)
Amit Aroraed3e5652010-10-27 12:02:53 +0530360 return *path;
361 path++;
362 }
363
364 filep = fopen("/proc/mounts", "r");
365 if (filep == NULL) {
366 fprintf(stderr, "powerdebug: Error opening /proc/mounts.");
Amit Arora6e774cd2010-10-28 11:31:24 +0530367 exit(1);
368 }
Amit Aroraed3e5652010-10-27 12:02:53 +0530369
370 while (fscanf(filep, "%*s %s %s %*s %*d %*d\n",
371 debugfs_mntpoint, fsname) == 2)
372 if (!strcmp(fsname, "debugfs"))
373 break;
374 fclose(filep);
375
376 if (strcmp(fsname, "debugfs"))
377 return NULL;
378
379 return debugfs_mntpoint;
380}