root/drivers/regulator/devres.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. devm_regulator_release
  2. _devm_regulator_get
  3. devm_regulator_get
  4. devm_regulator_get_exclusive
  5. devm_regulator_get_optional
  6. devm_regulator_match
  7. devm_regulator_put
  8. devm_regulator_bulk_release
  9. devm_regulator_bulk_get
  10. devm_rdev_release
  11. devm_regulator_register
  12. devm_rdev_match
  13. devm_regulator_unregister
  14. devm_regulator_match_supply_alias
  15. devm_regulator_destroy_supply_alias
  16. devm_regulator_register_supply_alias
  17. devm_regulator_unregister_supply_alias
  18. devm_regulator_bulk_register_supply_alias
  19. devm_regulator_bulk_unregister_supply_alias
  20. devm_regulator_match_notifier
  21. devm_regulator_destroy_notifier
  22. devm_regulator_register_notifier
  23. devm_regulator_unregister_notifier

   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 
  17 static void devm_regulator_release(struct device *dev, void *res)
  18 {
  19         regulator_put(*(struct regulator **)res);
  20 }
  21 
  22 static 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  */
  51 struct regulator *devm_regulator_get(struct device *dev, const char *id)
  52 {
  53         return _devm_regulator_get(dev, id, NORMAL_GET);
  54 }
  55 EXPORT_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  */
  66 struct regulator *devm_regulator_get_exclusive(struct device *dev,
  67                                                const char *id)
  68 {
  69         return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
  70 }
  71 EXPORT_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  */
  82 struct regulator *devm_regulator_get_optional(struct device *dev,
  83                                               const char *id)
  84 {
  85         return _devm_regulator_get(dev, id, OPTIONAL_GET);
  86 }
  87 EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
  88 
  89 static 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  */
 107 void 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 }
 116 EXPORT_SYMBOL_GPL(devm_regulator_put);
 117 
 118 struct regulator_bulk_devres {
 119         struct regulator_bulk_data *consumers;
 120         int num_consumers;
 121 };
 122 
 123 static 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  */
 145 int 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 }
 167 EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
 168 
 169 static 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  */
 184 struct 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 }
 205 EXPORT_SYMBOL_GPL(devm_regulator_register);
 206 
 207 static 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  */
 225 void 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 }
 233 EXPORT_SYMBOL_GPL(devm_regulator_unregister);
 234 
 235 struct regulator_supply_alias_match {
 236         struct device *dev;
 237         const char *id;
 238 };
 239 
 240 static 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 
 249 static 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  */
 269 int 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 }
 295 EXPORT_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  */
 309 void 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 }
 322 EXPORT_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  */
 343 int 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 
 362 err:
 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 }
 372 EXPORT_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  */
 387 void 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 }
 396 EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
 397 
 398 struct regulator_notifier_match {
 399         struct regulator *regulator;
 400         struct notifier_block *nb;
 401 };
 402 
 403 static 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 
 412 static 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  */
 429 int 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 }
 454 EXPORT_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  */
 467 void 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 }
 481 EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);

/* [<][>][^][v][top][bottom][index][help] */