uboot/drivers/power/regulator/regulator-uclass.c
<<
>>
Prefs
   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
   8#include <common.h>
   9#include <errno.h>
  10#include <dm.h>
  11#include <dm/uclass-internal.h>
  12#include <power/pmic.h>
  13#include <power/regulator.h>
  14
  15DECLARE_GLOBAL_DATA_PTR;
  16
  17int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep)
  18{
  19        struct dm_regulator_uclass_platdata *uc_pdata;
  20
  21        *modep = NULL;
  22
  23        uc_pdata = dev_get_uclass_platdata(dev);
  24        if (!uc_pdata)
  25                return -ENXIO;
  26
  27        *modep = uc_pdata->mode;
  28        return uc_pdata->mode_count;
  29}
  30
  31int regulator_get_value(struct udevice *dev)
  32{
  33        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  34
  35        if (!ops || !ops->get_value)
  36                return -ENOSYS;
  37
  38        return ops->get_value(dev);
  39}
  40
  41int regulator_set_value(struct udevice *dev, int uV)
  42{
  43        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  44        struct dm_regulator_uclass_platdata *uc_pdata;
  45
  46        uc_pdata = dev_get_uclass_platdata(dev);
  47        if (uc_pdata->min_uV != -ENODATA && uV < uc_pdata->min_uV)
  48                return -EINVAL;
  49        if (uc_pdata->max_uV != -ENODATA && uV > uc_pdata->max_uV)
  50                return -EINVAL;
  51
  52        if (!ops || !ops->set_value)
  53                return -ENOSYS;
  54
  55        return ops->set_value(dev, uV);
  56}
  57
  58/*
  59 * To be called with at most caution as there is no check
  60 * before setting the actual voltage value.
  61 */
  62int regulator_set_value_force(struct udevice *dev, int uV)
  63{
  64        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  65
  66        if (!ops || !ops->set_value)
  67                return -ENOSYS;
  68
  69        return ops->set_value(dev, uV);
  70}
  71
  72int regulator_get_current(struct udevice *dev)
  73{
  74        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  75
  76        if (!ops || !ops->get_current)
  77                return -ENOSYS;
  78
  79        return ops->get_current(dev);
  80}
  81
  82int regulator_set_current(struct udevice *dev, int uA)
  83{
  84        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
  85        struct dm_regulator_uclass_platdata *uc_pdata;
  86
  87        uc_pdata = dev_get_uclass_platdata(dev);
  88        if (uc_pdata->min_uA != -ENODATA && uA < uc_pdata->min_uA)
  89                return -EINVAL;
  90        if (uc_pdata->max_uA != -ENODATA && uA > uc_pdata->max_uA)
  91                return -EINVAL;
  92
  93        if (!ops || !ops->set_current)
  94                return -ENOSYS;
  95
  96        return ops->set_current(dev, uA);
  97}
  98
  99int regulator_get_enable(struct udevice *dev)
 100{
 101        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 102
 103        if (!ops || !ops->get_enable)
 104                return -ENOSYS;
 105
 106        return ops->get_enable(dev);
 107}
 108
 109int regulator_set_enable(struct udevice *dev, bool enable)
 110{
 111        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 112
 113        if (!ops || !ops->set_enable)
 114                return -ENOSYS;
 115
 116        return ops->set_enable(dev, enable);
 117}
 118
 119int regulator_get_mode(struct udevice *dev)
 120{
 121        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 122
 123        if (!ops || !ops->get_mode)
 124                return -ENOSYS;
 125
 126        return ops->get_mode(dev);
 127}
 128
 129int regulator_set_mode(struct udevice *dev, int mode)
 130{
 131        const struct dm_regulator_ops *ops = dev_get_driver_ops(dev);
 132
 133        if (!ops || !ops->set_mode)
 134                return -ENOSYS;
 135
 136        return ops->set_mode(dev, mode);
 137}
 138
 139int regulator_get_by_platname(const char *plat_name, struct udevice **devp)
 140{
 141        struct dm_regulator_uclass_platdata *uc_pdata;
 142        struct udevice *dev;
 143        int ret;
 144
 145        *devp = NULL;
 146
 147        for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
 148             ret = uclass_find_next_device(&dev)) {
 149                if (ret) {
 150                        debug("regulator %s, ret=%d\n", dev->name, ret);
 151                        continue;
 152                }
 153
 154                uc_pdata = dev_get_uclass_platdata(dev);
 155                if (!uc_pdata || strcmp(plat_name, uc_pdata->name))
 156                        continue;
 157
 158                return uclass_get_device_tail(dev, 0, devp);
 159        }
 160
 161        debug("%s: can't find: %s, ret=%d\n", __func__, plat_name, ret);
 162
 163        return -ENODEV;
 164}
 165
 166int regulator_get_by_devname(const char *devname, struct udevice **devp)
 167{
 168        return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
 169}
 170
 171int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
 172                                struct udevice **devp)
 173{
 174        return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
 175                                            supply_name, devp);
 176}
 177
 178int regulator_autoset(struct udevice *dev)
 179{
 180        struct dm_regulator_uclass_platdata *uc_pdata;
 181        int ret = 0;
 182
 183        uc_pdata = dev_get_uclass_platdata(dev);
 184        if (!uc_pdata->always_on && !uc_pdata->boot_on)
 185                return -EMEDIUMTYPE;
 186
 187        if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
 188                ret = regulator_set_value(dev, uc_pdata->min_uV);
 189        if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
 190                ret = regulator_set_current(dev, uc_pdata->min_uA);
 191
 192        if (!ret)
 193                ret = regulator_set_enable(dev, true);
 194
 195        return ret;
 196}
 197
 198static void regulator_show(struct udevice *dev, int ret)
 199{
 200        struct dm_regulator_uclass_platdata *uc_pdata;
 201
 202        uc_pdata = dev_get_uclass_platdata(dev);
 203
 204        printf("%s@%s: ", dev->name, uc_pdata->name);
 205        if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
 206                printf("set %d uV", uc_pdata->min_uV);
 207        if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
 208                printf("; set %d uA", uc_pdata->min_uA);
 209        printf("; enabling");
 210        if (ret)
 211                printf(" (ret: %d)", ret);
 212        printf("\n");
 213}
 214
 215int regulator_autoset_by_name(const char *platname, struct udevice **devp)
 216{
 217        struct udevice *dev;
 218        int ret;
 219
 220        ret = regulator_get_by_platname(platname, &dev);
 221        if (devp)
 222                *devp = dev;
 223        if (ret) {
 224                debug("Can get the regulator: %s (err=%d)\n", platname, ret);
 225                return ret;
 226        }
 227
 228        return regulator_autoset(dev);
 229}
 230
 231int regulator_list_autoset(const char *list_platname[],
 232                           struct udevice *list_devp[],
 233                           bool verbose)
 234{
 235        struct udevice *dev;
 236        int error = 0, i = 0, ret;
 237
 238        while (list_platname[i]) {
 239                ret = regulator_autoset_by_name(list_platname[i], &dev);
 240                if (ret != -EMEDIUMTYPE && verbose)
 241                        regulator_show(dev, ret);
 242                if (ret & !error)
 243                        error = ret;
 244
 245                if (list_devp)
 246                        list_devp[i] = dev;
 247
 248                i++;
 249        }
 250
 251        return error;
 252}
 253
 254static bool regulator_name_is_unique(struct udevice *check_dev,
 255                                     const char *check_name)
 256{
 257        struct dm_regulator_uclass_platdata *uc_pdata;
 258        struct udevice *dev;
 259        int check_len = strlen(check_name);
 260        int ret;
 261        int len;
 262
 263        for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
 264             ret = uclass_find_next_device(&dev)) {
 265                if (ret || dev == check_dev)
 266                        continue;
 267
 268                uc_pdata = dev_get_uclass_platdata(dev);
 269                len = strlen(uc_pdata->name);
 270                if (len != check_len)
 271                        continue;
 272
 273                if (!strcmp(uc_pdata->name, check_name))
 274                        return false;
 275        }
 276
 277        return true;
 278}
 279
 280static int regulator_post_bind(struct udevice *dev)
 281{
 282        struct dm_regulator_uclass_platdata *uc_pdata;
 283        const char *property = "regulator-name";
 284
 285        uc_pdata = dev_get_uclass_platdata(dev);
 286
 287        /* Regulator's mandatory constraint */
 288        uc_pdata->name = dev_read_string(dev, property);
 289        if (!uc_pdata->name) {
 290                debug("%s: dev '%s' has no property '%s'\n",
 291                      __func__, dev->name, property);
 292                uc_pdata->name = dev_read_name(dev);
 293                if (!uc_pdata->name)
 294                        return -EINVAL;
 295        }
 296
 297        if (regulator_name_is_unique(dev, uc_pdata->name))
 298                return 0;
 299
 300        debug("'%s' of dev: '%s', has nonunique value: '%s\n",
 301              property, dev->name, uc_pdata->name);
 302
 303        return -EINVAL;
 304}
 305
 306static int regulator_pre_probe(struct udevice *dev)
 307{
 308        struct dm_regulator_uclass_platdata *uc_pdata;
 309
 310        uc_pdata = dev_get_uclass_platdata(dev);
 311        if (!uc_pdata)
 312                return -ENXIO;
 313
 314        /* Regulator's optional constraints */
 315        uc_pdata->min_uV = dev_read_u32_default(dev, "regulator-min-microvolt",
 316                                                -ENODATA);
 317        uc_pdata->max_uV = dev_read_u32_default(dev, "regulator-max-microvolt",
 318                                                -ENODATA);
 319        uc_pdata->min_uA = dev_read_u32_default(dev, "regulator-min-microamp",
 320                                                -ENODATA);
 321        uc_pdata->max_uA = dev_read_u32_default(dev, "regulator-max-microamp",
 322                                                -ENODATA);
 323        uc_pdata->always_on = dev_read_bool(dev, "regulator-always-on");
 324        uc_pdata->boot_on = dev_read_bool(dev, "regulator-boot-on");
 325
 326        /* Those values are optional (-ENODATA if unset) */
 327        if ((uc_pdata->min_uV != -ENODATA) &&
 328            (uc_pdata->max_uV != -ENODATA) &&
 329            (uc_pdata->min_uV == uc_pdata->max_uV))
 330                uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
 331
 332        /* Those values are optional (-ENODATA if unset) */
 333        if ((uc_pdata->min_uA != -ENODATA) &&
 334            (uc_pdata->max_uA != -ENODATA) &&
 335            (uc_pdata->min_uA == uc_pdata->max_uA))
 336                uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
 337
 338        return 0;
 339}
 340
 341int regulators_enable_boot_on(bool verbose)
 342{
 343        struct udevice *dev;
 344        struct uclass *uc;
 345        int ret;
 346
 347        ret = uclass_get(UCLASS_REGULATOR, &uc);
 348        if (ret)
 349                return ret;
 350        for (uclass_first_device(UCLASS_REGULATOR, &dev);
 351             dev;
 352             uclass_next_device(&dev)) {
 353                ret = regulator_autoset(dev);
 354                if (ret == -EMEDIUMTYPE) {
 355                        ret = 0;
 356                        continue;
 357                }
 358                if (verbose)
 359                        regulator_show(dev, ret);
 360                if (ret == -ENOSYS)
 361                        ret = 0;
 362        }
 363
 364        return ret;
 365}
 366
 367UCLASS_DRIVER(regulator) = {
 368        .id             = UCLASS_REGULATOR,
 369        .name           = "regulator",
 370        .post_bind      = regulator_post_bind,
 371        .pre_probe      = regulator_pre_probe,
 372        .per_device_platdata_auto_alloc_size =
 373                                sizeof(struct dm_regulator_uclass_platdata),
 374};
 375