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, ®ulator_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