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