blob: 549a7444c3e547aff11ab1557b3f105c978bc2e5 [file] [log] [blame]
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00001/*
2 * Powerdebug : power debugging tool
Amit Arora17552782010-12-02 12:23:14 +05303 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00004 * Copyright (C) 2016, Linaro Limited.
Amit Arora17552782010-12-02 12:23:14 +05305 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00006 * Author:
7 * Daniel Lezcano <daniel.lezcano@linaro.org>
Amit Arora17552782010-12-02 12:23:14 +05308 *
Daniel Lezcano7c15fad2016-02-18 15:57:43 +00009 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
Daniel Lezcano2e6ecca2011-03-26 22:05:51 +010023#define SYSFS_REGULATOR "/sys/class/regulator"
Daniel Lezcano15627482011-06-15 15:45:12 +020024#define VALUE_MAX 16
25
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020026#define _GNU_SOURCE
27#include <stdio.h>
28#undef _GNU_SOURCE
29#include <sys/types.h>
30#include <stdbool.h>
31#include <dirent.h>
32#include <string.h>
33#include <stdlib.h>
Sanjay Singh Rawat03fdbc02014-05-27 16:52:27 +053034#include <unistd.h>
35
Daniel Lezcanob301b082011-06-15 15:45:12 +020036#include "display.h"
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020037#include "powerdebug.h"
38#include "tree.h"
39#include "utils.h"
Daniel Lezcano2e6ecca2011-03-26 22:05:51 +010040
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020041struct regulator_info {
42 char name[NAME_MAX];
43 char state[VALUE_MAX];
44 char status[VALUE_MAX];
45 char type[VALUE_MAX];
46 char opmode[VALUE_MAX];
47 int microvolts;
48 int min_microvolts;
49 int max_microvolts;
50 int microamps;
51 int min_microamps;
52 int max_microamps;
53 int requested_microamps;
54 int num_users;
55};
56
57struct regulator_data {
58 const char *name;
59 const char *ifmt;
60 const char *ofmt;
61 bool derefme;
62};
63
64static struct regulator_data regdata[] = {
65 { "name", "%s", "\tname: %s\n" },
66 { "status", "%s", "\tstatus: %s\n" },
67 { "state", "%s", "\tstate: %s\n" },
68 { "type", "%s", "\ttype: %s\n" },
69 { "num_users", "%d", "\tnum_users: %d\n", true },
70 { "microvolts", "%d", "\tmicrovolts: %d\n", true },
71 { "max_microvolts", "%d", "\tmax_microvolts: %d\n", true },
72 { "min_microvolts", "%d", "\tmin_microvolts: %d\n", true },
73};
74
75static struct tree *reg_tree;
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +053076static bool regulator_error = false;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020077
78static struct regulator_info *regulator_alloc(void)
Amit Arora17552782010-12-02 12:23:14 +053079{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020080 struct regulator_info *regi;
Amit Arora17552782010-12-02 12:23:14 +053081
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020082 regi = malloc(sizeof(*regi));
83 if (regi)
84 memset(regi, 0, sizeof(*regi));
Daniel Lezcano4aab2fe2011-03-26 22:05:53 +010085
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020086 return regi;
Amit Arora17552782010-12-02 12:23:14 +053087}
88
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020089static int regulator_dump_cb(struct tree *tree, void *data)
Amit Arora17552782010-12-02 12:23:14 +053090{
91 int i;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020092 char buffer[NAME_MAX];
93 size_t nregdata = sizeof(regdata) / sizeof(regdata[0]);
Amit Arora17552782010-12-02 12:23:14 +053094
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020095 if (!strncmp("regulator.", tree->name, strlen("regulator.")))
96 printf("\n%s:\n", tree->name);
97
98 for (i = 0; i < nregdata; i++) {
Sanjay Singh Rawat9fe0c052013-02-22 17:57:18 +053099 int val;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200100
101 if (file_read_value(tree->path, regdata[i].name,
102 regdata[i].ifmt, buffer))
103 continue;
104
Sanjay Singh Rawat9fe0c052013-02-22 17:57:18 +0530105 if (regdata[i].derefme) {
106 val = atoi(buffer);
107 printf(regdata[i].ofmt, val);
108 } else
109 printf(regdata[i].ofmt, buffer);
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200110 }
111
112 return 0;
113}
114
115int regulator_dump(void)
116{
Amit Arora422c52f2010-12-02 16:22:29 +0530117 printf("\nRegulator Information:\n");
118 printf("*********************\n\n");
119
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200120 return tree_for_each(reg_tree, regulator_dump_cb, NULL);
Amit Arora17552782010-12-02 12:23:14 +0530121}
122
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200123static int regulator_display_cb(struct tree *t, void *data)
Amit Arora17552782010-12-02 12:23:14 +0530124{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200125 struct regulator_info *reg = t->private;
126 int *line = data;
127 char *buf;
Amit Arora17552782010-12-02 12:23:14 +0530128
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200129 /* we skip the root node of the tree */
130 if (!t->parent)
131 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530132
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200133 if (!strlen(reg->name))
134 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530135
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200136 if (asprintf(&buf, "%-11s %-11s %-11s %-11s %-11d %-11d %-11d %-12d",
137 reg->name, reg->status, reg->state, reg->type,
138 reg->num_users, reg->microvolts, reg->min_microvolts,
139 reg->max_microvolts) < 0)
140 return -1;
Amit Arora17552782010-12-02 12:23:14 +0530141
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200142 display_print_line(REGULATOR, *line, buf, reg->num_users, t);
143
144 (*line)++;
145
146 free(buf);
147
148 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530149}
150
Daniel Lezcanofa453332011-06-21 00:57:08 +0200151static int regulator_print_header(void)
152{
153 char *buf;
154 int ret;
155
156 if (asprintf(&buf, "%-11s %-11s %-11s %-11s %-11s %-11s %-11s %-12s",
157 "Name", "Status", "State", "Type", "Users", "Microvolts",
158 "Min u-volts", "Max u-volts") < 0)
159 return -1;
160
Daniel Lezcano372ffba2011-06-21 00:57:08 +0200161 ret = display_column_name(buf);
Daniel Lezcanofa453332011-06-21 00:57:08 +0200162
163 free(buf);
164
165 return ret;
166
167}
168
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200169static int regulator_filter_cb(const char *name)
170{
171 /* let's ignore some directories in order to avoid to be
172 * pulled inside the sysfs circular symlinks mess/hell
173 * (choose the word which fit better)
174 */
175 if (!strcmp(name, "device"))
176 return 1;
177
178 if (!strcmp(name, "subsystem"))
179 return 1;
180
181 if (!strcmp(name, "driver"))
182 return 1;
183
184 return 0;
185}
186
187static inline int read_regulator_cb(struct tree *t, void *data)
188{
189 struct regulator_info *reg = t->private;
190
191 file_read_value(t->path, "name", "%s", reg->name);
192 file_read_value(t->path, "state", "%s", reg->state);
193 file_read_value(t->path, "status", "%s", reg->status);
194 file_read_value(t->path, "type", "%s", reg->type);
195 file_read_value(t->path, "opmode", "%s", reg->opmode);
196 file_read_value(t->path, "num_users", "%d", &reg->num_users);
197 file_read_value(t->path, "microvolts", "%d", &reg->microvolts);
198 file_read_value(t->path, "min_microvolts", "%d", &reg->min_microvolts);
199 file_read_value(t->path, "max_microvolts", "%d", &reg->max_microvolts);
200 file_read_value(t->path, "microamps", "%d", &reg->microamps);
201 file_read_value(t->path, "min_microamps", "%d", &reg->min_microamps);
202 file_read_value(t->path, "max_microamps", "%d", &reg->max_microamps);
203
204 return 0;
205}
206
Shaojie Sunc1462e72013-08-20 20:35:15 +0800207static int read_regulator_info(struct tree *tree)
208{
209 return tree_for_each(tree, read_regulator_cb, NULL);
210}
211
212static int regulator_print_info(struct tree *tree)
213{
214 int ret, line = 0;
215
216 display_reset_cursor(REGULATOR);
217
218 regulator_print_header();
219
220 ret = tree_for_each(tree, regulator_display_cb, &line);
221
222 display_refresh_pad(REGULATOR);
223
224 return ret;
225}
226
227static int regulator_display(bool refresh)
228{
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530229 if (regulator_error) {
230 display_message(REGULATOR,
231 "error: path " SYSFS_REGULATOR " not found");
232 return -2;
233 }
234
Shaojie Sunc1462e72013-08-20 20:35:15 +0800235 if (refresh && read_regulator_info(reg_tree))
236 return -1;
237
238 return regulator_print_info(reg_tree);
239}
240
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200241static int fill_regulator_cb(struct tree *t, void *data)
242{
243 struct regulator_info *reg;
244
245 reg = regulator_alloc();
Sanjay Singh Rawat5fef0052013-04-17 15:02:01 +0530246 if (!reg) {
247 printf("error: unable to allocate memory for regulator\n");
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200248 return -1;
Sanjay Singh Rawat5fef0052013-04-17 15:02:01 +0530249 }
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200250 t->private = reg;
251
252 /* we skip the root node but we set it expanded for its children */
253 if (!t->parent)
254 return 0;
255
256 return read_regulator_cb(t, data);
257}
258
259static int fill_regulator_tree(void)
260{
261 return tree_for_each(reg_tree, fill_regulator_cb, NULL);
262}
263
Daniel Lezcanob301b082011-06-15 15:45:12 +0200264static struct display_ops regulator_ops = {
265 .display = regulator_display,
266};
267
Daniel Lezcanob4eec7e2016-02-18 16:44:55 +0000268int regulator_init(struct powerdebug_options *options)
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200269{
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530270 int ret = 0;
271
Daniel Lezcanob4eec7e2016-02-18 16:44:55 +0000272 if (!(options->flags & REGULATOR_OPTION))
273 return 0;
274
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530275 ret = display_register(REGULATOR, &regulator_ops);
Sanjay Singh Rawat03fdbc02014-05-27 16:52:27 +0530276 if (ret)
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530277 printf("error: regulator display register failed");
278
279 if (access(SYSFS_REGULATOR, F_OK))
280 regulator_error = true; /* set the flag */
281
Daniel Lezcano25fc4a32011-08-25 15:46:13 +0200282 reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb, false);
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200283 if (!reg_tree)
284 return -1;
285
Daniel Lezcanocaafece2011-06-27 22:59:17 +0200286 if (fill_regulator_tree())
287 return -1;
288
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530289 return ret;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200290}