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