xref: /openbmc/linux/drivers/regulator/devres.c (revision a7c15187)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20cdfcc0fSMark Brown /*
30cdfcc0fSMark Brown  * devres.c  --  Voltage/Current Regulator framework devres implementation.
40cdfcc0fSMark Brown  *
50cdfcc0fSMark Brown  * Copyright 2013 Linaro Ltd
60cdfcc0fSMark Brown  */
70cdfcc0fSMark Brown 
80cdfcc0fSMark Brown #include <linux/kernel.h>
90cdfcc0fSMark Brown #include <linux/err.h>
100cdfcc0fSMark Brown #include <linux/regmap.h>
110cdfcc0fSMark Brown #include <linux/regulator/consumer.h>
120cdfcc0fSMark Brown #include <linux/regulator/driver.h>
130cdfcc0fSMark Brown #include <linux/module.h>
140cdfcc0fSMark Brown 
150cdfcc0fSMark Brown #include "internal.h"
160cdfcc0fSMark Brown 
170cdfcc0fSMark Brown static void devm_regulator_release(struct device *dev, void *res)
180cdfcc0fSMark Brown {
190cdfcc0fSMark Brown 	regulator_put(*(struct regulator **)res);
200cdfcc0fSMark Brown }
210cdfcc0fSMark Brown 
220cdfcc0fSMark Brown static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
230cdfcc0fSMark Brown 					     int get_type)
240cdfcc0fSMark Brown {
250cdfcc0fSMark Brown 	struct regulator **ptr, *regulator;
260cdfcc0fSMark Brown 
270cdfcc0fSMark Brown 	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
280cdfcc0fSMark Brown 	if (!ptr)
290cdfcc0fSMark Brown 		return ERR_PTR(-ENOMEM);
300cdfcc0fSMark Brown 
31a8bd42a9SDmitry Torokhov 	regulator = _regulator_get(dev, id, get_type);
320cdfcc0fSMark Brown 	if (!IS_ERR(regulator)) {
330cdfcc0fSMark Brown 		*ptr = regulator;
340cdfcc0fSMark Brown 		devres_add(dev, ptr);
350cdfcc0fSMark Brown 	} else {
360cdfcc0fSMark Brown 		devres_free(ptr);
370cdfcc0fSMark Brown 	}
380cdfcc0fSMark Brown 
390cdfcc0fSMark Brown 	return regulator;
400cdfcc0fSMark Brown }
410cdfcc0fSMark Brown 
420cdfcc0fSMark Brown /**
430cdfcc0fSMark Brown  * devm_regulator_get - Resource managed regulator_get()
44a7c15187SLee Jones  * @dev: device to supply
45a7c15187SLee Jones  * @id:  supply name or regulator ID.
460cdfcc0fSMark Brown  *
470cdfcc0fSMark Brown  * Managed regulator_get(). Regulators returned from this function are
480cdfcc0fSMark Brown  * automatically regulator_put() on driver detach. See regulator_get() for more
490cdfcc0fSMark Brown  * information.
500cdfcc0fSMark Brown  */
510cdfcc0fSMark Brown struct regulator *devm_regulator_get(struct device *dev, const char *id)
520cdfcc0fSMark Brown {
530cdfcc0fSMark Brown 	return _devm_regulator_get(dev, id, NORMAL_GET);
540cdfcc0fSMark Brown }
550cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get);
560cdfcc0fSMark Brown 
570cdfcc0fSMark Brown /**
580cdfcc0fSMark Brown  * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
59a7c15187SLee Jones  * @dev: device to supply
60a7c15187SLee Jones  * @id:  supply name or regulator ID.
610cdfcc0fSMark Brown  *
620cdfcc0fSMark Brown  * Managed regulator_get_exclusive(). Regulators returned from this function
630cdfcc0fSMark Brown  * are automatically regulator_put() on driver detach. See regulator_get() for
640cdfcc0fSMark Brown  * more information.
650cdfcc0fSMark Brown  */
660cdfcc0fSMark Brown struct regulator *devm_regulator_get_exclusive(struct device *dev,
670cdfcc0fSMark Brown 					       const char *id)
680cdfcc0fSMark Brown {
690cdfcc0fSMark Brown 	return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
700cdfcc0fSMark Brown }
710cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
720cdfcc0fSMark Brown 
730cdfcc0fSMark Brown /**
740cdfcc0fSMark Brown  * devm_regulator_get_optional - Resource managed regulator_get_optional()
75a7c15187SLee Jones  * @dev: device to supply
76a7c15187SLee Jones  * @id:  supply name or regulator ID.
770cdfcc0fSMark Brown  *
780cdfcc0fSMark Brown  * Managed regulator_get_optional(). Regulators returned from this
790cdfcc0fSMark Brown  * function are automatically regulator_put() on driver detach. See
800cdfcc0fSMark Brown  * regulator_get_optional() for more information.
810cdfcc0fSMark Brown  */
820cdfcc0fSMark Brown struct regulator *devm_regulator_get_optional(struct device *dev,
830cdfcc0fSMark Brown 					      const char *id)
840cdfcc0fSMark Brown {
850cdfcc0fSMark Brown 	return _devm_regulator_get(dev, id, OPTIONAL_GET);
860cdfcc0fSMark Brown }
870cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
880cdfcc0fSMark Brown 
890cdfcc0fSMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data)
900cdfcc0fSMark Brown {
910cdfcc0fSMark Brown 	struct regulator **r = res;
920cdfcc0fSMark Brown 	if (!r || !*r) {
930cdfcc0fSMark Brown 		WARN_ON(!r || !*r);
940cdfcc0fSMark Brown 		return 0;
950cdfcc0fSMark Brown 	}
960cdfcc0fSMark Brown 	return *r == data;
970cdfcc0fSMark Brown }
980cdfcc0fSMark Brown 
990cdfcc0fSMark Brown /**
1000cdfcc0fSMark Brown  * devm_regulator_put - Resource managed regulator_put()
1010cdfcc0fSMark Brown  * @regulator: regulator to free
1020cdfcc0fSMark Brown  *
1030cdfcc0fSMark Brown  * Deallocate a regulator allocated with devm_regulator_get(). Normally
1040cdfcc0fSMark Brown  * this function will not need to be called and the resource management
1050cdfcc0fSMark Brown  * code will ensure that the resource is freed.
1060cdfcc0fSMark Brown  */
1070cdfcc0fSMark Brown void devm_regulator_put(struct regulator *regulator)
1080cdfcc0fSMark Brown {
1090cdfcc0fSMark Brown 	int rc;
1100cdfcc0fSMark Brown 
1110cdfcc0fSMark Brown 	rc = devres_release(regulator->dev, devm_regulator_release,
1120cdfcc0fSMark Brown 			    devm_regulator_match, regulator);
1130cdfcc0fSMark Brown 	if (rc != 0)
1140cdfcc0fSMark Brown 		WARN_ON(rc);
1150cdfcc0fSMark Brown }
1160cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put);
1170cdfcc0fSMark Brown 
1183eaeb475SDmitry Torokhov struct regulator_bulk_devres {
1193eaeb475SDmitry Torokhov 	struct regulator_bulk_data *consumers;
1203eaeb475SDmitry Torokhov 	int num_consumers;
1213eaeb475SDmitry Torokhov };
1223eaeb475SDmitry Torokhov 
1233eaeb475SDmitry Torokhov static void devm_regulator_bulk_release(struct device *dev, void *res)
1243eaeb475SDmitry Torokhov {
1253eaeb475SDmitry Torokhov 	struct regulator_bulk_devres *devres = res;
1263eaeb475SDmitry Torokhov 
1273eaeb475SDmitry Torokhov 	regulator_bulk_free(devres->num_consumers, devres->consumers);
1283eaeb475SDmitry Torokhov }
1293eaeb475SDmitry Torokhov 
1300cdfcc0fSMark Brown /**
1310cdfcc0fSMark Brown  * devm_regulator_bulk_get - managed get multiple regulator consumers
1320cdfcc0fSMark Brown  *
133a7c15187SLee Jones  * @dev:           device to supply
134a7c15187SLee Jones  * @num_consumers: number of consumers to register
135a7c15187SLee Jones  * @consumers:     configuration of consumers; clients are stored here.
1360cdfcc0fSMark Brown  *
1370cdfcc0fSMark Brown  * @return 0 on success, an errno on failure.
1380cdfcc0fSMark Brown  *
1390cdfcc0fSMark Brown  * This helper function allows drivers to get several regulator
1400cdfcc0fSMark Brown  * consumers in one operation with management, the regulators will
1410cdfcc0fSMark Brown  * automatically be freed when the device is unbound.  If any of the
1420cdfcc0fSMark Brown  * regulators cannot be acquired then any regulators that were
1430cdfcc0fSMark Brown  * allocated will be freed before returning to the caller.
1440cdfcc0fSMark Brown  */
1450cdfcc0fSMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers,
1460cdfcc0fSMark Brown 			    struct regulator_bulk_data *consumers)
1470cdfcc0fSMark Brown {
1483eaeb475SDmitry Torokhov 	struct regulator_bulk_devres *devres;
1490cdfcc0fSMark Brown 	int ret;
1500cdfcc0fSMark Brown 
1513eaeb475SDmitry Torokhov 	devres = devres_alloc(devm_regulator_bulk_release,
1523eaeb475SDmitry Torokhov 			      sizeof(*devres), GFP_KERNEL);
1533eaeb475SDmitry Torokhov 	if (!devres)
1543eaeb475SDmitry Torokhov 		return -ENOMEM;
1550cdfcc0fSMark Brown 
1563eaeb475SDmitry Torokhov 	ret = regulator_bulk_get(dev, num_consumers, consumers);
1573eaeb475SDmitry Torokhov 	if (!ret) {
1583eaeb475SDmitry Torokhov 		devres->consumers = consumers;
1593eaeb475SDmitry Torokhov 		devres->num_consumers = num_consumers;
1603eaeb475SDmitry Torokhov 		devres_add(dev, devres);
1613eaeb475SDmitry Torokhov 	} else {
1623eaeb475SDmitry Torokhov 		devres_free(devres);
1630cdfcc0fSMark Brown 	}
1640cdfcc0fSMark Brown 
1650cdfcc0fSMark Brown 	return ret;
1660cdfcc0fSMark Brown }
1670cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
1680cdfcc0fSMark Brown 
1690cdfcc0fSMark Brown static void devm_rdev_release(struct device *dev, void *res)
1700cdfcc0fSMark Brown {
1710cdfcc0fSMark Brown 	regulator_unregister(*(struct regulator_dev **)res);
1720cdfcc0fSMark Brown }
1730cdfcc0fSMark Brown 
1740cdfcc0fSMark Brown /**
1750cdfcc0fSMark Brown  * devm_regulator_register - Resource managed regulator_register()
1769565cccdSLee Jones  * @dev:            device to supply
1770cdfcc0fSMark Brown  * @regulator_desc: regulator to register
1780cdfcc0fSMark Brown  * @config:         runtime configuration for regulator
1790cdfcc0fSMark Brown  *
1800cdfcc0fSMark Brown  * Called by regulator drivers to register a regulator.  Returns a
1810cdfcc0fSMark Brown  * valid pointer to struct regulator_dev on success or an ERR_PTR() on
1820cdfcc0fSMark Brown  * error.  The regulator will automatically be released when the device
1830cdfcc0fSMark Brown  * is unbound.
1840cdfcc0fSMark Brown  */
1850cdfcc0fSMark Brown struct regulator_dev *devm_regulator_register(struct device *dev,
1860cdfcc0fSMark Brown 				  const struct regulator_desc *regulator_desc,
1870cdfcc0fSMark Brown 				  const struct regulator_config *config)
1880cdfcc0fSMark Brown {
1890cdfcc0fSMark Brown 	struct regulator_dev **ptr, *rdev;
1900cdfcc0fSMark Brown 
1910cdfcc0fSMark Brown 	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
1920cdfcc0fSMark Brown 			   GFP_KERNEL);
1930cdfcc0fSMark Brown 	if (!ptr)
1940cdfcc0fSMark Brown 		return ERR_PTR(-ENOMEM);
1950cdfcc0fSMark Brown 
1960cdfcc0fSMark Brown 	rdev = regulator_register(regulator_desc, config);
1970cdfcc0fSMark Brown 	if (!IS_ERR(rdev)) {
1980cdfcc0fSMark Brown 		*ptr = rdev;
1990cdfcc0fSMark Brown 		devres_add(dev, ptr);
2000cdfcc0fSMark Brown 	} else {
2010cdfcc0fSMark Brown 		devres_free(ptr);
2020cdfcc0fSMark Brown 	}
2030cdfcc0fSMark Brown 
2040cdfcc0fSMark Brown 	return rdev;
2050cdfcc0fSMark Brown }
2060cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_register);
2070cdfcc0fSMark Brown 
2080cdfcc0fSMark Brown static int devm_rdev_match(struct device *dev, void *res, void *data)
2090cdfcc0fSMark Brown {
2100cdfcc0fSMark Brown 	struct regulator_dev **r = res;
2110cdfcc0fSMark Brown 	if (!r || !*r) {
2120cdfcc0fSMark Brown 		WARN_ON(!r || !*r);
2130cdfcc0fSMark Brown 		return 0;
2140cdfcc0fSMark Brown 	}
2150cdfcc0fSMark Brown 	return *r == data;
2160cdfcc0fSMark Brown }
2170cdfcc0fSMark Brown 
2180cdfcc0fSMark Brown /**
2190cdfcc0fSMark Brown  * devm_regulator_unregister - Resource managed regulator_unregister()
2209565cccdSLee Jones  * @dev:  device to supply
2219565cccdSLee Jones  * @rdev: regulator to free
2220cdfcc0fSMark Brown  *
2230cdfcc0fSMark Brown  * Unregister a regulator registered with devm_regulator_register().
2240cdfcc0fSMark Brown  * Normally this function will not need to be called and the resource
2250cdfcc0fSMark Brown  * management code will ensure that the resource is freed.
2260cdfcc0fSMark Brown  */
2270cdfcc0fSMark Brown void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
2280cdfcc0fSMark Brown {
2290cdfcc0fSMark Brown 	int rc;
2300cdfcc0fSMark Brown 
2310cdfcc0fSMark Brown 	rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
2320cdfcc0fSMark Brown 	if (rc != 0)
2330cdfcc0fSMark Brown 		WARN_ON(rc);
2340cdfcc0fSMark Brown }
2350cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_unregister);
236a06ccd9cSCharles Keepax 
237a06ccd9cSCharles Keepax struct regulator_supply_alias_match {
238a06ccd9cSCharles Keepax 	struct device *dev;
239a06ccd9cSCharles Keepax 	const char *id;
240a06ccd9cSCharles Keepax };
241a06ccd9cSCharles Keepax 
242a06ccd9cSCharles Keepax static int devm_regulator_match_supply_alias(struct device *dev, void *res,
243a06ccd9cSCharles Keepax 					     void *data)
244a06ccd9cSCharles Keepax {
245a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
246a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *target = data;
247a06ccd9cSCharles Keepax 
248a06ccd9cSCharles Keepax 	return match->dev == target->dev && strcmp(match->id, target->id) == 0;
249a06ccd9cSCharles Keepax }
250a06ccd9cSCharles Keepax 
251a06ccd9cSCharles Keepax static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
252a06ccd9cSCharles Keepax {
253a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
254a06ccd9cSCharles Keepax 
255a06ccd9cSCharles Keepax 	regulator_unregister_supply_alias(match->dev, match->id);
256a06ccd9cSCharles Keepax }
257a06ccd9cSCharles Keepax 
258a06ccd9cSCharles Keepax /**
259a06ccd9cSCharles Keepax  * devm_regulator_register_supply_alias - Resource managed
260a06ccd9cSCharles Keepax  * regulator_register_supply_alias()
261a06ccd9cSCharles Keepax  *
262a7c15187SLee Jones  * @dev:       device to supply
263a7c15187SLee Jones  * @id:        supply name or regulator ID
264a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
265a7c15187SLee Jones  * @alias_id:  supply name or regulator ID that should be used to lookup the
266a06ccd9cSCharles Keepax  * supply
267a06ccd9cSCharles Keepax  *
268a06ccd9cSCharles Keepax  * The supply alias will automatically be unregistered when the source
269a06ccd9cSCharles Keepax  * device is unbound.
270a06ccd9cSCharles Keepax  */
271a06ccd9cSCharles Keepax int devm_regulator_register_supply_alias(struct device *dev, const char *id,
272a06ccd9cSCharles Keepax 					 struct device *alias_dev,
273a06ccd9cSCharles Keepax 					 const char *alias_id)
274a06ccd9cSCharles Keepax {
275a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match;
276a06ccd9cSCharles Keepax 	int ret;
277a06ccd9cSCharles Keepax 
278a06ccd9cSCharles Keepax 	match = devres_alloc(devm_regulator_destroy_supply_alias,
279a06ccd9cSCharles Keepax 			   sizeof(struct regulator_supply_alias_match),
280a06ccd9cSCharles Keepax 			   GFP_KERNEL);
281a06ccd9cSCharles Keepax 	if (!match)
282a06ccd9cSCharles Keepax 		return -ENOMEM;
283a06ccd9cSCharles Keepax 
284a06ccd9cSCharles Keepax 	match->dev = dev;
285a06ccd9cSCharles Keepax 	match->id = id;
286a06ccd9cSCharles Keepax 
287a06ccd9cSCharles Keepax 	ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
288a06ccd9cSCharles Keepax 	if (ret < 0) {
289a06ccd9cSCharles Keepax 		devres_free(match);
290a06ccd9cSCharles Keepax 		return ret;
291a06ccd9cSCharles Keepax 	}
292a06ccd9cSCharles Keepax 
293a06ccd9cSCharles Keepax 	devres_add(dev, match);
294a06ccd9cSCharles Keepax 
295a06ccd9cSCharles Keepax 	return 0;
296a06ccd9cSCharles Keepax }
297a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
298a06ccd9cSCharles Keepax 
299a06ccd9cSCharles Keepax /**
300a06ccd9cSCharles Keepax  * devm_regulator_unregister_supply_alias - Resource managed
301a06ccd9cSCharles Keepax  * regulator_unregister_supply_alias()
302a06ccd9cSCharles Keepax  *
303a7c15187SLee Jones  * @dev: device to supply
304a7c15187SLee Jones  * @id:  supply name or regulator ID
305a06ccd9cSCharles Keepax  *
306a06ccd9cSCharles Keepax  * Unregister an alias registered with
307a06ccd9cSCharles Keepax  * devm_regulator_register_supply_alias(). Normally this function
308a06ccd9cSCharles Keepax  * will not need to be called and the resource management code
309a06ccd9cSCharles Keepax  * will ensure that the resource is freed.
310a06ccd9cSCharles Keepax  */
311a06ccd9cSCharles Keepax void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
312a06ccd9cSCharles Keepax {
313a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match match;
314a06ccd9cSCharles Keepax 	int rc;
315a06ccd9cSCharles Keepax 
316a06ccd9cSCharles Keepax 	match.dev = dev;
317a06ccd9cSCharles Keepax 	match.id = id;
318a06ccd9cSCharles Keepax 
319a06ccd9cSCharles Keepax 	rc = devres_release(dev, devm_regulator_destroy_supply_alias,
320a06ccd9cSCharles Keepax 			    devm_regulator_match_supply_alias, &match);
321a06ccd9cSCharles Keepax 	if (rc != 0)
322a06ccd9cSCharles Keepax 		WARN_ON(rc);
323a06ccd9cSCharles Keepax }
324a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
325a06ccd9cSCharles Keepax 
326a06ccd9cSCharles Keepax /**
327a06ccd9cSCharles Keepax  * devm_regulator_bulk_register_supply_alias - Managed register
328a06ccd9cSCharles Keepax  * multiple aliases
329a06ccd9cSCharles Keepax  *
330a7c15187SLee Jones  * @dev:       device to supply
331a7c15187SLee Jones  * @id:        list of supply names or regulator IDs
332a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
333a7c15187SLee Jones  * @alias_id:  list of supply names or regulator IDs that should be used to
334a06ccd9cSCharles Keepax  *             lookup the supply
335a7c15187SLee Jones  * @num_id:    number of aliases to register
336a06ccd9cSCharles Keepax  *
337a06ccd9cSCharles Keepax  * @return 0 on success, an errno on failure.
338a06ccd9cSCharles Keepax  *
339a06ccd9cSCharles Keepax  * This helper function allows drivers to register several supply
340a06ccd9cSCharles Keepax  * aliases in one operation, the aliases will be automatically
341a06ccd9cSCharles Keepax  * unregisters when the source device is unbound.  If any of the
342a06ccd9cSCharles Keepax  * aliases cannot be registered any aliases that were registered
343a06ccd9cSCharles Keepax  * will be removed before returning to the caller.
344a06ccd9cSCharles Keepax  */
345a06ccd9cSCharles Keepax int devm_regulator_bulk_register_supply_alias(struct device *dev,
3469f8c0fe9SLee Jones 					      const char *const *id,
347a06ccd9cSCharles Keepax 					      struct device *alias_dev,
3489f8c0fe9SLee Jones 					      const char *const *alias_id,
349a06ccd9cSCharles Keepax 					      int num_id)
350a06ccd9cSCharles Keepax {
351a06ccd9cSCharles Keepax 	int i;
352a06ccd9cSCharles Keepax 	int ret;
353a06ccd9cSCharles Keepax 
354a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i) {
355a06ccd9cSCharles Keepax 		ret = devm_regulator_register_supply_alias(dev, id[i],
356a06ccd9cSCharles Keepax 							   alias_dev,
357a06ccd9cSCharles Keepax 							   alias_id[i]);
358a06ccd9cSCharles Keepax 		if (ret < 0)
359a06ccd9cSCharles Keepax 			goto err;
360a06ccd9cSCharles Keepax 	}
361a06ccd9cSCharles Keepax 
362a06ccd9cSCharles Keepax 	return 0;
363a06ccd9cSCharles Keepax 
364a06ccd9cSCharles Keepax err:
365a06ccd9cSCharles Keepax 	dev_err(dev,
366a06ccd9cSCharles Keepax 		"Failed to create supply alias %s,%s -> %s,%s\n",
367a06ccd9cSCharles Keepax 		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
368a06ccd9cSCharles Keepax 
369a06ccd9cSCharles Keepax 	while (--i >= 0)
370a06ccd9cSCharles Keepax 		devm_regulator_unregister_supply_alias(dev, id[i]);
371a06ccd9cSCharles Keepax 
372a06ccd9cSCharles Keepax 	return ret;
373a06ccd9cSCharles Keepax }
374a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
375a06ccd9cSCharles Keepax 
376a06ccd9cSCharles Keepax /**
377a06ccd9cSCharles Keepax  * devm_regulator_bulk_unregister_supply_alias - Managed unregister
378a06ccd9cSCharles Keepax  * multiple aliases
379a06ccd9cSCharles Keepax  *
380a7c15187SLee Jones  * @dev:    device to supply
381a7c15187SLee Jones  * @id:     list of supply names or regulator IDs
382a7c15187SLee Jones  * @num_id: number of aliases to unregister
383a06ccd9cSCharles Keepax  *
384a06ccd9cSCharles Keepax  * Unregister aliases registered with
385a06ccd9cSCharles Keepax  * devm_regulator_bulk_register_supply_alias(). Normally this function
386a06ccd9cSCharles Keepax  * will not need to be called and the resource management code
387a06ccd9cSCharles Keepax  * will ensure that the resource is freed.
388a06ccd9cSCharles Keepax  */
389a06ccd9cSCharles Keepax void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
3909f8c0fe9SLee Jones 						 const char *const *id,
391a06ccd9cSCharles Keepax 						 int num_id)
392a06ccd9cSCharles Keepax {
393a06ccd9cSCharles Keepax 	int i;
394a06ccd9cSCharles Keepax 
395a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i)
396a06ccd9cSCharles Keepax 		devm_regulator_unregister_supply_alias(dev, id[i]);
397a06ccd9cSCharles Keepax }
398a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
399046db763SCharles Keepax 
400046db763SCharles Keepax struct regulator_notifier_match {
401046db763SCharles Keepax 	struct regulator *regulator;
402046db763SCharles Keepax 	struct notifier_block *nb;
403046db763SCharles Keepax };
404046db763SCharles Keepax 
405046db763SCharles Keepax static int devm_regulator_match_notifier(struct device *dev, void *res,
406046db763SCharles Keepax 					 void *data)
407046db763SCharles Keepax {
408046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
409046db763SCharles Keepax 	struct regulator_notifier_match *target = data;
410046db763SCharles Keepax 
411046db763SCharles Keepax 	return match->regulator == target->regulator && match->nb == target->nb;
412046db763SCharles Keepax }
413046db763SCharles Keepax 
414046db763SCharles Keepax static void devm_regulator_destroy_notifier(struct device *dev, void *res)
415046db763SCharles Keepax {
416046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
417046db763SCharles Keepax 
418046db763SCharles Keepax 	regulator_unregister_notifier(match->regulator, match->nb);
419046db763SCharles Keepax }
420046db763SCharles Keepax 
421046db763SCharles Keepax /**
422046db763SCharles Keepax  * devm_regulator_register_notifier - Resource managed
423046db763SCharles Keepax  * regulator_register_notifier
424046db763SCharles Keepax  *
425046db763SCharles Keepax  * @regulator: regulator source
426046db763SCharles Keepax  * @nb:        notifier block
427046db763SCharles Keepax  *
428046db763SCharles Keepax  * The notifier will be registers under the consumer device and be
429046db763SCharles Keepax  * automatically be unregistered when the source device is unbound.
430046db763SCharles Keepax  */
431046db763SCharles Keepax int devm_regulator_register_notifier(struct regulator *regulator,
432046db763SCharles Keepax 				     struct notifier_block *nb)
433046db763SCharles Keepax {
434046db763SCharles Keepax 	struct regulator_notifier_match *match;
435046db763SCharles Keepax 	int ret;
436046db763SCharles Keepax 
437046db763SCharles Keepax 	match = devres_alloc(devm_regulator_destroy_notifier,
438046db763SCharles Keepax 			     sizeof(struct regulator_notifier_match),
439046db763SCharles Keepax 			     GFP_KERNEL);
440046db763SCharles Keepax 	if (!match)
441046db763SCharles Keepax 		return -ENOMEM;
442046db763SCharles Keepax 
443046db763SCharles Keepax 	match->regulator = regulator;
444046db763SCharles Keepax 	match->nb = nb;
445046db763SCharles Keepax 
446046db763SCharles Keepax 	ret = regulator_register_notifier(regulator, nb);
447046db763SCharles Keepax 	if (ret < 0) {
448046db763SCharles Keepax 		devres_free(match);
449046db763SCharles Keepax 		return ret;
450046db763SCharles Keepax 	}
451046db763SCharles Keepax 
452046db763SCharles Keepax 	devres_add(regulator->dev, match);
453046db763SCharles Keepax 
454046db763SCharles Keepax 	return 0;
455046db763SCharles Keepax }
456046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
457046db763SCharles Keepax 
458046db763SCharles Keepax /**
459046db763SCharles Keepax  * devm_regulator_unregister_notifier - Resource managed
460046db763SCharles Keepax  * regulator_unregister_notifier()
461046db763SCharles Keepax  *
462046db763SCharles Keepax  * @regulator: regulator source
463046db763SCharles Keepax  * @nb:        notifier block
464046db763SCharles Keepax  *
465046db763SCharles Keepax  * Unregister a notifier registered with devm_regulator_register_notifier().
466046db763SCharles Keepax  * Normally this function will not need to be called and the resource
467046db763SCharles Keepax  * management code will ensure that the resource is freed.
468046db763SCharles Keepax  */
469046db763SCharles Keepax void devm_regulator_unregister_notifier(struct regulator *regulator,
470046db763SCharles Keepax 					struct notifier_block *nb)
471046db763SCharles Keepax {
472046db763SCharles Keepax 	struct regulator_notifier_match match;
473046db763SCharles Keepax 	int rc;
474046db763SCharles Keepax 
475046db763SCharles Keepax 	match.regulator = regulator;
476046db763SCharles Keepax 	match.nb = nb;
477046db763SCharles Keepax 
478046db763SCharles Keepax 	rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
479046db763SCharles Keepax 			    devm_regulator_match_notifier, &match);
480046db763SCharles Keepax 	if (rc != 0)
481046db763SCharles Keepax 		WARN_ON(rc);
482046db763SCharles Keepax }
483046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
484