"Das U-Boot" Source Tree
at master 468 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2014-2015 Samsung Electronics 4 * Przemyslaw Marczak <p.marczak@samsung.com> 5 */ 6#include <command.h> 7#include <errno.h> 8#include <dm.h> 9#include <dm/uclass-internal.h> 10#include <linux/printk.h> 11#include <power/regulator.h> 12 13#define LIMIT_DEVNAME 20 14#define LIMIT_OFNAME 32 15#define LIMIT_INFO 18 16 17static struct udevice *currdev; 18 19static int failure(int ret) 20{ 21 printf("Error: %d (%s)\n", ret, errno_str(ret)); 22 23 return CMD_RET_FAILURE; 24} 25 26static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 27{ 28 struct dm_regulator_uclass_plat *uc_pdata; 29 const char *name; 30 int ret = -ENXIO; 31 32 switch (argc) { 33 case 2: 34 name = argv[1]; 35 ret = regulator_get_by_platname(name, &currdev); 36 if (ret) { 37 printf("Can't get the regulator: %s!\n", name); 38 return failure(ret); 39 } 40 fallthrough; 41 case 1: 42 if (!currdev) { 43 printf("Regulator device is not set!\n\n"); 44 return CMD_RET_USAGE; 45 } 46 47 uc_pdata = dev_get_uclass_plat(currdev); 48 if (!uc_pdata) { 49 printf("%s: no regulator platform data!\n", currdev->name); 50 return failure(ret); 51 } 52 53 printf("dev: %s @ %s\n", uc_pdata->name, currdev->name); 54 } 55 56 return CMD_RET_SUCCESS; 57} 58 59static int curr_dev_and_plat(struct udevice **devp, 60 struct dm_regulator_uclass_plat **uc_pdata, 61 bool allow_type_fixed) 62{ 63 *devp = NULL; 64 *uc_pdata = NULL; 65 66 if (!currdev) { 67 printf("First, set the regulator device!\n"); 68 return CMD_RET_FAILURE; 69 } 70 71 *devp = currdev; 72 73 *uc_pdata = dev_get_uclass_plat(*devp); 74 if (!*uc_pdata) { 75 pr_err("Regulator: %s - missing platform data!\n", currdev->name); 76 return CMD_RET_FAILURE; 77 } 78 79 if (!allow_type_fixed && (*uc_pdata)->type == REGULATOR_TYPE_FIXED) { 80 printf("Operation not allowed for fixed regulator!\n"); 81 return CMD_RET_FAILURE; 82 } 83 84 return CMD_RET_SUCCESS; 85} 86 87static int do_list(struct cmd_tbl *cmdtp, int flag, int argc, 88 char *const argv[]) 89{ 90 struct dm_regulator_uclass_plat *uc_pdata; 91 struct udevice *dev; 92 int ret; 93 94 printf("| %-*.*s| %-*.*s| %s\n", 95 LIMIT_DEVNAME, LIMIT_DEVNAME, "Device", 96 LIMIT_OFNAME, LIMIT_OFNAME, "regulator-name", 97 "Parent"); 98 99 for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev; 100 ret = uclass_find_next_device(&dev)) { 101 if (ret) 102 continue; 103 104 uc_pdata = dev_get_uclass_plat(dev); 105 printf("| %-*.*s| %-*.*s| %s\n", 106 LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name, 107 LIMIT_OFNAME, LIMIT_OFNAME, uc_pdata->name, 108 dev->parent->name); 109 } 110 111 return ret; 112} 113 114static int constraint(const char *name, int val, const char *val_name) 115{ 116 printf("%-*s", LIMIT_INFO, name); 117 if (val < 0) { 118 printf(" %s (err: %d)\n", errno_str(val), val); 119 return val; 120 } 121 122 if (val_name) 123 printf(" %d (%s)\n", val, val_name); 124 else 125 printf(" %d\n", val); 126 127 return 0; 128} 129 130static const char *get_mode_name(struct dm_regulator_mode *mode, 131 int mode_count, 132 int mode_id) 133{ 134 while (mode_count--) { 135 if (mode->id == mode_id) 136 return mode->name; 137 mode++; 138 } 139 140 return NULL; 141} 142 143static int do_info(struct cmd_tbl *cmdtp, int flag, int argc, 144 char *const argv[]) 145{ 146 struct udevice *dev; 147 struct dm_regulator_uclass_plat *uc_pdata; 148 struct dm_regulator_mode *modes; 149 const char *parent_uc; 150 int mode_count; 151 int ret; 152 int i; 153 154 ret = curr_dev_and_plat(&dev, &uc_pdata, true); 155 if (ret) 156 return ret; 157 158 parent_uc = dev_get_uclass_name(dev->parent); 159 160 printf("%s\n%-*s %s\n%-*s %s\n%-*s %s\n%-*s %s\n%-*s\n", 161 "Regulator info:", 162 LIMIT_INFO, "* regulator-name:", uc_pdata->name, 163 LIMIT_INFO, "* device name:", dev->name, 164 LIMIT_INFO, "* parent name:", dev->parent->name, 165 LIMIT_INFO, "* parent uclass:", parent_uc, 166 LIMIT_INFO, "* constraints:"); 167 168 constraint(" - min uV:", uc_pdata->min_uV, NULL); 169 constraint(" - max uV:", uc_pdata->max_uV, NULL); 170 constraint(" - min uA:", uc_pdata->min_uA, NULL); 171 constraint(" - max uA:", uc_pdata->max_uA, NULL); 172 constraint(" - always on:", uc_pdata->always_on, 173 uc_pdata->always_on ? "true" : "false"); 174 constraint(" - boot on:", uc_pdata->boot_on, 175 uc_pdata->boot_on ? "true" : "false"); 176 177 mode_count = regulator_mode(dev, &modes); 178 constraint("* op modes:", mode_count, NULL); 179 180 for (i = 0; i < mode_count; i++, modes++) 181 constraint(" - mode id:", modes->id, modes->name); 182 183 return CMD_RET_SUCCESS; 184} 185 186static void do_status_detail(struct udevice *dev, 187 struct dm_regulator_uclass_plat *uc_pdata) 188{ 189 int current, value, mode; 190 const char *mode_name; 191 bool enabled; 192 193 printf("Regulator %s status:\n", uc_pdata->name); 194 195 enabled = regulator_get_enable(dev); 196 constraint(" * enable:", enabled, enabled ? "true" : "false"); 197 198 value = regulator_get_value(dev); 199 constraint(" * value uV:", value, NULL); 200 201 current = regulator_get_current(dev); 202 constraint(" * current uA:", current, NULL); 203 204 mode = regulator_get_mode(dev); 205 mode_name = get_mode_name(uc_pdata->mode, uc_pdata->mode_count, mode); 206 constraint(" * mode id:", mode, mode_name); 207} 208 209static void do_status_line(struct udevice *dev, int status) 210{ 211 struct dm_regulator_uclass_plat *pdata; 212 int current, value, mode; 213 const char *mode_name; 214 bool enabled; 215 216 pdata = dev_get_uclass_plat(dev); 217 enabled = regulator_get_enable(dev); 218 value = regulator_get_value(dev); 219 current = regulator_get_current(dev); 220 mode = regulator_get_mode(dev); 221 mode_name = get_mode_name(pdata->mode, pdata->mode_count, mode); 222 printf("%-20s %-10s ", pdata->name, enabled ? "enabled" : "disabled"); 223 if (value >= 0) 224 printf("%10d ", value); 225 else 226 printf("%10s ", "-"); 227 if (current >= 0) 228 printf("%10d ", current); 229 else 230 printf("%10s ", "-"); 231 if (mode >= 0) 232 printf("%-10s", mode_name); 233 else 234 printf("%-10s", "-"); 235 printf(" %i", status); 236 printf("\n"); 237} 238 239static int do_status(struct cmd_tbl *cmdtp, int flag, int argc, 240 char *const argv[]) 241{ 242 struct dm_regulator_uclass_plat *uc_pdata; 243 struct udevice *dev; 244 int ret; 245 246 if (currdev && (argc < 2 || strcmp(argv[1], "-a"))) { 247 ret = curr_dev_and_plat(&dev, &uc_pdata, true); 248 if (ret) 249 return CMD_RET_FAILURE; 250 do_status_detail(dev, uc_pdata); 251 return 0; 252 } 253 254 /* Show all of them in a list, probing them as needed */ 255 printf("%-20s %-10s %10s %10s %-10s %s\n", "Name", "Enabled", "uV", "mA", 256 "Mode", "Status"); 257 for (ret = uclass_first_device_check(UCLASS_REGULATOR, &dev); dev; 258 ret = uclass_next_device_check(&dev)) 259 do_status_line(dev, ret); 260 261 return CMD_RET_SUCCESS; 262} 263 264static int do_value(struct cmd_tbl *cmdtp, int flag, int argc, 265 char *const argv[]) 266{ 267 struct udevice *dev; 268 struct dm_regulator_uclass_plat *uc_pdata; 269 int value; 270 int force; 271 int ret; 272 273 ret = curr_dev_and_plat(&dev, &uc_pdata, argc == 1); 274 if (ret) 275 return ret; 276 277 if (argc == 1) { 278 ret = regulator_get_value(dev); 279 if (ret < 0) { 280 printf("Regulator: %s - can't get the Voltage!\n", 281 uc_pdata->name); 282 return failure(ret); 283 } 284 285 printf("%d uV\n", ret); 286 return CMD_RET_SUCCESS; 287 } 288 289 if (argc == 3) 290 force = !strcmp("-f", argv[2]); 291 else 292 force = 0; 293 294 value = simple_strtoul(argv[1], NULL, 0); 295 if ((value < uc_pdata->min_uV || value > uc_pdata->max_uV) && !force) { 296 printf("Value exceeds regulator constraint limits %d..%d uV\n", 297 uc_pdata->min_uV, uc_pdata->max_uV); 298 return CMD_RET_FAILURE; 299 } 300 301 if (!force) 302 ret = regulator_set_value(dev, value); 303 else 304 ret = regulator_set_value_force(dev, value); 305 if (ret) { 306 printf("Regulator: %s - can't set the Voltage!\n", 307 uc_pdata->name); 308 return failure(ret); 309 } 310 311 return CMD_RET_SUCCESS; 312} 313 314static int do_current(struct cmd_tbl *cmdtp, int flag, int argc, 315 char *const argv[]) 316{ 317 struct udevice *dev; 318 struct dm_regulator_uclass_plat *uc_pdata; 319 int current; 320 int ret; 321 322 ret = curr_dev_and_plat(&dev, &uc_pdata, argc == 1); 323 if (ret) 324 return ret; 325 326 if (argc == 1) { 327 ret = regulator_get_current(dev); 328 if (ret < 0) { 329 printf("Regulator: %s - can't get the Current!\n", 330 uc_pdata->name); 331 return failure(ret); 332 } 333 334 printf("%d uA\n", ret); 335 return CMD_RET_SUCCESS; 336 } 337 338 current = simple_strtoul(argv[1], NULL, 0); 339 if (current < uc_pdata->min_uA || current > uc_pdata->max_uA) { 340 printf("Current exceeds regulator constraint limits\n"); 341 return CMD_RET_FAILURE; 342 } 343 344 ret = regulator_set_current(dev, current); 345 if (ret) { 346 printf("Regulator: %s - can't set the Current!\n", 347 uc_pdata->name); 348 return failure(ret); 349 } 350 351 return CMD_RET_SUCCESS; 352} 353 354static int do_mode(struct cmd_tbl *cmdtp, int flag, int argc, 355 char *const argv[]) 356{ 357 struct udevice *dev; 358 struct dm_regulator_uclass_plat *uc_pdata; 359 int mode; 360 int ret; 361 362 ret = curr_dev_and_plat(&dev, &uc_pdata, false); 363 if (ret) 364 return ret; 365 366 if (argc == 1) { 367 ret = regulator_get_mode(dev); 368 if (ret < 0) { 369 printf("Regulator: %s - can't get the operation mode!\n", 370 uc_pdata->name); 371 return failure(ret); 372 } 373 374 printf("mode id: %d\n", ret); 375 return CMD_RET_SUCCESS; 376 } 377 378 mode = simple_strtoul(argv[1], NULL, 0); 379 380 ret = regulator_set_mode(dev, mode); 381 if (ret) { 382 printf("Regulator: %s - can't set the operation mode!\n", 383 uc_pdata->name); 384 return failure(ret); 385 } 386 387 return CMD_RET_SUCCESS; 388} 389 390static int do_enable(struct cmd_tbl *cmdtp, int flag, int argc, 391 char *const argv[]) 392{ 393 struct udevice *dev; 394 struct dm_regulator_uclass_plat *uc_pdata; 395 int ret; 396 397 ret = curr_dev_and_plat(&dev, &uc_pdata, true); 398 if (ret) 399 return ret; 400 401 ret = regulator_set_enable(dev, true); 402 if (ret) { 403 printf("Regulator: %s - can't enable!\n", uc_pdata->name); 404 return failure(ret); 405 } 406 407 return CMD_RET_SUCCESS; 408} 409 410static int do_disable(struct cmd_tbl *cmdtp, int flag, int argc, 411 char *const argv[]) 412{ 413 struct udevice *dev; 414 struct dm_regulator_uclass_plat *uc_pdata; 415 int ret; 416 417 ret = curr_dev_and_plat(&dev, &uc_pdata, true); 418 if (ret) 419 return ret; 420 421 ret = regulator_set_enable(dev, false); 422 if (ret) { 423 printf("Regulator: %s - can't disable!\n", uc_pdata->name); 424 return failure(ret); 425 } 426 427 return CMD_RET_SUCCESS; 428} 429 430static struct cmd_tbl subcmd[] = { 431 U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""), 432 U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""), 433 U_BOOT_CMD_MKENT(info, 2, 1, do_info, "", ""), 434 U_BOOT_CMD_MKENT(status, 2, 1, do_status, "", ""), 435 U_BOOT_CMD_MKENT(value, 3, 1, do_value, "", ""), 436 U_BOOT_CMD_MKENT(current, 3, 1, do_current, "", ""), 437 U_BOOT_CMD_MKENT(mode, 2, 1, do_mode, "", ""), 438 U_BOOT_CMD_MKENT(enable, 1, 1, do_enable, "", ""), 439 U_BOOT_CMD_MKENT(disable, 1, 1, do_disable, "", ""), 440}; 441 442static int do_regulator(struct cmd_tbl *cmdtp, int flag, int argc, 443 char *const argv[]) 444{ 445 struct cmd_tbl *cmd; 446 447 argc--; 448 argv++; 449 450 cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd)); 451 if (cmd == NULL || argc > cmd->maxargs) 452 return CMD_RET_USAGE; 453 454 return cmd->cmd(cmdtp, flag, argc, argv); 455} 456 457U_BOOT_CMD(regulator, CONFIG_SYS_MAXARGS, 1, do_regulator, 458 "uclass operations", 459 "list - list UCLASS regulator devices\n" 460 "regulator dev [regulator-name] - show/[set] operating regulator device\n" 461 "regulator info - print constraints info\n" 462 "regulator status [-a] - print operating status [for all]\n" 463 "regulator value [val] [-f] - print/[set] voltage value [uV] (force)\n" 464 "regulator current [val] - print/[set] current value [uA]\n" 465 "regulator mode [id] - print/[set] operating mode id\n" 466 "regulator enable - enable the regulator output\n" 467 "regulator disable - disable the regulator output\n" 468);