xref: /openbmc/linux/drivers/regulator/devres.c (revision 046db763)
10cdfcc0fSMark Brown /*
20cdfcc0fSMark Brown  * devres.c  --  Voltage/Current Regulator framework devres implementation.
30cdfcc0fSMark Brown  *
40cdfcc0fSMark Brown  * Copyright 2013 Linaro Ltd
50cdfcc0fSMark Brown  *
60cdfcc0fSMark Brown  *  This program is free software; you can redistribute  it and/or modify it
70cdfcc0fSMark Brown  *  under  the terms of  the GNU General  Public License as published by the
80cdfcc0fSMark Brown  *  Free Software Foundation;  either version 2 of the  License, or (at your
90cdfcc0fSMark Brown  *  option) any later version.
100cdfcc0fSMark Brown  *
110cdfcc0fSMark Brown  */
120cdfcc0fSMark Brown 
130cdfcc0fSMark Brown #include <linux/kernel.h>
140cdfcc0fSMark Brown #include <linux/err.h>
150cdfcc0fSMark Brown #include <linux/regmap.h>
160cdfcc0fSMark Brown #include <linux/regulator/consumer.h>
170cdfcc0fSMark Brown #include <linux/regulator/driver.h>
180cdfcc0fSMark Brown #include <linux/module.h>
190cdfcc0fSMark Brown 
200cdfcc0fSMark Brown #include "internal.h"
210cdfcc0fSMark Brown 
220cdfcc0fSMark Brown enum {
230cdfcc0fSMark Brown 	NORMAL_GET,
240cdfcc0fSMark Brown 	EXCLUSIVE_GET,
250cdfcc0fSMark Brown 	OPTIONAL_GET,
260cdfcc0fSMark Brown };
270cdfcc0fSMark Brown 
280cdfcc0fSMark Brown static void devm_regulator_release(struct device *dev, void *res)
290cdfcc0fSMark Brown {
300cdfcc0fSMark Brown 	regulator_put(*(struct regulator **)res);
310cdfcc0fSMark Brown }
320cdfcc0fSMark Brown 
330cdfcc0fSMark Brown static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
340cdfcc0fSMark Brown 					     int get_type)
350cdfcc0fSMark Brown {
360cdfcc0fSMark Brown 	struct regulator **ptr, *regulator;
370cdfcc0fSMark Brown 
380cdfcc0fSMark Brown 	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
390cdfcc0fSMark Brown 	if (!ptr)
400cdfcc0fSMark Brown 		return ERR_PTR(-ENOMEM);
410cdfcc0fSMark Brown 
420cdfcc0fSMark Brown 	switch (get_type) {
430cdfcc0fSMark Brown 	case NORMAL_GET:
440cdfcc0fSMark Brown 		regulator = regulator_get(dev, id);
450cdfcc0fSMark Brown 		break;
460cdfcc0fSMark Brown 	case EXCLUSIVE_GET:
470cdfcc0fSMark Brown 		regulator = regulator_get_exclusive(dev, id);
480cdfcc0fSMark Brown 		break;
490cdfcc0fSMark Brown 	case OPTIONAL_GET:
500cdfcc0fSMark Brown 		regulator = regulator_get_optional(dev, id);
510cdfcc0fSMark Brown 		break;
520cdfcc0fSMark Brown 	default:
530cdfcc0fSMark Brown 		regulator = ERR_PTR(-EINVAL);
540cdfcc0fSMark Brown 	}
550cdfcc0fSMark Brown 
560cdfcc0fSMark Brown 	if (!IS_ERR(regulator)) {
570cdfcc0fSMark Brown 		*ptr = regulator;
580cdfcc0fSMark Brown 		devres_add(dev, ptr);
590cdfcc0fSMark Brown 	} else {
600cdfcc0fSMark Brown 		devres_free(ptr);
610cdfcc0fSMark Brown 	}
620cdfcc0fSMark Brown 
630cdfcc0fSMark Brown 	return regulator;
640cdfcc0fSMark Brown }
650cdfcc0fSMark Brown 
660cdfcc0fSMark Brown /**
670cdfcc0fSMark Brown  * devm_regulator_get - Resource managed regulator_get()
680cdfcc0fSMark Brown  * @dev: device for regulator "consumer"
690cdfcc0fSMark Brown  * @id: Supply name or regulator ID.
700cdfcc0fSMark Brown  *
710cdfcc0fSMark Brown  * Managed regulator_get(). Regulators returned from this function are
720cdfcc0fSMark Brown  * automatically regulator_put() on driver detach. See regulator_get() for more
730cdfcc0fSMark Brown  * information.
740cdfcc0fSMark Brown  */
750cdfcc0fSMark Brown struct regulator *devm_regulator_get(struct device *dev, const char *id)
760cdfcc0fSMark Brown {
770cdfcc0fSMark Brown 	return _devm_regulator_get(dev, id, NORMAL_GET);
780cdfcc0fSMark Brown }
790cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get);
800cdfcc0fSMark Brown 
810cdfcc0fSMark Brown /**
820cdfcc0fSMark Brown  * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
830cdfcc0fSMark Brown  * @dev: device for regulator "consumer"
840cdfcc0fSMark Brown  * @id: Supply name or regulator ID.
850cdfcc0fSMark Brown  *
860cdfcc0fSMark Brown  * Managed regulator_get_exclusive(). Regulators returned from this function
870cdfcc0fSMark Brown  * are automatically regulator_put() on driver detach. See regulator_get() for
880cdfcc0fSMark Brown  * more information.
890cdfcc0fSMark Brown  */
900cdfcc0fSMark Brown struct regulator *devm_regulator_get_exclusive(struct device *dev,
910cdfcc0fSMark Brown 					       const char *id)
920cdfcc0fSMark Brown {
930cdfcc0fSMark Brown 	return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
940cdfcc0fSMark Brown }
950cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
960cdfcc0fSMark Brown 
970cdfcc0fSMark Brown /**
980cdfcc0fSMark Brown  * devm_regulator_get_optional - Resource managed regulator_get_optional()
990cdfcc0fSMark Brown  * @dev: device for regulator "consumer"
1000cdfcc0fSMark Brown  * @id: Supply name or regulator ID.
1010cdfcc0fSMark Brown  *
1020cdfcc0fSMark Brown  * Managed regulator_get_optional(). Regulators returned from this
1030cdfcc0fSMark Brown  * function are automatically regulator_put() on driver detach. See
1040cdfcc0fSMark Brown  * regulator_get_optional() for more information.
1050cdfcc0fSMark Brown  */
1060cdfcc0fSMark Brown struct regulator *devm_regulator_get_optional(struct device *dev,
1070cdfcc0fSMark Brown 					      const char *id)
1080cdfcc0fSMark Brown {
1090cdfcc0fSMark Brown 	return _devm_regulator_get(dev, id, OPTIONAL_GET);
1100cdfcc0fSMark Brown }
1110cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
1120cdfcc0fSMark Brown 
1130cdfcc0fSMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data)
1140cdfcc0fSMark Brown {
1150cdfcc0fSMark Brown 	struct regulator **r = res;
1160cdfcc0fSMark Brown 	if (!r || !*r) {
1170cdfcc0fSMark Brown 		WARN_ON(!r || !*r);
1180cdfcc0fSMark Brown 		return 0;
1190cdfcc0fSMark Brown 	}
1200cdfcc0fSMark Brown 	return *r == data;
1210cdfcc0fSMark Brown }
1220cdfcc0fSMark Brown 
1230cdfcc0fSMark Brown /**
1240cdfcc0fSMark Brown  * devm_regulator_put - Resource managed regulator_put()
1250cdfcc0fSMark Brown  * @regulator: regulator to free
1260cdfcc0fSMark Brown  *
1270cdfcc0fSMark Brown  * Deallocate a regulator allocated with devm_regulator_get(). Normally
1280cdfcc0fSMark Brown  * this function will not need to be called and the resource management
1290cdfcc0fSMark Brown  * code will ensure that the resource is freed.
1300cdfcc0fSMark Brown  */
1310cdfcc0fSMark Brown void devm_regulator_put(struct regulator *regulator)
1320cdfcc0fSMark Brown {
1330cdfcc0fSMark Brown 	int rc;
1340cdfcc0fSMark Brown 
1350cdfcc0fSMark Brown 	rc = devres_release(regulator->dev, devm_regulator_release,
1360cdfcc0fSMark Brown 			    devm_regulator_match, regulator);
1370cdfcc0fSMark Brown 	if (rc != 0)
1380cdfcc0fSMark Brown 		WARN_ON(rc);
1390cdfcc0fSMark Brown }
1400cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put);
1410cdfcc0fSMark Brown 
1420cdfcc0fSMark Brown /**
1430cdfcc0fSMark Brown  * devm_regulator_bulk_get - managed get multiple regulator consumers
1440cdfcc0fSMark Brown  *
1450cdfcc0fSMark Brown  * @dev:           Device to supply
1460cdfcc0fSMark Brown  * @num_consumers: Number of consumers to register
1470cdfcc0fSMark Brown  * @consumers:     Configuration of consumers; clients are stored here.
1480cdfcc0fSMark Brown  *
1490cdfcc0fSMark Brown  * @return 0 on success, an errno on failure.
1500cdfcc0fSMark Brown  *
1510cdfcc0fSMark Brown  * This helper function allows drivers to get several regulator
1520cdfcc0fSMark Brown  * consumers in one operation with management, the regulators will
1530cdfcc0fSMark Brown  * automatically be freed when the device is unbound.  If any of the
1540cdfcc0fSMark Brown  * regulators cannot be acquired then any regulators that were
1550cdfcc0fSMark Brown  * allocated will be freed before returning to the caller.
1560cdfcc0fSMark Brown  */
1570cdfcc0fSMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers,
1580cdfcc0fSMark Brown 			    struct regulator_bulk_data *consumers)
1590cdfcc0fSMark Brown {
1600cdfcc0fSMark Brown 	int i;
1610cdfcc0fSMark Brown 	int ret;
1620cdfcc0fSMark Brown 
1630cdfcc0fSMark Brown 	for (i = 0; i < num_consumers; i++)
1640cdfcc0fSMark Brown 		consumers[i].consumer = NULL;
1650cdfcc0fSMark Brown 
1660cdfcc0fSMark Brown 	for (i = 0; i < num_consumers; i++) {
1670cdfcc0fSMark Brown 		consumers[i].consumer = devm_regulator_get(dev,
1680cdfcc0fSMark Brown 							   consumers[i].supply);
1690cdfcc0fSMark Brown 		if (IS_ERR(consumers[i].consumer)) {
1700cdfcc0fSMark Brown 			ret = PTR_ERR(consumers[i].consumer);
1710cdfcc0fSMark Brown 			dev_err(dev, "Failed to get supply '%s': %d\n",
1720cdfcc0fSMark Brown 				consumers[i].supply, ret);
1730cdfcc0fSMark Brown 			consumers[i].consumer = NULL;
1740cdfcc0fSMark Brown 			goto err;
1750cdfcc0fSMark Brown 		}
1760cdfcc0fSMark Brown 	}
1770cdfcc0fSMark Brown 
1780cdfcc0fSMark Brown 	return 0;
1790cdfcc0fSMark Brown 
1800cdfcc0fSMark Brown err:
1810cdfcc0fSMark Brown 	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
1820cdfcc0fSMark Brown 		devm_regulator_put(consumers[i].consumer);
1830cdfcc0fSMark Brown 
1840cdfcc0fSMark Brown 	return ret;
1850cdfcc0fSMark Brown }
1860cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
1870cdfcc0fSMark Brown 
1880cdfcc0fSMark Brown static void devm_rdev_release(struct device *dev, void *res)
1890cdfcc0fSMark Brown {
1900cdfcc0fSMark Brown 	regulator_unregister(*(struct regulator_dev **)res);
1910cdfcc0fSMark Brown }
1920cdfcc0fSMark Brown 
1930cdfcc0fSMark Brown /**
1940cdfcc0fSMark Brown  * devm_regulator_register - Resource managed regulator_register()
1950cdfcc0fSMark Brown  * @regulator_desc: regulator to register
1960cdfcc0fSMark Brown  * @config: runtime configuration for regulator
1970cdfcc0fSMark Brown  *
1980cdfcc0fSMark Brown  * Called by regulator drivers to register a regulator.  Returns a
1990cdfcc0fSMark Brown  * valid pointer to struct regulator_dev on success or an ERR_PTR() on
2000cdfcc0fSMark Brown  * error.  The regulator will automatically be released when the device
2010cdfcc0fSMark Brown  * is unbound.
2020cdfcc0fSMark Brown  */
2030cdfcc0fSMark Brown struct regulator_dev *devm_regulator_register(struct device *dev,
2040cdfcc0fSMark Brown 				  const struct regulator_desc *regulator_desc,
2050cdfcc0fSMark Brown 				  const struct regulator_config *config)
2060cdfcc0fSMark Brown {
2070cdfcc0fSMark Brown 	struct regulator_dev **ptr, *rdev;
2080cdfcc0fSMark Brown 
2090cdfcc0fSMark Brown 	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
2100cdfcc0fSMark Brown 			   GFP_KERNEL);
2110cdfcc0fSMark Brown 	if (!ptr)
2120cdfcc0fSMark Brown 		return ERR_PTR(-ENOMEM);
2130cdfcc0fSMark Brown 
2140cdfcc0fSMark Brown 	rdev = regulator_register(regulator_desc, config);
2150cdfcc0fSMark Brown 	if (!IS_ERR(rdev)) {
2160cdfcc0fSMark Brown 		*ptr = rdev;
2170cdfcc0fSMark Brown 		devres_add(dev, ptr);
2180cdfcc0fSMark Brown 	} else {
2190cdfcc0fSMark Brown 		devres_free(ptr);
2200cdfcc0fSMark Brown 	}
2210cdfcc0fSMark Brown 
2220cdfcc0fSMark Brown 	return rdev;
2230cdfcc0fSMark Brown }
2240cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_register);
2250cdfcc0fSMark Brown 
2260cdfcc0fSMark Brown static int devm_rdev_match(struct device *dev, void *res, void *data)
2270cdfcc0fSMark Brown {
2280cdfcc0fSMark Brown 	struct regulator_dev **r = res;
2290cdfcc0fSMark Brown 	if (!r || !*r) {
2300cdfcc0fSMark Brown 		WARN_ON(!r || !*r);
2310cdfcc0fSMark Brown 		return 0;
2320cdfcc0fSMark Brown 	}
2330cdfcc0fSMark Brown 	return *r == data;
2340cdfcc0fSMark Brown }
2350cdfcc0fSMark Brown 
2360cdfcc0fSMark Brown /**
2370cdfcc0fSMark Brown  * devm_regulator_unregister - Resource managed regulator_unregister()
2380cdfcc0fSMark Brown  * @regulator: regulator to free
2390cdfcc0fSMark Brown  *
2400cdfcc0fSMark Brown  * Unregister a regulator registered with devm_regulator_register().
2410cdfcc0fSMark Brown  * Normally this function will not need to be called and the resource
2420cdfcc0fSMark Brown  * management code will ensure that the resource is freed.
2430cdfcc0fSMark Brown  */
2440cdfcc0fSMark Brown void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
2450cdfcc0fSMark Brown {
2460cdfcc0fSMark Brown 	int rc;
2470cdfcc0fSMark Brown 
2480cdfcc0fSMark Brown 	rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
2490cdfcc0fSMark Brown 	if (rc != 0)
2500cdfcc0fSMark Brown 		WARN_ON(rc);
2510cdfcc0fSMark Brown }
2520cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_unregister);
253a06ccd9cSCharles Keepax 
254a06ccd9cSCharles Keepax struct regulator_supply_alias_match {
255a06ccd9cSCharles Keepax 	struct device *dev;
256a06ccd9cSCharles Keepax 	const char *id;
257a06ccd9cSCharles Keepax };
258a06ccd9cSCharles Keepax 
259a06ccd9cSCharles Keepax static int devm_regulator_match_supply_alias(struct device *dev, void *res,
260a06ccd9cSCharles Keepax 					     void *data)
261a06ccd9cSCharles Keepax {
262a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
263a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *target = data;
264a06ccd9cSCharles Keepax 
265a06ccd9cSCharles Keepax 	return match->dev == target->dev && strcmp(match->id, target->id) == 0;
266a06ccd9cSCharles Keepax }
267a06ccd9cSCharles Keepax 
268a06ccd9cSCharles Keepax static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
269a06ccd9cSCharles Keepax {
270a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
271a06ccd9cSCharles Keepax 
272a06ccd9cSCharles Keepax 	regulator_unregister_supply_alias(match->dev, match->id);
273a06ccd9cSCharles Keepax }
274a06ccd9cSCharles Keepax 
275a06ccd9cSCharles Keepax /**
276a06ccd9cSCharles Keepax  * devm_regulator_register_supply_alias - Resource managed
277a06ccd9cSCharles Keepax  * regulator_register_supply_alias()
278a06ccd9cSCharles Keepax  *
279a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
280a06ccd9cSCharles Keepax  * @id: Supply name or regulator ID
281a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
282a06ccd9cSCharles Keepax  * @alias_id: Supply name or regulator ID that should be used to lookup the
283a06ccd9cSCharles Keepax  * supply
284a06ccd9cSCharles Keepax  *
285a06ccd9cSCharles Keepax  * The supply alias will automatically be unregistered when the source
286a06ccd9cSCharles Keepax  * device is unbound.
287a06ccd9cSCharles Keepax  */
288a06ccd9cSCharles Keepax int devm_regulator_register_supply_alias(struct device *dev, const char *id,
289a06ccd9cSCharles Keepax 					 struct device *alias_dev,
290a06ccd9cSCharles Keepax 					 const char *alias_id)
291a06ccd9cSCharles Keepax {
292a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match;
293a06ccd9cSCharles Keepax 	int ret;
294a06ccd9cSCharles Keepax 
295a06ccd9cSCharles Keepax 	match = devres_alloc(devm_regulator_destroy_supply_alias,
296a06ccd9cSCharles Keepax 			   sizeof(struct regulator_supply_alias_match),
297a06ccd9cSCharles Keepax 			   GFP_KERNEL);
298a06ccd9cSCharles Keepax 	if (!match)
299a06ccd9cSCharles Keepax 		return -ENOMEM;
300a06ccd9cSCharles Keepax 
301a06ccd9cSCharles Keepax 	match->dev = dev;
302a06ccd9cSCharles Keepax 	match->id = id;
303a06ccd9cSCharles Keepax 
304a06ccd9cSCharles Keepax 	ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
305a06ccd9cSCharles Keepax 	if (ret < 0) {
306a06ccd9cSCharles Keepax 		devres_free(match);
307a06ccd9cSCharles Keepax 		return ret;
308a06ccd9cSCharles Keepax 	}
309a06ccd9cSCharles Keepax 
310a06ccd9cSCharles Keepax 	devres_add(dev, match);
311a06ccd9cSCharles Keepax 
312a06ccd9cSCharles Keepax 	return 0;
313a06ccd9cSCharles Keepax }
314a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
315a06ccd9cSCharles Keepax 
316a06ccd9cSCharles Keepax /**
317a06ccd9cSCharles Keepax  * devm_regulator_unregister_supply_alias - Resource managed
318a06ccd9cSCharles Keepax  * regulator_unregister_supply_alias()
319a06ccd9cSCharles Keepax  *
320a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
321a06ccd9cSCharles Keepax  * @id: Supply name or regulator ID
322a06ccd9cSCharles Keepax  *
323a06ccd9cSCharles Keepax  * Unregister an alias registered with
324a06ccd9cSCharles Keepax  * devm_regulator_register_supply_alias(). Normally this function
325a06ccd9cSCharles Keepax  * will not need to be called and the resource management code
326a06ccd9cSCharles Keepax  * will ensure that the resource is freed.
327a06ccd9cSCharles Keepax  */
328a06ccd9cSCharles Keepax void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
329a06ccd9cSCharles Keepax {
330a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match match;
331a06ccd9cSCharles Keepax 	int rc;
332a06ccd9cSCharles Keepax 
333a06ccd9cSCharles Keepax 	match.dev = dev;
334a06ccd9cSCharles Keepax 	match.id = id;
335a06ccd9cSCharles Keepax 
336a06ccd9cSCharles Keepax 	rc = devres_release(dev, devm_regulator_destroy_supply_alias,
337a06ccd9cSCharles Keepax 			    devm_regulator_match_supply_alias, &match);
338a06ccd9cSCharles Keepax 	if (rc != 0)
339a06ccd9cSCharles Keepax 		WARN_ON(rc);
340a06ccd9cSCharles Keepax }
341a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
342a06ccd9cSCharles Keepax 
343a06ccd9cSCharles Keepax /**
344a06ccd9cSCharles Keepax  * devm_regulator_bulk_register_supply_alias - Managed register
345a06ccd9cSCharles Keepax  * multiple aliases
346a06ccd9cSCharles Keepax  *
347a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
348a06ccd9cSCharles Keepax  * @id: List of supply names or regulator IDs
349a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
350a06ccd9cSCharles Keepax  * @alias_id: List of supply names or regulator IDs that should be used to
351a06ccd9cSCharles Keepax  * lookup the supply
352a06ccd9cSCharles Keepax  * @num_id: Number of aliases to register
353a06ccd9cSCharles Keepax  *
354a06ccd9cSCharles Keepax  * @return 0 on success, an errno on failure.
355a06ccd9cSCharles Keepax  *
356a06ccd9cSCharles Keepax  * This helper function allows drivers to register several supply
357a06ccd9cSCharles Keepax  * aliases in one operation, the aliases will be automatically
358a06ccd9cSCharles Keepax  * unregisters when the source device is unbound.  If any of the
359a06ccd9cSCharles Keepax  * aliases cannot be registered any aliases that were registered
360a06ccd9cSCharles Keepax  * will be removed before returning to the caller.
361a06ccd9cSCharles Keepax  */
362a06ccd9cSCharles Keepax int devm_regulator_bulk_register_supply_alias(struct device *dev,
3639f8c0fe9SLee Jones 					      const char *const *id,
364a06ccd9cSCharles Keepax 					      struct device *alias_dev,
3659f8c0fe9SLee Jones 					      const char *const *alias_id,
366a06ccd9cSCharles Keepax 					      int num_id)
367a06ccd9cSCharles Keepax {
368a06ccd9cSCharles Keepax 	int i;
369a06ccd9cSCharles Keepax 	int ret;
370a06ccd9cSCharles Keepax 
371a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i) {
372a06ccd9cSCharles Keepax 		ret = devm_regulator_register_supply_alias(dev, id[i],
373a06ccd9cSCharles Keepax 							   alias_dev,
374a06ccd9cSCharles Keepax 							   alias_id[i]);
375a06ccd9cSCharles Keepax 		if (ret < 0)
376a06ccd9cSCharles Keepax 			goto err;
377a06ccd9cSCharles Keepax 	}
378a06ccd9cSCharles Keepax 
379a06ccd9cSCharles Keepax 	return 0;
380a06ccd9cSCharles Keepax 
381a06ccd9cSCharles Keepax err:
382a06ccd9cSCharles Keepax 	dev_err(dev,
383a06ccd9cSCharles Keepax 		"Failed to create supply alias %s,%s -> %s,%s\n",
384a06ccd9cSCharles Keepax 		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
385a06ccd9cSCharles Keepax 
386a06ccd9cSCharles Keepax 	while (--i >= 0)
387a06ccd9cSCharles Keepax 		devm_regulator_unregister_supply_alias(dev, id[i]);
388a06ccd9cSCharles Keepax 
389a06ccd9cSCharles Keepax 	return ret;
390a06ccd9cSCharles Keepax }
391a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
392a06ccd9cSCharles Keepax 
393a06ccd9cSCharles Keepax /**
394a06ccd9cSCharles Keepax  * devm_regulator_bulk_unregister_supply_alias - Managed unregister
395a06ccd9cSCharles Keepax  * multiple aliases
396a06ccd9cSCharles Keepax  *
397a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
398a06ccd9cSCharles Keepax  * @id: List of supply names or regulator IDs
399a06ccd9cSCharles Keepax  * @num_id: Number of aliases to unregister
400a06ccd9cSCharles Keepax  *
401a06ccd9cSCharles Keepax  * Unregister aliases registered with
402a06ccd9cSCharles Keepax  * devm_regulator_bulk_register_supply_alias(). Normally this function
403a06ccd9cSCharles Keepax  * will not need to be called and the resource management code
404a06ccd9cSCharles Keepax  * will ensure that the resource is freed.
405a06ccd9cSCharles Keepax  */
406a06ccd9cSCharles Keepax void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
4079f8c0fe9SLee Jones 						 const char *const *id,
408a06ccd9cSCharles Keepax 						 int num_id)
409a06ccd9cSCharles Keepax {
410a06ccd9cSCharles Keepax 	int i;
411a06ccd9cSCharles Keepax 
412a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i)
413a06ccd9cSCharles Keepax 		devm_regulator_unregister_supply_alias(dev, id[i]);
414a06ccd9cSCharles Keepax }
415a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
416046db763SCharles Keepax 
417046db763SCharles Keepax struct regulator_notifier_match {
418046db763SCharles Keepax 	struct regulator *regulator;
419046db763SCharles Keepax 	struct notifier_block *nb;
420046db763SCharles Keepax };
421046db763SCharles Keepax 
422046db763SCharles Keepax static int devm_regulator_match_notifier(struct device *dev, void *res,
423046db763SCharles Keepax 					 void *data)
424046db763SCharles Keepax {
425046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
426046db763SCharles Keepax 	struct regulator_notifier_match *target = data;
427046db763SCharles Keepax 
428046db763SCharles Keepax 	return match->regulator == target->regulator && match->nb == target->nb;
429046db763SCharles Keepax }
430046db763SCharles Keepax 
431046db763SCharles Keepax static void devm_regulator_destroy_notifier(struct device *dev, void *res)
432046db763SCharles Keepax {
433046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
434046db763SCharles Keepax 
435046db763SCharles Keepax 	regulator_unregister_notifier(match->regulator, match->nb);
436046db763SCharles Keepax }
437046db763SCharles Keepax 
438046db763SCharles Keepax /**
439046db763SCharles Keepax  * devm_regulator_register_notifier - Resource managed
440046db763SCharles Keepax  * regulator_register_notifier
441046db763SCharles Keepax  *
442046db763SCharles Keepax  * @regulator: regulator source
443046db763SCharles Keepax  * @nb: notifier block
444046db763SCharles Keepax  *
445046db763SCharles Keepax  * The notifier will be registers under the consumer device and be
446046db763SCharles Keepax  * automatically be unregistered when the source device is unbound.
447046db763SCharles Keepax  */
448046db763SCharles Keepax int devm_regulator_register_notifier(struct regulator *regulator,
449046db763SCharles Keepax 				     struct notifier_block *nb)
450046db763SCharles Keepax {
451046db763SCharles Keepax 	struct regulator_notifier_match *match;
452046db763SCharles Keepax 	int ret;
453046db763SCharles Keepax 
454046db763SCharles Keepax 	match = devres_alloc(devm_regulator_destroy_notifier,
455046db763SCharles Keepax 			     sizeof(struct regulator_notifier_match),
456046db763SCharles Keepax 			     GFP_KERNEL);
457046db763SCharles Keepax 	if (!match)
458046db763SCharles Keepax 		return -ENOMEM;
459046db763SCharles Keepax 
460046db763SCharles Keepax 	match->regulator = regulator;
461046db763SCharles Keepax 	match->nb = nb;
462046db763SCharles Keepax 
463046db763SCharles Keepax 	ret = regulator_register_notifier(regulator, nb);
464046db763SCharles Keepax 	if (ret < 0) {
465046db763SCharles Keepax 		devres_free(match);
466046db763SCharles Keepax 		return ret;
467046db763SCharles Keepax 	}
468046db763SCharles Keepax 
469046db763SCharles Keepax 	devres_add(regulator->dev, match);
470046db763SCharles Keepax 
471046db763SCharles Keepax 	return 0;
472046db763SCharles Keepax }
473046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
474046db763SCharles Keepax 
475046db763SCharles Keepax /**
476046db763SCharles Keepax  * devm_regulator_unregister_notifier - Resource managed
477046db763SCharles Keepax  * regulator_unregister_notifier()
478046db763SCharles Keepax  *
479046db763SCharles Keepax  * @regulator: regulator source
480046db763SCharles Keepax  * @nb: notifier block
481046db763SCharles Keepax  *
482046db763SCharles Keepax  * Unregister a notifier registered with devm_regulator_register_notifier().
483046db763SCharles Keepax  * Normally this function will not need to be called and the resource
484046db763SCharles Keepax  * management code will ensure that the resource is freed.
485046db763SCharles Keepax  */
486046db763SCharles Keepax void devm_regulator_unregister_notifier(struct regulator *regulator,
487046db763SCharles Keepax 					struct notifier_block *nb)
488046db763SCharles Keepax {
489046db763SCharles Keepax 	struct regulator_notifier_match match;
490046db763SCharles Keepax 	int rc;
491046db763SCharles Keepax 
492046db763SCharles Keepax 	match.regulator = regulator;
493046db763SCharles Keepax 	match.nb = nb;
494046db763SCharles Keepax 
495046db763SCharles Keepax 	rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
496046db763SCharles Keepax 			    devm_regulator_match_notifier, &match);
497046db763SCharles Keepax 	if (rc != 0)
498046db763SCharles Keepax 		WARN_ON(rc);
499046db763SCharles Keepax }
500046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
501