blob: 4b9d36e1a73717c6b3ed556523c2309b7873f0c4 [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 Lezcanob25be4a2011-06-15 15:45:12 +020021#define _GNU_SOURCE
22#include <stdio.h>
23#undef _GNU_SOURCE
24#include <sys/types.h>
25#include <stdbool.h>
26#include <dirent.h>
27#include <string.h>
28#include <stdlib.h>
Daniel Lezcanob301b082011-06-15 15:45:12 +020029#include "display.h"
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020030#include "powerdebug.h"
31#include "tree.h"
32#include "utils.h"
Daniel Lezcano2e6ecca2011-03-26 22:05:51 +010033
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020034struct regulator_info {
35 char name[NAME_MAX];
36 char state[VALUE_MAX];
37 char status[VALUE_MAX];
38 char type[VALUE_MAX];
39 char opmode[VALUE_MAX];
40 int microvolts;
41 int min_microvolts;
42 int max_microvolts;
43 int microamps;
44 int min_microamps;
45 int max_microamps;
46 int requested_microamps;
47 int num_users;
48};
49
50struct regulator_data {
51 const char *name;
52 const char *ifmt;
53 const char *ofmt;
54 bool derefme;
55};
56
57static struct regulator_data regdata[] = {
58 { "name", "%s", "\tname: %s\n" },
59 { "status", "%s", "\tstatus: %s\n" },
60 { "state", "%s", "\tstate: %s\n" },
61 { "type", "%s", "\ttype: %s\n" },
62 { "num_users", "%d", "\tnum_users: %d\n", true },
63 { "microvolts", "%d", "\tmicrovolts: %d\n", true },
64 { "max_microvolts", "%d", "\tmax_microvolts: %d\n", true },
65 { "min_microvolts", "%d", "\tmin_microvolts: %d\n", true },
66};
67
68static struct tree *reg_tree;
69
70static struct regulator_info *regulator_alloc(void)
Amit Arora17552782010-12-02 12:23:14 +053071{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020072 struct regulator_info *regi;
Amit Arora17552782010-12-02 12:23:14 +053073
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020074 regi = malloc(sizeof(*regi));
75 if (regi)
76 memset(regi, 0, sizeof(*regi));
Daniel Lezcano4aab2fe2011-03-26 22:05:53 +010077
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020078 return regi;
Amit Arora17552782010-12-02 12:23:14 +053079}
80
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020081static int regulator_dump_cb(struct tree *tree, void *data)
Amit Arora17552782010-12-02 12:23:14 +053082{
83 int i;
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020084 char buffer[NAME_MAX];
85 size_t nregdata = sizeof(regdata) / sizeof(regdata[0]);
Amit Arora17552782010-12-02 12:23:14 +053086
Daniel Lezcanob25be4a2011-06-15 15:45:12 +020087 if (!strncmp("regulator.", tree->name, strlen("regulator.")))
88 printf("\n%s:\n", tree->name);
89
90 for (i = 0; i < nregdata; i++) {
91
92 if (file_read_value(tree->path, regdata[i].name,
93 regdata[i].ifmt, buffer))
94 continue;
95
96 printf(regdata[i].ofmt, regdata[i].derefme ?
97 *((int *)buffer) : buffer);
98 }
99
100 return 0;
101}
102
103int regulator_dump(void)
104{
Amit Arora422c52f2010-12-02 16:22:29 +0530105 printf("\nRegulator Information:\n");
106 printf("*********************\n\n");
107
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200108 return tree_for_each(reg_tree, regulator_dump_cb, NULL);
Amit Arora17552782010-12-02 12:23:14 +0530109}
110
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200111static int regulator_display_cb(struct tree *t, void *data)
Amit Arora17552782010-12-02 12:23:14 +0530112{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200113 struct regulator_info *reg = t->private;
114 int *line = data;
115 char *buf;
Amit Arora17552782010-12-02 12:23:14 +0530116
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200117 /* we skip the root node of the tree */
118 if (!t->parent)
119 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530120
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200121 if (!strlen(reg->name))
122 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530123
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200124 if (asprintf(&buf, "%-11s %-11s %-11s %-11s %-11d %-11d %-11d %-12d",
125 reg->name, reg->status, reg->state, reg->type,
126 reg->num_users, reg->microvolts, reg->min_microvolts,
127 reg->max_microvolts) < 0)
128 return -1;
Amit Arora17552782010-12-02 12:23:14 +0530129
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200130 display_print_line(REGULATOR, *line, buf, reg->num_users, t);
131
132 (*line)++;
133
134 free(buf);
135
136 return 0;
Amit Arora17552782010-12-02 12:23:14 +0530137}
138
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200139int regulator_display(void)
Amit Arora17552782010-12-02 12:23:14 +0530140{
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200141 int ret, line = 0;
Amit Arora17552782010-12-02 12:23:14 +0530142
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200143 display_reset_cursor(REGULATOR);
Amit Arora17552782010-12-02 12:23:14 +0530144
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200145 print_regulator_header();
Amit Arora17552782010-12-02 12:23:14 +0530146
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200147 ret = tree_for_each(reg_tree, regulator_display_cb, &line);
Amit Arora17552782010-12-02 12:23:14 +0530148
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200149 display_refresh_pad(REGULATOR);
Amit Arora17552782010-12-02 12:23:14 +0530150
151 return ret;
152}
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200153
154static int regulator_filter_cb(const char *name)
155{
156 /* let's ignore some directories in order to avoid to be
157 * pulled inside the sysfs circular symlinks mess/hell
158 * (choose the word which fit better)
159 */
160 if (!strcmp(name, "device"))
161 return 1;
162
163 if (!strcmp(name, "subsystem"))
164 return 1;
165
166 if (!strcmp(name, "driver"))
167 return 1;
168
169 return 0;
170}
171
172static inline int read_regulator_cb(struct tree *t, void *data)
173{
174 struct regulator_info *reg = t->private;
175
176 file_read_value(t->path, "name", "%s", reg->name);
177 file_read_value(t->path, "state", "%s", reg->state);
178 file_read_value(t->path, "status", "%s", reg->status);
179 file_read_value(t->path, "type", "%s", reg->type);
180 file_read_value(t->path, "opmode", "%s", reg->opmode);
181 file_read_value(t->path, "num_users", "%d", &reg->num_users);
182 file_read_value(t->path, "microvolts", "%d", &reg->microvolts);
183 file_read_value(t->path, "min_microvolts", "%d", &reg->min_microvolts);
184 file_read_value(t->path, "max_microvolts", "%d", &reg->max_microvolts);
185 file_read_value(t->path, "microamps", "%d", &reg->microamps);
186 file_read_value(t->path, "min_microamps", "%d", &reg->min_microamps);
187 file_read_value(t->path, "max_microamps", "%d", &reg->max_microamps);
188
189 return 0;
190}
191
192static int fill_regulator_cb(struct tree *t, void *data)
193{
194 struct regulator_info *reg;
195
196 reg = regulator_alloc();
197 if (!reg)
198 return -1;
199 t->private = reg;
200
201 /* we skip the root node but we set it expanded for its children */
202 if (!t->parent)
203 return 0;
204
205 return read_regulator_cb(t, data);
206}
207
208static int fill_regulator_tree(void)
209{
210 return tree_for_each(reg_tree, fill_regulator_cb, NULL);
211}
212
Daniel Lezcanob301b082011-06-15 15:45:12 +0200213static struct display_ops regulator_ops = {
214 .display = regulator_display,
215};
216
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200217int regulator_init(void)
218{
Daniel Lezcanob301b082011-06-15 15:45:12 +0200219 if (display_register(REGULATOR, &regulator_ops))
220 return -1;
221
Daniel Lezcanob25be4a2011-06-15 15:45:12 +0200222 reg_tree = tree_load(SYSFS_REGULATOR, regulator_filter_cb);
223 if (!reg_tree)
224 return -1;
225
226 return fill_regulator_tree();
227}