752 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * devres.c -- Voltage/Current Regulator framework devres implementation.4 *5 * Copyright 2013 Linaro Ltd6 */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 to supply45 * @id: supply name or regulator ID.46 *47 * Managed regulator_get(). Regulators returned from this function are48 * automatically regulator_put() on driver detach. See regulator_get() for more49 * 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 to supply60 * @id: supply name or regulator ID.61 *62 * Managed regulator_get_exclusive(). Regulators returned from this function63 * are automatically regulator_put() on driver detach. See regulator_get() for64 * 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 73static void regulator_action_disable(void *d)74{75 struct regulator *r = (struct regulator *)d;76 77 regulator_disable(r);78}79 80static int _devm_regulator_get_enable(struct device *dev, const char *id,81 int get_type)82{83 struct regulator *r;84 int ret;85 86 r = _devm_regulator_get(dev, id, get_type);87 if (IS_ERR(r))88 return PTR_ERR(r);89 90 ret = regulator_enable(r);91 if (!ret)92 ret = devm_add_action_or_reset(dev, ®ulator_action_disable, r);93 94 if (ret)95 devm_regulator_put(r);96 97 return ret;98}99 100/**101 * devm_regulator_get_enable_optional - Resource managed regulator get and enable102 * @dev: device to supply103 * @id: supply name or regulator ID.104 *105 * Get and enable regulator for duration of the device life-time.106 * regulator_disable() and regulator_put() are automatically called on driver107 * detach. See regulator_get_optional() and regulator_enable() for more108 * information.109 */110int devm_regulator_get_enable_optional(struct device *dev, const char *id)111{112 return _devm_regulator_get_enable(dev, id, OPTIONAL_GET);113}114EXPORT_SYMBOL_GPL(devm_regulator_get_enable_optional);115 116/**117 * devm_regulator_get_enable - Resource managed regulator get and enable118 * @dev: device to supply119 * @id: supply name or regulator ID.120 *121 * Get and enable regulator for duration of the device life-time.122 * regulator_disable() and regulator_put() are automatically called on driver123 * detach. See regulator_get() and regulator_enable() for more124 * information.125 */126int devm_regulator_get_enable(struct device *dev, const char *id)127{128 return _devm_regulator_get_enable(dev, id, NORMAL_GET);129}130EXPORT_SYMBOL_GPL(devm_regulator_get_enable);131 132/**133 * devm_regulator_get_optional - Resource managed regulator_get_optional()134 * @dev: device to supply135 * @id: supply name or regulator ID.136 *137 * Managed regulator_get_optional(). Regulators returned from this138 * function are automatically regulator_put() on driver detach. See139 * regulator_get_optional() for more information.140 */141struct regulator *devm_regulator_get_optional(struct device *dev,142 const char *id)143{144 return _devm_regulator_get(dev, id, OPTIONAL_GET);145}146EXPORT_SYMBOL_GPL(devm_regulator_get_optional);147 148/**149 * devm_regulator_get_enable_read_voltage - Resource managed regulator get and150 * enable that returns the voltage151 * @dev: device to supply152 * @id: supply name or regulator ID.153 *154 * Get and enable regulator for duration of the device life-time.155 * regulator_disable() and regulator_put() are automatically called on driver156 * detach. See regulator_get_optional(), regulator_enable(), and157 * regulator_get_voltage() for more information.158 *159 * This is a convenience function for supplies that provide a reference voltage160 * where the consumer driver just needs to know the voltage and keep the161 * regulator enabled.162 *163 * In cases where the supply is not strictly required, callers can check for164 * -ENODEV error and handle it accordingly.165 *166 * Returns: voltage in microvolts on success, or an negative error number on failure.167 */168int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id)169{170 struct regulator *r;171 int ret;172 173 /*174 * Since we need a real voltage, we use devm_regulator_get_optional()175 * rather than getting a dummy regulator with devm_regulator_get() and176 * then letting regulator_get_voltage() fail with -EINVAL. This way, the177 * caller can handle the -ENODEV negative error number if needed instead178 * of the ambiguous -EINVAL.179 */180 r = devm_regulator_get_optional(dev, id);181 if (IS_ERR(r))182 return PTR_ERR(r);183 184 ret = regulator_enable(r);185 if (ret)186 goto err_regulator_put;187 188 ret = devm_add_action_or_reset(dev, regulator_action_disable, r);189 if (ret)190 goto err_regulator_put;191 192 ret = regulator_get_voltage(r);193 if (ret < 0)194 goto err_release_action;195 196 return ret;197 198err_release_action:199 devm_release_action(dev, regulator_action_disable, r);200err_regulator_put:201 devm_regulator_put(r);202 203 return ret;204}205EXPORT_SYMBOL_GPL(devm_regulator_get_enable_read_voltage);206 207static int devm_regulator_match(struct device *dev, void *res, void *data)208{209 struct regulator **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_put - Resource managed regulator_put()219 * @regulator: regulator to free220 *221 * Deallocate a regulator allocated with devm_regulator_get(). Normally222 * this function will not need to be called and the resource management223 * code will ensure that the resource is freed.224 */225void devm_regulator_put(struct regulator *regulator)226{227 int rc;228 229 rc = devres_release(regulator->dev, devm_regulator_release,230 devm_regulator_match, regulator);231 if (rc != 0)232 WARN_ON(rc);233}234EXPORT_SYMBOL_GPL(devm_regulator_put);235 236struct regulator_bulk_devres {237 struct regulator_bulk_data *consumers;238 int num_consumers;239};240 241static void devm_regulator_bulk_release(struct device *dev, void *res)242{243 struct regulator_bulk_devres *devres = res;244 245 regulator_bulk_free(devres->num_consumers, devres->consumers);246}247 248static int _devm_regulator_bulk_get(struct device *dev, int num_consumers,249 struct regulator_bulk_data *consumers,250 enum regulator_get_type get_type)251{252 struct regulator_bulk_devres *devres;253 int ret;254 255 devres = devres_alloc(devm_regulator_bulk_release,256 sizeof(*devres), GFP_KERNEL);257 if (!devres)258 return -ENOMEM;259 260 ret = _regulator_bulk_get(dev, num_consumers, consumers, get_type);261 if (!ret) {262 devres->consumers = consumers;263 devres->num_consumers = num_consumers;264 devres_add(dev, devres);265 } else {266 devres_free(devres);267 }268 269 return ret;270}271 272/**273 * devm_regulator_bulk_get - managed get multiple regulator consumers274 *275 * @dev: device to supply276 * @num_consumers: number of consumers to register277 * @consumers: configuration of consumers; clients are stored here.278 *279 * @return 0 on success, a negative error number on failure.280 *281 * This helper function allows drivers to get several regulator282 * consumers in one operation with management, the regulators will283 * automatically be freed when the device is unbound. If any of the284 * regulators cannot be acquired then any regulators that were285 * allocated will be freed before returning to the caller.286 */287int devm_regulator_bulk_get(struct device *dev, int num_consumers,288 struct regulator_bulk_data *consumers)289{290 return _devm_regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET);291}292EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);293 294/**295 * devm_regulator_bulk_get_exclusive - managed exclusive get of multiple296 * regulator consumers297 *298 * @dev: device to supply299 * @num_consumers: number of consumers to register300 * @consumers: configuration of consumers; clients are stored here.301 *302 * @return 0 on success, a negative error number on failure.303 *304 * This helper function allows drivers to exclusively get several305 * regulator consumers in one operation with management, the regulators306 * will automatically be freed when the device is unbound. If any of307 * the regulators cannot be acquired then any regulators that were308 * allocated will be freed before returning to the caller.309 */310int devm_regulator_bulk_get_exclusive(struct device *dev, int num_consumers,311 struct regulator_bulk_data *consumers)312{313 return _devm_regulator_bulk_get(dev, num_consumers, consumers, EXCLUSIVE_GET);314}315EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_exclusive);316 317/**318 * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data319 *320 * @dev: device to supply321 * @num_consumers: number of consumers to register322 * @in_consumers: const configuration of consumers323 * @out_consumers: in_consumers is copied here and this is passed to324 * devm_regulator_bulk_get().325 *326 * This is a convenience function to allow bulk regulator configuration327 * to be stored "static const" in files.328 *329 * Return: 0 on success, a negative error number on failure.330 */331int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,332 const struct regulator_bulk_data *in_consumers,333 struct regulator_bulk_data **out_consumers)334{335 *out_consumers = devm_kmemdup(dev, in_consumers,336 num_consumers * sizeof(*in_consumers),337 GFP_KERNEL);338 if (*out_consumers == NULL)339 return -ENOMEM;340 341 return devm_regulator_bulk_get(dev, num_consumers, *out_consumers);342}343EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);344 345static int devm_regulator_bulk_match(struct device *dev, void *res,346 void *data)347{348 struct regulator_bulk_devres *match = res;349 struct regulator_bulk_data *target = data;350 351 /*352 * We check the put uses same consumer list as the get did.353 * We _could_ scan all entries in consumer array and check the354 * regulators match but ATM I don't see the need. We can change this355 * later if needed.356 */357 return match->consumers == target;358}359 360/**361 * devm_regulator_bulk_put - Resource managed regulator_bulk_put()362 * @consumers: consumers to free363 *364 * Deallocate regulators allocated with devm_regulator_bulk_get(). Normally365 * this function will not need to be called and the resource management366 * code will ensure that the resource is freed.367 */368void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)369{370 int rc;371 struct regulator *regulator = consumers[0].consumer;372 373 rc = devres_release(regulator->dev, devm_regulator_bulk_release,374 devm_regulator_bulk_match, consumers);375 if (rc != 0)376 WARN_ON(rc);377}378EXPORT_SYMBOL_GPL(devm_regulator_bulk_put);379 380static void devm_regulator_bulk_disable(void *res)381{382 struct regulator_bulk_devres *devres = res;383 int i;384 385 for (i = 0; i < devres->num_consumers; i++)386 regulator_disable(devres->consumers[i].consumer);387}388 389/**390 * devm_regulator_bulk_get_enable - managed get'n enable multiple regulators391 *392 * @dev: device to supply393 * @num_consumers: number of consumers to register394 * @id: list of supply names or regulator IDs395 *396 * @return 0 on success, a negative error number on failure.397 *398 * This helper function allows drivers to get several regulator399 * consumers in one operation with management, the regulators will400 * automatically be freed when the device is unbound. If any of the401 * regulators cannot be acquired then any regulators that were402 * allocated will be freed before returning to the caller.403 */404int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,405 const char * const *id)406{407 struct regulator_bulk_devres *devres;408 struct regulator_bulk_data *consumers;409 int i, ret;410 411 devres = devm_kmalloc(dev, sizeof(*devres), GFP_KERNEL);412 if (!devres)413 return -ENOMEM;414 415 devres->consumers = devm_kcalloc(dev, num_consumers, sizeof(*consumers),416 GFP_KERNEL);417 consumers = devres->consumers;418 if (!consumers)419 return -ENOMEM;420 421 devres->num_consumers = num_consumers;422 423 for (i = 0; i < num_consumers; i++)424 consumers[i].supply = id[i];425 426 ret = devm_regulator_bulk_get(dev, num_consumers, consumers);427 if (ret)428 return ret;429 430 for (i = 0; i < num_consumers; i++) {431 ret = regulator_enable(consumers[i].consumer);432 if (ret)433 goto unwind;434 }435 436 ret = devm_add_action(dev, devm_regulator_bulk_disable, devres);437 if (!ret)438 return 0;439 440unwind:441 while (--i >= 0)442 regulator_disable(consumers[i].consumer);443 444 devm_regulator_bulk_put(consumers);445 446 return ret;447}448EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_enable);449 450static void devm_rdev_release(struct device *dev, void *res)451{452 regulator_unregister(*(struct regulator_dev **)res);453}454 455/**456 * devm_regulator_register - Resource managed regulator_register()457 * @dev: device to supply458 * @regulator_desc: regulator to register459 * @config: runtime configuration for regulator460 *461 * Called by regulator drivers to register a regulator. Returns a462 * valid pointer to struct regulator_dev on success or an ERR_PTR() on463 * error. The regulator will automatically be released when the device464 * is unbound.465 */466struct regulator_dev *devm_regulator_register(struct device *dev,467 const struct regulator_desc *regulator_desc,468 const struct regulator_config *config)469{470 struct regulator_dev **ptr, *rdev;471 472 ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),473 GFP_KERNEL);474 if (!ptr)475 return ERR_PTR(-ENOMEM);476 477 rdev = regulator_register(dev, regulator_desc, config);478 if (!IS_ERR(rdev)) {479 *ptr = rdev;480 devres_add(dev, ptr);481 } else {482 devres_free(ptr);483 }484 485 return rdev;486}487EXPORT_SYMBOL_GPL(devm_regulator_register);488 489struct regulator_supply_alias_match {490 struct device *dev;491 const char *id;492};493 494static int devm_regulator_match_supply_alias(struct device *dev, void *res,495 void *data)496{497 struct regulator_supply_alias_match *match = res;498 struct regulator_supply_alias_match *target = data;499 500 return match->dev == target->dev && strcmp(match->id, target->id) == 0;501}502 503static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)504{505 struct regulator_supply_alias_match *match = res;506 507 regulator_unregister_supply_alias(match->dev, match->id);508}509 510/**511 * devm_regulator_register_supply_alias - Resource managed512 * regulator_register_supply_alias()513 *514 * @dev: device to supply515 * @id: supply name or regulator ID516 * @alias_dev: device that should be used to lookup the supply517 * @alias_id: supply name or regulator ID that should be used to lookup the518 * supply519 *520 * The supply alias will automatically be unregistered when the source521 * device is unbound.522 */523int devm_regulator_register_supply_alias(struct device *dev, const char *id,524 struct device *alias_dev,525 const char *alias_id)526{527 struct regulator_supply_alias_match *match;528 int ret;529 530 match = devres_alloc(devm_regulator_destroy_supply_alias,531 sizeof(struct regulator_supply_alias_match),532 GFP_KERNEL);533 if (!match)534 return -ENOMEM;535 536 match->dev = dev;537 match->id = id;538 539 ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);540 if (ret < 0) {541 devres_free(match);542 return ret;543 }544 545 devres_add(dev, match);546 547 return 0;548}549EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);550 551static void devm_regulator_unregister_supply_alias(struct device *dev,552 const char *id)553{554 struct regulator_supply_alias_match match;555 int rc;556 557 match.dev = dev;558 match.id = id;559 560 rc = devres_release(dev, devm_regulator_destroy_supply_alias,561 devm_regulator_match_supply_alias, &match);562 if (rc != 0)563 WARN_ON(rc);564}565 566/**567 * devm_regulator_bulk_register_supply_alias - Managed register568 * multiple aliases569 *570 * @dev: device to supply571 * @id: list of supply names or regulator IDs572 * @alias_dev: device that should be used to lookup the supply573 * @alias_id: list of supply names or regulator IDs that should be used to574 * lookup the supply575 * @num_id: number of aliases to register576 *577 * @return 0 on success, a negative error number on failure.578 *579 * This helper function allows drivers to register several supply580 * aliases in one operation, the aliases will be automatically581 * unregisters when the source device is unbound. If any of the582 * aliases cannot be registered any aliases that were registered583 * will be removed before returning to the caller.584 */585int devm_regulator_bulk_register_supply_alias(struct device *dev,586 const char *const *id,587 struct device *alias_dev,588 const char *const *alias_id,589 int num_id)590{591 int i;592 int ret;593 594 for (i = 0; i < num_id; ++i) {595 ret = devm_regulator_register_supply_alias(dev, id[i],596 alias_dev,597 alias_id[i]);598 if (ret < 0)599 goto err;600 }601 602 return 0;603 604err:605 dev_err(dev,606 "Failed to create supply alias %s,%s -> %s,%s\n",607 id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));608 609 while (--i >= 0)610 devm_regulator_unregister_supply_alias(dev, id[i]);611 612 return ret;613}614EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);615 616struct regulator_notifier_match {617 struct regulator *regulator;618 struct notifier_block *nb;619};620 621static int devm_regulator_match_notifier(struct device *dev, void *res,622 void *data)623{624 struct regulator_notifier_match *match = res;625 struct regulator_notifier_match *target = data;626 627 return match->regulator == target->regulator && match->nb == target->nb;628}629 630static void devm_regulator_destroy_notifier(struct device *dev, void *res)631{632 struct regulator_notifier_match *match = res;633 634 regulator_unregister_notifier(match->regulator, match->nb);635}636 637/**638 * devm_regulator_register_notifier - Resource managed639 * regulator_register_notifier640 *641 * @regulator: regulator source642 * @nb: notifier block643 *644 * The notifier will be registers under the consumer device and be645 * automatically be unregistered when the source device is unbound.646 */647int devm_regulator_register_notifier(struct regulator *regulator,648 struct notifier_block *nb)649{650 struct regulator_notifier_match *match;651 int ret;652 653 match = devres_alloc(devm_regulator_destroy_notifier,654 sizeof(struct regulator_notifier_match),655 GFP_KERNEL);656 if (!match)657 return -ENOMEM;658 659 match->regulator = regulator;660 match->nb = nb;661 662 ret = regulator_register_notifier(regulator, nb);663 if (ret < 0) {664 devres_free(match);665 return ret;666 }667 668 devres_add(regulator->dev, match);669 670 return 0;671}672EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);673 674/**675 * devm_regulator_unregister_notifier - Resource managed676 * regulator_unregister_notifier()677 *678 * @regulator: regulator source679 * @nb: notifier block680 *681 * Unregister a notifier registered with devm_regulator_register_notifier().682 * Normally this function will not need to be called and the resource683 * management code will ensure that the resource is freed.684 */685void devm_regulator_unregister_notifier(struct regulator *regulator,686 struct notifier_block *nb)687{688 struct regulator_notifier_match match;689 int rc;690 691 match.regulator = regulator;692 match.nb = nb;693 694 rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,695 devm_regulator_match_notifier, &match);696 if (rc != 0)697 WARN_ON(rc);698}699EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);700 701static void regulator_irq_helper_drop(void *res)702{703 regulator_irq_helper_cancel(&res);704}705 706/**707 * devm_regulator_irq_helper - resource managed registration of IRQ based708 * regulator event/error notifier709 *710 * @dev: device to which lifetime the helper's lifetime is711 * bound.712 * @d: IRQ helper descriptor.713 * @irq: IRQ used to inform events/errors to be notified.714 * @irq_flags: Extra IRQ flags to be OR'ed with the default715 * IRQF_ONESHOT when requesting the (threaded) irq.716 * @common_errs: Errors which can be flagged by this IRQ for all rdevs.717 * When IRQ is re-enabled these errors will be cleared718 * from all associated regulators719 * @per_rdev_errs: Optional error flag array describing errors specific720 * for only some of the regulators. These errors will be721 * or'ed with common errors. If this is given the array722 * should contain rdev_amount flags. Can be set to NULL723 * if there is no regulator specific error flags for this724 * IRQ.725 * @rdev: Array of pointers to regulators associated with this726 * IRQ.727 * @rdev_amount: Amount of regulators associated with this IRQ.728 *729 * Return: handle to irq_helper or an ERR_PTR() encoded negative error number.730 */731void *devm_regulator_irq_helper(struct device *dev,732 const struct regulator_irq_desc *d, int irq,733 int irq_flags, int common_errs,734 int *per_rdev_errs,735 struct regulator_dev **rdev, int rdev_amount)736{737 void *ptr;738 int ret;739 740 ptr = regulator_irq_helper(dev, d, irq, irq_flags, common_errs,741 per_rdev_errs, rdev, rdev_amount);742 if (IS_ERR(ptr))743 return ptr;744 745 ret = devm_add_action_or_reset(dev, regulator_irq_helper_drop, ptr);746 if (ret)747 return ERR_PTR(ret);748 749 return ptr;750}751EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);752