blob: 5cf9da7f3ca5034dcfd48a7a3ef2e612b6964b6e [file] [log] [blame]
Amit Arora39f29542010-09-14 12:03:22 +05301/*******************************************************************************
Amit Kucheriac0e17fc2011-01-17 09:35:52 +02002 * Copyright (C) 2010, Linaro Limited.
Amit Arora39f29542010-09-14 12:03:22 +05303 *
4 * This file is part of PowerDebug.
5 *
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors:
12 * Amit Arora <amit.arora@linaro.org> (IBM Corporation)
13 * - initial API and implementation
14 *******************************************************************************/
15
Amit Arorae9e16b02010-08-03 10:15:20 +053016#include <getopt.h>
Daniel Lezcanoc5afe832011-03-23 14:37:36 +010017#include <stdbool.h>
Daniel Lezcano2ef06e92011-05-24 15:27:49 +020018#include <math.h>
Daniel Lezcanocac52d92011-03-26 22:05:49 +010019#include "regulator.h"
Daniel Lezcano192c1d22011-03-26 22:06:14 +010020#include "display.h"
Daniel Lezcanof0e06652011-03-26 22:06:19 +010021#include "clocks.h"
Amit Arorae9e16b02010-08-03 10:15:20 +053022#include "powerdebug.h"
23
Daniel Lezcano20be6782011-03-26 22:06:03 +010024static int highlighted_row;
Amit Arorae9e16b02010-08-03 10:15:20 +053025
Amit Arora422c52f2010-12-02 16:22:29 +053026void usage(void)
Amit Arorae9e16b02010-08-03 10:15:20 +053027{
Amit Arora422c52f2010-12-02 16:22:29 +053028 printf("Usage: powerdebug [OPTIONS]\n");
29 printf("\n");
30 printf("powerdebug -d [ -r ] [ -s ] [ -c [ -p <clock-name> ] ] "
31 "[ -v ]\n");
32 printf("powerdebug [ -r | -s | -c ]\n");
Amit Arora17552782010-12-02 12:23:14 +053033 printf(" -r, --regulator Show regulator information\n");
34 printf(" -s, --sensor Show sensor information\n");
35 printf(" -c, --clock Show clock information\n");
Amit Arora422c52f2010-12-02 16:22:29 +053036 printf(" -p, --findparents Show all parents for a particular"
Amit Kucheriaa0adae42011-01-12 10:54:23 -060037 " clock\n");
Amit Arora17552782010-12-02 12:23:14 +053038 printf(" -t, --time Set ticktime in seconds (eg. 10.0)\n");
39 printf(" -d, --dump Dump information once (no refresh)\n");
Amit Arora422c52f2010-12-02 16:22:29 +053040 printf(" -v, --verbose Verbose mode (use with -r and/or"
Amit Kucheriaa0adae42011-01-12 10:54:23 -060041 " -s)\n");
Amit Arora17552782010-12-02 12:23:14 +053042 printf(" -V, --version Show Version\n");
43 printf(" -h, --help Help\n");
Amit Arorae9e16b02010-08-03 10:15:20 +053044}
45
Amit Arora17552782010-12-02 12:23:14 +053046void version()
Amit Arorae9e16b02010-08-03 10:15:20 +053047{
Amit Arora17552782010-12-02 12:23:14 +053048 printf("powerdebug version %s\n", VERSION);
Amit Arorae9e16b02010-08-03 10:15:20 +053049}
50
Daniel Lezcano316bcae2011-03-23 14:37:30 +010051/*
52 * Options:
53 * -r, --regulator : regulator
54 * -s, --sensor : sensors
55 * -c, --clock : clocks
56 * -p, --findparents : clockname whose parents have to be found
57 * -t, --time : ticktime
58 * -d, --dump : dump
59 * -v, --verbose : verbose
60 * -V, --version : version
61 * -h, --help : help
62 * no option / default : show usage!
63 */
64
65static struct option long_options[] = {
66 { "regulator", 0, 0, 'r' },
67 { "sensor", 0, 0, 's' },
68 { "clock", 0, 0, 'c' },
69 { "findparents", 1, 0, 'p' },
70 { "time", 1, 0, 't' },
71 { "dump", 0, 0, 'd' },
72 { "verbose", 0, 0, 'v' },
73 { "version", 0, 0, 'V' },
74 { "help", 0, 0, 'h' },
75 { 0, 0, 0, 0 }
76};
77
78struct powerdebug_options {
Daniel Lezcanoc5afe832011-03-23 14:37:36 +010079 bool verbose;
Daniel Lezcanoc5afe832011-03-23 14:37:36 +010080 bool regulators;
81 bool sensors;
82 bool clocks;
Daniel Lezcanoa70d9492011-03-23 14:37:40 +010083 bool dump;
Daniel Lezcanoc5afe832011-03-23 14:37:36 +010084 unsigned int ticktime;
Daniel Lezcano558a6d52011-03-23 14:37:41 +010085 int selectedwindow;
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +010086 char *clkname;
Daniel Lezcano316bcae2011-03-23 14:37:30 +010087};
88
89int getoptions(int argc, char *argv[], struct powerdebug_options *options)
Amit Arorae9e16b02010-08-03 10:15:20 +053090{
Daniel Lezcano316bcae2011-03-23 14:37:30 +010091 int c;
Amit Arorae9e16b02010-08-03 10:15:20 +053092
Daniel Lezcano316bcae2011-03-23 14:37:30 +010093 memset(options, 0, sizeof(*options));
94 options->ticktime = 10;
Daniel Lezcano558a6d52011-03-23 14:37:41 +010095 options->selectedwindow = -1;
Amit Arorae9e16b02010-08-03 10:15:20 +053096
Amit Arorafefe8bf2010-08-05 13:31:20 +053097 while (1) {
98 int optindex = 0;
Amit Arorafefe8bf2010-08-05 13:31:20 +053099
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100100 c = getopt_long(argc, argv, "rscp:t:dvVh",
101 long_options, &optindex);
Amit Arorafefe8bf2010-08-05 13:31:20 +0530102 if (c == -1)
103 break;
104
105 switch (c) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530106 case 'r':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100107 options->regulators = true;
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100108 options->selectedwindow = REGULATOR;
Amit Arora6e774cd2010-10-28 11:31:24 +0530109 break;
110 case 's':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100111 options->sensors = true;
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100112 options->selectedwindow = SENSOR;
Amit Arora6e774cd2010-10-28 11:31:24 +0530113 break;
114 case 'c':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100115 options->clocks = true;
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100116 options->selectedwindow = CLOCK;
Amit Arora6e774cd2010-10-28 11:31:24 +0530117 break;
Amit Aroraf4fb8102010-11-30 13:55:50 +0530118 case 'p':
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100119 options->clkname = strdup(optarg);
120 if (!options->clkname) {
Daniel Lezcano9420fde2011-03-23 14:37:31 +0100121 fprintf(stderr, "failed to allocate memory");
122 return -1;
123 }
Amit Kucheriaeab558a2011-03-25 09:51:41 +0200124 options->dump = true; /* Assume -dc in case of -p */
125 options->clocks = true;
Amit Aroraf4fb8102010-11-30 13:55:50 +0530126 break;
Amit Arora6e774cd2010-10-28 11:31:24 +0530127 case 't':
Daniel Lezcano7f112da2011-03-23 14:37:32 +0100128 options->ticktime = atoi(optarg);
Amit Arora6e774cd2010-10-28 11:31:24 +0530129 break;
130 case 'd':
Daniel Lezcanoa70d9492011-03-23 14:37:40 +0100131 options->dump = true;
Amit Arora6e774cd2010-10-28 11:31:24 +0530132 break;
133 case 'v':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100134 options->verbose = true;
Amit Arora6e774cd2010-10-28 11:31:24 +0530135 break;
136 case 'V':
137 version();
138 break;
Amit Arora6e774cd2010-10-28 11:31:24 +0530139 case '?':
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100140 fprintf(stderr, "%s: Unknown option %c'.\n",
Amit Kucheriaa0adae42011-01-12 10:54:23 -0600141 argv[0], optopt);
Amit Arora6e774cd2010-10-28 11:31:24 +0530142 default:
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100143 return -1;
Amit Arorafefe8bf2010-08-05 13:31:20 +0530144 }
Amit Arorae9e16b02010-08-03 10:15:20 +0530145 }
Amit Aroraa06a7302010-12-02 15:59:37 +0530146
Daniel Lezcano934fc092011-03-26 22:06:18 +0100147 /* No system specified to be dump, let's default to all */
148 if (!options->regulators && !options->clocks && !options->sensors)
149 options->regulators = options->clocks = options->sensors = true;
Amit Arorafefe8bf2010-08-05 13:31:20 +0530150
Daniel Lezcanoc9c14622011-03-26 22:06:10 +0100151 if (options->selectedwindow == -1)
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100152 options->selectedwindow = CLOCK;
Amit Arorae9e16b02010-08-03 10:15:20 +0530153
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100154 return 0;
155}
156
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100157int keystroke_callback(bool *enter_hit, bool *findparent_ncurses,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200158 char *clkname_str, bool *refreshwin, bool *cont,
Daniel Lezcano60a41022011-03-23 14:37:35 +0100159 struct powerdebug_options *options)
160{
161 char keychar;
162 int keystroke = getch();
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100163 int oldselectedwin = options->selectedwindow;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100164
165 if (keystroke == EOF)
166 exit(0);
167
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200168 if (keystroke == KEY_RIGHT || keystroke == '\t') {
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100169 options->selectedwindow++;
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200170 options->selectedwindow %= TOTAL_FEATURE_WINS;
171 }
Daniel Lezcano60a41022011-03-23 14:37:35 +0100172
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200173 if (keystroke == KEY_LEFT || keystroke == KEY_BTAB) {
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100174 options->selectedwindow--;
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200175 if (options->selectedwindow < 0)
176 options->selectedwindow = TOTAL_FEATURE_WINS - 1;
177 }
Daniel Lezcano60a41022011-03-23 14:37:35 +0100178
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100179 if (options->selectedwindow == CLOCK) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200180
181 if (keystroke == KEY_DOWN) {
182 display_next_line();
183 *cont = true;
184 }
185
186 if (keystroke == KEY_UP) {
187 display_prev_line();
188 *cont = true;
189 }
190
191#if 0
192 /* TODO : fix with a new panel applicable for all subsystems */
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200193 if (keystroke == '/')
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100194 *findparent_ncurses = true;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200195#endif
Daniel Lezcano60a41022011-03-23 14:37:35 +0100196
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200197 if ((keystroke == '\e' || oldselectedwin !=
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100198 options->selectedwindow) && *findparent_ncurses) {
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100199 *findparent_ncurses = false;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100200 clkname_str[0] = '\0';
201 }
202
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200203 if (*findparent_ncurses && keystroke != '\r') {
Daniel Lezcano60a41022011-03-23 14:37:35 +0100204 int len = strlen(clkname_str);
205 char str[2];
206
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200207 if (keystroke == KEY_BACKSPACE) {
Daniel Lezcano60a41022011-03-23 14:37:35 +0100208 if (len > 0)
209 len--;
210
211 clkname_str[len] = '\0';
212 } else {
213 if (strlen(clkname_str) ||
214 keystroke != '/') {
215 str[0] = keystroke;
216 str[1] = '\0';
217 if (len < 63)
218 strcat(clkname_str,
219 str);
220 }
221 }
222 }
223 }
224
225 keychar = toupper(keystroke);
226//#define DEBUG
227#ifdef DEBUG
Daniel Lezcano1c25df92011-06-08 23:30:00 +0200228 fini_curses();
Daniel Lezcano60a41022011-03-23 14:37:35 +0100229 printf("key entered %d:%c\n", keystroke, keychar);
230 exit(1);
231#endif
232
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200233 if (keystroke == '\r')
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100234 *enter_hit = true;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100235
236 if (keychar == 'Q' && !*findparent_ncurses)
237 return 1;
238 if (keychar == 'R') {
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100239 *refreshwin = true;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100240 options->ticktime = 3;
241 } else
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100242 *refreshwin = false;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100243
244 return 0;
245}
246
Daniel Lezcano08198262011-03-26 22:06:02 +0100247int mainloop(struct powerdebug_options *options,
248 struct regulator_info *reg_info, int nr_reg)
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100249{
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100250 bool findparent_ncurses = false;
251 bool refreshwin = false;
252 bool enter_hit = false;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200253 bool cont = false;
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100254 char clkname_str[64];
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100255
Daniel Lezcano934fc092011-03-26 22:06:18 +0100256 strcpy(clkname_str, "");
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100257
Amit Kucheriaa0adae42011-01-12 10:54:23 -0600258 while (1) {
Amit Arora47fd9182010-08-24 13:26:06 +0530259 int key = 0;
260 struct timeval tval;
261 fd_set readfds;
Amit Arorae9e16b02010-08-03 10:15:20 +0530262
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200263 if (options->selectedwindow != CLOCK || !cont) {
264 create_windows(options->selectedwindow);
265 show_header(options->selectedwindow);
266 create_selectedwindow(options->selectedwindow);
267 }
Amit Aroraac4e8652010-11-09 11:16:53 +0530268
Daniel Lezcano95b0dac2011-06-08 23:30:00 +0200269 if (options->selectedwindow == REGULATOR) {
Daniel Lezcano08198262011-03-26 22:06:02 +0100270 regulator_read_info(reg_info, nr_reg);
Daniel Lezcanob5746712011-03-26 22:06:05 +0100271 show_regulator_info(reg_info, nr_reg,
272 options->verbose);
Amit Arora47fd9182010-08-24 13:26:06 +0530273 }
274
Daniel Lezcano95b0dac2011-06-08 23:30:00 +0200275 if (options->selectedwindow == CLOCK) {
Daniel Lezcano934fc092011-03-26 22:06:18 +0100276
Daniel Lezcanodf51b2f2011-05-24 15:27:49 +0200277 int hrow;
Amit Arora0e512722010-10-01 12:24:16 +0530278
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200279 if (!cont) {
Amit Aroraa06a7302010-12-02 15:59:37 +0530280
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200281 if (!findparent_ncurses) {
282 int command = 0;
283
284 if (enter_hit) {
285 clock_toggle_expanded();
286 command = CLOCK_SELECTED;
287 }
288 if (refreshwin)
289 command = REFRESH_WINDOW;
290 hrow = read_and_print_clock_info(
291 highlighted_row,
292 command);
293 highlighted_row = hrow;
294 enter_hit = false;
295 } else
296 find_parents_for_clock(clkname_str,
297 enter_hit);
298 } else cont = false;
Amit Arora6e774cd2010-10-28 11:31:24 +0530299 }
Amit Arora47fd9182010-08-24 13:26:06 +0530300
Daniel Lezcano95b0dac2011-06-08 23:30:00 +0200301 if (options->selectedwindow == SENSOR)
Daniel Lezcanob5746712011-03-26 22:06:05 +0100302 print_sensor_header();
Amit Arora47fd9182010-08-24 13:26:06 +0530303
Amit Arora47fd9182010-08-24 13:26:06 +0530304 FD_ZERO(&readfds);
305 FD_SET(0, &readfds);
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100306 tval.tv_sec = options->ticktime;
307 tval.tv_usec = (options->ticktime - tval.tv_sec) * 1000000;
Amit Arora47fd9182010-08-24 13:26:06 +0530308
Daniel Lezcanoe8cf9b82011-06-08 23:30:01 +0200309 again:
Amit Arora47fd9182010-08-24 13:26:06 +0530310 key = select(1, &readfds, NULL, NULL, &tval);
Daniel Lezcano60a41022011-03-23 14:37:35 +0100311 if (!key)
312 continue;
Amit Arora47fd9182010-08-24 13:26:06 +0530313
Daniel Lezcanoe8cf9b82011-06-08 23:30:01 +0200314 if (key < 0) {
315 if (errno == EINTR)
316 goto again;
317 break;
318 }
319
Daniel Lezcano60a41022011-03-23 14:37:35 +0100320 if (keystroke_callback(&enter_hit, &findparent_ncurses,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200321 clkname_str, &refreshwin, &cont, options))
Daniel Lezcano60a41022011-03-23 14:37:35 +0100322 break;
Amit Arora97006e52010-10-28 11:56:08 +0530323
Amit Arorae9e16b02010-08-03 10:15:20 +0530324 }
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100325
326 return 0;
327}
328
Daniel Lezcano21c04d42011-03-26 22:06:04 +0100329static int powerdebug_dump(struct powerdebug_options *options,
330 struct regulator_info *reg_info, int nr_reg)
331{
Daniel Lezcanob5746712011-03-26 22:06:05 +0100332 if (options->regulators) {
333 regulator_read_info(reg_info, nr_reg);
334 regulator_print_info(reg_info, nr_reg, options->verbose);
335 }
336
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200337 if (options->clocks)
338 read_and_dump_clock_info(options->clkname);
Daniel Lezcanob5746712011-03-26 22:06:05 +0100339
340 if (options->sensors)
341 read_and_print_sensor_info(options->verbose);
342
Daniel Lezcano21c04d42011-03-26 22:06:04 +0100343 return 0;
344}
345
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100346static int powerdebug_display(struct powerdebug_options *options,
347 struct regulator_info *reg_info, int nr_reg)
348{
349 if (display_init()) {
350 printf("failed to initialize display\n");
351 return -1;
352 }
353
354 if (mainloop(options, reg_info, nr_reg))
355 return -1;
356
357 return 0;
358}
359
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100360static struct powerdebug_options *powerdebug_init(void)
361{
362 struct powerdebug_options *options;
363
364 options = malloc(sizeof(*options));
365 if (!options)
366 return NULL;
367
368 memset(options, 0, sizeof(*options));
369
370 return options;
371}
372
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100373int main(int argc, char **argv)
374{
375 struct powerdebug_options *options;
Daniel Lezcano08198262011-03-26 22:06:02 +0100376 struct regulator_info *regulators_info;
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100377 int numregulators, ret;
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100378
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100379 options = powerdebug_init();
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100380 if (!options) {
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100381 fprintf(stderr, "not enough memory to allocate options\n");
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100382 return 1;
383 }
384
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100385 if (getoptions(argc, argv, options)) {
386 usage();
387 return 1;
388 }
389
Daniel Lezcano4aab2fe2011-03-26 22:05:53 +0100390 regulators_info = regulator_init(&numregulators);
391 if (!regulators_info) {
392 printf("not enough memory to allocate regulators info\n");
Daniel Lezcano6e48fa42011-03-26 22:06:23 +0100393 options->regulators = false;
Daniel Lezcano4aab2fe2011-03-26 22:05:53 +0100394 }
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100395
Daniel Lezcanof0e06652011-03-26 22:06:19 +0100396 if (clock_init()) {
397 printf("failed to initialize clock details (check debugfs)\n");
398 options->clocks = false;
399 }
400
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100401 ret = options->dump ?
402 powerdebug_dump(options, regulators_info, numregulators) :
403 powerdebug_display(options, regulators_info, numregulators);
Daniel Lezcano21c04d42011-03-26 22:06:04 +0100404
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100405 return ret < 0;
Amit Arorae9e16b02010-08-03 10:15:20 +0530406}