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