xref: /openbmc/linux/drivers/regulator/devres.c (revision 8f3cbcd6)
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 
devm_regulator_release(struct device * dev,void * res)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 
_devm_regulator_get(struct device * dev,const char * id,int get_type)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  */
devm_regulator_get(struct device * dev,const char * id)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  */
devm_regulator_get_exclusive(struct device * dev,const char * id)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 
regulator_action_disable(void * d)73da279e69SMatti Vaittinen static void regulator_action_disable(void *d)
74da279e69SMatti Vaittinen {
75da279e69SMatti Vaittinen 	struct regulator *r = (struct regulator *)d;
76da279e69SMatti Vaittinen 
77da279e69SMatti Vaittinen 	regulator_disable(r);
78da279e69SMatti Vaittinen }
79da279e69SMatti Vaittinen 
_devm_regulator_get_enable(struct device * dev,const char * id,int get_type)80da279e69SMatti Vaittinen static int _devm_regulator_get_enable(struct device *dev, const char *id,
81da279e69SMatti Vaittinen 				      int get_type)
82da279e69SMatti Vaittinen {
83da279e69SMatti Vaittinen 	struct regulator *r;
84da279e69SMatti Vaittinen 	int ret;
85da279e69SMatti Vaittinen 
86da279e69SMatti Vaittinen 	r = _devm_regulator_get(dev, id, get_type);
87da279e69SMatti Vaittinen 	if (IS_ERR(r))
88da279e69SMatti Vaittinen 		return PTR_ERR(r);
89da279e69SMatti Vaittinen 
90da279e69SMatti Vaittinen 	ret = regulator_enable(r);
91da279e69SMatti Vaittinen 	if (!ret)
92da279e69SMatti Vaittinen 		ret = devm_add_action_or_reset(dev, &regulator_action_disable, r);
93da279e69SMatti Vaittinen 
94da279e69SMatti Vaittinen 	if (ret)
95da279e69SMatti Vaittinen 		devm_regulator_put(r);
96da279e69SMatti Vaittinen 
97da279e69SMatti Vaittinen 	return ret;
98da279e69SMatti Vaittinen }
99da279e69SMatti Vaittinen 
100da279e69SMatti Vaittinen /**
101da279e69SMatti Vaittinen  * devm_regulator_get_enable_optional - Resource managed regulator get and enable
102da279e69SMatti Vaittinen  * @dev: device to supply
103da279e69SMatti Vaittinen  * @id:  supply name or regulator ID.
104da279e69SMatti Vaittinen  *
105da279e69SMatti Vaittinen  * Get and enable regulator for duration of the device life-time.
106da279e69SMatti Vaittinen  * regulator_disable() and regulator_put() are automatically called on driver
107da279e69SMatti Vaittinen  * detach. See regulator_get_optional() and regulator_enable() for more
108da279e69SMatti Vaittinen  * information.
109da279e69SMatti Vaittinen  */
devm_regulator_get_enable_optional(struct device * dev,const char * id)110da279e69SMatti Vaittinen int devm_regulator_get_enable_optional(struct device *dev, const char *id)
111da279e69SMatti Vaittinen {
112da279e69SMatti Vaittinen 	return _devm_regulator_get_enable(dev, id, OPTIONAL_GET);
113da279e69SMatti Vaittinen }
114da279e69SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_get_enable_optional);
115da279e69SMatti Vaittinen 
116da279e69SMatti Vaittinen /**
117da279e69SMatti Vaittinen  * devm_regulator_get_enable - Resource managed regulator get and enable
118da279e69SMatti Vaittinen  * @dev: device to supply
119da279e69SMatti Vaittinen  * @id:  supply name or regulator ID.
120da279e69SMatti Vaittinen  *
121da279e69SMatti Vaittinen  * Get and enable regulator for duration of the device life-time.
122da279e69SMatti Vaittinen  * regulator_disable() and regulator_put() are automatically called on driver
123da279e69SMatti Vaittinen  * detach. See regulator_get() and regulator_enable() for more
124da279e69SMatti Vaittinen  * information.
125da279e69SMatti Vaittinen  */
devm_regulator_get_enable(struct device * dev,const char * id)126da279e69SMatti Vaittinen int devm_regulator_get_enable(struct device *dev, const char *id)
127da279e69SMatti Vaittinen {
128da279e69SMatti Vaittinen 	return _devm_regulator_get_enable(dev, id, NORMAL_GET);
129da279e69SMatti Vaittinen }
130da279e69SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_get_enable);
131da279e69SMatti Vaittinen 
1320cdfcc0fSMark Brown /**
1330cdfcc0fSMark Brown  * devm_regulator_get_optional - Resource managed regulator_get_optional()
134a7c15187SLee Jones  * @dev: device to supply
135a7c15187SLee Jones  * @id:  supply name or regulator ID.
1360cdfcc0fSMark Brown  *
1370cdfcc0fSMark Brown  * Managed regulator_get_optional(). Regulators returned from this
1380cdfcc0fSMark Brown  * function are automatically regulator_put() on driver detach. See
1390cdfcc0fSMark Brown  * regulator_get_optional() for more information.
1400cdfcc0fSMark Brown  */
devm_regulator_get_optional(struct device * dev,const char * id)1410cdfcc0fSMark Brown struct regulator *devm_regulator_get_optional(struct device *dev,
1420cdfcc0fSMark Brown 					      const char *id)
1430cdfcc0fSMark Brown {
1440cdfcc0fSMark Brown 	return _devm_regulator_get(dev, id, OPTIONAL_GET);
1450cdfcc0fSMark Brown }
1460cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
1470cdfcc0fSMark Brown 
devm_regulator_match(struct device * dev,void * res,void * data)1480cdfcc0fSMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data)
1490cdfcc0fSMark Brown {
1500cdfcc0fSMark Brown 	struct regulator **r = res;
1510cdfcc0fSMark Brown 	if (!r || !*r) {
1520cdfcc0fSMark Brown 		WARN_ON(!r || !*r);
1530cdfcc0fSMark Brown 		return 0;
1540cdfcc0fSMark Brown 	}
1550cdfcc0fSMark Brown 	return *r == data;
1560cdfcc0fSMark Brown }
1570cdfcc0fSMark Brown 
1580cdfcc0fSMark Brown /**
1590cdfcc0fSMark Brown  * devm_regulator_put - Resource managed regulator_put()
1600cdfcc0fSMark Brown  * @regulator: regulator to free
1610cdfcc0fSMark Brown  *
1620cdfcc0fSMark Brown  * Deallocate a regulator allocated with devm_regulator_get(). Normally
1630cdfcc0fSMark Brown  * this function will not need to be called and the resource management
1640cdfcc0fSMark Brown  * code will ensure that the resource is freed.
1650cdfcc0fSMark Brown  */
devm_regulator_put(struct regulator * regulator)1660cdfcc0fSMark Brown void devm_regulator_put(struct regulator *regulator)
1670cdfcc0fSMark Brown {
1680cdfcc0fSMark Brown 	int rc;
1690cdfcc0fSMark Brown 
1700cdfcc0fSMark Brown 	rc = devres_release(regulator->dev, devm_regulator_release,
1710cdfcc0fSMark Brown 			    devm_regulator_match, regulator);
1720cdfcc0fSMark Brown 	if (rc != 0)
1730cdfcc0fSMark Brown 		WARN_ON(rc);
1740cdfcc0fSMark Brown }
1750cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put);
1760cdfcc0fSMark Brown 
1773eaeb475SDmitry Torokhov struct regulator_bulk_devres {
1783eaeb475SDmitry Torokhov 	struct regulator_bulk_data *consumers;
1793eaeb475SDmitry Torokhov 	int num_consumers;
1803eaeb475SDmitry Torokhov };
1813eaeb475SDmitry Torokhov 
devm_regulator_bulk_release(struct device * dev,void * res)1823eaeb475SDmitry Torokhov static void devm_regulator_bulk_release(struct device *dev, void *res)
1833eaeb475SDmitry Torokhov {
1843eaeb475SDmitry Torokhov 	struct regulator_bulk_devres *devres = res;
1853eaeb475SDmitry Torokhov 
1863eaeb475SDmitry Torokhov 	regulator_bulk_free(devres->num_consumers, devres->consumers);
1873eaeb475SDmitry Torokhov }
1883eaeb475SDmitry Torokhov 
_devm_regulator_bulk_get(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers,enum regulator_get_type get_type)189fd184506SZev Weiss static int _devm_regulator_bulk_get(struct device *dev, int num_consumers,
190fd184506SZev Weiss 				    struct regulator_bulk_data *consumers,
191fd184506SZev Weiss 				    enum regulator_get_type get_type)
192fd184506SZev Weiss {
193fd184506SZev Weiss 	struct regulator_bulk_devres *devres;
194fd184506SZev Weiss 	int ret;
195fd184506SZev Weiss 
196fd184506SZev Weiss 	devres = devres_alloc(devm_regulator_bulk_release,
197fd184506SZev Weiss 			      sizeof(*devres), GFP_KERNEL);
198fd184506SZev Weiss 	if (!devres)
199fd184506SZev Weiss 		return -ENOMEM;
200fd184506SZev Weiss 
201fd184506SZev Weiss 	ret = _regulator_bulk_get(dev, num_consumers, consumers, get_type);
202fd184506SZev Weiss 	if (!ret) {
203fd184506SZev Weiss 		devres->consumers = consumers;
204fd184506SZev Weiss 		devres->num_consumers = num_consumers;
205fd184506SZev Weiss 		devres_add(dev, devres);
206fd184506SZev Weiss 	} else {
207fd184506SZev Weiss 		devres_free(devres);
208fd184506SZev Weiss 	}
209fd184506SZev Weiss 
210fd184506SZev Weiss 	return ret;
211fd184506SZev Weiss }
212fd184506SZev Weiss 
2130cdfcc0fSMark Brown /**
2140cdfcc0fSMark Brown  * devm_regulator_bulk_get - managed get multiple regulator consumers
2150cdfcc0fSMark Brown  *
216a7c15187SLee Jones  * @dev:           device to supply
217a7c15187SLee Jones  * @num_consumers: number of consumers to register
218a7c15187SLee Jones  * @consumers:     configuration of consumers; clients are stored here.
2190cdfcc0fSMark Brown  *
2200cdfcc0fSMark Brown  * @return 0 on success, an errno on failure.
2210cdfcc0fSMark Brown  *
2220cdfcc0fSMark Brown  * This helper function allows drivers to get several regulator
2230cdfcc0fSMark Brown  * consumers in one operation with management, the regulators will
2240cdfcc0fSMark Brown  * automatically be freed when the device is unbound.  If any of the
2250cdfcc0fSMark Brown  * regulators cannot be acquired then any regulators that were
2260cdfcc0fSMark Brown  * allocated will be freed before returning to the caller.
2270cdfcc0fSMark Brown  */
devm_regulator_bulk_get(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers)2280cdfcc0fSMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers,
2290cdfcc0fSMark Brown 			    struct regulator_bulk_data *consumers)
2300cdfcc0fSMark Brown {
231fd184506SZev Weiss 	return _devm_regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET);
2320cdfcc0fSMark Brown }
2330cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
2340cdfcc0fSMark Brown 
2351de452a0SDouglas Anderson /**
236fd184506SZev Weiss  * devm_regulator_bulk_get_exclusive - managed exclusive get of multiple
237fd184506SZev Weiss  * regulator consumers
238fd184506SZev Weiss  *
239fd184506SZev Weiss  * @dev:           device to supply
240fd184506SZev Weiss  * @num_consumers: number of consumers to register
241fd184506SZev Weiss  * @consumers:     configuration of consumers; clients are stored here.
242fd184506SZev Weiss  *
243fd184506SZev Weiss  * @return 0 on success, an errno on failure.
244fd184506SZev Weiss  *
245fd184506SZev Weiss  * This helper function allows drivers to exclusively get several
246fd184506SZev Weiss  * regulator consumers in one operation with management, the regulators
247fd184506SZev Weiss  * will automatically be freed when the device is unbound.  If any of
248fd184506SZev Weiss  * the regulators cannot be acquired then any regulators that were
249fd184506SZev Weiss  * allocated will be freed before returning to the caller.
250fd184506SZev Weiss  */
devm_regulator_bulk_get_exclusive(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers)251fd184506SZev Weiss int devm_regulator_bulk_get_exclusive(struct device *dev, int num_consumers,
252fd184506SZev Weiss 				      struct regulator_bulk_data *consumers)
253fd184506SZev Weiss {
254fd184506SZev Weiss 	return _devm_regulator_bulk_get(dev, num_consumers, consumers, EXCLUSIVE_GET);
255fd184506SZev Weiss }
256fd184506SZev Weiss EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_exclusive);
257fd184506SZev Weiss 
258fd184506SZev Weiss /**
2591de452a0SDouglas Anderson  * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data
2601de452a0SDouglas Anderson  *
2611de452a0SDouglas Anderson  * @dev:           device to supply
2621de452a0SDouglas Anderson  * @num_consumers: number of consumers to register
2631de452a0SDouglas Anderson  * @in_consumers:  const configuration of consumers
2641de452a0SDouglas Anderson  * @out_consumers: in_consumers is copied here and this is passed to
2651de452a0SDouglas Anderson  *		   devm_regulator_bulk_get().
2661de452a0SDouglas Anderson  *
2671de452a0SDouglas Anderson  * This is a convenience function to allow bulk regulator configuration
2681de452a0SDouglas Anderson  * to be stored "static const" in files.
2691de452a0SDouglas Anderson  *
2701de452a0SDouglas Anderson  * Return: 0 on success, an errno on failure.
2711de452a0SDouglas Anderson  */
devm_regulator_bulk_get_const(struct device * dev,int num_consumers,const struct regulator_bulk_data * in_consumers,struct regulator_bulk_data ** out_consumers)2721de452a0SDouglas Anderson int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
2731de452a0SDouglas Anderson 				  const struct regulator_bulk_data *in_consumers,
2741de452a0SDouglas Anderson 				  struct regulator_bulk_data **out_consumers)
2751de452a0SDouglas Anderson {
2761de452a0SDouglas Anderson 	*out_consumers = devm_kmemdup(dev, in_consumers,
2771de452a0SDouglas Anderson 				      num_consumers * sizeof(*in_consumers),
2781de452a0SDouglas Anderson 				      GFP_KERNEL);
2791de452a0SDouglas Anderson 	if (*out_consumers == NULL)
2801de452a0SDouglas Anderson 		return -ENOMEM;
2811de452a0SDouglas Anderson 
2821de452a0SDouglas Anderson 	return devm_regulator_bulk_get(dev, num_consumers, *out_consumers);
2831de452a0SDouglas Anderson }
2841de452a0SDouglas Anderson EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
2851de452a0SDouglas Anderson 
devm_regulator_bulk_match(struct device * dev,void * res,void * data)286da279e69SMatti Vaittinen static int devm_regulator_bulk_match(struct device *dev, void *res,
287da279e69SMatti Vaittinen 				     void *data)
288da279e69SMatti Vaittinen {
289da279e69SMatti Vaittinen 	struct regulator_bulk_devres *match = res;
290da279e69SMatti Vaittinen 	struct regulator_bulk_data *target = data;
291da279e69SMatti Vaittinen 
292da279e69SMatti Vaittinen 	/*
293da279e69SMatti Vaittinen 	 * We check the put uses same consumer list as the get did.
294da279e69SMatti Vaittinen 	 * We _could_ scan all entries in consumer array and check the
295da279e69SMatti Vaittinen 	 * regulators match but ATM I don't see the need. We can change this
296da279e69SMatti Vaittinen 	 * later if needed.
297da279e69SMatti Vaittinen 	 */
298da279e69SMatti Vaittinen 	return match->consumers == target;
299da279e69SMatti Vaittinen }
300da279e69SMatti Vaittinen 
301da279e69SMatti Vaittinen /**
302da279e69SMatti Vaittinen  * devm_regulator_bulk_put - Resource managed regulator_bulk_put()
303da279e69SMatti Vaittinen  * @consumers: consumers to free
304da279e69SMatti Vaittinen  *
305da279e69SMatti Vaittinen  * Deallocate regulators allocated with devm_regulator_bulk_get(). Normally
306da279e69SMatti Vaittinen  * this function will not need to be called and the resource management
307da279e69SMatti Vaittinen  * code will ensure that the resource is freed.
308da279e69SMatti Vaittinen  */
devm_regulator_bulk_put(struct regulator_bulk_data * consumers)309da279e69SMatti Vaittinen void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)
310da279e69SMatti Vaittinen {
311da279e69SMatti Vaittinen 	int rc;
312da279e69SMatti Vaittinen 	struct regulator *regulator = consumers[0].consumer;
313da279e69SMatti Vaittinen 
314da279e69SMatti Vaittinen 	rc = devres_release(regulator->dev, devm_regulator_bulk_release,
315da279e69SMatti Vaittinen 			    devm_regulator_bulk_match, consumers);
316da279e69SMatti Vaittinen 	if (rc != 0)
317da279e69SMatti Vaittinen 		WARN_ON(rc);
318da279e69SMatti Vaittinen }
319da279e69SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_bulk_put);
320da279e69SMatti Vaittinen 
devm_regulator_bulk_disable(void * res)321da279e69SMatti Vaittinen static void devm_regulator_bulk_disable(void *res)
322da279e69SMatti Vaittinen {
323da279e69SMatti Vaittinen 	struct regulator_bulk_devres *devres = res;
324da279e69SMatti Vaittinen 	int i;
325da279e69SMatti Vaittinen 
326da279e69SMatti Vaittinen 	for (i = 0; i < devres->num_consumers; i++)
327da279e69SMatti Vaittinen 		regulator_disable(devres->consumers[i].consumer);
328da279e69SMatti Vaittinen }
329da279e69SMatti Vaittinen 
330da279e69SMatti Vaittinen /**
331da279e69SMatti Vaittinen  * devm_regulator_bulk_get_enable - managed get'n enable multiple regulators
332da279e69SMatti Vaittinen  *
333da279e69SMatti Vaittinen  * @dev:           device to supply
334da279e69SMatti Vaittinen  * @num_consumers: number of consumers to register
335da279e69SMatti Vaittinen  * @id:            list of supply names or regulator IDs
336da279e69SMatti Vaittinen  *
337da279e69SMatti Vaittinen  * @return 0 on success, an errno on failure.
338da279e69SMatti Vaittinen  *
339da279e69SMatti Vaittinen  * This helper function allows drivers to get several regulator
340da279e69SMatti Vaittinen  * consumers in one operation with management, the regulators will
341da279e69SMatti Vaittinen  * automatically be freed when the device is unbound.  If any of the
342da279e69SMatti Vaittinen  * regulators cannot be acquired then any regulators that were
343da279e69SMatti Vaittinen  * allocated will be freed before returning to the caller.
344da279e69SMatti Vaittinen  */
devm_regulator_bulk_get_enable(struct device * dev,int num_consumers,const char * const * id)345da279e69SMatti Vaittinen int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,
346da279e69SMatti Vaittinen 				   const char * const *id)
347da279e69SMatti Vaittinen {
348da279e69SMatti Vaittinen 	struct regulator_bulk_devres *devres;
349da279e69SMatti Vaittinen 	struct regulator_bulk_data *consumers;
350da279e69SMatti Vaittinen 	int i, ret;
351da279e69SMatti Vaittinen 
352da279e69SMatti Vaittinen 	devres = devm_kmalloc(dev, sizeof(*devres), GFP_KERNEL);
353da279e69SMatti Vaittinen 	if (!devres)
354da279e69SMatti Vaittinen 		return -ENOMEM;
355da279e69SMatti Vaittinen 
356da279e69SMatti Vaittinen 	devres->consumers = devm_kcalloc(dev, num_consumers, sizeof(*consumers),
357da279e69SMatti Vaittinen 					 GFP_KERNEL);
358da279e69SMatti Vaittinen 	consumers = devres->consumers;
359da279e69SMatti Vaittinen 	if (!consumers)
360da279e69SMatti Vaittinen 		return -ENOMEM;
361da279e69SMatti Vaittinen 
362da279e69SMatti Vaittinen 	devres->num_consumers = num_consumers;
363da279e69SMatti Vaittinen 
364da279e69SMatti Vaittinen 	for (i = 0; i < num_consumers; i++)
365da279e69SMatti Vaittinen 		consumers[i].supply = id[i];
366da279e69SMatti Vaittinen 
367da279e69SMatti Vaittinen 	ret = devm_regulator_bulk_get(dev, num_consumers, consumers);
368da279e69SMatti Vaittinen 	if (ret)
369da279e69SMatti Vaittinen 		return ret;
370da279e69SMatti Vaittinen 
371da279e69SMatti Vaittinen 	for (i = 0; i < num_consumers; i++) {
372da279e69SMatti Vaittinen 		ret = regulator_enable(consumers[i].consumer);
373da279e69SMatti Vaittinen 		if (ret)
374da279e69SMatti Vaittinen 			goto unwind;
375da279e69SMatti Vaittinen 	}
376da279e69SMatti Vaittinen 
377da279e69SMatti Vaittinen 	ret = devm_add_action(dev, devm_regulator_bulk_disable, devres);
378da279e69SMatti Vaittinen 	if (!ret)
379da279e69SMatti Vaittinen 		return 0;
380da279e69SMatti Vaittinen 
381da279e69SMatti Vaittinen unwind:
382da279e69SMatti Vaittinen 	while (--i >= 0)
383da279e69SMatti Vaittinen 		regulator_disable(consumers[i].consumer);
384da279e69SMatti Vaittinen 
385da279e69SMatti Vaittinen 	devm_regulator_bulk_put(consumers);
386da279e69SMatti Vaittinen 
387da279e69SMatti Vaittinen 	return ret;
388da279e69SMatti Vaittinen }
389da279e69SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_enable);
390da279e69SMatti Vaittinen 
devm_rdev_release(struct device * dev,void * res)3910cdfcc0fSMark Brown static void devm_rdev_release(struct device *dev, void *res)
3920cdfcc0fSMark Brown {
3930cdfcc0fSMark Brown 	regulator_unregister(*(struct regulator_dev **)res);
3940cdfcc0fSMark Brown }
3950cdfcc0fSMark Brown 
3960cdfcc0fSMark Brown /**
3970cdfcc0fSMark Brown  * devm_regulator_register - Resource managed regulator_register()
3989565cccdSLee Jones  * @dev:            device to supply
3990cdfcc0fSMark Brown  * @regulator_desc: regulator to register
4000cdfcc0fSMark Brown  * @config:         runtime configuration for regulator
4010cdfcc0fSMark Brown  *
4020cdfcc0fSMark Brown  * Called by regulator drivers to register a regulator.  Returns a
4030cdfcc0fSMark Brown  * valid pointer to struct regulator_dev on success or an ERR_PTR() on
4040cdfcc0fSMark Brown  * error.  The regulator will automatically be released when the device
4050cdfcc0fSMark Brown  * is unbound.
4060cdfcc0fSMark Brown  */
devm_regulator_register(struct device * dev,const struct regulator_desc * regulator_desc,const struct regulator_config * config)4070cdfcc0fSMark Brown struct regulator_dev *devm_regulator_register(struct device *dev,
4080cdfcc0fSMark Brown 				  const struct regulator_desc *regulator_desc,
4090cdfcc0fSMark Brown 				  const struct regulator_config *config)
4100cdfcc0fSMark Brown {
4110cdfcc0fSMark Brown 	struct regulator_dev **ptr, *rdev;
4120cdfcc0fSMark Brown 
4130cdfcc0fSMark Brown 	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
4140cdfcc0fSMark Brown 			   GFP_KERNEL);
4150cdfcc0fSMark Brown 	if (!ptr)
4160cdfcc0fSMark Brown 		return ERR_PTR(-ENOMEM);
4170cdfcc0fSMark Brown 
418*8f3cbcd6SChiYuan Huang 	rdev = regulator_register(dev, regulator_desc, config);
4190cdfcc0fSMark Brown 	if (!IS_ERR(rdev)) {
4200cdfcc0fSMark Brown 		*ptr = rdev;
4210cdfcc0fSMark Brown 		devres_add(dev, ptr);
4220cdfcc0fSMark Brown 	} else {
4230cdfcc0fSMark Brown 		devres_free(ptr);
4240cdfcc0fSMark Brown 	}
4250cdfcc0fSMark Brown 
4260cdfcc0fSMark Brown 	return rdev;
4270cdfcc0fSMark Brown }
4280cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_register);
4290cdfcc0fSMark Brown 
430a06ccd9cSCharles Keepax struct regulator_supply_alias_match {
431a06ccd9cSCharles Keepax 	struct device *dev;
432a06ccd9cSCharles Keepax 	const char *id;
433a06ccd9cSCharles Keepax };
434a06ccd9cSCharles Keepax 
devm_regulator_match_supply_alias(struct device * dev,void * res,void * data)435a06ccd9cSCharles Keepax static int devm_regulator_match_supply_alias(struct device *dev, void *res,
436a06ccd9cSCharles Keepax 					     void *data)
437a06ccd9cSCharles Keepax {
438a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
439a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *target = data;
440a06ccd9cSCharles Keepax 
441a06ccd9cSCharles Keepax 	return match->dev == target->dev && strcmp(match->id, target->id) == 0;
442a06ccd9cSCharles Keepax }
443a06ccd9cSCharles Keepax 
devm_regulator_destroy_supply_alias(struct device * dev,void * res)444a06ccd9cSCharles Keepax static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
445a06ccd9cSCharles Keepax {
446a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
447a06ccd9cSCharles Keepax 
448a06ccd9cSCharles Keepax 	regulator_unregister_supply_alias(match->dev, match->id);
449a06ccd9cSCharles Keepax }
450a06ccd9cSCharles Keepax 
451a06ccd9cSCharles Keepax /**
452a06ccd9cSCharles Keepax  * devm_regulator_register_supply_alias - Resource managed
453a06ccd9cSCharles Keepax  * regulator_register_supply_alias()
454a06ccd9cSCharles Keepax  *
455a7c15187SLee Jones  * @dev:       device to supply
456a7c15187SLee Jones  * @id:        supply name or regulator ID
457a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
458a7c15187SLee Jones  * @alias_id:  supply name or regulator ID that should be used to lookup the
459a06ccd9cSCharles Keepax  * supply
460a06ccd9cSCharles Keepax  *
461a06ccd9cSCharles Keepax  * The supply alias will automatically be unregistered when the source
462a06ccd9cSCharles Keepax  * device is unbound.
463a06ccd9cSCharles Keepax  */
devm_regulator_register_supply_alias(struct device * dev,const char * id,struct device * alias_dev,const char * alias_id)464a06ccd9cSCharles Keepax int devm_regulator_register_supply_alias(struct device *dev, const char *id,
465a06ccd9cSCharles Keepax 					 struct device *alias_dev,
466a06ccd9cSCharles Keepax 					 const char *alias_id)
467a06ccd9cSCharles Keepax {
468a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match;
469a06ccd9cSCharles Keepax 	int ret;
470a06ccd9cSCharles Keepax 
471a06ccd9cSCharles Keepax 	match = devres_alloc(devm_regulator_destroy_supply_alias,
472a06ccd9cSCharles Keepax 			   sizeof(struct regulator_supply_alias_match),
473a06ccd9cSCharles Keepax 			   GFP_KERNEL);
474a06ccd9cSCharles Keepax 	if (!match)
475a06ccd9cSCharles Keepax 		return -ENOMEM;
476a06ccd9cSCharles Keepax 
477a06ccd9cSCharles Keepax 	match->dev = dev;
478a06ccd9cSCharles Keepax 	match->id = id;
479a06ccd9cSCharles Keepax 
480a06ccd9cSCharles Keepax 	ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
481a06ccd9cSCharles Keepax 	if (ret < 0) {
482a06ccd9cSCharles Keepax 		devres_free(match);
483a06ccd9cSCharles Keepax 		return ret;
484a06ccd9cSCharles Keepax 	}
485a06ccd9cSCharles Keepax 
486a06ccd9cSCharles Keepax 	devres_add(dev, match);
487a06ccd9cSCharles Keepax 
488a06ccd9cSCharles Keepax 	return 0;
489a06ccd9cSCharles Keepax }
490a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
491a06ccd9cSCharles Keepax 
devm_regulator_unregister_supply_alias(struct device * dev,const char * id)4924d9f4d1dSAlexandru Ardelean static void devm_regulator_unregister_supply_alias(struct device *dev,
4934d9f4d1dSAlexandru Ardelean 						   const char *id)
494a06ccd9cSCharles Keepax {
495a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match match;
496a06ccd9cSCharles Keepax 	int rc;
497a06ccd9cSCharles Keepax 
498a06ccd9cSCharles Keepax 	match.dev = dev;
499a06ccd9cSCharles Keepax 	match.id = id;
500a06ccd9cSCharles Keepax 
501a06ccd9cSCharles Keepax 	rc = devres_release(dev, devm_regulator_destroy_supply_alias,
502a06ccd9cSCharles Keepax 			    devm_regulator_match_supply_alias, &match);
503a06ccd9cSCharles Keepax 	if (rc != 0)
504a06ccd9cSCharles Keepax 		WARN_ON(rc);
505a06ccd9cSCharles Keepax }
506a06ccd9cSCharles Keepax 
507a06ccd9cSCharles Keepax /**
508a06ccd9cSCharles Keepax  * devm_regulator_bulk_register_supply_alias - Managed register
509a06ccd9cSCharles Keepax  * multiple aliases
510a06ccd9cSCharles Keepax  *
511a7c15187SLee Jones  * @dev:       device to supply
512a7c15187SLee Jones  * @id:        list of supply names or regulator IDs
513a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
514a7c15187SLee Jones  * @alias_id:  list of supply names or regulator IDs that should be used to
515a06ccd9cSCharles Keepax  *             lookup the supply
516a7c15187SLee Jones  * @num_id:    number of aliases to register
517a06ccd9cSCharles Keepax  *
518a06ccd9cSCharles Keepax  * @return 0 on success, an errno on failure.
519a06ccd9cSCharles Keepax  *
520a06ccd9cSCharles Keepax  * This helper function allows drivers to register several supply
521a06ccd9cSCharles Keepax  * aliases in one operation, the aliases will be automatically
522a06ccd9cSCharles Keepax  * unregisters when the source device is unbound.  If any of the
523a06ccd9cSCharles Keepax  * aliases cannot be registered any aliases that were registered
524a06ccd9cSCharles Keepax  * will be removed before returning to the caller.
525a06ccd9cSCharles Keepax  */
devm_regulator_bulk_register_supply_alias(struct device * dev,const char * const * id,struct device * alias_dev,const char * const * alias_id,int num_id)526a06ccd9cSCharles Keepax int devm_regulator_bulk_register_supply_alias(struct device *dev,
5279f8c0fe9SLee Jones 					      const char *const *id,
528a06ccd9cSCharles Keepax 					      struct device *alias_dev,
5299f8c0fe9SLee Jones 					      const char *const *alias_id,
530a06ccd9cSCharles Keepax 					      int num_id)
531a06ccd9cSCharles Keepax {
532a06ccd9cSCharles Keepax 	int i;
533a06ccd9cSCharles Keepax 	int ret;
534a06ccd9cSCharles Keepax 
535a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i) {
536a06ccd9cSCharles Keepax 		ret = devm_regulator_register_supply_alias(dev, id[i],
537a06ccd9cSCharles Keepax 							   alias_dev,
538a06ccd9cSCharles Keepax 							   alias_id[i]);
539a06ccd9cSCharles Keepax 		if (ret < 0)
540a06ccd9cSCharles Keepax 			goto err;
541a06ccd9cSCharles Keepax 	}
542a06ccd9cSCharles Keepax 
543a06ccd9cSCharles Keepax 	return 0;
544a06ccd9cSCharles Keepax 
545a06ccd9cSCharles Keepax err:
546a06ccd9cSCharles Keepax 	dev_err(dev,
547a06ccd9cSCharles Keepax 		"Failed to create supply alias %s,%s -> %s,%s\n",
548a06ccd9cSCharles Keepax 		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
549a06ccd9cSCharles Keepax 
550a06ccd9cSCharles Keepax 	while (--i >= 0)
551a06ccd9cSCharles Keepax 		devm_regulator_unregister_supply_alias(dev, id[i]);
552a06ccd9cSCharles Keepax 
553a06ccd9cSCharles Keepax 	return ret;
554a06ccd9cSCharles Keepax }
555a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
556a06ccd9cSCharles Keepax 
557046db763SCharles Keepax struct regulator_notifier_match {
558046db763SCharles Keepax 	struct regulator *regulator;
559046db763SCharles Keepax 	struct notifier_block *nb;
560046db763SCharles Keepax };
561046db763SCharles Keepax 
devm_regulator_match_notifier(struct device * dev,void * res,void * data)562046db763SCharles Keepax static int devm_regulator_match_notifier(struct device *dev, void *res,
563046db763SCharles Keepax 					 void *data)
564046db763SCharles Keepax {
565046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
566046db763SCharles Keepax 	struct regulator_notifier_match *target = data;
567046db763SCharles Keepax 
568046db763SCharles Keepax 	return match->regulator == target->regulator && match->nb == target->nb;
569046db763SCharles Keepax }
570046db763SCharles Keepax 
devm_regulator_destroy_notifier(struct device * dev,void * res)571046db763SCharles Keepax static void devm_regulator_destroy_notifier(struct device *dev, void *res)
572046db763SCharles Keepax {
573046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
574046db763SCharles Keepax 
575046db763SCharles Keepax 	regulator_unregister_notifier(match->regulator, match->nb);
576046db763SCharles Keepax }
577046db763SCharles Keepax 
578046db763SCharles Keepax /**
579046db763SCharles Keepax  * devm_regulator_register_notifier - Resource managed
580046db763SCharles Keepax  * regulator_register_notifier
581046db763SCharles Keepax  *
582046db763SCharles Keepax  * @regulator: regulator source
583046db763SCharles Keepax  * @nb:        notifier block
584046db763SCharles Keepax  *
585046db763SCharles Keepax  * The notifier will be registers under the consumer device and be
586046db763SCharles Keepax  * automatically be unregistered when the source device is unbound.
587046db763SCharles Keepax  */
devm_regulator_register_notifier(struct regulator * regulator,struct notifier_block * nb)588046db763SCharles Keepax int devm_regulator_register_notifier(struct regulator *regulator,
589046db763SCharles Keepax 				     struct notifier_block *nb)
590046db763SCharles Keepax {
591046db763SCharles Keepax 	struct regulator_notifier_match *match;
592046db763SCharles Keepax 	int ret;
593046db763SCharles Keepax 
594046db763SCharles Keepax 	match = devres_alloc(devm_regulator_destroy_notifier,
595046db763SCharles Keepax 			     sizeof(struct regulator_notifier_match),
596046db763SCharles Keepax 			     GFP_KERNEL);
597046db763SCharles Keepax 	if (!match)
598046db763SCharles Keepax 		return -ENOMEM;
599046db763SCharles Keepax 
600046db763SCharles Keepax 	match->regulator = regulator;
601046db763SCharles Keepax 	match->nb = nb;
602046db763SCharles Keepax 
603046db763SCharles Keepax 	ret = regulator_register_notifier(regulator, nb);
604046db763SCharles Keepax 	if (ret < 0) {
605046db763SCharles Keepax 		devres_free(match);
606046db763SCharles Keepax 		return ret;
607046db763SCharles Keepax 	}
608046db763SCharles Keepax 
609046db763SCharles Keepax 	devres_add(regulator->dev, match);
610046db763SCharles Keepax 
611046db763SCharles Keepax 	return 0;
612046db763SCharles Keepax }
613046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
614046db763SCharles Keepax 
615046db763SCharles Keepax /**
616046db763SCharles Keepax  * devm_regulator_unregister_notifier - Resource managed
617046db763SCharles Keepax  * regulator_unregister_notifier()
618046db763SCharles Keepax  *
619046db763SCharles Keepax  * @regulator: regulator source
620046db763SCharles Keepax  * @nb:        notifier block
621046db763SCharles Keepax  *
622046db763SCharles Keepax  * Unregister a notifier registered with devm_regulator_register_notifier().
623046db763SCharles Keepax  * Normally this function will not need to be called and the resource
624046db763SCharles Keepax  * management code will ensure that the resource is freed.
625046db763SCharles Keepax  */
devm_regulator_unregister_notifier(struct regulator * regulator,struct notifier_block * nb)626046db763SCharles Keepax void devm_regulator_unregister_notifier(struct regulator *regulator,
627046db763SCharles Keepax 					struct notifier_block *nb)
628046db763SCharles Keepax {
629046db763SCharles Keepax 	struct regulator_notifier_match match;
630046db763SCharles Keepax 	int rc;
631046db763SCharles Keepax 
632046db763SCharles Keepax 	match.regulator = regulator;
633046db763SCharles Keepax 	match.nb = nb;
634046db763SCharles Keepax 
635046db763SCharles Keepax 	rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
636046db763SCharles Keepax 			    devm_regulator_match_notifier, &match);
637046db763SCharles Keepax 	if (rc != 0)
638046db763SCharles Keepax 		WARN_ON(rc);
639046db763SCharles Keepax }
640046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
6417111c6d1SMatti Vaittinen 
regulator_irq_helper_drop(void * res)6427111c6d1SMatti Vaittinen static void regulator_irq_helper_drop(void *res)
6437111c6d1SMatti Vaittinen {
6447111c6d1SMatti Vaittinen 	regulator_irq_helper_cancel(&res);
6457111c6d1SMatti Vaittinen }
6467111c6d1SMatti Vaittinen 
6477111c6d1SMatti Vaittinen /**
6487111c6d1SMatti Vaittinen  * devm_regulator_irq_helper - resource managed registration of IRQ based
6497111c6d1SMatti Vaittinen  * regulator event/error notifier
6507111c6d1SMatti Vaittinen  *
6517111c6d1SMatti Vaittinen  * @dev:		device to which lifetime the helper's lifetime is
6527111c6d1SMatti Vaittinen  *			bound.
6537111c6d1SMatti Vaittinen  * @d:			IRQ helper descriptor.
6547111c6d1SMatti Vaittinen  * @irq:		IRQ used to inform events/errors to be notified.
6557111c6d1SMatti Vaittinen  * @irq_flags:		Extra IRQ flags to be OR'ed with the default
6567111c6d1SMatti Vaittinen  *			IRQF_ONESHOT when requesting the (threaded) irq.
6577111c6d1SMatti Vaittinen  * @common_errs:	Errors which can be flagged by this IRQ for all rdevs.
6587111c6d1SMatti Vaittinen  *			When IRQ is re-enabled these errors will be cleared
6597111c6d1SMatti Vaittinen  *			from all associated regulators
6607111c6d1SMatti Vaittinen  * @per_rdev_errs:	Optional error flag array describing errors specific
6617111c6d1SMatti Vaittinen  *			for only some of the regulators. These errors will be
6627111c6d1SMatti Vaittinen  *			or'ed with common errors. If this is given the array
6637111c6d1SMatti Vaittinen  *			should contain rdev_amount flags. Can be set to NULL
6647111c6d1SMatti Vaittinen  *			if there is no regulator specific error flags for this
6657111c6d1SMatti Vaittinen  *			IRQ.
6667111c6d1SMatti Vaittinen  * @rdev:		Array of pointers to regulators associated with this
6677111c6d1SMatti Vaittinen  *			IRQ.
6687111c6d1SMatti Vaittinen  * @rdev_amount:	Amount of regulators associated with this IRQ.
6697111c6d1SMatti Vaittinen  *
6707111c6d1SMatti Vaittinen  * Return: handle to irq_helper or an ERR_PTR() encoded error code.
6717111c6d1SMatti Vaittinen  */
devm_regulator_irq_helper(struct device * dev,const struct regulator_irq_desc * d,int irq,int irq_flags,int common_errs,int * per_rdev_errs,struct regulator_dev ** rdev,int rdev_amount)6727111c6d1SMatti Vaittinen void *devm_regulator_irq_helper(struct device *dev,
6737111c6d1SMatti Vaittinen 				const struct regulator_irq_desc *d, int irq,
6747111c6d1SMatti Vaittinen 				int irq_flags, int common_errs,
6757111c6d1SMatti Vaittinen 				int *per_rdev_errs,
6767111c6d1SMatti Vaittinen 				struct regulator_dev **rdev, int rdev_amount)
6777111c6d1SMatti Vaittinen {
6787111c6d1SMatti Vaittinen 	void *ptr;
6797111c6d1SMatti Vaittinen 	int ret;
6807111c6d1SMatti Vaittinen 
6817111c6d1SMatti Vaittinen 	ptr = regulator_irq_helper(dev, d, irq, irq_flags, common_errs,
6827111c6d1SMatti Vaittinen 				    per_rdev_errs, rdev, rdev_amount);
6837111c6d1SMatti Vaittinen 	if (IS_ERR(ptr))
6847111c6d1SMatti Vaittinen 		return ptr;
6857111c6d1SMatti Vaittinen 
6867111c6d1SMatti Vaittinen 	ret = devm_add_action_or_reset(dev, regulator_irq_helper_drop, ptr);
6877111c6d1SMatti Vaittinen 	if (ret)
6887111c6d1SMatti Vaittinen 		return ERR_PTR(ret);
6897111c6d1SMatti Vaittinen 
6907111c6d1SMatti Vaittinen 	return ptr;
6917111c6d1SMatti Vaittinen }
6927111c6d1SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);
693