brintos

brintos / linux-shallow public Read only

0
0
Text · 21.1 KiB · 1b893cd Raw
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, &regulator_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