xref: /linux-6.15/drivers/regulator/devres.c (revision 6ddd1159)
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 
148b250c20bSDavid Lechner /**
149b250c20bSDavid Lechner  * devm_regulator_get_enable_read_voltage - Resource managed regulator get and
150b250c20bSDavid Lechner  *                                          enable that returns the voltage
151b250c20bSDavid Lechner  * @dev: device to supply
152b250c20bSDavid Lechner  * @id:  supply name or regulator ID.
153b250c20bSDavid Lechner  *
154b250c20bSDavid Lechner  * Get and enable regulator for duration of the device life-time.
155b250c20bSDavid Lechner  * regulator_disable() and regulator_put() are automatically called on driver
156b250c20bSDavid Lechner  * detach. See regulator_get_optional(), regulator_enable(), and
157b250c20bSDavid Lechner  * regulator_get_voltage() for more information.
158b250c20bSDavid Lechner  *
159b250c20bSDavid Lechner  * This is a convenience function for supplies that provide a reference voltage
160b250c20bSDavid Lechner  * where the consumer driver just needs to know the voltage and keep the
161b250c20bSDavid Lechner  * regulator enabled.
162b250c20bSDavid Lechner  *
163b250c20bSDavid Lechner  * In cases where the supply is not strictly required, callers can check for
164b250c20bSDavid Lechner  * -ENODEV error and handle it accordingly.
165b250c20bSDavid Lechner  *
16698ce82a5SChen-Yu Tsai  * Returns: voltage in microvolts on success, or an negative error number on failure.
167b250c20bSDavid Lechner  */
devm_regulator_get_enable_read_voltage(struct device * dev,const char * id)168b250c20bSDavid Lechner int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id)
169b250c20bSDavid Lechner {
170b250c20bSDavid Lechner 	struct regulator *r;
171b250c20bSDavid Lechner 	int ret;
172b250c20bSDavid Lechner 
173b250c20bSDavid Lechner 	/*
174b250c20bSDavid Lechner 	 * Since we need a real voltage, we use devm_regulator_get_optional()
175b250c20bSDavid Lechner 	 * rather than getting a dummy regulator with devm_regulator_get() and
176b250c20bSDavid Lechner 	 * then letting regulator_get_voltage() fail with -EINVAL. This way, the
17798ce82a5SChen-Yu Tsai 	 * caller can handle the -ENODEV negative error number if needed instead
17898ce82a5SChen-Yu Tsai 	 * of the ambiguous -EINVAL.
179b250c20bSDavid Lechner 	 */
180b250c20bSDavid Lechner 	r = devm_regulator_get_optional(dev, id);
181b250c20bSDavid Lechner 	if (IS_ERR(r))
182b250c20bSDavid Lechner 		return PTR_ERR(r);
183b250c20bSDavid Lechner 
184b250c20bSDavid Lechner 	ret = regulator_enable(r);
185b250c20bSDavid Lechner 	if (ret)
186b250c20bSDavid Lechner 		goto err_regulator_put;
187b250c20bSDavid Lechner 
188b250c20bSDavid Lechner 	ret = devm_add_action_or_reset(dev, regulator_action_disable, r);
189b250c20bSDavid Lechner 	if (ret)
190b250c20bSDavid Lechner 		goto err_regulator_put;
191b250c20bSDavid Lechner 
192b250c20bSDavid Lechner 	ret = regulator_get_voltage(r);
193b250c20bSDavid Lechner 	if (ret < 0)
194b250c20bSDavid Lechner 		goto err_release_action;
195b250c20bSDavid Lechner 
196257b2335SDavid Lechner 	return ret;
197b250c20bSDavid Lechner 
198b250c20bSDavid Lechner err_release_action:
199b250c20bSDavid Lechner 	devm_release_action(dev, regulator_action_disable, r);
200b250c20bSDavid Lechner err_regulator_put:
201b250c20bSDavid Lechner 	devm_regulator_put(r);
202b250c20bSDavid Lechner 
203b250c20bSDavid Lechner 	return ret;
204b250c20bSDavid Lechner }
205b250c20bSDavid Lechner EXPORT_SYMBOL_GPL(devm_regulator_get_enable_read_voltage);
206b250c20bSDavid Lechner 
devm_regulator_match(struct device * dev,void * res,void * data)2070cdfcc0fSMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data)
2080cdfcc0fSMark Brown {
2090cdfcc0fSMark Brown 	struct regulator **r = res;
2100cdfcc0fSMark Brown 	if (!r || !*r) {
2110cdfcc0fSMark Brown 		WARN_ON(!r || !*r);
2120cdfcc0fSMark Brown 		return 0;
2130cdfcc0fSMark Brown 	}
2140cdfcc0fSMark Brown 	return *r == data;
2150cdfcc0fSMark Brown }
2160cdfcc0fSMark Brown 
2170cdfcc0fSMark Brown /**
2180cdfcc0fSMark Brown  * devm_regulator_put - Resource managed regulator_put()
2190cdfcc0fSMark Brown  * @regulator: regulator to free
2200cdfcc0fSMark Brown  *
2210cdfcc0fSMark Brown  * Deallocate a regulator allocated with devm_regulator_get(). Normally
2220cdfcc0fSMark Brown  * this function will not need to be called and the resource management
2230cdfcc0fSMark Brown  * code will ensure that the resource is freed.
2240cdfcc0fSMark Brown  */
devm_regulator_put(struct regulator * regulator)2250cdfcc0fSMark Brown void devm_regulator_put(struct regulator *regulator)
2260cdfcc0fSMark Brown {
2270cdfcc0fSMark Brown 	int rc;
2280cdfcc0fSMark Brown 
2290cdfcc0fSMark Brown 	rc = devres_release(regulator->dev, devm_regulator_release,
2300cdfcc0fSMark Brown 			    devm_regulator_match, regulator);
2310cdfcc0fSMark Brown 	if (rc != 0)
2320cdfcc0fSMark Brown 		WARN_ON(rc);
2330cdfcc0fSMark Brown }
2340cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put);
2350cdfcc0fSMark Brown 
2363eaeb475SDmitry Torokhov struct regulator_bulk_devres {
2373eaeb475SDmitry Torokhov 	struct regulator_bulk_data *consumers;
2383eaeb475SDmitry Torokhov 	int num_consumers;
2393eaeb475SDmitry Torokhov };
2403eaeb475SDmitry Torokhov 
devm_regulator_bulk_release(struct device * dev,void * res)2413eaeb475SDmitry Torokhov static void devm_regulator_bulk_release(struct device *dev, void *res)
2423eaeb475SDmitry Torokhov {
2433eaeb475SDmitry Torokhov 	struct regulator_bulk_devres *devres = res;
2443eaeb475SDmitry Torokhov 
2453eaeb475SDmitry Torokhov 	regulator_bulk_free(devres->num_consumers, devres->consumers);
2463eaeb475SDmitry Torokhov }
2473eaeb475SDmitry Torokhov 
_devm_regulator_bulk_get(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers,enum regulator_get_type get_type)248fd184506SZev Weiss static int _devm_regulator_bulk_get(struct device *dev, int num_consumers,
249fd184506SZev Weiss 				    struct regulator_bulk_data *consumers,
250fd184506SZev Weiss 				    enum regulator_get_type get_type)
251fd184506SZev Weiss {
252fd184506SZev Weiss 	struct regulator_bulk_devres *devres;
253fd184506SZev Weiss 	int ret;
254fd184506SZev Weiss 
255fd184506SZev Weiss 	devres = devres_alloc(devm_regulator_bulk_release,
256fd184506SZev Weiss 			      sizeof(*devres), GFP_KERNEL);
257fd184506SZev Weiss 	if (!devres)
258fd184506SZev Weiss 		return -ENOMEM;
259fd184506SZev Weiss 
260fd184506SZev Weiss 	ret = _regulator_bulk_get(dev, num_consumers, consumers, get_type);
261fd184506SZev Weiss 	if (!ret) {
262fd184506SZev Weiss 		devres->consumers = consumers;
263fd184506SZev Weiss 		devres->num_consumers = num_consumers;
264fd184506SZev Weiss 		devres_add(dev, devres);
265fd184506SZev Weiss 	} else {
266fd184506SZev Weiss 		devres_free(devres);
267fd184506SZev Weiss 	}
268fd184506SZev Weiss 
269fd184506SZev Weiss 	return ret;
270fd184506SZev Weiss }
271fd184506SZev Weiss 
2720cdfcc0fSMark Brown /**
2730cdfcc0fSMark Brown  * devm_regulator_bulk_get - managed get multiple regulator consumers
2740cdfcc0fSMark Brown  *
275a7c15187SLee Jones  * @dev:           device to supply
276a7c15187SLee Jones  * @num_consumers: number of consumers to register
277a7c15187SLee Jones  * @consumers:     configuration of consumers; clients are stored here.
2780cdfcc0fSMark Brown  *
27998ce82a5SChen-Yu Tsai  * @return 0 on success, a negative error number on failure.
2800cdfcc0fSMark Brown  *
2810cdfcc0fSMark Brown  * This helper function allows drivers to get several regulator
2820cdfcc0fSMark Brown  * consumers in one operation with management, the regulators will
2830cdfcc0fSMark Brown  * automatically be freed when the device is unbound.  If any of the
2840cdfcc0fSMark Brown  * regulators cannot be acquired then any regulators that were
2850cdfcc0fSMark Brown  * allocated will be freed before returning to the caller.
2860cdfcc0fSMark Brown  */
devm_regulator_bulk_get(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers)2870cdfcc0fSMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers,
2880cdfcc0fSMark Brown 			    struct regulator_bulk_data *consumers)
2890cdfcc0fSMark Brown {
290fd184506SZev Weiss 	return _devm_regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET);
2910cdfcc0fSMark Brown }
2920cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
2930cdfcc0fSMark Brown 
2941de452a0SDouglas Anderson /**
295fd184506SZev Weiss  * devm_regulator_bulk_get_exclusive - managed exclusive get of multiple
296fd184506SZev Weiss  * regulator consumers
297fd184506SZev Weiss  *
298fd184506SZev Weiss  * @dev:           device to supply
299fd184506SZev Weiss  * @num_consumers: number of consumers to register
300fd184506SZev Weiss  * @consumers:     configuration of consumers; clients are stored here.
301fd184506SZev Weiss  *
30298ce82a5SChen-Yu Tsai  * @return 0 on success, a negative error number on failure.
303fd184506SZev Weiss  *
304fd184506SZev Weiss  * This helper function allows drivers to exclusively get several
305fd184506SZev Weiss  * regulator consumers in one operation with management, the regulators
306fd184506SZev Weiss  * will automatically be freed when the device is unbound.  If any of
307fd184506SZev Weiss  * the regulators cannot be acquired then any regulators that were
308fd184506SZev Weiss  * allocated will be freed before returning to the caller.
309fd184506SZev Weiss  */
devm_regulator_bulk_get_exclusive(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers)310fd184506SZev Weiss int devm_regulator_bulk_get_exclusive(struct device *dev, int num_consumers,
311fd184506SZev Weiss 				      struct regulator_bulk_data *consumers)
312fd184506SZev Weiss {
313fd184506SZev Weiss 	return _devm_regulator_bulk_get(dev, num_consumers, consumers, EXCLUSIVE_GET);
314fd184506SZev Weiss }
315fd184506SZev Weiss EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_exclusive);
316fd184506SZev Weiss 
317fd184506SZev Weiss /**
3181de452a0SDouglas Anderson  * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data
3191de452a0SDouglas Anderson  *
3201de452a0SDouglas Anderson  * @dev:           device to supply
3211de452a0SDouglas Anderson  * @num_consumers: number of consumers to register
3221de452a0SDouglas Anderson  * @in_consumers:  const configuration of consumers
3231de452a0SDouglas Anderson  * @out_consumers: in_consumers is copied here and this is passed to
3241de452a0SDouglas Anderson  *		   devm_regulator_bulk_get().
3251de452a0SDouglas Anderson  *
3261de452a0SDouglas Anderson  * This is a convenience function to allow bulk regulator configuration
3271de452a0SDouglas Anderson  * to be stored "static const" in files.
3281de452a0SDouglas Anderson  *
32998ce82a5SChen-Yu Tsai  * Return: 0 on success, a negative error number on failure.
3301de452a0SDouglas 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)3311de452a0SDouglas Anderson int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
3321de452a0SDouglas Anderson 				  const struct regulator_bulk_data *in_consumers,
3331de452a0SDouglas Anderson 				  struct regulator_bulk_data **out_consumers)
3341de452a0SDouglas Anderson {
335*6ddd1159SRaag Jadav 	*out_consumers = devm_kmemdup_array(dev, in_consumers, num_consumers,
336*6ddd1159SRaag Jadav 					    sizeof(*in_consumers), GFP_KERNEL);
3371de452a0SDouglas Anderson 	if (*out_consumers == NULL)
3381de452a0SDouglas Anderson 		return -ENOMEM;
3391de452a0SDouglas Anderson 
3401de452a0SDouglas Anderson 	return devm_regulator_bulk_get(dev, num_consumers, *out_consumers);
3411de452a0SDouglas Anderson }
3421de452a0SDouglas Anderson EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
3431de452a0SDouglas Anderson 
devm_regulator_bulk_match(struct device * dev,void * res,void * data)344da279e69SMatti Vaittinen static int devm_regulator_bulk_match(struct device *dev, void *res,
345da279e69SMatti Vaittinen 				     void *data)
346da279e69SMatti Vaittinen {
347da279e69SMatti Vaittinen 	struct regulator_bulk_devres *match = res;
348da279e69SMatti Vaittinen 	struct regulator_bulk_data *target = data;
349da279e69SMatti Vaittinen 
350da279e69SMatti Vaittinen 	/*
351da279e69SMatti Vaittinen 	 * We check the put uses same consumer list as the get did.
352da279e69SMatti Vaittinen 	 * We _could_ scan all entries in consumer array and check the
353da279e69SMatti Vaittinen 	 * regulators match but ATM I don't see the need. We can change this
354da279e69SMatti Vaittinen 	 * later if needed.
355da279e69SMatti Vaittinen 	 */
356da279e69SMatti Vaittinen 	return match->consumers == target;
357da279e69SMatti Vaittinen }
358da279e69SMatti Vaittinen 
359da279e69SMatti Vaittinen /**
360da279e69SMatti Vaittinen  * devm_regulator_bulk_put - Resource managed regulator_bulk_put()
361da279e69SMatti Vaittinen  * @consumers: consumers to free
362da279e69SMatti Vaittinen  *
363da279e69SMatti Vaittinen  * Deallocate regulators allocated with devm_regulator_bulk_get(). Normally
364da279e69SMatti Vaittinen  * this function will not need to be called and the resource management
365da279e69SMatti Vaittinen  * code will ensure that the resource is freed.
366da279e69SMatti Vaittinen  */
devm_regulator_bulk_put(struct regulator_bulk_data * consumers)367da279e69SMatti Vaittinen void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)
368da279e69SMatti Vaittinen {
369da279e69SMatti Vaittinen 	int rc;
370da279e69SMatti Vaittinen 	struct regulator *regulator = consumers[0].consumer;
371da279e69SMatti Vaittinen 
372da279e69SMatti Vaittinen 	rc = devres_release(regulator->dev, devm_regulator_bulk_release,
373da279e69SMatti Vaittinen 			    devm_regulator_bulk_match, consumers);
374da279e69SMatti Vaittinen 	if (rc != 0)
375da279e69SMatti Vaittinen 		WARN_ON(rc);
376da279e69SMatti Vaittinen }
377da279e69SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_bulk_put);
378da279e69SMatti Vaittinen 
devm_regulator_bulk_disable(void * res)379da279e69SMatti Vaittinen static void devm_regulator_bulk_disable(void *res)
380da279e69SMatti Vaittinen {
381da279e69SMatti Vaittinen 	struct regulator_bulk_devres *devres = res;
382da279e69SMatti Vaittinen 	int i;
383da279e69SMatti Vaittinen 
384da279e69SMatti Vaittinen 	for (i = 0; i < devres->num_consumers; i++)
385da279e69SMatti Vaittinen 		regulator_disable(devres->consumers[i].consumer);
386da279e69SMatti Vaittinen }
387da279e69SMatti Vaittinen 
388da279e69SMatti Vaittinen /**
389da279e69SMatti Vaittinen  * devm_regulator_bulk_get_enable - managed get'n enable multiple regulators
390da279e69SMatti Vaittinen  *
391da279e69SMatti Vaittinen  * @dev:           device to supply
392da279e69SMatti Vaittinen  * @num_consumers: number of consumers to register
393da279e69SMatti Vaittinen  * @id:            list of supply names or regulator IDs
394da279e69SMatti Vaittinen  *
39598ce82a5SChen-Yu Tsai  * @return 0 on success, a negative error number on failure.
396da279e69SMatti Vaittinen  *
397da279e69SMatti Vaittinen  * This helper function allows drivers to get several regulator
398da279e69SMatti Vaittinen  * consumers in one operation with management, the regulators will
399da279e69SMatti Vaittinen  * automatically be freed when the device is unbound.  If any of the
400da279e69SMatti Vaittinen  * regulators cannot be acquired then any regulators that were
401da279e69SMatti Vaittinen  * allocated will be freed before returning to the caller.
402da279e69SMatti Vaittinen  */
devm_regulator_bulk_get_enable(struct device * dev,int num_consumers,const char * const * id)403da279e69SMatti Vaittinen int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,
404da279e69SMatti Vaittinen 				   const char * const *id)
405da279e69SMatti Vaittinen {
406da279e69SMatti Vaittinen 	struct regulator_bulk_devres *devres;
407da279e69SMatti Vaittinen 	struct regulator_bulk_data *consumers;
408da279e69SMatti Vaittinen 	int i, ret;
409da279e69SMatti Vaittinen 
410da279e69SMatti Vaittinen 	devres = devm_kmalloc(dev, sizeof(*devres), GFP_KERNEL);
411da279e69SMatti Vaittinen 	if (!devres)
412da279e69SMatti Vaittinen 		return -ENOMEM;
413da279e69SMatti Vaittinen 
414da279e69SMatti Vaittinen 	devres->consumers = devm_kcalloc(dev, num_consumers, sizeof(*consumers),
415da279e69SMatti Vaittinen 					 GFP_KERNEL);
416da279e69SMatti Vaittinen 	consumers = devres->consumers;
417da279e69SMatti Vaittinen 	if (!consumers)
418da279e69SMatti Vaittinen 		return -ENOMEM;
419da279e69SMatti Vaittinen 
420da279e69SMatti Vaittinen 	devres->num_consumers = num_consumers;
421da279e69SMatti Vaittinen 
422da279e69SMatti Vaittinen 	for (i = 0; i < num_consumers; i++)
423da279e69SMatti Vaittinen 		consumers[i].supply = id[i];
424da279e69SMatti Vaittinen 
425da279e69SMatti Vaittinen 	ret = devm_regulator_bulk_get(dev, num_consumers, consumers);
426da279e69SMatti Vaittinen 	if (ret)
427da279e69SMatti Vaittinen 		return ret;
428da279e69SMatti Vaittinen 
429da279e69SMatti Vaittinen 	for (i = 0; i < num_consumers; i++) {
430da279e69SMatti Vaittinen 		ret = regulator_enable(consumers[i].consumer);
431da279e69SMatti Vaittinen 		if (ret)
432da279e69SMatti Vaittinen 			goto unwind;
433da279e69SMatti Vaittinen 	}
434da279e69SMatti Vaittinen 
435da279e69SMatti Vaittinen 	ret = devm_add_action(dev, devm_regulator_bulk_disable, devres);
436da279e69SMatti Vaittinen 	if (!ret)
437da279e69SMatti Vaittinen 		return 0;
438da279e69SMatti Vaittinen 
439da279e69SMatti Vaittinen unwind:
440da279e69SMatti Vaittinen 	while (--i >= 0)
441da279e69SMatti Vaittinen 		regulator_disable(consumers[i].consumer);
442da279e69SMatti Vaittinen 
443da279e69SMatti Vaittinen 	devm_regulator_bulk_put(consumers);
444da279e69SMatti Vaittinen 
445da279e69SMatti Vaittinen 	return ret;
446da279e69SMatti Vaittinen }
447da279e69SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_enable);
448da279e69SMatti Vaittinen 
devm_rdev_release(struct device * dev,void * res)4490cdfcc0fSMark Brown static void devm_rdev_release(struct device *dev, void *res)
4500cdfcc0fSMark Brown {
4510cdfcc0fSMark Brown 	regulator_unregister(*(struct regulator_dev **)res);
4520cdfcc0fSMark Brown }
4530cdfcc0fSMark Brown 
4540cdfcc0fSMark Brown /**
4550cdfcc0fSMark Brown  * devm_regulator_register - Resource managed regulator_register()
4569565cccdSLee Jones  * @dev:            device to supply
4570cdfcc0fSMark Brown  * @regulator_desc: regulator to register
4580cdfcc0fSMark Brown  * @config:         runtime configuration for regulator
4590cdfcc0fSMark Brown  *
4600cdfcc0fSMark Brown  * Called by regulator drivers to register a regulator.  Returns a
4610cdfcc0fSMark Brown  * valid pointer to struct regulator_dev on success or an ERR_PTR() on
4620cdfcc0fSMark Brown  * error.  The regulator will automatically be released when the device
4630cdfcc0fSMark Brown  * is unbound.
4640cdfcc0fSMark Brown  */
devm_regulator_register(struct device * dev,const struct regulator_desc * regulator_desc,const struct regulator_config * config)4650cdfcc0fSMark Brown struct regulator_dev *devm_regulator_register(struct device *dev,
4660cdfcc0fSMark Brown 				  const struct regulator_desc *regulator_desc,
4670cdfcc0fSMark Brown 				  const struct regulator_config *config)
4680cdfcc0fSMark Brown {
4690cdfcc0fSMark Brown 	struct regulator_dev **ptr, *rdev;
4700cdfcc0fSMark Brown 
4710cdfcc0fSMark Brown 	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
4720cdfcc0fSMark Brown 			   GFP_KERNEL);
4730cdfcc0fSMark Brown 	if (!ptr)
4740cdfcc0fSMark Brown 		return ERR_PTR(-ENOMEM);
4750cdfcc0fSMark Brown 
4768f3cbcd6SChiYuan Huang 	rdev = regulator_register(dev, regulator_desc, config);
4770cdfcc0fSMark Brown 	if (!IS_ERR(rdev)) {
4780cdfcc0fSMark Brown 		*ptr = rdev;
4790cdfcc0fSMark Brown 		devres_add(dev, ptr);
4800cdfcc0fSMark Brown 	} else {
4810cdfcc0fSMark Brown 		devres_free(ptr);
4820cdfcc0fSMark Brown 	}
4830cdfcc0fSMark Brown 
4840cdfcc0fSMark Brown 	return rdev;
4850cdfcc0fSMark Brown }
4860cdfcc0fSMark Brown EXPORT_SYMBOL_GPL(devm_regulator_register);
4870cdfcc0fSMark Brown 
488a06ccd9cSCharles Keepax struct regulator_supply_alias_match {
489a06ccd9cSCharles Keepax 	struct device *dev;
490a06ccd9cSCharles Keepax 	const char *id;
491a06ccd9cSCharles Keepax };
492a06ccd9cSCharles Keepax 
devm_regulator_match_supply_alias(struct device * dev,void * res,void * data)493a06ccd9cSCharles Keepax static int devm_regulator_match_supply_alias(struct device *dev, void *res,
494a06ccd9cSCharles Keepax 					     void *data)
495a06ccd9cSCharles Keepax {
496a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
497a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *target = data;
498a06ccd9cSCharles Keepax 
499a06ccd9cSCharles Keepax 	return match->dev == target->dev && strcmp(match->id, target->id) == 0;
500a06ccd9cSCharles Keepax }
501a06ccd9cSCharles Keepax 
devm_regulator_destroy_supply_alias(struct device * dev,void * res)502a06ccd9cSCharles Keepax static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
503a06ccd9cSCharles Keepax {
504a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match = res;
505a06ccd9cSCharles Keepax 
506a06ccd9cSCharles Keepax 	regulator_unregister_supply_alias(match->dev, match->id);
507a06ccd9cSCharles Keepax }
508a06ccd9cSCharles Keepax 
509a06ccd9cSCharles Keepax /**
510a06ccd9cSCharles Keepax  * devm_regulator_register_supply_alias - Resource managed
511a06ccd9cSCharles Keepax  * regulator_register_supply_alias()
512a06ccd9cSCharles Keepax  *
513a7c15187SLee Jones  * @dev:       device to supply
514a7c15187SLee Jones  * @id:        supply name or regulator ID
515a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
516a7c15187SLee Jones  * @alias_id:  supply name or regulator ID that should be used to lookup the
517a06ccd9cSCharles Keepax  * supply
518a06ccd9cSCharles Keepax  *
519a06ccd9cSCharles Keepax  * The supply alias will automatically be unregistered when the source
520a06ccd9cSCharles Keepax  * device is unbound.
521a06ccd9cSCharles Keepax  */
devm_regulator_register_supply_alias(struct device * dev,const char * id,struct device * alias_dev,const char * alias_id)522a06ccd9cSCharles Keepax int devm_regulator_register_supply_alias(struct device *dev, const char *id,
523a06ccd9cSCharles Keepax 					 struct device *alias_dev,
524a06ccd9cSCharles Keepax 					 const char *alias_id)
525a06ccd9cSCharles Keepax {
526a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match *match;
527a06ccd9cSCharles Keepax 	int ret;
528a06ccd9cSCharles Keepax 
529a06ccd9cSCharles Keepax 	match = devres_alloc(devm_regulator_destroy_supply_alias,
530a06ccd9cSCharles Keepax 			   sizeof(struct regulator_supply_alias_match),
531a06ccd9cSCharles Keepax 			   GFP_KERNEL);
532a06ccd9cSCharles Keepax 	if (!match)
533a06ccd9cSCharles Keepax 		return -ENOMEM;
534a06ccd9cSCharles Keepax 
535a06ccd9cSCharles Keepax 	match->dev = dev;
536a06ccd9cSCharles Keepax 	match->id = id;
537a06ccd9cSCharles Keepax 
538a06ccd9cSCharles Keepax 	ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
539a06ccd9cSCharles Keepax 	if (ret < 0) {
540a06ccd9cSCharles Keepax 		devres_free(match);
541a06ccd9cSCharles Keepax 		return ret;
542a06ccd9cSCharles Keepax 	}
543a06ccd9cSCharles Keepax 
544a06ccd9cSCharles Keepax 	devres_add(dev, match);
545a06ccd9cSCharles Keepax 
546a06ccd9cSCharles Keepax 	return 0;
547a06ccd9cSCharles Keepax }
548a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
549a06ccd9cSCharles Keepax 
devm_regulator_unregister_supply_alias(struct device * dev,const char * id)5504d9f4d1dSAlexandru Ardelean static void devm_regulator_unregister_supply_alias(struct device *dev,
5514d9f4d1dSAlexandru Ardelean 						   const char *id)
552a06ccd9cSCharles Keepax {
553a06ccd9cSCharles Keepax 	struct regulator_supply_alias_match match;
554a06ccd9cSCharles Keepax 	int rc;
555a06ccd9cSCharles Keepax 
556a06ccd9cSCharles Keepax 	match.dev = dev;
557a06ccd9cSCharles Keepax 	match.id = id;
558a06ccd9cSCharles Keepax 
559a06ccd9cSCharles Keepax 	rc = devres_release(dev, devm_regulator_destroy_supply_alias,
560a06ccd9cSCharles Keepax 			    devm_regulator_match_supply_alias, &match);
561a06ccd9cSCharles Keepax 	if (rc != 0)
562a06ccd9cSCharles Keepax 		WARN_ON(rc);
563a06ccd9cSCharles Keepax }
564a06ccd9cSCharles Keepax 
565a06ccd9cSCharles Keepax /**
566a06ccd9cSCharles Keepax  * devm_regulator_bulk_register_supply_alias - Managed register
567a06ccd9cSCharles Keepax  * multiple aliases
568a06ccd9cSCharles Keepax  *
569a7c15187SLee Jones  * @dev:       device to supply
570a7c15187SLee Jones  * @id:        list of supply names or regulator IDs
571a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
572a7c15187SLee Jones  * @alias_id:  list of supply names or regulator IDs that should be used to
573a06ccd9cSCharles Keepax  *             lookup the supply
574a7c15187SLee Jones  * @num_id:    number of aliases to register
575a06ccd9cSCharles Keepax  *
57698ce82a5SChen-Yu Tsai  * @return 0 on success, a negative error number on failure.
577a06ccd9cSCharles Keepax  *
578a06ccd9cSCharles Keepax  * This helper function allows drivers to register several supply
579a06ccd9cSCharles Keepax  * aliases in one operation, the aliases will be automatically
580a06ccd9cSCharles Keepax  * unregisters when the source device is unbound.  If any of the
581a06ccd9cSCharles Keepax  * aliases cannot be registered any aliases that were registered
582a06ccd9cSCharles Keepax  * will be removed before returning to the caller.
583a06ccd9cSCharles 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)584a06ccd9cSCharles Keepax int devm_regulator_bulk_register_supply_alias(struct device *dev,
5859f8c0fe9SLee Jones 					      const char *const *id,
586a06ccd9cSCharles Keepax 					      struct device *alias_dev,
5879f8c0fe9SLee Jones 					      const char *const *alias_id,
588a06ccd9cSCharles Keepax 					      int num_id)
589a06ccd9cSCharles Keepax {
590a06ccd9cSCharles Keepax 	int i;
591a06ccd9cSCharles Keepax 	int ret;
592a06ccd9cSCharles Keepax 
593a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i) {
594a06ccd9cSCharles Keepax 		ret = devm_regulator_register_supply_alias(dev, id[i],
595a06ccd9cSCharles Keepax 							   alias_dev,
596a06ccd9cSCharles Keepax 							   alias_id[i]);
597a06ccd9cSCharles Keepax 		if (ret < 0)
598a06ccd9cSCharles Keepax 			goto err;
599a06ccd9cSCharles Keepax 	}
600a06ccd9cSCharles Keepax 
601a06ccd9cSCharles Keepax 	return 0;
602a06ccd9cSCharles Keepax 
603a06ccd9cSCharles Keepax err:
604a06ccd9cSCharles Keepax 	dev_err(dev,
605a06ccd9cSCharles Keepax 		"Failed to create supply alias %s,%s -> %s,%s\n",
606a06ccd9cSCharles Keepax 		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
607a06ccd9cSCharles Keepax 
608a06ccd9cSCharles Keepax 	while (--i >= 0)
609a06ccd9cSCharles Keepax 		devm_regulator_unregister_supply_alias(dev, id[i]);
610a06ccd9cSCharles Keepax 
611a06ccd9cSCharles Keepax 	return ret;
612a06ccd9cSCharles Keepax }
613a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
614a06ccd9cSCharles Keepax 
615046db763SCharles Keepax struct regulator_notifier_match {
616046db763SCharles Keepax 	struct regulator *regulator;
617046db763SCharles Keepax 	struct notifier_block *nb;
618046db763SCharles Keepax };
619046db763SCharles Keepax 
devm_regulator_match_notifier(struct device * dev,void * res,void * data)620046db763SCharles Keepax static int devm_regulator_match_notifier(struct device *dev, void *res,
621046db763SCharles Keepax 					 void *data)
622046db763SCharles Keepax {
623046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
624046db763SCharles Keepax 	struct regulator_notifier_match *target = data;
625046db763SCharles Keepax 
626046db763SCharles Keepax 	return match->regulator == target->regulator && match->nb == target->nb;
627046db763SCharles Keepax }
628046db763SCharles Keepax 
devm_regulator_destroy_notifier(struct device * dev,void * res)629046db763SCharles Keepax static void devm_regulator_destroy_notifier(struct device *dev, void *res)
630046db763SCharles Keepax {
631046db763SCharles Keepax 	struct regulator_notifier_match *match = res;
632046db763SCharles Keepax 
633046db763SCharles Keepax 	regulator_unregister_notifier(match->regulator, match->nb);
634046db763SCharles Keepax }
635046db763SCharles Keepax 
636046db763SCharles Keepax /**
637046db763SCharles Keepax  * devm_regulator_register_notifier - Resource managed
638046db763SCharles Keepax  * regulator_register_notifier
639046db763SCharles Keepax  *
640046db763SCharles Keepax  * @regulator: regulator source
641046db763SCharles Keepax  * @nb:        notifier block
642046db763SCharles Keepax  *
643046db763SCharles Keepax  * The notifier will be registers under the consumer device and be
644046db763SCharles Keepax  * automatically be unregistered when the source device is unbound.
645046db763SCharles Keepax  */
devm_regulator_register_notifier(struct regulator * regulator,struct notifier_block * nb)646046db763SCharles Keepax int devm_regulator_register_notifier(struct regulator *regulator,
647046db763SCharles Keepax 				     struct notifier_block *nb)
648046db763SCharles Keepax {
649046db763SCharles Keepax 	struct regulator_notifier_match *match;
650046db763SCharles Keepax 	int ret;
651046db763SCharles Keepax 
652046db763SCharles Keepax 	match = devres_alloc(devm_regulator_destroy_notifier,
653046db763SCharles Keepax 			     sizeof(struct regulator_notifier_match),
654046db763SCharles Keepax 			     GFP_KERNEL);
655046db763SCharles Keepax 	if (!match)
656046db763SCharles Keepax 		return -ENOMEM;
657046db763SCharles Keepax 
658046db763SCharles Keepax 	match->regulator = regulator;
659046db763SCharles Keepax 	match->nb = nb;
660046db763SCharles Keepax 
661046db763SCharles Keepax 	ret = regulator_register_notifier(regulator, nb);
662046db763SCharles Keepax 	if (ret < 0) {
663046db763SCharles Keepax 		devres_free(match);
664046db763SCharles Keepax 		return ret;
665046db763SCharles Keepax 	}
666046db763SCharles Keepax 
667046db763SCharles Keepax 	devres_add(regulator->dev, match);
668046db763SCharles Keepax 
669046db763SCharles Keepax 	return 0;
670046db763SCharles Keepax }
671046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_register_notifier);
672046db763SCharles Keepax 
673046db763SCharles Keepax /**
674046db763SCharles Keepax  * devm_regulator_unregister_notifier - Resource managed
675046db763SCharles Keepax  * regulator_unregister_notifier()
676046db763SCharles Keepax  *
677046db763SCharles Keepax  * @regulator: regulator source
678046db763SCharles Keepax  * @nb:        notifier block
679046db763SCharles Keepax  *
680046db763SCharles Keepax  * Unregister a notifier registered with devm_regulator_register_notifier().
681046db763SCharles Keepax  * Normally this function will not need to be called and the resource
682046db763SCharles Keepax  * management code will ensure that the resource is freed.
683046db763SCharles Keepax  */
devm_regulator_unregister_notifier(struct regulator * regulator,struct notifier_block * nb)684046db763SCharles Keepax void devm_regulator_unregister_notifier(struct regulator *regulator,
685046db763SCharles Keepax 					struct notifier_block *nb)
686046db763SCharles Keepax {
687046db763SCharles Keepax 	struct regulator_notifier_match match;
688046db763SCharles Keepax 	int rc;
689046db763SCharles Keepax 
690046db763SCharles Keepax 	match.regulator = regulator;
691046db763SCharles Keepax 	match.nb = nb;
692046db763SCharles Keepax 
693046db763SCharles Keepax 	rc = devres_release(regulator->dev, devm_regulator_destroy_notifier,
694046db763SCharles Keepax 			    devm_regulator_match_notifier, &match);
695046db763SCharles Keepax 	if (rc != 0)
696046db763SCharles Keepax 		WARN_ON(rc);
697046db763SCharles Keepax }
698046db763SCharles Keepax EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);
6997111c6d1SMatti Vaittinen 
regulator_irq_helper_drop(void * res)7007111c6d1SMatti Vaittinen static void regulator_irq_helper_drop(void *res)
7017111c6d1SMatti Vaittinen {
7027111c6d1SMatti Vaittinen 	regulator_irq_helper_cancel(&res);
7037111c6d1SMatti Vaittinen }
7047111c6d1SMatti Vaittinen 
7057111c6d1SMatti Vaittinen /**
7067111c6d1SMatti Vaittinen  * devm_regulator_irq_helper - resource managed registration of IRQ based
7077111c6d1SMatti Vaittinen  * regulator event/error notifier
7087111c6d1SMatti Vaittinen  *
7097111c6d1SMatti Vaittinen  * @dev:		device to which lifetime the helper's lifetime is
7107111c6d1SMatti Vaittinen  *			bound.
7117111c6d1SMatti Vaittinen  * @d:			IRQ helper descriptor.
7127111c6d1SMatti Vaittinen  * @irq:		IRQ used to inform events/errors to be notified.
7137111c6d1SMatti Vaittinen  * @irq_flags:		Extra IRQ flags to be OR'ed with the default
7147111c6d1SMatti Vaittinen  *			IRQF_ONESHOT when requesting the (threaded) irq.
7157111c6d1SMatti Vaittinen  * @common_errs:	Errors which can be flagged by this IRQ for all rdevs.
7167111c6d1SMatti Vaittinen  *			When IRQ is re-enabled these errors will be cleared
7177111c6d1SMatti Vaittinen  *			from all associated regulators
7187111c6d1SMatti Vaittinen  * @per_rdev_errs:	Optional error flag array describing errors specific
7197111c6d1SMatti Vaittinen  *			for only some of the regulators. These errors will be
7207111c6d1SMatti Vaittinen  *			or'ed with common errors. If this is given the array
7217111c6d1SMatti Vaittinen  *			should contain rdev_amount flags. Can be set to NULL
7227111c6d1SMatti Vaittinen  *			if there is no regulator specific error flags for this
7237111c6d1SMatti Vaittinen  *			IRQ.
7247111c6d1SMatti Vaittinen  * @rdev:		Array of pointers to regulators associated with this
7257111c6d1SMatti Vaittinen  *			IRQ.
7267111c6d1SMatti Vaittinen  * @rdev_amount:	Amount of regulators associated with this IRQ.
7277111c6d1SMatti Vaittinen  *
72898ce82a5SChen-Yu Tsai  * Return: handle to irq_helper or an ERR_PTR() encoded negative error number.
7297111c6d1SMatti 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)7307111c6d1SMatti Vaittinen void *devm_regulator_irq_helper(struct device *dev,
7317111c6d1SMatti Vaittinen 				const struct regulator_irq_desc *d, int irq,
7327111c6d1SMatti Vaittinen 				int irq_flags, int common_errs,
7337111c6d1SMatti Vaittinen 				int *per_rdev_errs,
7347111c6d1SMatti Vaittinen 				struct regulator_dev **rdev, int rdev_amount)
7357111c6d1SMatti Vaittinen {
7367111c6d1SMatti Vaittinen 	void *ptr;
7377111c6d1SMatti Vaittinen 	int ret;
7387111c6d1SMatti Vaittinen 
7397111c6d1SMatti Vaittinen 	ptr = regulator_irq_helper(dev, d, irq, irq_flags, common_errs,
7407111c6d1SMatti Vaittinen 				    per_rdev_errs, rdev, rdev_amount);
7417111c6d1SMatti Vaittinen 	if (IS_ERR(ptr))
7427111c6d1SMatti Vaittinen 		return ptr;
7437111c6d1SMatti Vaittinen 
7447111c6d1SMatti Vaittinen 	ret = devm_add_action_or_reset(dev, regulator_irq_helper_drop, ptr);
7457111c6d1SMatti Vaittinen 	if (ret)
7467111c6d1SMatti Vaittinen 		return ERR_PTR(ret);
7477111c6d1SMatti Vaittinen 
7487111c6d1SMatti Vaittinen 	return ptr;
7497111c6d1SMatti Vaittinen }
7507111c6d1SMatti Vaittinen EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);
75136ec3f43SChen-Yu Tsai 
75236ec3f43SChen-Yu Tsai #if IS_ENABLED(CONFIG_OF)
_devm_of_regulator_get(struct device * dev,struct device_node * node,const char * id,int get_type)75336ec3f43SChen-Yu Tsai static struct regulator *_devm_of_regulator_get(struct device *dev, struct device_node *node,
75436ec3f43SChen-Yu Tsai 						const char *id, int get_type)
75536ec3f43SChen-Yu Tsai {
75636ec3f43SChen-Yu Tsai 	struct regulator **ptr, *regulator;
75736ec3f43SChen-Yu Tsai 
75836ec3f43SChen-Yu Tsai 	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
75936ec3f43SChen-Yu Tsai 	if (!ptr)
76036ec3f43SChen-Yu Tsai 		return ERR_PTR(-ENOMEM);
76136ec3f43SChen-Yu Tsai 
76236ec3f43SChen-Yu Tsai 	regulator = _of_regulator_get(dev, node, id, get_type);
76336ec3f43SChen-Yu Tsai 	if (!IS_ERR(regulator)) {
76436ec3f43SChen-Yu Tsai 		*ptr = regulator;
76536ec3f43SChen-Yu Tsai 		devres_add(dev, ptr);
76636ec3f43SChen-Yu Tsai 	} else {
76736ec3f43SChen-Yu Tsai 		devres_free(ptr);
76836ec3f43SChen-Yu Tsai 	}
76936ec3f43SChen-Yu Tsai 
77036ec3f43SChen-Yu Tsai 	return regulator;
77136ec3f43SChen-Yu Tsai }
77236ec3f43SChen-Yu Tsai 
77336ec3f43SChen-Yu Tsai /**
77436ec3f43SChen-Yu Tsai  * devm_of_regulator_get - Resource managed of_regulator_get()
77536ec3f43SChen-Yu Tsai  * @dev: device used for dev_printk() messages and resource lifetime management
77636ec3f43SChen-Yu Tsai  * @node: device node for regulator "consumer"
77736ec3f43SChen-Yu Tsai  * @id:  supply name or regulator ID.
77836ec3f43SChen-Yu Tsai  *
77936ec3f43SChen-Yu Tsai  * Managed of_regulator_get(). Regulators returned from this
78036ec3f43SChen-Yu Tsai  * function are automatically regulator_put() on driver detach. See
78136ec3f43SChen-Yu Tsai  * of_regulator_get() for more information.
78236ec3f43SChen-Yu Tsai  */
devm_of_regulator_get(struct device * dev,struct device_node * node,const char * id)78336ec3f43SChen-Yu Tsai struct regulator *devm_of_regulator_get(struct device *dev, struct device_node *node,
78436ec3f43SChen-Yu Tsai 						 const char *id)
78536ec3f43SChen-Yu Tsai {
78636ec3f43SChen-Yu Tsai 	return _devm_of_regulator_get(dev, node, id, NORMAL_GET);
78736ec3f43SChen-Yu Tsai }
78836ec3f43SChen-Yu Tsai EXPORT_SYMBOL_GPL(devm_of_regulator_get);
78936ec3f43SChen-Yu Tsai 
790 /**
791  * devm_of_regulator_get_optional - Resource managed of_regulator_get_optional()
792  * @dev: device used for dev_printk() messages and resource lifetime management
793  * @node: device node for regulator "consumer"
794  * @id:  supply name or regulator ID.
795  *
796  * Managed regulator_get_optional(). Regulators returned from this
797  * function are automatically regulator_put() on driver detach. See
798  * of_regulator_get_optional() for more information.
799  */
devm_of_regulator_get_optional(struct device * dev,struct device_node * node,const char * id)800 struct regulator *devm_of_regulator_get_optional(struct device *dev, struct device_node *node,
801 						 const char *id)
802 {
803 	return _devm_of_regulator_get(dev, node, id, OPTIONAL_GET);
804 }
805 EXPORT_SYMBOL_GPL(devm_of_regulator_get_optional);
806 #endif
807