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