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