blob: 0e1c2c6cf6922d4367f8f592c025a2d3435f7901 [file] [log] [blame]
Amit Arora17552782010-12-02 12:23:14 +05301/*******************************************************************************
Amit Kucheriac0e17fc2011-01-17 09:35:52 +02002 * Copyright (C) 2010, Linaro Limited.
Amit Arora17552782010-12-02 12:23:14 +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
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020014 * Daniel Lezcano <daniel.lezcano@linaro.org> (IBM Corporation)
15 * - rewrote code and API based on the tree
Amit Arora17552782010-12-02 12:23:14 +053016 *******************************************************************************/
17
18#include "regulator.h"
19
Daniel Lezcano2e6ecca2011-03-26 22:05:51 +010020#define SYSFS_REGULATOR "/sys/class/regulator"
Daniel Lezcano15627482011-06-15 15:45:12 +020021#define VALUE_MAX 16
22
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020023#define _GNU_SOURCE
24#include <stdio.h>
25#undef _GNU_SOURCE
26#include <sys/types.h>
27#include <stdbool.h>
28#include <dirent.h>
29#include <string.h>
30#include <stdlib.h>
Sanjay Singh Rawat03fdbc02014-05-27 16:52:27 +053031#include <unistd.h>
32
Daniel Lezcanob301b082011-06-15 15:45:12 +020033#include "display.h"
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020034#include "powerdebug.h"
35#include "tree.h"
36#include "utils.h"
Daniel Lezcano2e6ecca2011-03-26 22:05:51 +010037
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020038struct regulator_info {
39 char name[NAME_MAX];
40 char state[VALUE_MAX];
41 char status[VALUE_MAX];
42 char type[VALUE_MAX];
43 char opmode[VALUE_MAX];
44 int microvolts;
45 int min_microvolts;
46 int max_microvolts;
47 int microamps;
48 int min_microamps;
49 int max_microamps;
50 int requested_microamps;
51 int num_users;
52};
53
54struct regulator_data {
55 const char *name;
56 const char *ifmt;
57 const char *ofmt;
58 bool derefme;
59};
60
61static struct regulator_data regdata[] = {
62 { "name", "%s", "\tname: %s\n" },
63 { "status", "%s", "\tstatus: %s\n" },
64 { "state", "%s", "\tstate: %s\n" },
65 { "type", "%s", "\ttype: %s\n" },
66 { "num_users", "%d", "\tnum_users: %d\n", true },
67 { "microvolts", "%d", "\tmicrovolts: %d\n", true },
68 { "max_microvolts", "%d", "\tmax_microvolts: %d\n", true },
69 { "min_microvolts", "%d", "\tmin_microvolts: %d\n", true },
70};
71
72static struct tree *reg_tree;
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +053073static bool regulator_error = false;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020074
75static struct regulator_info *regulator_alloc(void)
Amit Arora17552782010-12-02 12:23:14 +053076{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020077 struct regulator_info *regi;
Amit Arora17552782010-12-02 12:23:14 +053078
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020079 regi = malloc(sizeof(*regi));
80 if (regi)
81 memset(regi, 0, sizeof(*regi));
Daniel Lezcano4aab2fe2011-03-26 22:05:53 +010082
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020083 return regi;
Amit Arora17552782010-12-02 12:23:14 +053084}
85
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020086static int regulator_dump_cb(struct tree *tree, void *data)
Amit Arora17552782010-12-02 12:23:14 +053087{
88 int i;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020089 char buffer[NAME_MAX];
90 size_t nregdata = sizeof(regdata) / sizeof(regdata[0]);
Amit Arora17552782010-12-02 12:23:14 +053091
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020092 if (!strncmp("regulator.", tree->name, strlen("regulator.")))
93 printf("\n%s:\n", tree->name);
94
95 for (i = 0; i < nregdata; i++) {
Sanjay Singh Rawat9fe0c052013-02-22 17:57:18 +053096 int val;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020097
98 if (file_read_value(tree->path, regdata[i].name,
99 regdata[i].ifmt, buffer))
100 continue;
101
Sanjay Singh Rawat9fe0c052013-02-22 17:57:18 +0530102 if (regdata[i].derefme) {
103 val = atoi(buffer);
104 printf(regdata[i].ofmt, val);
105 } else
106 printf(regdata[i].ofmt, buffer);
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200107 }
108
109 return 0;
110}
111
112int regulator_dump(void)
113{
Amit Arora422c52f2010-12-02 16:22:29 +0530114 printf("\nRegulator Information:\n");
115 printf("*********************\n\n");
116
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200117 return tree_for_each(reg_tree, regulator_dump_cb, NULL);
Amit Arora17552782010-12-02 12:23:14 +0530118}
119
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200120static int regulator_display_cb(struct tree *t, void *data)
Amit Arora17552782010-12-02 12:23:14 +0530121{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200122 struct regulator_info *reg = t->private;
123 int *line = data;
124 char *buf;
Amit Arora17552782010-12-02 12:23:14 +0530125
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200126 /* we skip the root node of the tree */
127 if (!t->parent)
128 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530129
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200130 if (!strlen(reg->name))
131 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530132
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200133 if (asprintf(&buf, "%-11s %-11s %-11s %-11s %-11d %-11d %-11d %-12d",
134 reg->name, reg->status, reg->state, reg->type,
135 reg->num_users, reg->microvolts, reg->min_microvolts,
136 reg->max_microvolts) < 0)
137 return -1;
Amit Arora17552782010-12-02 12:23:14 +0530138
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200139 display_print_line(REGULATOR, *line, buf, reg->num_users, t);
140
141 (*line)++;
142
143 free(buf);
144
145 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530146}
147
Daniel Lezcanofa453332011-06-21 00:57:08 +0200148static int regulator_print_header(void)
149{
150 char *buf;
151 int ret;
152
153 if (asprintf(&buf, "%-11s %-11s %-11s %-11s %-11s %-11s %-11s %-12s",
154 "Name", "Status", "State", "Type", "Users", "Microvolts",
155 "Min u-volts", "Max u-volts") < 0)
156 return -1;
157
Daniel Lezcano372ffba2011-06-21 00:57:08 +0200158 ret = display_column_name(buf);
Daniel Lezcanofa453332011-06-21 00:57:08 +0200159
160 free(buf);
161
162 return ret;
163
164}
165
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200166static int regulator_filter_cb(const char *name)
167{
168 /* let's ignore some directories in order to avoid to be
169 * pulled inside the sysfs circular symlinks mess/hell
170 * (choose the word which fit better)
171 */
172 if (!strcmp(name, "device"))
173 return 1;
174
175 if (!strcmp(name, "subsystem"))
176 return 1;
177
178 if (!strcmp(name, "driver"))
179 return 1;
180
181 return 0;
182}
183
184static inline int read_regulator_cb(struct tree *t, void *data)
185{
186 struct regulator_info *reg = t->private;
187
188 file_read_value(t->path, "name", "%s", reg->name);
189 file_read_value(t->path, "state", "%s", reg->state);
190 file_read_value(t->path, "status", "%s", reg->status);
191 file_read_value(t->path, "type", "%s", reg->type);
192 file_read_value(t->path, "opmode", "%s", reg->opmode);
193 file_read_value(t->path, "num_users", "%d", &reg->num_users);
194 file_read_value(t->path, "microvolts", "%d", &reg->microvolts);
195 file_read_value(t->path, "min_microvolts", "%d", &reg->min_microvolts);
196 file_read_value(t->path, "max_microvolts", "%d", &reg->max_microvolts);
197 file_read_value(t->path, "microamps", "%d", &reg->microamps);
198 file_read_value(t->path, "min_microamps", "%d", &reg->min_microamps);
199 file_read_value(t->path, "max_microamps", "%d", &reg->max_microamps);
200
201 return 0;
202}
203
Shaojie Sunc1462e72013-08-20 20:35:15 +0800204static int read_regulator_info(struct tree *tree)
205{
206 return tree_for_each(tree, read_regulator_cb, NULL);
207}
208
209static int regulator_print_info(struct tree *tree)
210{
211 int ret, line = 0;
212
213 display_reset_cursor(REGULATOR);
214
215 regulator_print_header();
216
217 ret = tree_for_each(tree, regulator_display_cb, &line);
218
219 display_refresh_pad(REGULATOR);
220
221 return ret;
222}
223
224static int regulator_display(bool refresh)
225{
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530226 if (regulator_error) {
227 display_message(REGULATOR,
228 "error: path " SYSFS_REGULATOR " not found");
229 return -2;
230 }
231
Shaojie Sunc1462e72013-08-20 20:35:15 +0800232 if (refresh && read_regulator_info(reg_tree))
233 return -1;
234
235 return regulator_print_info(reg_tree);
236}
237
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200238static int fill_regulator_cb(struct tree *t, void *data)
239{
240 struct regulator_info *reg;
241
242 reg = regulator_alloc();
Sanjay Singh Rawat5fef0052013-04-17 15:02:01 +0530243 if (!reg) {
244 printf("error: unable to allocate memory for regulator\n");
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200245 return -1;
Sanjay Singh Rawat5fef0052013-04-17 15:02:01 +0530246 }
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200247 t->private = reg;
248
249 /* we skip the root node but we set it expanded for its children */
250 if (!t->parent)
251 return 0;
252
253 return read_regulator_cb(t, data);
254}
255
256static int fill_regulator_tree(void)
257{
258 return tree_for_each(reg_tree, fill_regulator_cb, NULL);
259}
260
Daniel Lezcanob301b082011-06-15 15:45:12 +0200261static struct display_ops regulator_ops = {
262 .display = regulator_display,
263};
264
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200265int regulator_init(void)
266{
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530267 int ret = 0;
268
269 ret = display_register(REGULATOR, &regulator_ops);
Sanjay Singh Rawat03fdbc02014-05-27 16:52:27 +0530270 if (ret)
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530271 printf("error: regulator display register failed");
272
273 if (access(SYSFS_REGULATOR, F_OK))
274 regulator_error = true; /* set the flag */
275
Daniel Lezcano25fc4a32011-08-25 15:46:13 +0200276 reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb, false);
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200277 if (!reg_tree)
278 return -1;
279
Daniel Lezcanocaafece2011-06-27 22:59:17 +0200280 if (fill_regulator_tree())
281 return -1;
282
Sanjay Singh Rawat96f6e052014-05-26 11:35:02 +0530283 return ret;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200284}