blob: b57de3d54337b71c1257e24056444885142f2cf0 [file] [log] [blame]
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00001/*
2 * Power debug tool (powerdebug)
Amit Arora728e0c92010-09-14 12:06:09 +05303 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00004 * Copyright (C) 2016, Linaro Limited.
Amit Arora728e0c92010-09-14 12:06:09 +05305 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00006 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
Amit Arora728e0c92010-09-14 12:06:09 +053010 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +000011 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020015 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +000016 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020019 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +000020 */
Amit Arora728e0c92010-09-14 12:06:09 +053021
Daniel Lezcano141c0482011-06-08 23:30:00 +020022#ifndef _GNU_SOURCE
23#define _GNU_SOURCE
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010024#include <stdio.h>
Daniel Lezcano141c0482011-06-08 23:30:00 +020025#undef _GNU_SOURCE
26#endif
Daniel Lezcano15627482011-06-15 15:45:12 +020027#include <string.h>
28#include <stdbool.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <sys/param.h>
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010032#include <mntent.h>
Daniel Lezcanoef323192011-03-26 22:06:20 +010033#include <sys/stat.h>
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010034
Amit Arora728e0c92010-09-14 12:06:09 +053035#include "powerdebug.h"
Daniel Lezcanob301b082011-06-15 15:45:12 +020036#include "display.h"
Daniel Lezcanoc193b602011-06-08 23:30:00 +020037#include "tree.h"
Daniel Lezcano88b38e32011-06-15 15:45:12 +020038#include "utils.h"
Amit Arora24ed7d12010-09-14 12:12:58 +053039
Shaojie Sun73e5d972013-08-21 17:04:34 +080040#ifndef uint
41#define uint unsigned int
42#endif
43
44
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020045struct clock_info {
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020046 int flags;
Shaojie Sun73e5d972013-08-21 17:04:34 +080047 uint rate;
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020048 int usecount;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020049 bool expanded;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +020050 char *prefix;
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +053051 int preparecount;
52 int enablecount;
53 int notifiercount;
Daniel Lezcanoc45662b2011-06-08 23:30:00 +020054} *clocks_info;
55
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +053056enum clock_fw_type{
57 CCF, /* common clock framework */
58 OCF, /* old clock framework */
59 MAX,
60};
61
Daniel Lezcano9d5431c2011-06-08 23:30:00 +020062static struct tree *clock_tree = NULL;
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +053063static int clock_fw;
Daniel Lezcanoc193b602011-06-08 23:30:00 +020064
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010065static int locate_debugfs(char *clk_path)
66{
Nishanth Menona14971b2011-09-20 11:31:17 +020067 strcpy(clk_path, "/sys/kernel/debug");
68 return 0;
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010069}
70
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020071static struct clock_info *clock_alloc(void)
Amit Arora24ed7d12010-09-14 12:12:58 +053072{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020073 struct clock_info *ci;
Daniel Lezcano9dc3fb32011-03-26 22:06:08 +010074
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020075 ci = malloc(sizeof(*ci));
76 if (ci)
77 memset(ci, 0, sizeof(*ci));
Daniel Lezcanoc5a65bf2011-03-26 22:06:11 +010078
Daniel Lezcano2adc48d2011-06-08 23:30:01 +020079 return ci;
Amit Arora24ed7d12010-09-14 12:12:58 +053080}
Amit Arora728e0c92010-09-14 12:06:09 +053081
Shaojie Sun2489bc72013-08-21 17:27:33 +080082static inline bool is_hex_clock(uint rate)
83{
84 return rate%10;
85}
86
Shaojie Sun73e5d972013-08-21 17:04:34 +080087static inline const char *clock_rate(uint *rate)
Daniel Lezcanoc6718332011-03-23 14:37:39 +010088{
Shaojie Sun2489bc72013-08-21 17:27:33 +080089 uint r, mod;
90 bool is_hex = is_hex_clock(*rate);
Daniel Lezcanoc6718332011-03-23 14:37:39 +010091
Daniel Lezcanoafe62252011-06-08 23:30:00 +020092 /* GHZ */
Shaojie Sun2489bc72013-08-21 17:27:33 +080093 if (is_hex) {
94 r = *rate >> 30;
95 mod = *rate&((1<<30)-1);
96 } else {
97 r = *rate / 1000000000;
98 mod = *rate % 1000000000;
99 }
100 if (r && !mod) {
101 *rate = r;
102 return "GHZ";
103 }
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100104
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200105 /* MHZ */
Shaojie Sun2489bc72013-08-21 17:27:33 +0800106 if (is_hex) {
107 r = *rate >> 20;
108 mod = *rate&((1<<20)-1);
109 } else {
110 r = *rate / 1000000;
111 mod = *rate % 1000000;
112 }
113 if (r && !mod) {
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200114 *rate = r;
115 return "MHZ";
116 }
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100117
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200118 /* KHZ */
Shaojie Sun2489bc72013-08-21 17:27:33 +0800119 if (is_hex) {
120 r = *rate >> 10;
121 mod = *rate&((1<<10)-1);
122 } else {
123 r = *rate / 1000;
124 mod = *rate % 1000;
125 }
126 if (r && !mod) {
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200127 *rate = r;
128 return "KHZ";
129 }
130
131 return "";
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100132}
133
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200134static int dump_clock_cb(struct tree *t, void *data)
Daniel Lezcanoef323192011-03-26 22:06:20 +0100135{
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200136 struct clock_info *clk = t->private;
137 struct clock_info *pclk;
138 const char *unit;
139 int ret = 0;
Shaojie Sun73e5d972013-08-21 17:04:34 +0800140 uint rate = clk->rate;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100141
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200142 if (!t->parent) {
143 printf("/\n");
144 clk->prefix = "";
145 return 0;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100146 }
147
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200148 pclk = t->parent->private;
149
150 if (!clk->prefix)
151 ret = asprintf(&clk->prefix, "%s%s%s", pclk->prefix,
152 t->depth > 1 ? " ": "", t->next ? "|" : " ");
153 if (ret < 0)
154 return -1;
155
156 unit = clock_rate(&rate);
157
Shaojie Sun73e5d972013-08-21 17:04:34 +0800158 printf("%s%s-- %s (flags:0x%x, usecount:%d, rate: %u %s)\n",
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200159 clk->prefix, !t->next ? "`" : "", t->name, clk->flags,
160 clk->usecount, rate, unit);
161
162 return 0;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100163}
164
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200165int dump_clock_info(void)
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100166{
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200167 return tree_for_each(clock_tree, dump_clock_cb, NULL);
168}
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100169
Daniel Lezcano3e38e0f2011-06-08 23:30:00 +0200170static int dump_all_parents(char *clkarg)
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200171{
172 struct tree *tree;
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100173
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200174 tree = tree_find(clock_tree, clkarg);
175 if (!tree) {
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100176 printf("Clock NOT found!\n");
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200177 return -1;
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100178 }
Daniel Lezcanoafe62252011-06-08 23:30:00 +0200179
180 return tree_for_each_parent(tree, dump_clock_cb, NULL);
Daniel Lezcanoc6718332011-03-23 14:37:39 +0100181}
182
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200183static inline int read_clock_cb(struct tree *t, void *data)
Daniel Lezcanoef323192011-03-26 22:06:20 +0100184{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200185 struct clock_info *clk = t->private;
Daniel Lezcanoef323192011-03-26 22:06:20 +0100186
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530187 if(clock_fw == CCF) {
188 file_read_value(t->path, "clk_flags", "%x", &clk->flags);
Shaojie Sun73e5d972013-08-21 17:04:34 +0800189 file_read_value(t->path, "clk_rate", "%u", &clk->rate);
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530190 file_read_value(t->path, "clk_prepare_count", "%d", &clk->preparecount);
191 file_read_value(t->path, "clk_enable_count", "%d", &clk->enablecount);
192 file_read_value(t->path, "clk_notifier_count", "%d", &clk->notifiercount);
193 }
194 else {
195 file_read_value(t->path, "flags", "%x", &clk->flags);
Shaojie Sun73e5d972013-08-21 17:04:34 +0800196 file_read_value(t->path, "rate", "%u", &clk->rate);
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530197 file_read_value(t->path, "usecount", "%d", &clk->usecount);
198 }
Amit Arora3bc8c922010-11-16 11:27:38 +0530199
200 return 0;
201}
202
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200203static int read_clock_info(struct tree *tree)
Amit Aroraac4e8652010-11-09 11:16:53 +0530204{
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200205 return tree_for_each(tree, read_clock_cb, NULL);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200206}
207
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200208static int fill_clock_cb(struct tree *t, void *data)
209{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200210 struct clock_info *clk;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200211
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200212 clk = clock_alloc();
213 if (!clk)
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200214 return -1;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200215 t->private = clk;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200216
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200217 /* we skip the root node but we set it expanded for its children */
218 if (!t->parent) {
219 clk->expanded = true;
220 return 0;
221 }
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200222
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200223 return read_clock_cb(t, data);
224}
225
226static int fill_clock_tree(void)
227{
228 return tree_for_each(clock_tree, fill_clock_cb, NULL);
229}
230
231static int is_collapsed(struct tree *t, void *data)
232{
233 struct clock_info *clk = t->private;
234
235 if (!clk->expanded)
236 return 1;
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200237
238 return 0;
239}
240
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200241static char *clock_line(struct tree *t)
Amit Aroraeb6cba92010-10-25 16:03:21 +0530242{
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200243 struct clock_info *clk;
Shaojie Sun73e5d972013-08-21 17:04:34 +0800244 uint rate;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200245 const char *clkunit;
246 char *clkrate, *clkname, *clkline = NULL;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200247
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200248 clk = t->private;
249 rate = clk->rate;
250 clkunit = clock_rate(&rate);
251
252 if (asprintf(&clkname, "%*s%s", (t->depth - 1) * 2, "", t->name) < 0)
253 return NULL;
254
255 if (asprintf(&clkrate, "%d%s", rate, clkunit) < 0)
256 goto free_clkname;
257
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530258 if(clock_fw == CCF) {
259 if (asprintf(&clkline, "%-35s 0x%-8x %-12s %-10d %-11d %-15d %-14d %-10d",
260 clkname, clk->flags, clkrate, clk->usecount, t->nrchild,
261 clk->preparecount, clk->enablecount, clk->notifiercount) < 0)
262 goto free_clkrate;
263 }
264 else {
265 if (asprintf(&clkline, "%-55s 0x%-16x %-12s %-9d %-8d",
266 clkname, clk->flags, clkrate, clk->usecount, t->nrchild) < 0)
267 goto free_clkrate;
268 }
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200269
270free_clkrate:
271 free(clkrate);
272free_clkname:
273 free(clkname);
274
275 return clkline;
276}
277
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200278static int _clock_print_info_cb(struct tree *t, void *data)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200279{
280 struct clock_info *clock = t->private;
281 int *line = data;
282 char *buffer;
283
Daniel Lezcano73b40022011-06-21 00:57:08 +0200284 /* we skip the root node of the tree */
285 if (!t->parent)
286 return 0;
287
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200288 buffer = clock_line(t);
289 if (!buffer)
Daniel Lezcano9d5431c2011-06-08 23:30:00 +0200290 return -1;
291
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200292 display_print_line(CLOCK, *line, buffer, clock->usecount, t);
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200293
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200294 (*line)++;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200295
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200296 free(buffer);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200297
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200298 return 0;
299}
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200300
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200301static int clock_print_info_cb(struct tree *t, void *data)
302{
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200303 /* we skip the root node of the tree */
304 if (!t->parent)
305 return 0;
306
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200307 /* show the clock when *all* its parent is expanded */
308 if (tree_for_each_parent(t->parent, is_collapsed, NULL))
309 return 0;
310
311 return _clock_print_info_cb(t, data);
312}
313
Daniel Lezcanofa453332011-06-21 00:57:08 +0200314static int clock_print_header(void)
315{
316 char *buf;
317 int ret;
318
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530319 if(clock_fw == CCF) {
320 if (asprintf(&buf, "%-35s %-10s %-12s %-10s %-11s %-15s %-14s %-14s",
321 "Name", "Flags", "Rate", "Usecount", "Children", "Prepare_Count",
322 "Enable_Count", "Notifier_Count") < 0)
323 return -1;
324 }
325 else {
326 if (asprintf(&buf, "%-55s %-16s %-12s %-9s %-8s",
Daniel Lezcanofa453332011-06-21 00:57:08 +0200327 "Name", "Flags", "Rate", "Usecount", "Children") < 0)
328 return -1;
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530329 }
Daniel Lezcanofa453332011-06-21 00:57:08 +0200330
Daniel Lezcano372ffba2011-06-21 00:57:08 +0200331 ret = display_column_name(buf);
Daniel Lezcanofa453332011-06-21 00:57:08 +0200332
333 free(buf);
334
335 return ret;
336}
337
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200338static int clock_print_info(struct tree *tree)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200339{
340 int ret, line = 0;
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200341
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200342 display_reset_cursor(CLOCK);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200343
Daniel Lezcanofa453332011-06-21 00:57:08 +0200344 clock_print_header();
345
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200346 ret = tree_for_each(tree, clock_print_info_cb, &line);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200347
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200348 display_refresh_pad(CLOCK);
Daniel Lezcanob2565a82011-06-08 23:30:00 +0200349
350 return ret;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200351}
352
Daniel Lezcano73b40022011-06-21 00:57:08 +0200353static int clock_select(void)
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200354{
Daniel Lezcanob3e6e812011-06-15 15:45:12 +0200355 struct tree *t = display_get_row_data(CLOCK);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200356 struct clock_info *clk = t->private;
357
358 clk->expanded = !clk->expanded;
359
360 return 0;
361}
362
363/*
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200364 * Read the clock information and fill the tree with the information
365 * found in the files. Then print the result to the text based interface
366 * Return 0 on success, < 0 otherwise
367 */
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200368static int clock_display(bool refresh)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200369{
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200370 if (refresh && read_clock_info(clock_tree))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200371 return -1;
372
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200373 return clock_print_info(clock_tree);
374}
375
Daniel Lezcano73b40022011-06-21 00:57:08 +0200376static int clock_find(const char *name)
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200377{
378 struct tree **ptree = NULL;
379 int i, nr, line = 0, ret = 0;
380
381 nr = tree_finds(clock_tree, name, &ptree);
382
383 display_reset_cursor(CLOCK);
384
385 for (i = 0; i < nr; i++) {
386
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200387 ret = _clock_print_info_cb(ptree[i], &line);
388 if (ret)
389 break;
Daniel Lezcanod577aaa2011-06-21 00:57:08 +0200390
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200391 }
392
393 display_refresh_pad(CLOCK);
394
395 free(ptree);
396
397 return ret;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200398}
399
Daniel Lezcano73b40022011-06-21 00:57:08 +0200400static int clock_selectf(void)
401{
402 struct tree *t = display_get_row_data(CLOCK);
403 int line = 0;
404
405 display_reset_cursor(CLOCK);
406
407 if (tree_for_each_parent(t, _clock_print_info_cb, &line))
408 return -1;
409
410 return display_refresh_pad(CLOCK);
411}
412
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200413/*
414 * Read the clock information and fill the tree with the information
415 * found in the files. Then dump to stdout a formatted result.
416 * @clk : a name for a specific clock we want to show
417 * Return 0 on success, < 0 otherwise
418 */
Daniel Lezcano597892a2011-06-15 15:45:12 +0200419int clock_dump(char *clk)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200420{
421 int ret;
422
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200423 if (read_clock_info(clock_tree))
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200424 return -1;
Amit Aroraeb6cba92010-10-25 16:03:21 +0530425
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200426 if (clk) {
427 printf("\nParents for \"%s\" Clock :\n\n", clk);
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200428 ret = dump_all_parents(clk);
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200429 printf("\n\n");
430 } else {
431 printf("\nClock Tree :\n");
432 printf("**********\n");
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200433 ret = dump_clock_info();
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200434 printf("\n\n");
435 }
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200436
437 return ret;
Daniel Lezcano28b53cd2011-06-08 23:30:00 +0200438}
Daniel Lezcanob301b082011-06-15 15:45:12 +0200439
440static struct display_ops clock_ops = {
441 .display = clock_display,
Daniel Lezcano73b40022011-06-21 00:57:08 +0200442 .select = clock_select,
Daniel Lezcanoa12163d2011-06-21 00:57:08 +0200443 .find = clock_find,
Daniel Lezcano73b40022011-06-21 00:57:08 +0200444 .selectf = clock_selectf,
Daniel Lezcanob301b082011-06-15 15:45:12 +0200445};
446
447/*
448 * Initialize the clock framework
449 */
Daniel Lezcanob4eec7e2016-02-18 16:44:55 +0000450int clock_init(struct powerdebug_options *options)
Daniel Lezcanob301b082011-06-15 15:45:12 +0200451{
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530452 char clk_dir_path[MAX+1][PATH_MAX];
Daniel Lezcanob301b082011-06-15 15:45:12 +0200453
Daniel Lezcanob4eec7e2016-02-18 16:44:55 +0000454 if (!(options->flags & CLOCK_OPTION))
455 return 0;
456
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530457 if (locate_debugfs(clk_dir_path[CCF]) || locate_debugfs(clk_dir_path[OCF]))
Daniel Lezcanob301b082011-06-15 15:45:12 +0200458 return -1;
459
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530460 sprintf(clk_dir_path[CCF], "%s/clk", clk_dir_path[CCF]);
461 sprintf(clk_dir_path[OCF], "%s/clock", clk_dir_path[OCF]);
462 if (!access(clk_dir_path[CCF], F_OK)) {
463 clock_fw = CCF;
464 strcpy(clk_dir_path[MAX],clk_dir_path[CCF]);
465 }
466 else if(!access(clk_dir_path[OCF], F_OK)) {
467 clock_fw = OCF;
468 strcpy(clk_dir_path[MAX],clk_dir_path[OCF]);
469 }
470 else
Daniel Lezcanob301b082011-06-15 15:45:12 +0200471 return -1;
472
Sanjay Singh Rawat88fdebb2013-01-24 18:13:47 +0530473 clock_tree = tree_load(clk_dir_path[MAX], NULL, false);
Daniel Lezcanob301b082011-06-15 15:45:12 +0200474 if (!clock_tree)
475 return -1;
476
Daniel Lezcanocaafece2011-06-27 22:59:17 +0200477 if (fill_clock_tree())
478 return -1;
479
480 return display_register(CLOCK, &clock_ops);
Daniel Lezcanob301b082011-06-15 15:45:12 +0200481}