linux/drivers/regulator/devres.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * devres.c  --  Voltage/Current Regulator framework devres implementation.
   4 *
   5 * Copyright 2013 Linaro Ltd
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/err.h>
  10#include <linux/regmap.h>
  11#include <linux/regulator/consumer.h>
  12#include <linux/regulator/driver.h>
  13#include <linux/module.h>
  14
  15#include "internal.h"
  16
  17static void devm_regulator_release(struct device *dev, void *res)
  18{
  19        regulator_put(*(struct regulator **)res);
  20}
  21
  22static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
  23                                             int get_type)
  24{
  25        struct regulator **ptr, *regulator;
  26
  27        ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
  28        if (!ptr)
  29                return ERR_PTR(-ENOMEM);
  30
  31        regulator = _regulator_get(dev, id, get_type);
  32        if (!IS_ERR(regulator)) {
  33                *ptr = regulator;
  34                devres_add(dev, ptr);
  35        } else {
  36                devres_free(ptr);
  37        }
  38
  39        return regulator;
  40}
  41
  42/**
  43 * devm_regulator_get - Resource managed regulator_get()
  44 * @dev: device for regulator "consumer"
  45 * @id: Supply name or regulator ID.
  46 *
  47 * Managed regulator_get(). Regulators returned from this function are
  48 * automatically regulator_put() on driver detach. See regulator_get() for more
  49 * information.
  50 */
  51struct regulator *devm_regulator_get(struct device *dev, const char *id)
  52{
  53        return _devm_regulator_get(dev, id, NORMAL_GET);
  54}
  55EXPORT_SYMBOL_GPL(devm_regulator_get);
  56
  57/**
  58 * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
  59 * @dev: device for regulator "consumer"
  60 * @id: Supply name or regulator ID.
  61 *
  62 * Managed regulator_get_exclusive(). Regulators returned from this function
  63 * are automatically regulator_put() on driver detach. See regulator_get() for
  64 * more information.
  65 */
  66struct regulator *devm_regulator_get_exclusive(struct device *dev,
  67                                               const char *id)
  68{
  69        return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
  70}
  71EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
  72
  73/**
  74 * devm_regulator_get_optional - Resource managed regulator_get_optional()
  75 * @dev: device for regulator "consumer"
  76 * @id: Supply name or regulator ID.
  77 *
  78 * Managed regulator_get_optional(). Regulators returned from this
  79 * function are automatically regulator_put() on driver detach. See
  80 * regulator_get_optional() for more information.
  81 */
  82struct regulator *devm_regulator_get_optional(struct device *dev,
  83                                              const char *id)
  84{
  85        return _devm_regulator_get(dev, id, OPTIONAL_GET);
  86}
  87EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
  88
  89static int devm_regulator_match(struct device *dev, void *res, void *data)
  90{
  91        struct regulator **r = res;
  92        if (!r || !*r) {
  93                WARN_ON(!r || !*r);
  94                return 0;
  95        }
  96        return *r == data;
  97}
  98
  99/**
 100 * devm_regulator_put - Resource managed regulator_put()
 101 * @regulator: regulator to free
 102 *
 103 * Deallocate a regulator allocated with devm_regulator_get(). Normally
 104 * this function will not need to be called and the resource management
 105 * code will ensure that the resource is freed.
 106 */
 107void devm_regulator_put(struct regulator *regulator)
 108{
 109        int rc;
 110
 111        rc = devres_release(regulator->dev, devm_regulator_release,
 112                            devm_regulator_match, regulator);
 113        if (rc != 0)
 114                WARN_ON(rc);
 115}
 116EXPORT_SYMBOL_GPL(devm_regulator_put);
 117
 118struct regulator_bulk_devres {
 119        struct regulator_bulk_data *consumers;
 120        int num_consumers;
 121};
 122
 123static void devm_regulator_bulk_release(struct device *dev, void *res)
 124{
 125        struct regulator_bulk_devres *devres = res;
 126
 127        regulator_bulk_free(devres->num_consumers, devres->consumers);
 128}
 129
 130/**
 131 * devm_regulator_bulk_get - managed get multiple regulator consumers
 132 *
 133 * @dev:           Device to supply
 134 * @num_consumers: Number of consumers to register
 135 * @consumers:     Configuration of consumers; clients are stored here.
 136 *
 137 * @return 0 on success, an errno on failure.
 138 *
 139 * This helper function allows drivers to get several regulator
 140 * consumers in one operation with management, the regulators will
 141 * automatically be freed when the device is unbound.  If any of the
 142 * regulators cannot be acquired then any regulators that were
 143 * allocated will be freed before returning to the caller.
 144 */
 145int devm_regulator_bulk_get(struct device *dev, int num_consumers,
 146                            struct regulator_bulk_data *consumers)
 147{
 148        struct regulator_bulk_devres *devres;
 149        int ret;
 150
 151        devres = devres_alloc(devm_regulator_bulk_release,
 152                              sizeof(*devres), GFP_KERNEL);
 153        if (!devres)
 154                return -ENOMEM;
 155
 156        ret = regulator_bulk_get(dev, num_consumers, consumers);
 157        if (!ret) {
 158                devres->consumers = consumers;
 159                devres->num_consumers = num_consumers;
 160                devres_add(dev, devres);
 161        } else {
 162                devres_free(devres);
 163        }
 164
 165        return ret;
 166}
 167EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
 168
 169static void devm_rdev_release(struct device *dev, void *res)
 170{
 171        regulator_unregister(*(struct regulator_dev **)res);
 172}
 173
 174/**
 175 * devm_regulator_register - Resource managed regulator_register()
 176 * @regulator_desc: regulator to register
 177 * @config: runtime configuration for regulator
 178 *
 179 * Called by regulator drivers to register a regulator.  Returns a
 180 * valid pointer to struct regulator_dev on success or an ERR_PTR() on
 181 * error.  The regulator will automatically be released when the device
 182 * is unbound.
 183 */
 184struct regulator_dev *devm_regulator_register(struct device *dev,
 185                                  const struct regulator_desc *regulator_desc,
 186                                  const struct regulator_config *config)
 187{
 188        struct regulator_dev **ptr, *rdev;
 189
 190        ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
 191                           GFP_KERNEL);
 192        if (!ptr)
 193                return ERR_PTR(-ENOMEM);
 194
 195        rdev = regulator_register(regulator_desc, config);
 196        if (!IS_ERR(rdev)) {
 197                *ptr = rdev;
 198                devres_add(dev, ptr);
 199        } else {
 200                devres_free(ptr);
 201        }
 202
 203        return rdev;
 204}
 205EXPORT_SYMBOL_GPL(devm_regulator_register);
 206
 207static int devm_rdev_match(struct device *dev, void *res, void *data)
 208{
 209        struct regulator_dev **r = res;
 210        if (!r || !*r) {
 211                WARN_ON(!r || !*r);
 212                return 0;
 213        }
 214        return *r == data;
 215}
 216
 217/**
 218 * devm_regulator_unregister - Resource managed regulator_unregister()
 219 * @regulator: regulator to free
 220 *
 221 * Unregister a regulator registered with devm_regulator_register().
 222 * Normally this function will not need to be called and the resource
 223 * management code will ensure that the resource is freed.
 224 */
 225void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
 226{
 227        int rc;
 228
 229        rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
 230        if (rc != 0)
 231                WARN_ON(rc);
 232}
 233EXPORT_SYMBOL_GPL(devm_regulator_unregister);
 234
 235struct regulator_supply_alias_match {
 236        struct device *dev;
 237        const char *id;
 238};
 239
 240static int devm_regulator_match_supply_alias(struct device *dev, void *res,
 241                                             void *data)
 242{
 243        struct regulator_supply_alias_match *match = res;
 244        struct regulator_supply_alias_match *target = data;
 245
 246        return match->dev == target->dev && strcmp(match->id, target->id) == 0;
 247}
 248
 249static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
 250{
 251        struct regulator_supply_alias_match *match = res;
 252
 253        regulator_unregister_supply_alias(match->dev, match->id);
 254}
 255
 256/**
 257 * devm_regulator_register_supply_alias - Resource managed
 258 * regulator_register_supply_alias()
 259 *
 260 * @dev: device that will be given as the regulator "consumer"
 261 * @id: Supply name or regulator ID
 262 * @alias_dev: device that should be used to lookup the supply
 263 * @alias_id: Supply name or regulator ID that should be used to lookup the
 264 * supply
 265 *
 266 * The supply alias will automatically be unregistered when the source
 267 * device is unbound.
 268 */
 269int devm_regulator_register_supply_alias(struct device *dev, const char *id,
 270                                         struct device *alias_dev,
 271                                         const char *alias_id)
 272{
 273        struct regulator_supply_alias_match *match;
 274        int ret;
 275
 276        match = devres_alloc(devm_regulator_destroy_supply_alias,
 277                           sizeof(struct regulator_supply_alias_match),
 278                           GFP_KERNEL);
 279        if (!match)
 280                return -ENOMEM;
 281
 282        match->dev = dev;
 283        match->id = id;
 284
 285        ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
 286        if (ret < 0) {
 287                devres_free(match);
 288                return ret;
 289        }
 290
 291        devres_add(dev, match);
 292
 293        return 0;
 294}
 295EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
 296
 297/**
 298 * devm_regulator_unregister_supply_alias - Resource managed
 299 * regulator_unregister_supply_alias()
 300 *
 301 * @dev: device that will be given as the regulator "consumer"
 302 * @id: Supply name or regulator ID
 303 *
 304 * Unregister an alias registered with
 305 * devm_regulator_register_supply_alias(). Normally this function
 306 * will not need to be called and the resource management code
 307 * will ensure that the resource is freed.
 308 */
 309void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
 310{
 311        struct regulator_supply_alias_match match;
 312        int rc;
 313
 314        match.dev = dev;
 315        match.id = id;
 316
 317        rc = devres_release(dev, devm_regulator_destroy_supply_alias,
 318                            devm_regulator_match_supply_alias, &match);
 319        if (rc != 0)
 320                WARN_ON(rc);
 321}
 322EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
 323
 324/**
 325 * devm_regulator_bulk_register_supply_alias - Managed register
 326 * multiple aliases
 327 *
 328 * @dev: device that will be given as the regulator "consumer"
 329 * @id: List of supply names or regulator IDs
 330 * @alias_dev: device that should be used to lookup the supply
 331 * @alias_id: List of supply names or regulator IDs that should be used to
 332 * lookup the supply
 333 * @num_id: Number of aliases to register
 334 *
 335 * @return 0 on success, an errno on failure.
 336 *
 337 * This helper function allows drivers to register several supply
 338 * aliases in one operation, the aliases will be automatically
 339 * unregisters when the source device is unbound.  If any of the
 340 * aliases cannot be registered any aliases that were registered
 341 * will be removed before returning to the caller.
 342 */
 343int devm_regulator_bulk_register_supply_alias(struct device *dev,
 344                                              const char *const *id,
 345                                              struct device *alias_dev,
 346                                              const char *const *alias_id,
 347                                              int num_id)
 348{
 349        int i;
 350        int ret;
 351
 352        for (i = 0; i < num_id; ++i) {
 353                ret = devm_regulator_register_supply_alias(dev, id[i],
 354                                                           alias_dev,
 355                                                           alias_id[i]);
 356                if (ret < 0)
 357                        goto err;
 358        }
 359
 360        return 0;
 361
 362err:
 363        dev_err(dev,
 364                "Failed to create supply alias %s,%s -> %s,%s\n",
 365                id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
 366
 367        while (--i >= 0)
 368                devm_regulator_unregister_supply_alias(dev, id[i]);
 369
 370        return ret;
 371}
 372EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
 373
 374/**
 375 * devm_regulator_bulk_unregister_supply_alias - Managed unregister
 376 * multiple aliases
 377 *
 378 * @dev: device that will be given as the regulator "consumer"
 379 * @id: List of supply names or regulator IDs
 380 * @num_id: Number of aliases to unregister
 381 *
 382 * Unregister aliases registered with
 383 * devm_regulator_bulk_register_supply_alias(). Normally this function
 384 * will not need to be called and the resource management code
 385 * will ensure that the resource is freed.
 386 */
 387void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
 388                                                 const char *const *id,
 389                                                 int num_id)
 390{
 391        int i;
 392
 393        for (i = 0; i < num_id; ++i)
 394                devm_regulator_unregister_supply_alias(dev, id[i]);
 395}
 396EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
 397
 398struct regulator_notifier_match {
 399        struct regulator *regulator;
 400        struct notifier_block *nb;
 401};
 402
 403static int devm_regulator_match_notifier(struct device *dev, void *res,
 404                                         void *data)
 405{
 406        struct regulator_notifier_match *match = res;
 407        struct regulator_notifier_match *target = data;
 408
 409        return match->regulator == target->regulator && match->nb == target->nb;
 410}
 411
 412static void devm_regulator_destroy_notifier(struct device *dev, void *res)
 413{
 414        struct regulator_notifier_match *match = res;
 415
 416        regulator_unregister_notifier(match->regulator, match->nb);
 417}
 418
 419/**
 420 * devm_regulator_register_notifier - Resource managed
 421 * regulator_register_notifier
 422 *
 423 * @regulator: regulator source
 424 * @nb: notifier block
 425 *
 426 * The notifier will be registers under the consumer device and be
 427 * automatically be unregistered when the source device is unbound.
 428 */
 429int devm_regulator_register_notifier(struct regulator *regulator,
 430                                     struct notifier_block *nb)
 431{
 432        struct regulator_notifier_match *match;
 433        int ret;
 434
 435        match = devres_alloc(devm_regulator_destroy_notifier,
 436                             sizeof(struct regulator_notifier_match),
 437                             GFP_KERNEL);
 438        if (!match)
 439                return -ENOMEM;
 440
 441        match->regulator = regulator;
 442        match->nb = nb;
 443
 444        ret = regulator_register_notifier(regulator, nb);
 445        if (ret < 0) {
 446                devres_free(match);
 447                return ret;
 448        }
 449
 450        devres_add(regulator->dev, match);
 451
 452        return 0;
 453}
 454EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
 455
 456/**
 457 * devm_regulator_unregister_notifier - Resource managed
 458 * regulator_unregister_notifier()
 459 *
 460 * @regulator: regulator source
 461 * @nb: notifier block
 462 *
 463 * Unregister a notifier registered with devm_regulator_register_notifier().
 464 * Normally this function will not need to be called and the resource
 465 * management code will ensure that the resource is freed.
 466 */
 467void devm_regulator_unregister_notifier(struct regulator *regulator,
 468                                        struct notifier_block *nb)
 469{
 470        struct regulator_notifier_match match;
 471        int rc;
 472
 473        match.regulator = regulator;
 474        match.nb = nb;
 475
 476        rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
 477                            devm_regulator_match_notifier, &match);
 478        if (rc != 0)
 479                WARN_ON(rc);
 480}
 481EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
 482