blob: 24db8c8a9ebe089842ddecacc8ed4b857b306fce [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
Amit Arora422c52f2010-12-02 16:22:29 +053024void usage(void)
Amit Arorae9e16b02010-08-03 10:15:20 +053025{
Amit Arora422c52f2010-12-02 16:22:29 +053026 printf("Usage: powerdebug [OPTIONS]\n");
27 printf("\n");
28 printf("powerdebug -d [ -r ] [ -s ] [ -c [ -p <clock-name> ] ] "
29 "[ -v ]\n");
30 printf("powerdebug [ -r | -s | -c ]\n");
Amit Arora17552782010-12-02 12:23:14 +053031 printf(" -r, --regulator Show regulator information\n");
32 printf(" -s, --sensor Show sensor information\n");
33 printf(" -c, --clock Show clock information\n");
Amit Arora422c52f2010-12-02 16:22:29 +053034 printf(" -p, --findparents Show all parents for a particular"
Amit Kucheriaa0adae42011-01-12 10:54:23 -060035 " clock\n");
Amit Arora17552782010-12-02 12:23:14 +053036 printf(" -t, --time Set ticktime in seconds (eg. 10.0)\n");
37 printf(" -d, --dump Dump information once (no refresh)\n");
Amit Arora422c52f2010-12-02 16:22:29 +053038 printf(" -v, --verbose Verbose mode (use with -r and/or"
Amit Kucheriaa0adae42011-01-12 10:54:23 -060039 " -s)\n");
Amit Arora17552782010-12-02 12:23:14 +053040 printf(" -V, --version Show Version\n");
41 printf(" -h, --help Help\n");
Amit Arorae9e16b02010-08-03 10:15:20 +053042}
43
Amit Arora17552782010-12-02 12:23:14 +053044void version()
Amit Arorae9e16b02010-08-03 10:15:20 +053045{
Amit Arora17552782010-12-02 12:23:14 +053046 printf("powerdebug version %s\n", VERSION);
Amit Arorae9e16b02010-08-03 10:15:20 +053047}
48
Daniel Lezcano316bcae2011-03-23 14:37:30 +010049/*
50 * Options:
51 * -r, --regulator : regulator
52 * -s, --sensor : sensors
53 * -c, --clock : clocks
54 * -p, --findparents : clockname whose parents have to be found
55 * -t, --time : ticktime
56 * -d, --dump : dump
57 * -v, --verbose : verbose
58 * -V, --version : version
59 * -h, --help : help
60 * no option / default : show usage!
61 */
62
63static struct option long_options[] = {
64 { "regulator", 0, 0, 'r' },
65 { "sensor", 0, 0, 's' },
66 { "clock", 0, 0, 'c' },
67 { "findparents", 1, 0, 'p' },
68 { "time", 1, 0, 't' },
69 { "dump", 0, 0, 'd' },
70 { "verbose", 0, 0, 'v' },
71 { "version", 0, 0, 'V' },
72 { "help", 0, 0, 'h' },
73 { 0, 0, 0, 0 }
74};
75
76struct powerdebug_options {
Daniel Lezcanoc5afe832011-03-23 14:37:36 +010077 bool verbose;
Daniel Lezcanoc5afe832011-03-23 14:37:36 +010078 bool regulators;
79 bool sensors;
80 bool clocks;
Daniel Lezcanoa70d9492011-03-23 14:37:40 +010081 bool dump;
Daniel Lezcanoc5afe832011-03-23 14:37:36 +010082 unsigned int ticktime;
Daniel Lezcano558a6d52011-03-23 14:37:41 +010083 int selectedwindow;
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +010084 char *clkname;
Daniel Lezcano316bcae2011-03-23 14:37:30 +010085};
86
87int getoptions(int argc, char *argv[], struct powerdebug_options *options)
Amit Arorae9e16b02010-08-03 10:15:20 +053088{
Daniel Lezcano316bcae2011-03-23 14:37:30 +010089 int c;
Amit Arorae9e16b02010-08-03 10:15:20 +053090
Daniel Lezcano316bcae2011-03-23 14:37:30 +010091 memset(options, 0, sizeof(*options));
92 options->ticktime = 10;
Daniel Lezcano558a6d52011-03-23 14:37:41 +010093 options->selectedwindow = -1;
Amit Arorae9e16b02010-08-03 10:15:20 +053094
Amit Arorafefe8bf2010-08-05 13:31:20 +053095 while (1) {
96 int optindex = 0;
Amit Arorafefe8bf2010-08-05 13:31:20 +053097
Daniel Lezcano316bcae2011-03-23 14:37:30 +010098 c = getopt_long(argc, argv, "rscp:t:dvVh",
99 long_options, &optindex);
Amit Arorafefe8bf2010-08-05 13:31:20 +0530100 if (c == -1)
101 break;
102
103 switch (c) {
Amit Arora6e774cd2010-10-28 11:31:24 +0530104 case 'r':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100105 options->regulators = true;
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100106 options->selectedwindow = REGULATOR;
Amit Arora6e774cd2010-10-28 11:31:24 +0530107 break;
108 case 's':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100109 options->sensors = true;
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100110 options->selectedwindow = SENSOR;
Amit Arora6e774cd2010-10-28 11:31:24 +0530111 break;
112 case 'c':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100113 options->clocks = true;
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100114 options->selectedwindow = CLOCK;
Amit Arora6e774cd2010-10-28 11:31:24 +0530115 break;
Amit Aroraf4fb8102010-11-30 13:55:50 +0530116 case 'p':
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100117 options->clkname = strdup(optarg);
118 if (!options->clkname) {
Daniel Lezcano9420fde2011-03-23 14:37:31 +0100119 fprintf(stderr, "failed to allocate memory");
120 return -1;
121 }
Amit Kucheriaeab558a2011-03-25 09:51:41 +0200122 options->dump = true; /* Assume -dc in case of -p */
123 options->clocks = true;
Amit Aroraf4fb8102010-11-30 13:55:50 +0530124 break;
Amit Arora6e774cd2010-10-28 11:31:24 +0530125 case 't':
Daniel Lezcano7f112da2011-03-23 14:37:32 +0100126 options->ticktime = atoi(optarg);
Amit Arora6e774cd2010-10-28 11:31:24 +0530127 break;
128 case 'd':
Daniel Lezcanoa70d9492011-03-23 14:37:40 +0100129 options->dump = true;
Amit Arora6e774cd2010-10-28 11:31:24 +0530130 break;
131 case 'v':
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100132 options->verbose = true;
Amit Arora6e774cd2010-10-28 11:31:24 +0530133 break;
134 case 'V':
135 version();
136 break;
Amit Arora6e774cd2010-10-28 11:31:24 +0530137 case '?':
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100138 fprintf(stderr, "%s: Unknown option %c'.\n",
Amit Kucheriaa0adae42011-01-12 10:54:23 -0600139 argv[0], optopt);
Amit Arora6e774cd2010-10-28 11:31:24 +0530140 default:
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100141 return -1;
Amit Arorafefe8bf2010-08-05 13:31:20 +0530142 }
Amit Arorae9e16b02010-08-03 10:15:20 +0530143 }
Amit Aroraa06a7302010-12-02 15:59:37 +0530144
Daniel Lezcano934fc092011-03-26 22:06:18 +0100145 /* No system specified to be dump, let's default to all */
146 if (!options->regulators && !options->clocks && !options->sensors)
147 options->regulators = options->clocks = options->sensors = true;
Amit Arorafefe8bf2010-08-05 13:31:20 +0530148
Daniel Lezcanoc9c14622011-03-26 22:06:10 +0100149 if (options->selectedwindow == -1)
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100150 options->selectedwindow = CLOCK;
Amit Arorae9e16b02010-08-03 10:15:20 +0530151
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100152 return 0;
153}
154
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100155int keystroke_callback(bool *enter_hit, bool *findparent_ncurses,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200156 char *clkname_str, bool *refreshwin, bool *cont,
Daniel Lezcano60a41022011-03-23 14:37:35 +0100157 struct powerdebug_options *options)
158{
159 char keychar;
160 int keystroke = getch();
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100161 int oldselectedwin = options->selectedwindow;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100162
163 if (keystroke == EOF)
164 exit(0);
165
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200166 if (keystroke == KEY_RIGHT || keystroke == '\t') {
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100167 options->selectedwindow++;
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200168 options->selectedwindow %= TOTAL_FEATURE_WINS;
169 }
Daniel Lezcano60a41022011-03-23 14:37:35 +0100170
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200171 if (keystroke == KEY_LEFT || keystroke == KEY_BTAB) {
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100172 options->selectedwindow--;
Daniel Lezcano2ef06e92011-05-24 15:27:49 +0200173 if (options->selectedwindow < 0)
174 options->selectedwindow = TOTAL_FEATURE_WINS - 1;
175 }
Daniel Lezcano60a41022011-03-23 14:37:35 +0100176
Daniel Lezcano2e9df762011-06-15 15:45:12 +0200177 if (keystroke == KEY_DOWN) {
178 display_next_line(options->selectedwindow);
179 *cont = true;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200180 }
Daniel Lezcano2e9df762011-06-15 15:45:12 +0200181
182 if (keystroke == KEY_UP) {
183 display_prev_line(options->selectedwindow);
184 *cont = true;
185 }
186
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100187 if (options->selectedwindow == CLOCK) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200188
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200189#if 0
190 /* TODO : fix with a new panel applicable for all subsystems */
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200191 if (keystroke == '/')
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100192 *findparent_ncurses = true;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200193#endif
Daniel Lezcano60a41022011-03-23 14:37:35 +0100194
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200195 if ((keystroke == '\e' || oldselectedwin !=
Daniel Lezcano558a6d52011-03-23 14:37:41 +0100196 options->selectedwindow) && *findparent_ncurses) {
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100197 *findparent_ncurses = false;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100198 clkname_str[0] = '\0';
199 }
200
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200201 if (*findparent_ncurses && keystroke != '\r') {
Daniel Lezcano60a41022011-03-23 14:37:35 +0100202 int len = strlen(clkname_str);
203 char str[2];
204
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200205 if (keystroke == KEY_BACKSPACE) {
Daniel Lezcano60a41022011-03-23 14:37:35 +0100206 if (len > 0)
207 len--;
208
209 clkname_str[len] = '\0';
210 } else {
211 if (strlen(clkname_str) ||
212 keystroke != '/') {
213 str[0] = keystroke;
214 str[1] = '\0';
215 if (len < 63)
216 strcat(clkname_str,
217 str);
218 }
219 }
220 }
221 }
222
223 keychar = toupper(keystroke);
224//#define DEBUG
225#ifdef DEBUG
Daniel Lezcano1c25df92011-06-08 23:30:00 +0200226 fini_curses();
Daniel Lezcano60a41022011-03-23 14:37:35 +0100227 printf("key entered %d:%c\n", keystroke, keychar);
228 exit(1);
229#endif
230
Daniel Lezcano3b42b5e2011-05-24 15:27:49 +0200231 if (keystroke == '\r')
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100232 *enter_hit = true;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100233
234 if (keychar == 'Q' && !*findparent_ncurses)
235 return 1;
236 if (keychar == 'R') {
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100237 *refreshwin = true;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100238 options->ticktime = 3;
239 } else
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100240 *refreshwin = false;
Daniel Lezcano60a41022011-03-23 14:37:35 +0100241
242 return 0;
243}
244
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200245int mainloop(struct powerdebug_options *options)
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100246{
Daniel Lezcanoc5afe832011-03-23 14:37:36 +0100247 bool findparent_ncurses = false;
248 bool refreshwin = false;
249 bool enter_hit = false;
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200250 bool cont = false;
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100251 char clkname_str[64];
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100252
Daniel Lezcano934fc092011-03-26 22:06:18 +0100253 strcpy(clkname_str, "");
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100254
Amit Kucheriaa0adae42011-01-12 10:54:23 -0600255 while (1) {
Amit Arora47fd9182010-08-24 13:26:06 +0530256 int key = 0;
257 struct timeval tval;
258 fd_set readfds;
Amit Arorae9e16b02010-08-03 10:15:20 +0530259
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200260 if (options->selectedwindow != CLOCK || !cont) {
261 create_windows(options->selectedwindow);
262 show_header(options->selectedwindow);
263 create_selectedwindow(options->selectedwindow);
264 }
Amit Aroraac4e8652010-11-09 11:16:53 +0530265
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200266 if (options->selectedwindow == REGULATOR)
267 regulator_display();
Amit Arora47fd9182010-08-24 13:26:06 +0530268
Daniel Lezcano95b0dac2011-06-08 23:30:00 +0200269 if (options->selectedwindow == CLOCK) {
Daniel Lezcano934fc092011-03-26 22:06:18 +0100270
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200271 if (!cont) {
Amit Aroraa06a7302010-12-02 15:59:37 +0530272
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200273 if (!findparent_ncurses) {
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200274
Daniel Lezcano05916f82011-06-08 23:30:01 +0200275 if (enter_hit)
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200276 clock_toggle_expanded();
Daniel Lezcano05916f82011-06-08 23:30:01 +0200277
278 read_and_print_clock_info();
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200279 enter_hit = false;
280 } else
281 find_parents_for_clock(clkname_str,
282 enter_hit);
283 } else cont = false;
Amit Arora6e774cd2010-10-28 11:31:24 +0530284 }
Amit Arora47fd9182010-08-24 13:26:06 +0530285
Daniel Lezcano95b0dac2011-06-08 23:30:00 +0200286 if (options->selectedwindow == SENSOR)
Daniel Lezcano2e9df762011-06-15 15:45:12 +0200287 sensor_display();
Amit Arora47fd9182010-08-24 13:26:06 +0530288
Amit Arora47fd9182010-08-24 13:26:06 +0530289 FD_ZERO(&readfds);
290 FD_SET(0, &readfds);
Daniel Lezcano316bcae2011-03-23 14:37:30 +0100291 tval.tv_sec = options->ticktime;
292 tval.tv_usec = (options->ticktime - tval.tv_sec) * 1000000;
Amit Arora47fd9182010-08-24 13:26:06 +0530293
Daniel Lezcanoe8cf9b82011-06-08 23:30:01 +0200294 again:
Amit Arora47fd9182010-08-24 13:26:06 +0530295 key = select(1, &readfds, NULL, NULL, &tval);
Daniel Lezcano60a41022011-03-23 14:37:35 +0100296 if (!key)
297 continue;
Amit Arora47fd9182010-08-24 13:26:06 +0530298
Daniel Lezcanoe8cf9b82011-06-08 23:30:01 +0200299 if (key < 0) {
300 if (errno == EINTR)
301 goto again;
302 break;
303 }
304
Daniel Lezcano60a41022011-03-23 14:37:35 +0100305 if (keystroke_callback(&enter_hit, &findparent_ncurses,
Daniel Lezcano2adc48d2011-06-08 23:30:01 +0200306 clkname_str, &refreshwin, &cont, options))
Daniel Lezcano60a41022011-03-23 14:37:35 +0100307 break;
Amit Arora97006e52010-10-28 11:56:08 +0530308
Amit Arorae9e16b02010-08-03 10:15:20 +0530309 }
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100310
311 return 0;
312}
313
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200314static int powerdebug_dump(struct powerdebug_options *options)
Daniel Lezcano21c04d42011-03-26 22:06:04 +0100315{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200316 if (options->regulators)
317 regulator_dump();
Daniel Lezcanob5746712011-03-26 22:06:05 +0100318
Daniel Lezcanoc7891942011-06-08 23:30:00 +0200319 if (options->clocks)
320 read_and_dump_clock_info(options->clkname);
Daniel Lezcanob5746712011-03-26 22:06:05 +0100321
322 if (options->sensors)
Daniel Lezcano3d0aef42011-06-15 15:45:12 +0200323 sensor_dump();
Daniel Lezcanob5746712011-03-26 22:06:05 +0100324
Daniel Lezcano21c04d42011-03-26 22:06:04 +0100325 return 0;
326}
327
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200328static int powerdebug_display(struct powerdebug_options *options)
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100329{
330 if (display_init()) {
331 printf("failed to initialize display\n");
332 return -1;
333 }
334
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200335 if (mainloop(options))
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100336 return -1;
337
338 return 0;
339}
340
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100341static struct powerdebug_options *powerdebug_init(void)
342{
343 struct powerdebug_options *options;
344
345 options = malloc(sizeof(*options));
346 if (!options)
347 return NULL;
348
349 memset(options, 0, sizeof(*options));
350
351 return options;
352}
353
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100354int main(int argc, char **argv)
355{
356 struct powerdebug_options *options;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200357 int ret;
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100358
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100359 options = powerdebug_init();
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100360 if (!options) {
Daniel Lezcano6e0c9c82011-03-26 22:06:07 +0100361 fprintf(stderr, "not enough memory to allocate options\n");
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100362 return 1;
363 }
364
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100365 if (getoptions(argc, argv, options)) {
366 usage();
367 return 1;
368 }
369
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200370 if (regulator_init()) {
Daniel Lezcano4aab2fe2011-03-26 22:05:53 +0100371 printf("not enough memory to allocate regulators info\n");
Daniel Lezcano6e48fa42011-03-26 22:06:23 +0100372 options->regulators = false;
Daniel Lezcano4aab2fe2011-03-26 22:05:53 +0100373 }
Daniel Lezcano0051f4f2011-03-23 14:37:34 +0100374
Daniel Lezcanof0e06652011-03-26 22:06:19 +0100375 if (clock_init()) {
376 printf("failed to initialize clock details (check debugfs)\n");
377 options->clocks = false;
378 }
379
Daniel Lezcano3d0aef42011-06-15 15:45:12 +0200380 if (sensor_init()) {
381 printf("failed to initialize sensors\n");
382 options->sensors = false;
383 }
384
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200385 ret = options->dump ? powerdebug_dump(options) :
386 powerdebug_display(options);
Daniel Lezcano21c04d42011-03-26 22:06:04 +0100387
Daniel Lezcanoc08f1f22011-03-26 22:06:21 +0100388 return ret < 0;
Amit Arorae9e16b02010-08-03 10:15:20 +0530389}