Blame view

cmd/regulator.c 11.1 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
2
3
4
  /*
   * Copyright (C) 2014-2015 Samsung Electronics
   * Przemyslaw Marczak <p.marczak@samsung.com>
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
5
6
7
8
9
10
   */
  #include <common.h>
  #include <errno.h>
  #include <dm.h>
  #include <dm/uclass-internal.h>
  #include <power/regulator.h>
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
11
  #define LIMIT_DEVNAME	20
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
12
13
  #define LIMIT_OFNAME	32
  #define LIMIT_INFO	18
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
14
15
  
  static struct udevice *currdev;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
16
  static int failure(int ret)
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
17
  {
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
18
19
  	printf("Error: %d (%s)
  ", ret, errno_str(ret));
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
20

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
21
  	return CMD_RET_FAILURE;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
22
23
24
25
26
  }
  
  static int do_dev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct dm_regulator_uclass_platdata *uc_pdata;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
27
28
  	const char *name;
  	int ret = -ENXIO;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
29
30
31
  
  	switch (argc) {
  	case 2:
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
32
33
34
35
36
37
38
  		name = argv[1];
  		ret = regulator_get_by_platname(name, &currdev);
  		if (ret) {
  			printf("Can't get the regulator: %s!
  ", name);
  			return failure(ret);
  		}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
39
  	case 1:
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
40
41
42
43
44
45
  		if (!currdev) {
  			printf("Regulator device is not set!
  
  ");
  			return CMD_RET_USAGE;
  		}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
46
  		uc_pdata = dev_get_uclass_platdata(currdev);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
47
48
49
50
51
  		if (!uc_pdata) {
  			printf("%s: no regulator platform data!
  ", currdev->name);
  			return failure(ret);
  		}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
52

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
53
54
  		printf("dev: %s @ %s
  ", uc_pdata->name, currdev->name);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
55
56
57
  	}
  
  	return CMD_RET_SUCCESS;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
58
  }
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
59
60
61
  static int curr_dev_and_platdata(struct udevice **devp,
  				 struct dm_regulator_uclass_platdata **uc_pdata,
  				 bool allow_type_fixed)
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
62
63
64
  {
  	*devp = NULL;
  	*uc_pdata = NULL;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
65
66
67
68
69
  	if (!currdev) {
  		printf("First, set the regulator device!
  ");
  		return CMD_RET_FAILURE;
  	}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
70
71
72
73
  
  	*devp = currdev;
  
  	*uc_pdata = dev_get_uclass_platdata(*devp);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
74
  	if (!*uc_pdata) {
71002b508   Seung-Woo Kim   cmd: add missing ...
75
76
  		pr_err("Regulator: %s - missing platform data!
  ", currdev->name);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
77
78
  		return CMD_RET_FAILURE;
  	}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
79
80
81
82
83
84
85
86
87
88
89
90
  
  	if (!allow_type_fixed && (*uc_pdata)->type == REGULATOR_TYPE_FIXED) {
  		printf("Operation not allowed for fixed regulator!
  ");
  		return CMD_RET_FAILURE;
  	}
  
  	return CMD_RET_SUCCESS;
  }
  
  static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
91
92
  	struct dm_regulator_uclass_platdata *uc_pdata;
  	struct udevice *dev;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
93
  	int ret;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
94
95
96
97
98
  	printf("| %-*.*s| %-*.*s| %s
  ",
  	       LIMIT_DEVNAME, LIMIT_DEVNAME, "Device",
  	       LIMIT_OFNAME, LIMIT_OFNAME, "regulator-name",
  	       "Parent");
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
99

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
100
101
102
103
  	for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
  	     ret = uclass_find_next_device(&dev)) {
  		if (ret)
  			continue;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
104

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
105
106
107
108
109
110
111
112
113
  		uc_pdata = dev_get_uclass_platdata(dev);
  		printf("| %-*.*s| %-*.*s| %s
  ",
  		       LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name,
  		       LIMIT_OFNAME, LIMIT_OFNAME, uc_pdata->name,
  		       dev->parent->name);
  	}
  
  	return ret;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  }
  
  static int constraint(const char *name, int val, const char *val_name)
  {
  	printf("%-*s", LIMIT_INFO, name);
  	if (val < 0) {
  		printf(" %s (err: %d)
  ", errno_str(val), val);
  		return val;
  	}
  
  	if (val_name)
  		printf(" %d (%s)
  ", val, val_name);
  	else
  		printf(" %d
  ", val);
  
  	return 0;
  }
  
  static const char *get_mode_name(struct dm_regulator_mode *mode,
  				 int mode_count,
  				 int mode_id)
  {
  	while (mode_count--) {
  		if (mode->id == mode_id)
  			return mode->name;
  		mode++;
  	}
  
  	return NULL;
  }
  
  static int do_info(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct udevice *dev;
  	struct dm_regulator_uclass_platdata *uc_pdata;
  	struct dm_regulator_mode *modes;
  	const char *parent_uc;
  	int mode_count;
  	int ret;
  	int i;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
157
  	ret = curr_dev_and_platdata(&dev, &uc_pdata, true);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
158
159
160
161
  	if (ret)
  		return ret;
  
  	parent_uc = dev_get_uclass_name(dev->parent);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
162
163
164
165
166
167
168
169
170
171
172
173
  	printf("%s
  %-*s %s
  %-*s %s
  %-*s %s
  %-*s %s
  %-*s
  ",
  	       "Regulator info:",
  	       LIMIT_INFO, "* regulator-name:", uc_pdata->name,
  	       LIMIT_INFO, "* device name:", dev->name,
  	       LIMIT_INFO, "* parent name:", dev->parent->name,
  	       LIMIT_INFO, "* parent uclass:", parent_uc,
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  	       LIMIT_INFO, "* constraints:");
  
  	constraint("  - min uV:", uc_pdata->min_uV, NULL);
  	constraint("  - max uV:", uc_pdata->max_uV, NULL);
  	constraint("  - min uA:", uc_pdata->min_uA, NULL);
  	constraint("  - max uA:", uc_pdata->max_uA, NULL);
  	constraint("  - always on:", uc_pdata->always_on,
  		   uc_pdata->always_on ? "true" : "false");
  	constraint("  - boot on:", uc_pdata->boot_on,
  		   uc_pdata->boot_on ? "true" : "false");
  
  	mode_count = regulator_mode(dev, &modes);
  	constraint("* op modes:", mode_count, NULL);
  
  	for (i = 0; i < mode_count; i++, modes++)
  		constraint("  - mode id:", modes->id, modes->name);
  
  	return CMD_RET_SUCCESS;
  }
931b24c5a   Simon Glass   dm: pmic: Add 're...
193
194
  static void do_status_detail(struct udevice *dev,
  			     struct dm_regulator_uclass_platdata *uc_pdata)
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
195
  {
931b24c5a   Simon Glass   dm: pmic: Add 're...
196
197
  	int current, value, mode;
  	const char *mode_name;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
198
  	bool enabled;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
199
200
  	printf("Regulator %s status:
  ", uc_pdata->name);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
201
202
203
204
205
206
207
208
209
210
211
212
  	enabled = regulator_get_enable(dev);
  	constraint(" * enable:", enabled, enabled ? "true" : "false");
  
  	value = regulator_get_value(dev);
  	constraint(" * value uV:", value, NULL);
  
  	current = regulator_get_current(dev);
  	constraint(" * current uA:", current, NULL);
  
  	mode = regulator_get_mode(dev);
  	mode_name = get_mode_name(uc_pdata->mode, uc_pdata->mode_count, mode);
  	constraint(" * mode id:", mode, mode_name);
931b24c5a   Simon Glass   dm: pmic: Add 're...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  }
  
  static void do_status_line(struct udevice *dev)
  {
  	struct dm_regulator_uclass_platdata *pdata;
  	int current, value, mode;
  	const char *mode_name;
  	bool enabled;
  
  	pdata = dev_get_uclass_platdata(dev);
  	enabled = regulator_get_enable(dev);
  	value = regulator_get_value(dev);
  	current = regulator_get_current(dev);
  	mode = regulator_get_mode(dev);
  	mode_name = get_mode_name(pdata->mode, pdata->mode_count, mode);
  	printf("%-20s %-10s ", pdata->name, enabled ? "enabled" : "disabled");
  	if (value >= 0)
  		printf("%10d ", value);
  	else
  		printf("%10s ", "-");
  	if (current >= 0)
  		printf("%10d ", current);
  	else
  		printf("%10s ", "-");
  	if (mode >= 0)
  		printf("%-10s", mode_name);
  	else
  		printf("%-10s", "-");
  	printf("
  ");
  }
  
  static int do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct dm_regulator_uclass_platdata *uc_pdata;
  	struct udevice *dev;
  	int ret;
  
  	if (currdev && (argc < 2 || strcmp(argv[1], "-a"))) {
  		ret = curr_dev_and_platdata(&dev, &uc_pdata, true);
  		if (ret)
  			return CMD_RET_FAILURE;
  		do_status_detail(dev, uc_pdata);
  		return 0;
  	}
  
  	/* Show all of them in a list, probing them as needed */
  	printf("%-20s %-10s %10s %10s %-10s
  ", "Name", "Enabled", "uV", "mA",
  	       "Mode");
  	for (ret = uclass_first_device(UCLASS_REGULATOR, &dev); dev;
  	     ret = uclass_next_device(&dev))
  		do_status_line(dev);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
266
267
268
269
270
271
272
273
274
275
276
  
  	return CMD_RET_SUCCESS;
  }
  
  static int do_value(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct udevice *dev;
  	struct dm_regulator_uclass_platdata *uc_pdata;
  	int value;
  	int force;
  	int ret;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
277
  	ret = curr_dev_and_platdata(&dev, &uc_pdata, argc == 1);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
278
279
280
281
  	if (ret)
  		return ret;
  
  	if (argc == 1) {
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
282
283
284
285
286
287
288
  		ret = regulator_get_value(dev);
  		if (ret < 0) {
  			printf("Regulator: %s - can't get the Voltage!
  ",
  			       uc_pdata->name);
  			return failure(ret);
  		}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
289

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
290
291
  		printf("%d uV
  ", ret);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
292
293
294
295
296
297
298
299
300
301
  		return CMD_RET_SUCCESS;
  	}
  
  	if (argc == 3)
  		force = !strcmp("-f", argv[2]);
  	else
  		force = 0;
  
  	value = simple_strtoul(argv[1], NULL, 0);
  	if ((value < uc_pdata->min_uV || value > uc_pdata->max_uV) && !force) {
224d1ddcc   Simon Glass   dm: pmic: Display...
302
303
304
  		printf("Value exceeds regulator constraint limits %d..%d uV
  ",
  		       uc_pdata->min_uV, uc_pdata->max_uV);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
305
306
  		return CMD_RET_FAILURE;
  	}
2f5d532f3   Keerthy   power: regulator:...
307
308
309
310
  	if (!force)
  		ret = regulator_set_value(dev, value);
  	else
  		ret = regulator_set_value_force(dev, value);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
311
312
313
314
315
316
  	if (ret) {
  		printf("Regulator: %s - can't set the Voltage!
  ",
  		       uc_pdata->name);
  		return failure(ret);
  	}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
317
318
319
320
321
322
323
324
325
326
  
  	return CMD_RET_SUCCESS;
  }
  
  static int do_current(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct udevice *dev;
  	struct dm_regulator_uclass_platdata *uc_pdata;
  	int current;
  	int ret;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
327
  	ret = curr_dev_and_platdata(&dev, &uc_pdata, argc == 1);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
328
329
330
331
  	if (ret)
  		return ret;
  
  	if (argc == 1) {
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
332
333
334
335
336
337
338
  		ret = regulator_get_current(dev);
  		if (ret < 0) {
  			printf("Regulator: %s - can't get the Current!
  ",
  			       uc_pdata->name);
  			return failure(ret);
  		}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
339

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
340
341
  		printf("%d uA
  ", ret);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
342
343
344
345
346
347
348
349
350
351
352
  		return CMD_RET_SUCCESS;
  	}
  
  	current = simple_strtoul(argv[1], NULL, 0);
  	if (current < uc_pdata->min_uA || current > uc_pdata->max_uA) {
  		printf("Current exceeds regulator constraint limits
  ");
  		return CMD_RET_FAILURE;
  	}
  
  	ret = regulator_set_current(dev, current);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
353
354
355
356
357
358
  	if (ret) {
  		printf("Regulator: %s - can't set the Current!
  ",
  		       uc_pdata->name);
  		return failure(ret);
  	}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
359
360
361
362
363
364
365
366
  
  	return CMD_RET_SUCCESS;
  }
  
  static int do_mode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct udevice *dev;
  	struct dm_regulator_uclass_platdata *uc_pdata;
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
367
368
  	int mode;
  	int ret;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
369
  	ret = curr_dev_and_platdata(&dev, &uc_pdata, false);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
370
371
372
373
  	if (ret)
  		return ret;
  
  	if (argc == 1) {
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
374
375
376
377
378
379
380
  		ret = regulator_get_mode(dev);
  		if (ret < 0) {
  			printf("Regulator: %s - can't get the operation mode!
  ",
  			       uc_pdata->name);
  			return failure(ret);
  		}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
381

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
382
383
  		printf("mode id: %d
  ", ret);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
384
385
  		return CMD_RET_SUCCESS;
  	}
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
386
  	mode = simple_strtoul(argv[1], NULL, 0);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
387

e09b2a02d   Przemyslaw Marczak   common: cmd regul...
388
389
390
391
392
393
394
  	ret = regulator_set_mode(dev, mode);
  	if (ret) {
  		printf("Regulator: %s - can't set the operation mode!
  ",
  		       uc_pdata->name);
  		return failure(ret);
  	}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
395
396
397
398
399
400
401
402
403
  
  	return CMD_RET_SUCCESS;
  }
  
  static int do_enable(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct udevice *dev;
  	struct dm_regulator_uclass_platdata *uc_pdata;
  	int ret;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
404
  	ret = curr_dev_and_platdata(&dev, &uc_pdata, true);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
405
406
407
408
  	if (ret)
  		return ret;
  
  	ret = regulator_set_enable(dev, true);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
409
410
411
412
413
  	if (ret) {
  		printf("Regulator: %s - can't enable!
  ", uc_pdata->name);
  		return failure(ret);
  	}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
414
415
416
417
418
419
420
421
422
  
  	return CMD_RET_SUCCESS;
  }
  
  static int do_disable(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
  	struct udevice *dev;
  	struct dm_regulator_uclass_platdata *uc_pdata;
  	int ret;
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
423
  	ret = curr_dev_and_platdata(&dev, &uc_pdata, true);
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
424
425
426
427
  	if (ret)
  		return ret;
  
  	ret = regulator_set_enable(dev, false);
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
428
429
430
431
432
  	if (ret) {
  		printf("Regulator: %s - can't disable!
  ", uc_pdata->name);
  		return failure(ret);
  	}
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
  
  	return CMD_RET_SUCCESS;
  }
  
  static cmd_tbl_t subcmd[] = {
  	U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""),
  	U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""),
  	U_BOOT_CMD_MKENT(info, 2, 1, do_info, "", ""),
  	U_BOOT_CMD_MKENT(status, 2, 1, do_status, "", ""),
  	U_BOOT_CMD_MKENT(value, 3, 1, do_value, "", ""),
  	U_BOOT_CMD_MKENT(current, 3, 1, do_current, "", ""),
  	U_BOOT_CMD_MKENT(mode, 2, 1, do_mode, "", ""),
  	U_BOOT_CMD_MKENT(enable, 1, 1, do_enable, "", ""),
  	U_BOOT_CMD_MKENT(disable, 1, 1, do_disable, "", ""),
  };
  
  static int do_regulator(cmd_tbl_t *cmdtp, int flag, int argc,
  			char * const argv[])
  {
  	cmd_tbl_t *cmd;
  
  	argc--;
  	argv++;
  
  	cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd));
  	if (cmd == NULL || argc > cmd->maxargs)
  		return CMD_RET_USAGE;
  
  	return cmd->cmd(cmdtp, flag, argc, argv);
  }
  
  U_BOOT_CMD(regulator, CONFIG_SYS_MAXARGS, 1, do_regulator,
  	"uclass operations",
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
466
467
468
469
470
471
  	"list             - list UCLASS regulator devices
  "
  	"regulator dev [regulator-name] - show/[set] operating regulator device
  "
  	"regulator info                 - print constraints info
  "
931b24c5a   Simon Glass   dm: pmic: Add 're...
472
473
  	"regulator status [-a]          - print operating status [for all]
  "
e09b2a02d   Przemyslaw Marczak   common: cmd regul...
474
475
476
477
478
479
480
481
482
483
  	"regulator value [val] [-f]     - print/[set] voltage value [uV] (force)
  "
  	"regulator current [val]        - print/[set] current value [uA]
  "
  	"regulator mode [id]            - print/[set] operating mode id
  "
  	"regulator enable               - enable the regulator output
  "
  	"regulator disable              - disable the regulator output
  "
6262b72b8   Przemyslaw Marczak   dm: regulator: ad...
484
  );