uboot/drivers/power/regulator/regulator-uclass.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
   7#define LOG_CATEGORY UCLASS_REGULATOR
   8
   9#include <common.h>
  10#include <errno.h>
  11#include <dm.h>
  12#include <log.h>
  13#include <dm/uclass-internal.h>
  14#include <linux/delay.h>
  15#include <power/pmic.h>
  16#include <power/regulator.h>
  17
  18int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep)
  19{
  20        struct dm_regulator_uclass_plat *uc_pdata;
  21
  22        *modep = NULL;
  23
  24        uc_pdata = dev_get_uclass_plat(dev);
  25        if (!uc_pdata)
  26                return -ENXIO;
  27
  28        *modep = uc_pdata->mode;
  29        return uc_pdata->mode_count;
  30}
  31
  32int regulator_get_value(struct udevice *dev)
  33{
  34        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  35
  36        if (!ops || !ops->get_value)
  37                return -ENOSYS;
  38
  39        return ops->get_value(dev);
  40}
  41
  42static void regulator_set_value_ramp_delay(struct udevice *dev, int old_uV,
  43                                           int new_uV, unsigned int ramp_delay)
  44{
  45        int delay = DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
  46
  47        debug("regulator %s: delay %u us (%d uV -> %d uV)\n", dev->name, delay,
  48              old_uV, new_uV);
  49
  50        udelay(delay);
  51}
  52
  53int regulator_set_value(struct udevice *dev, int uV)
  54{
  55        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  56        struct dm_regulator_uclass_plat *uc_pdata;
  57        int ret, old_uV = uV, is_enabled = 0;
  58
  59        uc_pdata = dev_get_uclass_plat(dev);
  60        if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
  61                return -EINVAL;
  62        if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
  63                return -EINVAL;
  64
  65        if (!ops || !ops->set_value)
  66                return -ENOSYS;
  67
  68        if (uc_pdata->ramp_delay) {
  69                is_enabled = regulator_get_enable(dev);
  70                old_uV = regulator_get_value(dev);
  71        }
  72
  73        ret = ops->set_value(dev, uV);
  74
  75        if (!ret) {
  76                if (uc_pdata->ramp_delay && old_uV > 0 && is_enabled)
  77                        regulator_set_value_ramp_delay(dev, old_uV, uV,
  78                                                       uc_pdata->ramp_delay);
  79        }
  80
  81        return ret;
  82}
  83
  84int regulator_set_suspend_value(struct udevice *dev, int uV)
  85{
  86        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  87        struct dm_regulator_uclass_plat *uc_pdata;
  88
  89        uc_pdata = dev_get_uclass_plat(dev);
  90        if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
  91                return -EINVAL;
  92        if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
  93                return -EINVAL;
  94
  95        if (!ops->set_suspend_value)
  96                return -ENOSYS;
  97
  98        return ops->set_suspend_value(dev, uV);
  99}
 100
 101int regulator_get_suspend_value(struct udevice *dev)
 102{
 103        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 104
 105        if (!ops->get_suspend_value)
 106                return -ENOSYS;
 107
 108        return ops->get_suspend_value(dev);
 109}
 110
 111/*
 112 * To be called with at most caution as there is no check
 113 * before setting the actual voltage value.
 114 */
 115int regulator_set_value_force(struct udevice *dev, int uV)
 116{
 117        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 118
 119        if (!ops || !ops->set_value)
 120                return -ENOSYS;
 121
 122        return ops->set_value(dev, uV);
 123}
 124
 125int regulator_get_current(struct udevice *dev)
 126{
 127        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 128
 129        if (!ops || !ops->get_current)
 130                return -ENOSYS;
 131
 132        return ops->get_current(dev);
 133}
 134
 135int regulator_set_current(struct udevice *dev, int uA)
 136{
 137        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 138        struct dm_regulator_uclass_plat *uc_pdata;
 139
 140        uc_pdata = dev_get_uclass_plat(dev);
 141        if (uc_pdata->min_uA != -ENODATA && uA < uc_pdata->min_uA)
 142                return -EINVAL;
 143        if (uc_pdata->max_uA != -ENODATA && uA > uc_pdata->max_uA)
 144                return -EINVAL;
 145
 146        if (!ops || !ops->set_current)
 147                return -ENOSYS;
 148
 149        return ops->set_current(dev, uA);
 150}
 151
 152int regulator_get_enable(struct udevice *dev)
 153{
 154        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 155
 156        if (!ops || !ops->get_enable)
 157                return -ENOSYS;
 158
 159        return ops->get_enable(dev);
 160}
 161
 162int regulator_set_enable(struct udevice *dev, bool enable)
 163{
 164        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 165        struct dm_regulator_uclass_plat *uc_pdata;
 166        int ret, old_enable = 0;
 167
 168        if (!ops || !ops->set_enable)
 169                return -ENOSYS;
 170
 171        uc_pdata = dev_get_uclass_plat(dev);
 172        if (!enable && uc_pdata->always_on)
 173                return -EACCES;
 174
 175        if (uc_pdata->ramp_delay)
 176                old_enable = regulator_get_enable(dev);
 177
 178        ret = ops->set_enable(dev, enable);
 179        if (!ret) {
 180                if (uc_pdata->ramp_delay && !old_enable && enable) {
 181                        int uV = regulator_get_value(dev);
 182
 183                        if (uV > 0) {
 184                                regulator_set_value_ramp_delay(dev, 0, uV,
 185                                                               uc_pdata->ramp_delay);
 186                        }
 187                }
 188        }
 189
 190        return ret;
 191}
 192
 193int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
 194{
 195        int ret;
 196
 197        ret = regulator_set_enable(dev, enable);
 198        if (ret == -ENOSYS || ret == -EACCES)
 199                return 0;
 200
 201        return ret;
 202}
 203
 204int regulator_set_suspend_enable(struct udevice *dev, bool enable)
 205{
 206        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 207
 208        if (!ops->set_suspend_enable)
 209                return -ENOSYS;
 210
 211        return ops->set_suspend_enable(dev, enable);
 212}
 213
 214int regulator_get_suspend_enable(struct udevice *dev)
 215{
 216        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 217
 218        if (!ops->get_suspend_enable)
 219                return -ENOSYS;
 220
 221        return ops->get_suspend_enable(dev);
 222}
 223
 224int regulator_get_mode(struct udevice *dev)
 225{
 226        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 227
 228        if (!ops || !ops->get_mode)
 229                return -ENOSYS;
 230
 231        return ops->get_mode(dev);
 232}
 233
 234int regulator_set_mode(struct udevice *dev, int mode)
 235{
 236        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 237
 238        if (!ops || !ops->set_mode)
 239                return -ENOSYS;
 240
 241        return ops->set_mode(dev, mode);
 242}
 243
 244int regulator_get_by_platname(const char *plat_name, struct udevice **devp)
 245{
 246        struct dm_regulator_uclass_plat *uc_pdata;
 247        struct udevice *dev;
 248        int ret;
 249
 250        *devp = NULL;
 251
 252        for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
 253             ret = uclass_find_next_device(&dev)) {
 254                if (ret) {
 255                        debug("regulator %s, ret=%d\n", dev->name, ret);
 256                        continue;
 257                }
 258
 259                uc_pdata = dev_get_uclass_plat(dev);
 260                if (!uc_pdata || strcmp(plat_name, uc_pdata->name))
 261                        continue;
 262
 263                return uclass_get_device_tail(dev, 0, devp);
 264        }
 265
 266        debug("%s: can't find: %s, ret=%d\n", __func__, plat_name, ret);
 267
 268        return -ENODEV;
 269}
 270
 271int regulator_get_by_devname(const char *devname, struct udevice **devp)
 272{
 273        return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
 274}
 275
 276int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
 277                                struct udevice **devp)
 278{
 279        return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
 280                                            supply_name, devp);
 281}
 282
 283int regulator_autoset(struct udevice *dev)
 284{
 285        struct dm_regulator_uclass_plat *uc_pdata;
 286        int ret = 0;
 287
 288        uc_pdata = dev_get_uclass_plat(dev);
 289
 290        ret = regulator_set_suspend_enable(dev, uc_pdata->suspend_on);
 291        if (!ret && uc_pdata->suspend_on) {
 292                ret = regulator_set_suspend_value(dev, uc_pdata->suspend_uV);
 293                if (!ret)
 294                        return ret;
 295        }
 296
 297        if (!uc_pdata->always_on && !uc_pdata->boot_on)
 298                return -EMEDIUMTYPE;
 299
 300        if (uc_pdata->type == REGULATOR_TYPE_FIXED)
 301                return regulator_set_enable(dev, true);
 302
 303        if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
 304                ret = regulator_set_value(dev, uc_pdata->min_uV);
 305        if (uc_pdata->init_uV > 0)
 306                ret = regulator_set_value(dev, uc_pdata->init_uV);
 307        if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
 308                ret = regulator_set_current(dev, uc_pdata->min_uA);
 309
 310        if (!ret)
 311                ret = regulator_set_enable(dev, true);
 312
 313        return ret;
 314}
 315
 316int regulator_unset(struct udevice *dev)
 317{
 318        struct dm_regulator_uclass_plat *uc_pdata;
 319
 320        uc_pdata = dev_get_uclass_plat(dev);
 321        if (uc_pdata && uc_pdata->force_off)
 322                return regulator_set_enable(dev, false);
 323
 324        return -EMEDIUMTYPE;
 325}
 326
 327static void regulator_show(struct udevice *dev, int ret)
 328{
 329        struct dm_regulator_uclass_plat *uc_pdata;
 330
 331        uc_pdata = dev_get_uclass_plat(dev);
 332
 333        printf("%s@%s: ", dev->name, uc_pdata->name);
 334        if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
 335                printf("set %d uV", uc_pdata->min_uV);
 336        if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
 337                printf("; set %d uA", uc_pdata->min_uA);
 338        printf("; enabling");
 339        if (ret)
 340                printf(" (ret: %d)", ret);
 341        printf("\n");
 342}
 343
 344int regulator_autoset_by_name(const char *platname, struct udevice **devp)
 345{
 346        struct udevice *dev;
 347        int ret;
 348
 349        ret = regulator_get_by_platname(platname, &dev);
 350        if (devp)
 351                *devp = dev;
 352        if (ret) {
 353                debug("Can get the regulator: %s (err=%d)\n", platname, ret);
 354                return ret;
 355        }
 356
 357        return regulator_autoset(dev);
 358}
 359
 360int regulator_list_autoset(const char *list_platname[],
 361                           struct udevice *list_devp[],
 362                           bool verbose)
 363{
 364        struct udevice *dev;
 365        int error = 0, i = 0, ret;
 366
 367        while (list_platname[i]) {
 368                ret = regulator_autoset_by_name(list_platname[i], &dev);
 369                if (ret != -EMEDIUMTYPE && verbose)
 370                        regulator_show(dev, ret);
 371                if (ret & !error)
 372                        error = ret;
 373
 374                if (list_devp)
 375                        list_devp[i] = dev;
 376
 377                i++;
 378        }
 379
 380        return error;
 381}
 382
 383static bool regulator_name_is_unique(struct udevice *check_dev,
 384                                     const char *check_name)
 385{
 386        struct dm_regulator_uclass_plat *uc_pdata;
 387        struct udevice *dev;
 388        int check_len = strlen(check_name);
 389        int ret;
 390        int len;
 391
 392        for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
 393             ret = uclass_find_next_device(&dev)) {
 394                if (ret || dev == check_dev)
 395                        continue;
 396
 397                uc_pdata = dev_get_uclass_plat(dev);
 398                len = strlen(uc_pdata->name);
 399                if (len != check_len)
 400                        continue;
 401
 402                if (!strcmp(uc_pdata->name, check_name))
 403                        return false;
 404        }
 405
 406        return true;
 407}
 408
 409static int regulator_post_bind(struct udevice *dev)
 410{
 411        struct dm_regulator_uclass_plat *uc_pdata;
 412        const char *property = "regulator-name";
 413
 414        uc_pdata = dev_get_uclass_plat(dev);
 415
 416        /* Regulator's mandatory constraint */
 417        uc_pdata->name = dev_read_string(dev, property);
 418        if (!uc_pdata->name) {
 419                debug("%s: dev '%s' has no property '%s'\n",
 420                      __func__, dev->name, property);
 421                uc_pdata->name = dev_read_name(dev);
 422                if (!uc_pdata->name)
 423                        return -EINVAL;
 424        }
 425
 426        if (regulator_name_is_unique(dev, uc_pdata->name))
 427                return 0;
 428
 429        debug("'%s' of dev: '%s', has nonunique value: '%s\n",
 430              property, dev->name, uc_pdata->name);
 431
 432        return -EINVAL;
 433}
 434
 435static int regulator_pre_probe(struct udevice *dev)
 436{
 437        struct dm_regulator_uclass_plat *uc_pdata;
 438        ofnode node;
 439
 440        uc_pdata = dev_get_uclass_plat(dev);
 441        if (!uc_pdata)
 442                return -ENXIO;
 443
 444        /* Regulator's optional constraints */
 445        uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt",
 446                                                -ENODATA);
 447        uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
 448                                                -ENODATA);
 449        uc_pdata->init_uV = dev_read_u32_default(dev, "regulator-init-microvolt",
 450                                                 -ENODATA);
 451        uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
 452                                                -ENODATA);
 453        uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
 454                                                -ENODATA);
 455        uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
 456        uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
 457        uc_pdata->ramp_delay = dev_read_u32_default(dev, "regulator-ramp-delay",
 458                                                    0);
 459        uc_pdata->force_off = dev_read_bool(dev, "regulator-force-boot-off");
 460
 461        node = dev_read_subnode(dev, "regulator-state-mem");
 462        if (ofnode_valid(node)) {
 463                uc_pdata->suspend_on = !ofnode_read_bool(node, "regulator-off-in-suspend");
 464                if (ofnode_read_u32(node, "regulator-suspend-microvolt", &uc_pdata->suspend_uV))
 465                        uc_pdata->suspend_uV = uc_pdata->max_uV;
 466        } else {
 467                uc_pdata->suspend_on = true;
 468                uc_pdata->suspend_uV = uc_pdata->max_uV;
 469        }
 470
 471        /* Those values are optional (-ENODATA if unset) */
 472        if ((uc_pdata->min_uV != -ENODATA) &&
 473            (uc_pdata->max_uV != -ENODATA) &&
 474            (uc_pdata->min_uV == uc_pdata->max_uV))
 475                uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
 476
 477        /* Those values are optional (-ENODATA if unset) */
 478        if ((uc_pdata->min_uA != -ENODATA) &&
 479            (uc_pdata->max_uA != -ENODATA) &&
 480            (uc_pdata->min_uA == uc_pdata->max_uA))
 481                uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
 482
 483        return 0;
 484}
 485
 486int regulators_enable_boot_on(bool verbose)
 487{
 488        struct udevice *dev;
 489        struct uclass *uc;
 490        int ret;
 491
 492        ret = uclass_get(UCLASS_REGULATOR, &uc);
 493        if (ret)
 494                return ret;
 495        for (uclass_first_device(UCLASS_REGULATOR, &dev);
 496             dev;
 497             uclass_next_device(&dev)) {
 498                ret = regulator_autoset(dev);
 499                if (ret == -EMEDIUMTYPE) {
 500                        ret = 0;
 501                        continue;
 502                }
 503                if (verbose)
 504                        regulator_show(dev, ret);
 505                if (ret == -ENOSYS)
 506                        ret = 0;
 507        }
 508
 509        return ret;
 510}
 511
 512int regulators_enable_boot_off(bool verbose)
 513{
 514        struct udevice *dev;
 515        struct uclass *uc;
 516        int ret;
 517
 518        ret = uclass_get(UCLASS_REGULATOR, &uc);
 519        if (ret)
 520                return ret;
 521        for (uclass_first_device(UCLASS_REGULATOR, &dev);
 522             dev;
 523             uclass_next_device(&dev)) {
 524                ret = regulator_unset(dev);
 525                if (ret == -EMEDIUMTYPE) {
 526                        ret = 0;
 527                        continue;
 528                }
 529                if (verbose)
 530                        regulator_show(dev, ret);
 531                if (ret == -ENOSYS)
 532                        ret = 0;
 533        }
 534
 535        return ret;
 536}
 537
 538UCLASS_DRIVER(regulator) = {
 539        .id             = UCLASS_REGULATOR,
 540        .name           = "regulator",
 541        .post_bind      = regulator_post_bind,
 542        .pre_probe      = regulator_pre_probe,
 543        .per_device_plat_auto   = sizeof(struct dm_regulator_uclass_plat),
 544};
 545