xref: /openbmc/linux/drivers/regulator/core.c (revision 2874c5fd)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2414c70cbSLiam Girdwood /*
3414c70cbSLiam Girdwood  * core.c  --  Voltage/Current Regulator framework.
4414c70cbSLiam Girdwood  *
5414c70cbSLiam Girdwood  * Copyright 2007, 2008 Wolfson Microelectronics PLC.
6a5766f11SLiam Girdwood  * Copyright 2008 SlimLogic Ltd.
7414c70cbSLiam Girdwood  *
8a5766f11SLiam Girdwood  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
9414c70cbSLiam Girdwood  */
10414c70cbSLiam Girdwood 
11414c70cbSLiam Girdwood #include <linux/kernel.h>
12414c70cbSLiam Girdwood #include <linux/init.h>
131130e5b3SMark Brown #include <linux/debugfs.h>
14414c70cbSLiam Girdwood #include <linux/device.h>
155a0e3ad6STejun Heo #include <linux/slab.h>
16f21e0e81SMark Brown #include <linux/async.h>
17414c70cbSLiam Girdwood #include <linux/err.h>
18414c70cbSLiam Girdwood #include <linux/mutex.h>
19414c70cbSLiam Girdwood #include <linux/suspend.h>
2031aae2beSMark Brown #include <linux/delay.h>
21778b28b4SRussell King #include <linux/gpio/consumer.h>
2269511a45SRajendra Nayak #include <linux/of.h>
2365b19ce6SMark Brown #include <linux/regmap.h>
2469511a45SRajendra Nayak #include <linux/regulator/of_regulator.h>
25414c70cbSLiam Girdwood #include <linux/regulator/consumer.h>
26414c70cbSLiam Girdwood #include <linux/regulator/driver.h>
27414c70cbSLiam Girdwood #include <linux/regulator/machine.h>
2865602c32SPaul Gortmaker #include <linux/module.h>
29414c70cbSLiam Girdwood 
3002fa3ec0SMark Brown #define CREATE_TRACE_POINTS
3102fa3ec0SMark Brown #include <trace/events/regulator.h>
3202fa3ec0SMark Brown 
3334abbd68SMark Brown #include "dummy.h"
340cdfcc0fSMark Brown #include "internal.h"
3534abbd68SMark Brown 
367d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...)					\
377d51a0dbSMark Brown 	pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
385da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...)					\
395da84fd9SJoe Perches 	pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
405da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...)					\
415da84fd9SJoe Perches 	pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
425da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...)					\
435da84fd9SJoe Perches 	pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
445da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...)					\
455da84fd9SJoe Perches 	pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
465da84fd9SJoe Perches 
47f8702f9eSDmitry Osipenko static DEFINE_WW_CLASS(regulator_ww_class);
48f8702f9eSDmitry Osipenko static DEFINE_MUTEX(regulator_nesting_mutex);
49414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex);
50414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list);
51f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list);
52a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list);
5321cf891aSMark Brown static bool has_full_constraints;
54414c70cbSLiam Girdwood 
551130e5b3SMark Brown static struct dentry *debugfs_root;
561130e5b3SMark Brown 
578dc5390dSMark Brown /*
58414c70cbSLiam Girdwood  * struct regulator_map
59414c70cbSLiam Girdwood  *
60414c70cbSLiam Girdwood  * Used to provide symbolic supply names to devices.
61414c70cbSLiam Girdwood  */
62414c70cbSLiam Girdwood struct regulator_map {
63414c70cbSLiam Girdwood 	struct list_head list;
6440f9244fSMark Brown 	const char *dev_name;   /* The dev_name() for the consumer */
65414c70cbSLiam Girdwood 	const char *supply;
66a5766f11SLiam Girdwood 	struct regulator_dev *regulator;
67414c70cbSLiam Girdwood };
68414c70cbSLiam Girdwood 
69414c70cbSLiam Girdwood /*
70f19b00daSKim, Milo  * struct regulator_enable_gpio
71f19b00daSKim, Milo  *
72f19b00daSKim, Milo  * Management for shared enable GPIO pin
73f19b00daSKim, Milo  */
74f19b00daSKim, Milo struct regulator_enable_gpio {
75f19b00daSKim, Milo 	struct list_head list;
76778b28b4SRussell King 	struct gpio_desc *gpiod;
77f19b00daSKim, Milo 	u32 enable_count;	/* a number of enabled shared GPIO */
78f19b00daSKim, Milo 	u32 request_count;	/* a number of requested shared GPIO */
79f19b00daSKim, Milo };
80f19b00daSKim, Milo 
81a06ccd9cSCharles Keepax /*
82a06ccd9cSCharles Keepax  * struct regulator_supply_alias
83a06ccd9cSCharles Keepax  *
84a06ccd9cSCharles Keepax  * Used to map lookups for a supply onto an alternative device.
85a06ccd9cSCharles Keepax  */
86a06ccd9cSCharles Keepax struct regulator_supply_alias {
87a06ccd9cSCharles Keepax 	struct list_head list;
88a06ccd9cSCharles Keepax 	struct device *src_dev;
89a06ccd9cSCharles Keepax 	const char *src_supply;
90a06ccd9cSCharles Keepax 	struct device *alias_dev;
91a06ccd9cSCharles Keepax 	const char *alias_supply;
92a06ccd9cSCharles Keepax };
93a06ccd9cSCharles Keepax 
94414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev);
955451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator);
96414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev);
97414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev);
98414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
997179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev,
100414c70cbSLiam Girdwood 				  unsigned long event, void *data);
10175790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
10275790251SMark Brown 				     int min_uV, int max_uV);
103c054c6c7SMaciej Purski static int regulator_balance_voltage(struct regulator_dev *rdev,
104c054c6c7SMaciej Purski 				     suspend_state_t state);
1059243a195SMaciej Purski static int regulator_set_voltage_rdev(struct regulator_dev *rdev,
1069243a195SMaciej Purski 				      int min_uV, int max_uV,
1079243a195SMaciej Purski 				      suspend_state_t state);
1083801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev,
1093801b86aSMark Brown 					  struct device *dev,
1103801b86aSMark Brown 					  const char *supply_name);
11136a1f1b6SJavier Martinez Canillas static void _regulator_put(struct regulator *regulator);
112414c70cbSLiam Girdwood 
1131083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev)
1141083c393SMark Brown {
1151083c393SMark Brown 	if (rdev->constraints && rdev->constraints->name)
1161083c393SMark Brown 		return rdev->constraints->name;
1171083c393SMark Brown 	else if (rdev->desc->name)
1181083c393SMark Brown 		return rdev->desc->name;
1191083c393SMark Brown 	else
1201083c393SMark Brown 		return "";
1211083c393SMark Brown }
1221083c393SMark Brown 
12387b28417SMark Brown static bool have_full_constraints(void)
12487b28417SMark Brown {
12575bc9641SMark Brown 	return has_full_constraints || of_have_populated_dt();
12687b28417SMark Brown }
12787b28417SMark Brown 
1288a34e979SWEN Pingbo static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops)
1298a34e979SWEN Pingbo {
1308a34e979SWEN Pingbo 	if (!rdev->constraints) {
1318a34e979SWEN Pingbo 		rdev_err(rdev, "no constraints\n");
1328a34e979SWEN Pingbo 		return false;
1338a34e979SWEN Pingbo 	}
1348a34e979SWEN Pingbo 
1358a34e979SWEN Pingbo 	if (rdev->constraints->valid_ops_mask & ops)
1368a34e979SWEN Pingbo 		return true;
1378a34e979SWEN Pingbo 
1388a34e979SWEN Pingbo 	return false;
1398a34e979SWEN Pingbo }
1408a34e979SWEN Pingbo 
14169511a45SRajendra Nayak /**
14266cf9a7eSMaciej Purski  * regulator_lock_nested - lock a single regulator
14366cf9a7eSMaciej Purski  * @rdev:		regulator source
144f8702f9eSDmitry Osipenko  * @ww_ctx:		w/w mutex acquire context
14566cf9a7eSMaciej Purski  *
14666cf9a7eSMaciej Purski  * This function can be called many times by one task on
14766cf9a7eSMaciej Purski  * a single regulator and its mutex will be locked only
14866cf9a7eSMaciej Purski  * once. If a task, which is calling this function is other
14966cf9a7eSMaciej Purski  * than the one, which initially locked the mutex, it will
15066cf9a7eSMaciej Purski  * wait on mutex.
15166cf9a7eSMaciej Purski  */
152f8702f9eSDmitry Osipenko static inline int regulator_lock_nested(struct regulator_dev *rdev,
153f8702f9eSDmitry Osipenko 					struct ww_acquire_ctx *ww_ctx)
15466cf9a7eSMaciej Purski {
155f8702f9eSDmitry Osipenko 	bool lock = false;
156f8702f9eSDmitry Osipenko 	int ret = 0;
157f8702f9eSDmitry Osipenko 
158f8702f9eSDmitry Osipenko 	mutex_lock(&regulator_nesting_mutex);
159f8702f9eSDmitry Osipenko 
160f8702f9eSDmitry Osipenko 	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
161f8702f9eSDmitry Osipenko 		if (rdev->mutex_owner == current)
16266cf9a7eSMaciej Purski 			rdev->ref_cnt++;
163f8702f9eSDmitry Osipenko 		else
164f8702f9eSDmitry Osipenko 			lock = true;
165f8702f9eSDmitry Osipenko 
166f8702f9eSDmitry Osipenko 		if (lock) {
167f8702f9eSDmitry Osipenko 			mutex_unlock(&regulator_nesting_mutex);
168f8702f9eSDmitry Osipenko 			ret = ww_mutex_lock(&rdev->mutex, ww_ctx);
169f8702f9eSDmitry Osipenko 			mutex_lock(&regulator_nesting_mutex);
17066cf9a7eSMaciej Purski 		}
171f8702f9eSDmitry Osipenko 	} else {
172f8702f9eSDmitry Osipenko 		lock = true;
17366cf9a7eSMaciej Purski 	}
17466cf9a7eSMaciej Purski 
175f8702f9eSDmitry Osipenko 	if (lock && ret != -EDEADLK) {
176f8702f9eSDmitry Osipenko 		rdev->ref_cnt++;
17766cf9a7eSMaciej Purski 		rdev->mutex_owner = current;
17866cf9a7eSMaciej Purski 	}
17966cf9a7eSMaciej Purski 
180f8702f9eSDmitry Osipenko 	mutex_unlock(&regulator_nesting_mutex);
181f8702f9eSDmitry Osipenko 
182f8702f9eSDmitry Osipenko 	return ret;
183f8702f9eSDmitry Osipenko }
184f8702f9eSDmitry Osipenko 
185f8702f9eSDmitry Osipenko /**
186f8702f9eSDmitry Osipenko  * regulator_lock - lock a single regulator
187f8702f9eSDmitry Osipenko  * @rdev:		regulator source
188f8702f9eSDmitry Osipenko  *
189f8702f9eSDmitry Osipenko  * This function can be called many times by one task on
190f8702f9eSDmitry Osipenko  * a single regulator and its mutex will be locked only
191f8702f9eSDmitry Osipenko  * once. If a task, which is calling this function is other
192f8702f9eSDmitry Osipenko  * than the one, which initially locked the mutex, it will
193f8702f9eSDmitry Osipenko  * wait on mutex.
194f8702f9eSDmitry Osipenko  */
195f8702f9eSDmitry Osipenko void regulator_lock(struct regulator_dev *rdev)
19666cf9a7eSMaciej Purski {
197f8702f9eSDmitry Osipenko 	regulator_lock_nested(rdev, NULL);
19866cf9a7eSMaciej Purski }
19914a74272SDmitry Osipenko EXPORT_SYMBOL_GPL(regulator_lock);
20066cf9a7eSMaciej Purski 
20166cf9a7eSMaciej Purski /**
20266cf9a7eSMaciej Purski  * regulator_unlock - unlock a single regulator
20366cf9a7eSMaciej Purski  * @rdev:		regulator_source
20466cf9a7eSMaciej Purski  *
20566cf9a7eSMaciej Purski  * This function unlocks the mutex when the
20666cf9a7eSMaciej Purski  * reference counter reaches 0.
20766cf9a7eSMaciej Purski  */
208f8702f9eSDmitry Osipenko void regulator_unlock(struct regulator_dev *rdev)
20966cf9a7eSMaciej Purski {
210f8702f9eSDmitry Osipenko 	mutex_lock(&regulator_nesting_mutex);
21166cf9a7eSMaciej Purski 
212f8702f9eSDmitry Osipenko 	if (--rdev->ref_cnt == 0) {
21366cf9a7eSMaciej Purski 		rdev->mutex_owner = NULL;
214f8702f9eSDmitry Osipenko 		ww_mutex_unlock(&rdev->mutex);
21566cf9a7eSMaciej Purski 	}
21666cf9a7eSMaciej Purski 
217f8702f9eSDmitry Osipenko 	WARN_ON_ONCE(rdev->ref_cnt < 0);
218f8702f9eSDmitry Osipenko 
219f8702f9eSDmitry Osipenko 	mutex_unlock(&regulator_nesting_mutex);
220f8702f9eSDmitry Osipenko }
22114a74272SDmitry Osipenko EXPORT_SYMBOL_GPL(regulator_unlock);
222f8702f9eSDmitry Osipenko 
223089e2cc2SDmitry Osipenko static bool regulator_supply_is_couple(struct regulator_dev *rdev)
2249f01cd4aSSascha Hauer {
225089e2cc2SDmitry Osipenko 	struct regulator_dev *c_rdev;
226fa731ac7SArnd Bergmann 	int i;
2279f01cd4aSSascha Hauer 
228089e2cc2SDmitry Osipenko 	for (i = 1; i < rdev->coupling_desc.n_coupled; i++) {
229089e2cc2SDmitry Osipenko 		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
230089e2cc2SDmitry Osipenko 
231089e2cc2SDmitry Osipenko 		if (rdev->supply->rdev == c_rdev)
232089e2cc2SDmitry Osipenko 			return true;
233089e2cc2SDmitry Osipenko 	}
234089e2cc2SDmitry Osipenko 
235089e2cc2SDmitry Osipenko 	return false;
236089e2cc2SDmitry Osipenko }
237089e2cc2SDmitry Osipenko 
238f8702f9eSDmitry Osipenko static void regulator_unlock_recursive(struct regulator_dev *rdev,
239f8702f9eSDmitry Osipenko 				       unsigned int n_coupled)
240f8702f9eSDmitry Osipenko {
241f8702f9eSDmitry Osipenko 	struct regulator_dev *c_rdev;
242f8702f9eSDmitry Osipenko 	int i;
243f8702f9eSDmitry Osipenko 
244f8702f9eSDmitry Osipenko 	for (i = n_coupled; i > 0; i--) {
245f8702f9eSDmitry Osipenko 		c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
246f8702f9eSDmitry Osipenko 
247f8702f9eSDmitry Osipenko 		if (!c_rdev)
248f8702f9eSDmitry Osipenko 			continue;
249f8702f9eSDmitry Osipenko 
250089e2cc2SDmitry Osipenko 		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev))
251f8702f9eSDmitry Osipenko 			regulator_unlock_recursive(
252f8702f9eSDmitry Osipenko 					c_rdev->supply->rdev,
253f8702f9eSDmitry Osipenko 					c_rdev->coupling_desc.n_coupled);
254f8702f9eSDmitry Osipenko 
255f8702f9eSDmitry Osipenko 		regulator_unlock(c_rdev);
256414c70cbSLiam Girdwood 	}
257414c70cbSLiam Girdwood }
258414c70cbSLiam Girdwood 
2599243a195SMaciej Purski static int regulator_lock_recursive(struct regulator_dev *rdev,
260f8702f9eSDmitry Osipenko 				    struct regulator_dev **new_contended_rdev,
261f8702f9eSDmitry Osipenko 				    struct regulator_dev **old_contended_rdev,
262f8702f9eSDmitry Osipenko 				    struct ww_acquire_ctx *ww_ctx)
2639f01cd4aSSascha Hauer {
2649243a195SMaciej Purski 	struct regulator_dev *c_rdev;
265f8702f9eSDmitry Osipenko 	int i, err;
2669f01cd4aSSascha Hauer 
2679243a195SMaciej Purski 	for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
2689243a195SMaciej Purski 		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
2699243a195SMaciej Purski 
2709243a195SMaciej Purski 		if (!c_rdev)
2719243a195SMaciej Purski 			continue;
2729243a195SMaciej Purski 
273f8702f9eSDmitry Osipenko 		if (c_rdev != *old_contended_rdev) {
274f8702f9eSDmitry Osipenko 			err = regulator_lock_nested(c_rdev, ww_ctx);
275f8702f9eSDmitry Osipenko 			if (err) {
276f8702f9eSDmitry Osipenko 				if (err == -EDEADLK) {
277f8702f9eSDmitry Osipenko 					*new_contended_rdev = c_rdev;
278f8702f9eSDmitry Osipenko 					goto err_unlock;
2799243a195SMaciej Purski 				}
2809243a195SMaciej Purski 
281f8702f9eSDmitry Osipenko 				/* shouldn't happen */
282f8702f9eSDmitry Osipenko 				WARN_ON_ONCE(err != -EALREADY);
283f8702f9eSDmitry Osipenko 			}
284f8702f9eSDmitry Osipenko 		} else {
285f8702f9eSDmitry Osipenko 			*old_contended_rdev = NULL;
286f8702f9eSDmitry Osipenko 		}
287f8702f9eSDmitry Osipenko 
288089e2cc2SDmitry Osipenko 		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
289f8702f9eSDmitry Osipenko 			err = regulator_lock_recursive(c_rdev->supply->rdev,
290f8702f9eSDmitry Osipenko 						       new_contended_rdev,
291f8702f9eSDmitry Osipenko 						       old_contended_rdev,
292f8702f9eSDmitry Osipenko 						       ww_ctx);
293f8702f9eSDmitry Osipenko 			if (err) {
294f8702f9eSDmitry Osipenko 				regulator_unlock(c_rdev);
295f8702f9eSDmitry Osipenko 				goto err_unlock;
296f8702f9eSDmitry Osipenko 			}
297f8702f9eSDmitry Osipenko 		}
298f8702f9eSDmitry Osipenko 	}
299f8702f9eSDmitry Osipenko 
300f8702f9eSDmitry Osipenko 	return 0;
301f8702f9eSDmitry Osipenko 
302f8702f9eSDmitry Osipenko err_unlock:
303f8702f9eSDmitry Osipenko 	regulator_unlock_recursive(rdev, i);
304f8702f9eSDmitry Osipenko 
305f8702f9eSDmitry Osipenko 	return err;
3069f01cd4aSSascha Hauer }
3079f01cd4aSSascha Hauer 
3089f01cd4aSSascha Hauer /**
3099243a195SMaciej Purski  * regulator_unlock_dependent - unlock regulator's suppliers and coupled
3109243a195SMaciej Purski  *				regulators
3119f01cd4aSSascha Hauer  * @rdev:			regulator source
312f8702f9eSDmitry Osipenko  * @ww_ctx:			w/w mutex acquire context
3139243a195SMaciej Purski  *
31448f1b4efSKrzysztof Kozlowski  * Unlock all regulators related with rdev by coupling or supplying.
3159f01cd4aSSascha Hauer  */
316f8702f9eSDmitry Osipenko static void regulator_unlock_dependent(struct regulator_dev *rdev,
317f8702f9eSDmitry Osipenko 				       struct ww_acquire_ctx *ww_ctx)
3189f01cd4aSSascha Hauer {
319f8702f9eSDmitry Osipenko 	regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled);
320f8702f9eSDmitry Osipenko 	ww_acquire_fini(ww_ctx);
3219f01cd4aSSascha Hauer }
3229f01cd4aSSascha Hauer 
3239f01cd4aSSascha Hauer /**
3249243a195SMaciej Purski  * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
3259243a195SMaciej Purski  * @rdev:			regulator source
326f8702f9eSDmitry Osipenko  * @ww_ctx:			w/w mutex acquire context
3279243a195SMaciej Purski  *
3289243a195SMaciej Purski  * This function as a wrapper on regulator_lock_recursive(), which locks
32948f1b4efSKrzysztof Kozlowski  * all regulators related with rdev by coupling or supplying.
3309243a195SMaciej Purski  */
331f8702f9eSDmitry Osipenko static void regulator_lock_dependent(struct regulator_dev *rdev,
332f8702f9eSDmitry Osipenko 				     struct ww_acquire_ctx *ww_ctx)
3339243a195SMaciej Purski {
334f8702f9eSDmitry Osipenko 	struct regulator_dev *new_contended_rdev = NULL;
335f8702f9eSDmitry Osipenko 	struct regulator_dev *old_contended_rdev = NULL;
336f8702f9eSDmitry Osipenko 	int err;
337f8702f9eSDmitry Osipenko 
338f8702f9eSDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
339f8702f9eSDmitry Osipenko 
340f8702f9eSDmitry Osipenko 	ww_acquire_init(ww_ctx, &regulator_ww_class);
341f8702f9eSDmitry Osipenko 
342f8702f9eSDmitry Osipenko 	do {
343f8702f9eSDmitry Osipenko 		if (new_contended_rdev) {
344f8702f9eSDmitry Osipenko 			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
345f8702f9eSDmitry Osipenko 			old_contended_rdev = new_contended_rdev;
346f8702f9eSDmitry Osipenko 			old_contended_rdev->ref_cnt++;
347f8702f9eSDmitry Osipenko 		}
348f8702f9eSDmitry Osipenko 
349f8702f9eSDmitry Osipenko 		err = regulator_lock_recursive(rdev,
350f8702f9eSDmitry Osipenko 					       &new_contended_rdev,
351f8702f9eSDmitry Osipenko 					       &old_contended_rdev,
352f8702f9eSDmitry Osipenko 					       ww_ctx);
353f8702f9eSDmitry Osipenko 
354f8702f9eSDmitry Osipenko 		if (old_contended_rdev)
355f8702f9eSDmitry Osipenko 			regulator_unlock(old_contended_rdev);
356f8702f9eSDmitry Osipenko 
357f8702f9eSDmitry Osipenko 	} while (err == -EDEADLK);
358f8702f9eSDmitry Osipenko 
359f8702f9eSDmitry Osipenko 	ww_acquire_done(ww_ctx);
360f8702f9eSDmitry Osipenko 
361f8702f9eSDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
362414c70cbSLiam Girdwood }
363414c70cbSLiam Girdwood 
364414c70cbSLiam Girdwood /**
365fe06051dSzoro  * of_get_child_regulator - get a child regulator device node
366fe06051dSzoro  * based on supply name
367fe06051dSzoro  * @parent: Parent device node
368fe06051dSzoro  * @prop_name: Combination regulator supply name and "-supply"
369fe06051dSzoro  *
370fe06051dSzoro  * Traverse all child nodes.
371fe06051dSzoro  * Extract the child regulator device node corresponding to the supply name.
372fe06051dSzoro  * returns the device node corresponding to the regulator if found, else
373fe06051dSzoro  * returns NULL.
374fe06051dSzoro  */
375fe06051dSzoro static struct device_node *of_get_child_regulator(struct device_node *parent,
376fe06051dSzoro 						  const char *prop_name)
377fe06051dSzoro {
378fe06051dSzoro 	struct device_node *regnode = NULL;
379fe06051dSzoro 	struct device_node *child = NULL;
380fe06051dSzoro 
381fe06051dSzoro 	for_each_child_of_node(parent, child) {
382fe06051dSzoro 		regnode = of_parse_phandle(child, prop_name, 0);
383fe06051dSzoro 
384fe06051dSzoro 		if (!regnode) {
385fe06051dSzoro 			regnode = of_get_child_regulator(child, prop_name);
386fe06051dSzoro 			if (regnode)
387fe06051dSzoro 				return regnode;
388fe06051dSzoro 		} else {
389fe06051dSzoro 			return regnode;
390fe06051dSzoro 		}
391fe06051dSzoro 	}
392fe06051dSzoro 	return NULL;
393fe06051dSzoro }
394fe06051dSzoro 
395fe06051dSzoro /**
39669511a45SRajendra Nayak  * of_get_regulator - get a regulator device node based on supply name
39769511a45SRajendra Nayak  * @dev: Device pointer for the consumer (of regulator) device
39869511a45SRajendra Nayak  * @supply: regulator supply name
39969511a45SRajendra Nayak  *
40069511a45SRajendra Nayak  * Extract the regulator device node corresponding to the supply name.
401167d41dcSMaxime Ripard  * returns the device node corresponding to the regulator if found, else
40269511a45SRajendra Nayak  * returns NULL.
40369511a45SRajendra Nayak  */
40469511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply)
40569511a45SRajendra Nayak {
40669511a45SRajendra Nayak 	struct device_node *regnode = NULL;
40769511a45SRajendra Nayak 	char prop_name[32]; /* 32 is max size of property name */
40869511a45SRajendra Nayak 
40969511a45SRajendra Nayak 	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
41069511a45SRajendra Nayak 
41169511a45SRajendra Nayak 	snprintf(prop_name, 32, "%s-supply", supply);
41269511a45SRajendra Nayak 	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
41369511a45SRajendra Nayak 
41469511a45SRajendra Nayak 	if (!regnode) {
415fe06051dSzoro 		regnode = of_get_child_regulator(dev->of_node, prop_name);
416fe06051dSzoro 		if (regnode)
417fe06051dSzoro 			return regnode;
418fe06051dSzoro 
4197799167bSRob Herring 		dev_dbg(dev, "Looking up %s property in node %pOF failed\n",
4207799167bSRob Herring 				prop_name, dev->of_node);
42169511a45SRajendra Nayak 		return NULL;
42269511a45SRajendra Nayak 	}
42369511a45SRajendra Nayak 	return regnode;
42469511a45SRajendra Nayak }
42569511a45SRajendra Nayak 
426414c70cbSLiam Girdwood /* Platform voltage constraint check */
427414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev,
428414c70cbSLiam Girdwood 				   int *min_uV, int *max_uV)
429414c70cbSLiam Girdwood {
430414c70cbSLiam Girdwood 	BUG_ON(*min_uV > *max_uV);
431414c70cbSLiam Girdwood 
4328a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
4337ebcf26cSStephen Boyd 		rdev_err(rdev, "voltage operation not allowed\n");
434414c70cbSLiam Girdwood 		return -EPERM;
435414c70cbSLiam Girdwood 	}
436414c70cbSLiam Girdwood 
437414c70cbSLiam Girdwood 	if (*max_uV > rdev->constraints->max_uV)
438414c70cbSLiam Girdwood 		*max_uV = rdev->constraints->max_uV;
439414c70cbSLiam Girdwood 	if (*min_uV < rdev->constraints->min_uV)
440414c70cbSLiam Girdwood 		*min_uV = rdev->constraints->min_uV;
441414c70cbSLiam Girdwood 
44289f425edSMark Brown 	if (*min_uV > *max_uV) {
44389f425edSMark Brown 		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
44454abd335SMark Brown 			 *min_uV, *max_uV);
445414c70cbSLiam Girdwood 		return -EINVAL;
44689f425edSMark Brown 	}
447414c70cbSLiam Girdwood 
448414c70cbSLiam Girdwood 	return 0;
449414c70cbSLiam Girdwood }
450414c70cbSLiam Girdwood 
451f7efad10SChunyan Zhang /* return 0 if the state is valid */
452f7efad10SChunyan Zhang static int regulator_check_states(suspend_state_t state)
453f7efad10SChunyan Zhang {
454f7efad10SChunyan Zhang 	return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE);
455f7efad10SChunyan Zhang }
456f7efad10SChunyan Zhang 
45705fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all
45805fda3b1SThomas Petazzoni  * regulator consumers
45905fda3b1SThomas Petazzoni  */
46005fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev,
461c360a6dfSChunyan Zhang 				     int *min_uV, int *max_uV,
462c360a6dfSChunyan Zhang 				     suspend_state_t state)
46305fda3b1SThomas Petazzoni {
46405fda3b1SThomas Petazzoni 	struct regulator *regulator;
465c360a6dfSChunyan Zhang 	struct regulator_voltage *voltage;
46605fda3b1SThomas Petazzoni 
46705fda3b1SThomas Petazzoni 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
468c360a6dfSChunyan Zhang 		voltage = &regulator->voltage[state];
4694aa922c0SMark Brown 		/*
4704aa922c0SMark Brown 		 * Assume consumers that didn't say anything are OK
4714aa922c0SMark Brown 		 * with anything in the constraint range.
4724aa922c0SMark Brown 		 */
473c360a6dfSChunyan Zhang 		if (!voltage->min_uV && !voltage->max_uV)
4744aa922c0SMark Brown 			continue;
4754aa922c0SMark Brown 
476c360a6dfSChunyan Zhang 		if (*max_uV > voltage->max_uV)
477c360a6dfSChunyan Zhang 			*max_uV = voltage->max_uV;
478c360a6dfSChunyan Zhang 		if (*min_uV < voltage->min_uV)
479c360a6dfSChunyan Zhang 			*min_uV = voltage->min_uV;
48005fda3b1SThomas Petazzoni 	}
48105fda3b1SThomas Petazzoni 
482dd8004afSMark Brown 	if (*min_uV > *max_uV) {
4839c7b4e8aSRuss Dill 		rdev_err(rdev, "Restricting voltage, %u-%uuV\n",
4849c7b4e8aSRuss Dill 			*min_uV, *max_uV);
48505fda3b1SThomas Petazzoni 		return -EINVAL;
486dd8004afSMark Brown 	}
48705fda3b1SThomas Petazzoni 
48805fda3b1SThomas Petazzoni 	return 0;
48905fda3b1SThomas Petazzoni }
49005fda3b1SThomas Petazzoni 
491414c70cbSLiam Girdwood /* current constraint check */
492414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev,
493414c70cbSLiam Girdwood 					int *min_uA, int *max_uA)
494414c70cbSLiam Girdwood {
495414c70cbSLiam Girdwood 	BUG_ON(*min_uA > *max_uA);
496414c70cbSLiam Girdwood 
4978a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) {
4987ebcf26cSStephen Boyd 		rdev_err(rdev, "current operation not allowed\n");
499414c70cbSLiam Girdwood 		return -EPERM;
500414c70cbSLiam Girdwood 	}
501414c70cbSLiam Girdwood 
502414c70cbSLiam Girdwood 	if (*max_uA > rdev->constraints->max_uA)
503414c70cbSLiam Girdwood 		*max_uA = rdev->constraints->max_uA;
504414c70cbSLiam Girdwood 	if (*min_uA < rdev->constraints->min_uA)
505414c70cbSLiam Girdwood 		*min_uA = rdev->constraints->min_uA;
506414c70cbSLiam Girdwood 
50789f425edSMark Brown 	if (*min_uA > *max_uA) {
50889f425edSMark Brown 		rdev_err(rdev, "unsupportable current range: %d-%duA\n",
50954abd335SMark Brown 			 *min_uA, *max_uA);
510414c70cbSLiam Girdwood 		return -EINVAL;
51189f425edSMark Brown 	}
512414c70cbSLiam Girdwood 
513414c70cbSLiam Girdwood 	return 0;
514414c70cbSLiam Girdwood }
515414c70cbSLiam Girdwood 
516414c70cbSLiam Girdwood /* operating mode constraint check */
517109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev,
518109c75afSCharles Keepax 				    unsigned int *mode)
519414c70cbSLiam Girdwood {
5202c608234SMark Brown 	switch (*mode) {
521e573520bSDavid Brownell 	case REGULATOR_MODE_FAST:
522e573520bSDavid Brownell 	case REGULATOR_MODE_NORMAL:
523e573520bSDavid Brownell 	case REGULATOR_MODE_IDLE:
524e573520bSDavid Brownell 	case REGULATOR_MODE_STANDBY:
525e573520bSDavid Brownell 		break;
526e573520bSDavid Brownell 	default:
52789f425edSMark Brown 		rdev_err(rdev, "invalid mode %x specified\n", *mode);
528e573520bSDavid Brownell 		return -EINVAL;
529e573520bSDavid Brownell 	}
530e573520bSDavid Brownell 
5318a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) {
5327ebcf26cSStephen Boyd 		rdev_err(rdev, "mode operation not allowed\n");
533414c70cbSLiam Girdwood 		return -EPERM;
534414c70cbSLiam Girdwood 	}
5352c608234SMark Brown 
5362c608234SMark Brown 	/* The modes are bitmasks, the most power hungry modes having
5372c608234SMark Brown 	 * the lowest values. If the requested mode isn't supported
5382c608234SMark Brown 	 * try higher modes. */
5392c608234SMark Brown 	while (*mode) {
5402c608234SMark Brown 		if (rdev->constraints->valid_modes_mask & *mode)
541414c70cbSLiam Girdwood 			return 0;
5422c608234SMark Brown 		*mode /= 2;
5432c608234SMark Brown 	}
5442c608234SMark Brown 
5452c608234SMark Brown 	return -EINVAL;
546414c70cbSLiam Girdwood }
547414c70cbSLiam Girdwood 
548f7efad10SChunyan Zhang static inline struct regulator_state *
549f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state)
550f7efad10SChunyan Zhang {
551f7efad10SChunyan Zhang 	if (rdev->constraints == NULL)
552f7efad10SChunyan Zhang 		return NULL;
553f7efad10SChunyan Zhang 
554f7efad10SChunyan Zhang 	switch (state) {
555f7efad10SChunyan Zhang 	case PM_SUSPEND_STANDBY:
556f7efad10SChunyan Zhang 		return &rdev->constraints->state_standby;
557f7efad10SChunyan Zhang 	case PM_SUSPEND_MEM:
558f7efad10SChunyan Zhang 		return &rdev->constraints->state_mem;
559f7efad10SChunyan Zhang 	case PM_SUSPEND_MAX:
560f7efad10SChunyan Zhang 		return &rdev->constraints->state_disk;
561f7efad10SChunyan Zhang 	default:
562f7efad10SChunyan Zhang 		return NULL;
563f7efad10SChunyan Zhang 	}
564f7efad10SChunyan Zhang }
565f7efad10SChunyan Zhang 
566414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev,
567414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
568414c70cbSLiam Girdwood {
569a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
570414c70cbSLiam Girdwood 	ssize_t ret;
571414c70cbSLiam Girdwood 
57266cf9a7eSMaciej Purski 	regulator_lock(rdev);
573414c70cbSLiam Girdwood 	ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev));
57466cf9a7eSMaciej Purski 	regulator_unlock(rdev);
575414c70cbSLiam Girdwood 
576414c70cbSLiam Girdwood 	return ret;
577414c70cbSLiam Girdwood }
5787ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);
579414c70cbSLiam Girdwood 
580414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev,
581414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
582414c70cbSLiam Girdwood {
583a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
584414c70cbSLiam Girdwood 
585414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
586414c70cbSLiam Girdwood }
5877ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);
588414c70cbSLiam Girdwood 
589587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr,
590587cea27SGreg Kroah-Hartman 			 char *buf)
591bc558a60SMark Brown {
592bc558a60SMark Brown 	struct regulator_dev *rdev = dev_get_drvdata(dev);
593bc558a60SMark Brown 
5941083c393SMark Brown 	return sprintf(buf, "%s\n", rdev_get_name(rdev));
595bc558a60SMark Brown }
596587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name);
597bc558a60SMark Brown 
59801de19d0SDouglas Anderson static const char *regulator_opmode_to_str(int mode)
599414c70cbSLiam Girdwood {
600414c70cbSLiam Girdwood 	switch (mode) {
601414c70cbSLiam Girdwood 	case REGULATOR_MODE_FAST:
60201de19d0SDouglas Anderson 		return "fast";
603414c70cbSLiam Girdwood 	case REGULATOR_MODE_NORMAL:
60401de19d0SDouglas Anderson 		return "normal";
605414c70cbSLiam Girdwood 	case REGULATOR_MODE_IDLE:
60601de19d0SDouglas Anderson 		return "idle";
607414c70cbSLiam Girdwood 	case REGULATOR_MODE_STANDBY:
60801de19d0SDouglas Anderson 		return "standby";
609414c70cbSLiam Girdwood 	}
61001de19d0SDouglas Anderson 	return "unknown";
61101de19d0SDouglas Anderson }
61201de19d0SDouglas Anderson 
61301de19d0SDouglas Anderson static ssize_t regulator_print_opmode(char *buf, int mode)
61401de19d0SDouglas Anderson {
61501de19d0SDouglas Anderson 	return sprintf(buf, "%s\n", regulator_opmode_to_str(mode));
616414c70cbSLiam Girdwood }
617414c70cbSLiam Girdwood 
6184fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev,
619414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
620414c70cbSLiam Girdwood {
621a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
622414c70cbSLiam Girdwood 
6234fca9545SDavid Brownell 	return regulator_print_opmode(buf, _regulator_get_mode(rdev));
6244fca9545SDavid Brownell }
6257ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL);
6264fca9545SDavid Brownell 
6274fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state)
6284fca9545SDavid Brownell {
629414c70cbSLiam Girdwood 	if (state > 0)
630414c70cbSLiam Girdwood 		return sprintf(buf, "enabled\n");
631414c70cbSLiam Girdwood 	else if (state == 0)
632414c70cbSLiam Girdwood 		return sprintf(buf, "disabled\n");
633414c70cbSLiam Girdwood 	else
634414c70cbSLiam Girdwood 		return sprintf(buf, "unknown\n");
635414c70cbSLiam Girdwood }
636414c70cbSLiam Girdwood 
6374fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev,
6384fca9545SDavid Brownell 				   struct device_attribute *attr, char *buf)
6394fca9545SDavid Brownell {
6404fca9545SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
6419332546fSMark Brown 	ssize_t ret;
6424fca9545SDavid Brownell 
64366cf9a7eSMaciej Purski 	regulator_lock(rdev);
6449332546fSMark Brown 	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
64566cf9a7eSMaciej Purski 	regulator_unlock(rdev);
6469332546fSMark Brown 
6479332546fSMark Brown 	return ret;
6484fca9545SDavid Brownell }
6497ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
6504fca9545SDavid Brownell 
651853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev,
652853116a1SDavid Brownell 				   struct device_attribute *attr, char *buf)
653853116a1SDavid Brownell {
654853116a1SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
655853116a1SDavid Brownell 	int status;
656853116a1SDavid Brownell 	char *label;
657853116a1SDavid Brownell 
658853116a1SDavid Brownell 	status = rdev->desc->ops->get_status(rdev);
659853116a1SDavid Brownell 	if (status < 0)
660853116a1SDavid Brownell 		return status;
661853116a1SDavid Brownell 
662853116a1SDavid Brownell 	switch (status) {
663853116a1SDavid Brownell 	case REGULATOR_STATUS_OFF:
664853116a1SDavid Brownell 		label = "off";
665853116a1SDavid Brownell 		break;
666853116a1SDavid Brownell 	case REGULATOR_STATUS_ON:
667853116a1SDavid Brownell 		label = "on";
668853116a1SDavid Brownell 		break;
669853116a1SDavid Brownell 	case REGULATOR_STATUS_ERROR:
670853116a1SDavid Brownell 		label = "error";
671853116a1SDavid Brownell 		break;
672853116a1SDavid Brownell 	case REGULATOR_STATUS_FAST:
673853116a1SDavid Brownell 		label = "fast";
674853116a1SDavid Brownell 		break;
675853116a1SDavid Brownell 	case REGULATOR_STATUS_NORMAL:
676853116a1SDavid Brownell 		label = "normal";
677853116a1SDavid Brownell 		break;
678853116a1SDavid Brownell 	case REGULATOR_STATUS_IDLE:
679853116a1SDavid Brownell 		label = "idle";
680853116a1SDavid Brownell 		break;
681853116a1SDavid Brownell 	case REGULATOR_STATUS_STANDBY:
682853116a1SDavid Brownell 		label = "standby";
683853116a1SDavid Brownell 		break;
684f59c8f9fSMark Brown 	case REGULATOR_STATUS_BYPASS:
685f59c8f9fSMark Brown 		label = "bypass";
686f59c8f9fSMark Brown 		break;
6871beaf762SKrystian Garbaciak 	case REGULATOR_STATUS_UNDEFINED:
6881beaf762SKrystian Garbaciak 		label = "undefined";
6891beaf762SKrystian Garbaciak 		break;
690853116a1SDavid Brownell 	default:
691853116a1SDavid Brownell 		return -ERANGE;
692853116a1SDavid Brownell 	}
693853116a1SDavid Brownell 
694853116a1SDavid Brownell 	return sprintf(buf, "%s\n", label);
695853116a1SDavid Brownell }
696853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL);
697853116a1SDavid Brownell 
698414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev,
699414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
700414c70cbSLiam Girdwood {
701a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
702414c70cbSLiam Girdwood 
703414c70cbSLiam Girdwood 	if (!rdev->constraints)
704414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
705414c70cbSLiam Girdwood 
706414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uA);
707414c70cbSLiam Girdwood }
7087ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL);
709414c70cbSLiam Girdwood 
710414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev,
711414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
712414c70cbSLiam Girdwood {
713a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
714414c70cbSLiam Girdwood 
715414c70cbSLiam Girdwood 	if (!rdev->constraints)
716414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
717414c70cbSLiam Girdwood 
718414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uA);
719414c70cbSLiam Girdwood }
7207ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL);
721414c70cbSLiam Girdwood 
722414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev,
723414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
724414c70cbSLiam Girdwood {
725a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
726414c70cbSLiam Girdwood 
727414c70cbSLiam Girdwood 	if (!rdev->constraints)
728414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
729414c70cbSLiam Girdwood 
730414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uV);
731414c70cbSLiam Girdwood }
7327ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL);
733414c70cbSLiam Girdwood 
734414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev,
735414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
736414c70cbSLiam Girdwood {
737a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
738414c70cbSLiam Girdwood 
739414c70cbSLiam Girdwood 	if (!rdev->constraints)
740414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
741414c70cbSLiam Girdwood 
742414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uV);
743414c70cbSLiam Girdwood }
7447ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL);
745414c70cbSLiam Girdwood 
746414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev,
747414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
748414c70cbSLiam Girdwood {
749a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
750414c70cbSLiam Girdwood 	struct regulator *regulator;
751414c70cbSLiam Girdwood 	int uA = 0;
752414c70cbSLiam Girdwood 
75366cf9a7eSMaciej Purski 	regulator_lock(rdev);
7545451781dSDouglas Anderson 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
7555451781dSDouglas Anderson 		if (regulator->enable_count)
756414c70cbSLiam Girdwood 			uA += regulator->uA_load;
7575451781dSDouglas Anderson 	}
75866cf9a7eSMaciej Purski 	regulator_unlock(rdev);
759414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", uA);
760414c70cbSLiam Girdwood }
7617ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
762414c70cbSLiam Girdwood 
763587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr,
764587cea27SGreg Kroah-Hartman 			      char *buf)
765414c70cbSLiam Girdwood {
766a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
767414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->use_count);
768414c70cbSLiam Girdwood }
769587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users);
770414c70cbSLiam Girdwood 
771587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr,
772587cea27SGreg Kroah-Hartman 			 char *buf)
773414c70cbSLiam Girdwood {
774a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
775414c70cbSLiam Girdwood 
776414c70cbSLiam Girdwood 	switch (rdev->desc->type) {
777414c70cbSLiam Girdwood 	case REGULATOR_VOLTAGE:
778414c70cbSLiam Girdwood 		return sprintf(buf, "voltage\n");
779414c70cbSLiam Girdwood 	case REGULATOR_CURRENT:
780414c70cbSLiam Girdwood 		return sprintf(buf, "current\n");
781414c70cbSLiam Girdwood 	}
782414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
783414c70cbSLiam Girdwood }
784587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type);
785414c70cbSLiam Girdwood 
786414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
787414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
788414c70cbSLiam Girdwood {
789a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
790414c70cbSLiam Girdwood 
791414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
792414c70cbSLiam Girdwood }
7937ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444,
7947ad68e2fSDavid Brownell 		regulator_suspend_mem_uV_show, NULL);
795414c70cbSLiam Girdwood 
796414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
797414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
798414c70cbSLiam Girdwood {
799a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
800414c70cbSLiam Girdwood 
801414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
802414c70cbSLiam Girdwood }
8037ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444,
8047ad68e2fSDavid Brownell 		regulator_suspend_disk_uV_show, NULL);
805414c70cbSLiam Girdwood 
806414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
807414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
808414c70cbSLiam Girdwood {
809a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
810414c70cbSLiam Girdwood 
811414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
812414c70cbSLiam Girdwood }
8137ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444,
8147ad68e2fSDavid Brownell 		regulator_suspend_standby_uV_show, NULL);
815414c70cbSLiam Girdwood 
816414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
817414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
818414c70cbSLiam Girdwood {
819a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
820414c70cbSLiam Girdwood 
8214fca9545SDavid Brownell 	return regulator_print_opmode(buf,
8224fca9545SDavid Brownell 		rdev->constraints->state_mem.mode);
823414c70cbSLiam Girdwood }
8247ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444,
8257ad68e2fSDavid Brownell 		regulator_suspend_mem_mode_show, NULL);
826414c70cbSLiam Girdwood 
827414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
828414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
829414c70cbSLiam Girdwood {
830a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
831414c70cbSLiam Girdwood 
8324fca9545SDavid Brownell 	return regulator_print_opmode(buf,
8334fca9545SDavid Brownell 		rdev->constraints->state_disk.mode);
834414c70cbSLiam Girdwood }
8357ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444,
8367ad68e2fSDavid Brownell 		regulator_suspend_disk_mode_show, NULL);
837414c70cbSLiam Girdwood 
838414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
839414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
840414c70cbSLiam Girdwood {
841a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
842414c70cbSLiam Girdwood 
8434fca9545SDavid Brownell 	return regulator_print_opmode(buf,
8444fca9545SDavid Brownell 		rdev->constraints->state_standby.mode);
845414c70cbSLiam Girdwood }
8467ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444,
8477ad68e2fSDavid Brownell 		regulator_suspend_standby_mode_show, NULL);
848414c70cbSLiam Girdwood 
849414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev,
850414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
851414c70cbSLiam Girdwood {
852a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
853414c70cbSLiam Girdwood 
8544fca9545SDavid Brownell 	return regulator_print_state(buf,
8554fca9545SDavid Brownell 			rdev->constraints->state_mem.enabled);
856414c70cbSLiam Girdwood }
8577ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444,
8587ad68e2fSDavid Brownell 		regulator_suspend_mem_state_show, NULL);
859414c70cbSLiam Girdwood 
860414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev,
861414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
862414c70cbSLiam Girdwood {
863a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
864414c70cbSLiam Girdwood 
8654fca9545SDavid Brownell 	return regulator_print_state(buf,
8664fca9545SDavid Brownell 			rdev->constraints->state_disk.enabled);
867414c70cbSLiam Girdwood }
8687ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444,
8697ad68e2fSDavid Brownell 		regulator_suspend_disk_state_show, NULL);
870414c70cbSLiam Girdwood 
871414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev,
872414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
873414c70cbSLiam Girdwood {
874a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
875414c70cbSLiam Girdwood 
8764fca9545SDavid Brownell 	return regulator_print_state(buf,
8774fca9545SDavid Brownell 			rdev->constraints->state_standby.enabled);
878414c70cbSLiam Girdwood }
8797ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444,
8807ad68e2fSDavid Brownell 		regulator_suspend_standby_state_show, NULL);
881bc558a60SMark Brown 
882f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev,
883f59c8f9fSMark Brown 				     struct device_attribute *attr, char *buf)
884f59c8f9fSMark Brown {
885f59c8f9fSMark Brown 	struct regulator_dev *rdev = dev_get_drvdata(dev);
886f59c8f9fSMark Brown 	const char *report;
887f59c8f9fSMark Brown 	bool bypass;
888f59c8f9fSMark Brown 	int ret;
889f59c8f9fSMark Brown 
890f59c8f9fSMark Brown 	ret = rdev->desc->ops->get_bypass(rdev, &bypass);
891f59c8f9fSMark Brown 
892f59c8f9fSMark Brown 	if (ret != 0)
893f59c8f9fSMark Brown 		report = "unknown";
894f59c8f9fSMark Brown 	else if (bypass)
895f59c8f9fSMark Brown 		report = "enabled";
896f59c8f9fSMark Brown 	else
897f59c8f9fSMark Brown 		report = "disabled";
898f59c8f9fSMark Brown 
899f59c8f9fSMark Brown 	return sprintf(buf, "%s\n", report);
900f59c8f9fSMark Brown }
901f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444,
902f59c8f9fSMark Brown 		   regulator_bypass_show, NULL);
9037ad68e2fSDavid Brownell 
904414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total
905414c70cbSLiam Girdwood  * consumer load. All locks held by caller */
9068460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev)
907414c70cbSLiam Girdwood {
908414c70cbSLiam Girdwood 	struct regulator *sibling;
909414c70cbSLiam Girdwood 	int current_uA = 0, output_uV, input_uV, err;
910414c70cbSLiam Girdwood 	unsigned int mode;
911414c70cbSLiam Girdwood 
9128460ef38SBjorn Andersson 	/*
9138460ef38SBjorn Andersson 	 * first check to see if we can set modes at all, otherwise just
9148460ef38SBjorn Andersson 	 * tell the consumer everything is OK.
9158460ef38SBjorn Andersson 	 */
91674a569eeSMarc Gonzalez 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) {
91774a569eeSMarc Gonzalez 		rdev_dbg(rdev, "DRMS operation not allowed\n");
9188460ef38SBjorn Andersson 		return 0;
91974a569eeSMarc Gonzalez 	}
9208460ef38SBjorn Andersson 
9218f4490e0SBjorn Andersson 	if (!rdev->desc->ops->get_optimum_mode &&
9228f4490e0SBjorn Andersson 	    !rdev->desc->ops->set_load)
9238460ef38SBjorn Andersson 		return 0;
9248460ef38SBjorn Andersson 
9258f4490e0SBjorn Andersson 	if (!rdev->desc->ops->set_mode &&
9268f4490e0SBjorn Andersson 	    !rdev->desc->ops->set_load)
9278460ef38SBjorn Andersson 		return -EINVAL;
928414c70cbSLiam Girdwood 
92957776617SJoonwoo Park 	/* calc total requested load */
9305451781dSDouglas Anderson 	list_for_each_entry(sibling, &rdev->consumer_list, list) {
9315451781dSDouglas Anderson 		if (sibling->enable_count)
93257776617SJoonwoo Park 			current_uA += sibling->uA_load;
9335451781dSDouglas Anderson 	}
93457776617SJoonwoo Park 
93557776617SJoonwoo Park 	current_uA += rdev->constraints->system_load;
93657776617SJoonwoo Park 
93757776617SJoonwoo Park 	if (rdev->desc->ops->set_load) {
93857776617SJoonwoo Park 		/* set the optimum mode for our new total regulator load */
93957776617SJoonwoo Park 		err = rdev->desc->ops->set_load(rdev, current_uA);
94057776617SJoonwoo Park 		if (err < 0)
94157776617SJoonwoo Park 			rdev_err(rdev, "failed to set load %d\n", current_uA);
94257776617SJoonwoo Park 	} else {
943414c70cbSLiam Girdwood 		/* get output voltage */
9441bf5a1f8SMark Brown 		output_uV = _regulator_get_voltage(rdev);
9458460ef38SBjorn Andersson 		if (output_uV <= 0) {
9468460ef38SBjorn Andersson 			rdev_err(rdev, "invalid output voltage found\n");
9478460ef38SBjorn Andersson 			return -EINVAL;
9488460ef38SBjorn Andersson 		}
949414c70cbSLiam Girdwood 
950414c70cbSLiam Girdwood 		/* get input voltage */
9511bf5a1f8SMark Brown 		input_uV = 0;
9521bf5a1f8SMark Brown 		if (rdev->supply)
9533f24f5adSAxel Lin 			input_uV = regulator_get_voltage(rdev->supply);
9541bf5a1f8SMark Brown 		if (input_uV <= 0)
955414c70cbSLiam Girdwood 			input_uV = rdev->constraints->input_uV;
9568460ef38SBjorn Andersson 		if (input_uV <= 0) {
9578460ef38SBjorn Andersson 			rdev_err(rdev, "invalid input voltage found\n");
9588460ef38SBjorn Andersson 			return -EINVAL;
9598460ef38SBjorn Andersson 		}
960414c70cbSLiam Girdwood 
961414c70cbSLiam Girdwood 		/* now get the optimum mode for our new total regulator load */
962414c70cbSLiam Girdwood 		mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
963414c70cbSLiam Girdwood 							 output_uV, current_uA);
964414c70cbSLiam Girdwood 
965414c70cbSLiam Girdwood 		/* check the new mode is allowed */
9662c608234SMark Brown 		err = regulator_mode_constrain(rdev, &mode);
9678460ef38SBjorn Andersson 		if (err < 0) {
9688460ef38SBjorn Andersson 			rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
9698460ef38SBjorn Andersson 				 current_uA, input_uV, output_uV);
9708460ef38SBjorn Andersson 			return err;
9718460ef38SBjorn Andersson 		}
9728460ef38SBjorn Andersson 
9738460ef38SBjorn Andersson 		err = rdev->desc->ops->set_mode(rdev, mode);
9748460ef38SBjorn Andersson 		if (err < 0)
9758460ef38SBjorn Andersson 			rdev_err(rdev, "failed to set optimum mode %x\n", mode);
9768f4490e0SBjorn Andersson 	}
9778460ef38SBjorn Andersson 
9788460ef38SBjorn Andersson 	return err;
979414c70cbSLiam Girdwood }
980414c70cbSLiam Girdwood 
981414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev,
982f7efad10SChunyan Zhang 				    suspend_state_t state)
983414c70cbSLiam Girdwood {
984414c70cbSLiam Girdwood 	int ret = 0;
985f7efad10SChunyan Zhang 	struct regulator_state *rstate;
986f7efad10SChunyan Zhang 
987f7efad10SChunyan Zhang 	rstate = regulator_get_suspend_state(rdev, state);
988f7efad10SChunyan Zhang 	if (rstate == NULL)
98957a0dd18SMark Brown 		return 0;
990638f85c5SMark Brown 
99148f1b4efSKrzysztof Kozlowski 	/* If we have no suspend mode configuration don't set anything;
9928ac0e95dSAxel Lin 	 * only warn if the driver implements set_suspend_voltage or
9938ac0e95dSAxel Lin 	 * set_suspend_mode callback.
994638f85c5SMark Brown 	 */
99572069f99SChunyan Zhang 	if (rstate->enabled != ENABLE_IN_SUSPEND &&
99672069f99SChunyan Zhang 	    rstate->enabled != DISABLE_IN_SUSPEND) {
9978ac0e95dSAxel Lin 		if (rdev->desc->ops->set_suspend_voltage ||
9988ac0e95dSAxel Lin 		    rdev->desc->ops->set_suspend_mode)
9995da84fd9SJoe Perches 			rdev_warn(rdev, "No configuration\n");
1000638f85c5SMark Brown 		return 0;
1001638f85c5SMark Brown 	}
1002638f85c5SMark Brown 
100372069f99SChunyan Zhang 	if (rstate->enabled == ENABLE_IN_SUSPEND &&
100472069f99SChunyan Zhang 		rdev->desc->ops->set_suspend_enable)
1005414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_enable(rdev);
100672069f99SChunyan Zhang 	else if (rstate->enabled == DISABLE_IN_SUSPEND &&
100772069f99SChunyan Zhang 		rdev->desc->ops->set_suspend_disable)
1008414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_disable(rdev);
10098ac0e95dSAxel Lin 	else /* OK if set_suspend_enable or set_suspend_disable is NULL */
10108ac0e95dSAxel Lin 		ret = 0;
10118ac0e95dSAxel Lin 
1012414c70cbSLiam Girdwood 	if (ret < 0) {
10135da84fd9SJoe Perches 		rdev_err(rdev, "failed to enabled/disable\n");
1014414c70cbSLiam Girdwood 		return ret;
1015414c70cbSLiam Girdwood 	}
1016414c70cbSLiam Girdwood 
1017414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
1018414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
1019414c70cbSLiam Girdwood 		if (ret < 0) {
10205da84fd9SJoe Perches 			rdev_err(rdev, "failed to set voltage\n");
1021414c70cbSLiam Girdwood 			return ret;
1022414c70cbSLiam Girdwood 		}
1023414c70cbSLiam Girdwood 	}
1024414c70cbSLiam Girdwood 
1025414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
1026414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
1027414c70cbSLiam Girdwood 		if (ret < 0) {
10285da84fd9SJoe Perches 			rdev_err(rdev, "failed to set mode\n");
1029414c70cbSLiam Girdwood 			return ret;
1030414c70cbSLiam Girdwood 		}
1031414c70cbSLiam Girdwood 	}
1032f7efad10SChunyan Zhang 
1033414c70cbSLiam Girdwood 	return ret;
1034414c70cbSLiam Girdwood }
1035414c70cbSLiam Girdwood 
1036414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev)
1037414c70cbSLiam Girdwood {
1038414c70cbSLiam Girdwood 	struct regulation_constraints *constraints = rdev->constraints;
1039a7068e39SStefan Wahren 	char buf[160] = "";
10405751a99fSStefan Wahren 	size_t len = sizeof(buf) - 1;
10418f031b48SMark Brown 	int count = 0;
10428f031b48SMark Brown 	int ret;
1043414c70cbSLiam Girdwood 
10448f031b48SMark Brown 	if (constraints->min_uV && constraints->max_uV) {
1045414c70cbSLiam Girdwood 		if (constraints->min_uV == constraints->max_uV)
10465751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count, "%d mV ",
1047414c70cbSLiam Girdwood 					   constraints->min_uV / 1000);
1048414c70cbSLiam Girdwood 		else
10495751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
10505751a99fSStefan Wahren 					   "%d <--> %d mV ",
1051414c70cbSLiam Girdwood 					   constraints->min_uV / 1000,
1052414c70cbSLiam Girdwood 					   constraints->max_uV / 1000);
10538f031b48SMark Brown 	}
10548f031b48SMark Brown 
10558f031b48SMark Brown 	if (!constraints->min_uV ||
10568f031b48SMark Brown 	    constraints->min_uV != constraints->max_uV) {
10578f031b48SMark Brown 		ret = _regulator_get_voltage(rdev);
10588f031b48SMark Brown 		if (ret > 0)
10595751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
10605751a99fSStefan Wahren 					   "at %d mV ", ret / 1000);
10618f031b48SMark Brown 	}
10628f031b48SMark Brown 
1063bf5892a8SMark Brown 	if (constraints->uV_offset)
10645751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "%dmV offset ",
1065bf5892a8SMark Brown 				   constraints->uV_offset / 1000);
1066bf5892a8SMark Brown 
10678f031b48SMark Brown 	if (constraints->min_uA && constraints->max_uA) {
1068414c70cbSLiam Girdwood 		if (constraints->min_uA == constraints->max_uA)
10695751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count, "%d mA ",
1070414c70cbSLiam Girdwood 					   constraints->min_uA / 1000);
1071414c70cbSLiam Girdwood 		else
10725751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
10735751a99fSStefan Wahren 					   "%d <--> %d mA ",
1074414c70cbSLiam Girdwood 					   constraints->min_uA / 1000,
1075414c70cbSLiam Girdwood 					   constraints->max_uA / 1000);
1076414c70cbSLiam Girdwood 	}
10778f031b48SMark Brown 
10788f031b48SMark Brown 	if (!constraints->min_uA ||
10798f031b48SMark Brown 	    constraints->min_uA != constraints->max_uA) {
10808f031b48SMark Brown 		ret = _regulator_get_current_limit(rdev);
10818f031b48SMark Brown 		if (ret > 0)
10825751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
10835751a99fSStefan Wahren 					   "at %d mA ", ret / 1000);
10848f031b48SMark Brown 	}
10858f031b48SMark Brown 
1086414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
10875751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "fast ");
1088414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
10895751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "normal ");
1090414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
10915751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "idle ");
1092414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
10935751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "standby");
1094414c70cbSLiam Girdwood 
1095215b8b05SUwe Kleine-König 	if (!count)
10965751a99fSStefan Wahren 		scnprintf(buf, len, "no parameters");
1097215b8b05SUwe Kleine-König 
1098194dbaefSMark Brown 	rdev_dbg(rdev, "%s\n", buf);
10994a682922SMark Brown 
11004a682922SMark Brown 	if ((constraints->min_uV != constraints->max_uV) &&
11018a34e979SWEN Pingbo 	    !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
11024a682922SMark Brown 		rdev_warn(rdev,
11034a682922SMark Brown 			  "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
1104414c70cbSLiam Girdwood }
1105414c70cbSLiam Girdwood 
1106e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev,
11071083c393SMark Brown 	struct regulation_constraints *constraints)
1108e79055d6SMark Brown {
1109272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
1110af5866c9SMark Brown 	int ret;
1111af5866c9SMark Brown 
1112af5866c9SMark Brown 	/* do we need to apply the constraint voltage */
1113af5866c9SMark Brown 	if (rdev->constraints->apply_uV &&
1114fa93fd4eSMark Brown 	    rdev->constraints->min_uV && rdev->constraints->max_uV) {
1115fa93fd4eSMark Brown 		int target_min, target_max;
1116064d5cd1SAlban Bedel 		int current_uV = _regulator_get_voltage(rdev);
111784b3a7c9SDouglas Anderson 
111884b3a7c9SDouglas Anderson 		if (current_uV == -ENOTRECOVERABLE) {
111948f1b4efSKrzysztof Kozlowski 			/* This regulator can't be read and must be initialized */
112084b3a7c9SDouglas Anderson 			rdev_info(rdev, "Setting %d-%duV\n",
112184b3a7c9SDouglas Anderson 				  rdev->constraints->min_uV,
112284b3a7c9SDouglas Anderson 				  rdev->constraints->max_uV);
112384b3a7c9SDouglas Anderson 			_regulator_do_set_voltage(rdev,
112484b3a7c9SDouglas Anderson 						  rdev->constraints->min_uV,
112584b3a7c9SDouglas Anderson 						  rdev->constraints->max_uV);
112684b3a7c9SDouglas Anderson 			current_uV = _regulator_get_voltage(rdev);
112784b3a7c9SDouglas Anderson 		}
112884b3a7c9SDouglas Anderson 
1129064d5cd1SAlban Bedel 		if (current_uV < 0) {
113069d58839SNishanth Menon 			rdev_err(rdev,
113169d58839SNishanth Menon 				 "failed to get the current voltage(%d)\n",
113269d58839SNishanth Menon 				 current_uV);
1133064d5cd1SAlban Bedel 			return current_uV;
1134064d5cd1SAlban Bedel 		}
1135fa93fd4eSMark Brown 
1136fa93fd4eSMark Brown 		/*
1137fa93fd4eSMark Brown 		 * If we're below the minimum voltage move up to the
1138fa93fd4eSMark Brown 		 * minimum voltage, if we're above the maximum voltage
1139fa93fd4eSMark Brown 		 * then move down to the maximum.
1140fa93fd4eSMark Brown 		 */
1141fa93fd4eSMark Brown 		target_min = current_uV;
1142fa93fd4eSMark Brown 		target_max = current_uV;
1143fa93fd4eSMark Brown 
1144fa93fd4eSMark Brown 		if (current_uV < rdev->constraints->min_uV) {
1145fa93fd4eSMark Brown 			target_min = rdev->constraints->min_uV;
1146fa93fd4eSMark Brown 			target_max = rdev->constraints->min_uV;
1147fa93fd4eSMark Brown 		}
1148fa93fd4eSMark Brown 
1149fa93fd4eSMark Brown 		if (current_uV > rdev->constraints->max_uV) {
1150fa93fd4eSMark Brown 			target_min = rdev->constraints->max_uV;
1151fa93fd4eSMark Brown 			target_max = rdev->constraints->max_uV;
1152fa93fd4eSMark Brown 		}
1153fa93fd4eSMark Brown 
1154fa93fd4eSMark Brown 		if (target_min != current_uV || target_max != current_uV) {
115545a91e8fSMark Brown 			rdev_info(rdev, "Bringing %duV into %d-%duV\n",
115645a91e8fSMark Brown 				  current_uV, target_min, target_max);
1157064d5cd1SAlban Bedel 			ret = _regulator_do_set_voltage(
1158fa93fd4eSMark Brown 				rdev, target_min, target_max);
1159af5866c9SMark Brown 			if (ret < 0) {
1160064d5cd1SAlban Bedel 				rdev_err(rdev,
1161fa93fd4eSMark Brown 					"failed to apply %d-%duV constraint(%d)\n",
1162fa93fd4eSMark Brown 					target_min, target_max, ret);
1163af5866c9SMark Brown 				return ret;
1164af5866c9SMark Brown 			}
1165af5866c9SMark Brown 		}
1166064d5cd1SAlban Bedel 	}
1167e79055d6SMark Brown 
1168e79055d6SMark Brown 	/* constrain machine-level voltage specs to fit
1169e79055d6SMark Brown 	 * the actual range supported by this regulator.
1170e79055d6SMark Brown 	 */
1171e79055d6SMark Brown 	if (ops->list_voltage && rdev->desc->n_voltages) {
1172e79055d6SMark Brown 		int	count = rdev->desc->n_voltages;
1173e79055d6SMark Brown 		int	i;
1174e79055d6SMark Brown 		int	min_uV = INT_MAX;
1175e79055d6SMark Brown 		int	max_uV = INT_MIN;
1176e79055d6SMark Brown 		int	cmin = constraints->min_uV;
1177e79055d6SMark Brown 		int	cmax = constraints->max_uV;
1178e79055d6SMark Brown 
1179e79055d6SMark Brown 		/* it's safe to autoconfigure fixed-voltage supplies
1180e79055d6SMark Brown 		   and the constraints are used by list_voltage. */
1181e79055d6SMark Brown 		if (count == 1 && !cmin) {
1182e79055d6SMark Brown 			cmin = 1;
1183e79055d6SMark Brown 			cmax = INT_MAX;
1184e79055d6SMark Brown 			constraints->min_uV = cmin;
1185e79055d6SMark Brown 			constraints->max_uV = cmax;
1186e79055d6SMark Brown 		}
1187e79055d6SMark Brown 
1188e79055d6SMark Brown 		/* voltage constraints are optional */
1189e79055d6SMark Brown 		if ((cmin == 0) && (cmax == 0))
1190e79055d6SMark Brown 			return 0;
1191e79055d6SMark Brown 
1192e79055d6SMark Brown 		/* else require explicit machine-level constraints */
1193e79055d6SMark Brown 		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
11945da84fd9SJoe Perches 			rdev_err(rdev, "invalid voltage constraints\n");
1195e79055d6SMark Brown 			return -EINVAL;
1196e79055d6SMark Brown 		}
1197e79055d6SMark Brown 
1198e79055d6SMark Brown 		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
1199e79055d6SMark Brown 		for (i = 0; i < count; i++) {
1200e79055d6SMark Brown 			int	value;
1201e79055d6SMark Brown 
1202e79055d6SMark Brown 			value = ops->list_voltage(rdev, i);
1203e79055d6SMark Brown 			if (value <= 0)
1204e79055d6SMark Brown 				continue;
1205e79055d6SMark Brown 
1206e79055d6SMark Brown 			/* maybe adjust [min_uV..max_uV] */
1207e79055d6SMark Brown 			if (value >= cmin && value < min_uV)
1208e79055d6SMark Brown 				min_uV = value;
1209e79055d6SMark Brown 			if (value <= cmax && value > max_uV)
1210e79055d6SMark Brown 				max_uV = value;
1211e79055d6SMark Brown 		}
1212e79055d6SMark Brown 
1213e79055d6SMark Brown 		/* final: [min_uV..max_uV] valid iff constraints valid */
1214e79055d6SMark Brown 		if (max_uV < min_uV) {
1215fff15befSMark Brown 			rdev_err(rdev,
1216fff15befSMark Brown 				 "unsupportable voltage constraints %u-%uuV\n",
1217fff15befSMark Brown 				 min_uV, max_uV);
1218e79055d6SMark Brown 			return -EINVAL;
1219e79055d6SMark Brown 		}
1220e79055d6SMark Brown 
1221e79055d6SMark Brown 		/* use regulator's subset of machine constraints */
1222e79055d6SMark Brown 		if (constraints->min_uV < min_uV) {
12235da84fd9SJoe Perches 			rdev_dbg(rdev, "override min_uV, %d -> %d\n",
12245da84fd9SJoe Perches 				 constraints->min_uV, min_uV);
1225e79055d6SMark Brown 			constraints->min_uV = min_uV;
1226e79055d6SMark Brown 		}
1227e79055d6SMark Brown 		if (constraints->max_uV > max_uV) {
12285da84fd9SJoe Perches 			rdev_dbg(rdev, "override max_uV, %d -> %d\n",
12295da84fd9SJoe Perches 				 constraints->max_uV, max_uV);
1230e79055d6SMark Brown 			constraints->max_uV = max_uV;
1231e79055d6SMark Brown 		}
1232e79055d6SMark Brown 	}
1233e79055d6SMark Brown 
1234e79055d6SMark Brown 	return 0;
1235e79055d6SMark Brown }
1236e79055d6SMark Brown 
1237f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev,
1238f8c1700dSLaxman Dewangan 	struct regulation_constraints *constraints)
1239f8c1700dSLaxman Dewangan {
1240272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
1241f8c1700dSLaxman Dewangan 	int ret;
1242f8c1700dSLaxman Dewangan 
1243f8c1700dSLaxman Dewangan 	if (!constraints->min_uA && !constraints->max_uA)
1244f8c1700dSLaxman Dewangan 		return 0;
1245f8c1700dSLaxman Dewangan 
1246f8c1700dSLaxman Dewangan 	if (constraints->min_uA > constraints->max_uA) {
1247f8c1700dSLaxman Dewangan 		rdev_err(rdev, "Invalid current constraints\n");
1248f8c1700dSLaxman Dewangan 		return -EINVAL;
1249f8c1700dSLaxman Dewangan 	}
1250f8c1700dSLaxman Dewangan 
1251f8c1700dSLaxman Dewangan 	if (!ops->set_current_limit || !ops->get_current_limit) {
1252f8c1700dSLaxman Dewangan 		rdev_warn(rdev, "Operation of current configuration missing\n");
1253f8c1700dSLaxman Dewangan 		return 0;
1254f8c1700dSLaxman Dewangan 	}
1255f8c1700dSLaxman Dewangan 
1256f8c1700dSLaxman Dewangan 	/* Set regulator current in constraints range */
1257f8c1700dSLaxman Dewangan 	ret = ops->set_current_limit(rdev, constraints->min_uA,
1258f8c1700dSLaxman Dewangan 			constraints->max_uA);
1259f8c1700dSLaxman Dewangan 	if (ret < 0) {
1260f8c1700dSLaxman Dewangan 		rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
1261f8c1700dSLaxman Dewangan 		return ret;
1262f8c1700dSLaxman Dewangan 	}
1263f8c1700dSLaxman Dewangan 
1264f8c1700dSLaxman Dewangan 	return 0;
1265f8c1700dSLaxman Dewangan }
1266f8c1700dSLaxman Dewangan 
126730c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev);
126830c21971SMarkus Pargmann 
1269a5766f11SLiam Girdwood /**
1270a5766f11SLiam Girdwood  * set_machine_constraints - sets regulator constraints
127169279fb9SMark Brown  * @rdev: regulator source
1272c8e7e464SMark Brown  * @constraints: constraints to apply
1273a5766f11SLiam Girdwood  *
1274a5766f11SLiam Girdwood  * Allows platform initialisation code to define and constrain
1275a5766f11SLiam Girdwood  * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
1276a5766f11SLiam Girdwood  * Constraints *must* be set by platform code in order for some
1277a5766f11SLiam Girdwood  * regulator operations to proceed i.e. set_voltage, set_current_limit,
1278a5766f11SLiam Girdwood  * set_mode.
1279a5766f11SLiam Girdwood  */
1280a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev,
1281f8c12fe3SMark Brown 	const struct regulation_constraints *constraints)
1282a5766f11SLiam Girdwood {
1283a5766f11SLiam Girdwood 	int ret = 0;
1284272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
1285e06f5b4fSMark Brown 
12869a8f5e07SMark Brown 	if (constraints)
1287f8c12fe3SMark Brown 		rdev->constraints = kmemdup(constraints, sizeof(*constraints),
1288f8c12fe3SMark Brown 					    GFP_KERNEL);
12899a8f5e07SMark Brown 	else
12909a8f5e07SMark Brown 		rdev->constraints = kzalloc(sizeof(*constraints),
12919a8f5e07SMark Brown 					    GFP_KERNEL);
1292f8c12fe3SMark Brown 	if (!rdev->constraints)
1293f8c12fe3SMark Brown 		return -ENOMEM;
1294af5866c9SMark Brown 
1295f8c12fe3SMark Brown 	ret = machine_constraints_voltage(rdev, rdev->constraints);
1296e79055d6SMark Brown 	if (ret != 0)
12976333ef46SCharles Keepax 		return ret;
12983e2b9abdSMark Brown 
1299f8c1700dSLaxman Dewangan 	ret = machine_constraints_current(rdev, rdev->constraints);
1300f8c1700dSLaxman Dewangan 	if (ret != 0)
13016333ef46SCharles Keepax 		return ret;
1302f8c1700dSLaxman Dewangan 
130336e4f839SStephen Boyd 	if (rdev->constraints->ilim_uA && ops->set_input_current_limit) {
130436e4f839SStephen Boyd 		ret = ops->set_input_current_limit(rdev,
130536e4f839SStephen Boyd 						   rdev->constraints->ilim_uA);
130636e4f839SStephen Boyd 		if (ret < 0) {
130736e4f839SStephen Boyd 			rdev_err(rdev, "failed to set input limit\n");
13086333ef46SCharles Keepax 			return ret;
130936e4f839SStephen Boyd 		}
131036e4f839SStephen Boyd 	}
131136e4f839SStephen Boyd 
1312a5766f11SLiam Girdwood 	/* do we need to setup our suspend state */
13139a8f5e07SMark Brown 	if (rdev->constraints->initial_state) {
1314f7efad10SChunyan Zhang 		ret = suspend_set_state(rdev, rdev->constraints->initial_state);
1315e06f5b4fSMark Brown 		if (ret < 0) {
13165da84fd9SJoe Perches 			rdev_err(rdev, "failed to set suspend state\n");
13176333ef46SCharles Keepax 			return ret;
1318e06f5b4fSMark Brown 		}
1319e06f5b4fSMark Brown 	}
1320a5766f11SLiam Girdwood 
13219a8f5e07SMark Brown 	if (rdev->constraints->initial_mode) {
1322a308466cSMark Brown 		if (!ops->set_mode) {
13235da84fd9SJoe Perches 			rdev_err(rdev, "no set_mode operation\n");
13246333ef46SCharles Keepax 			return -EINVAL;
1325a308466cSMark Brown 		}
1326a308466cSMark Brown 
1327f8c12fe3SMark Brown 		ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
1328a308466cSMark Brown 		if (ret < 0) {
13295da84fd9SJoe Perches 			rdev_err(rdev, "failed to set initial mode: %d\n", ret);
13306333ef46SCharles Keepax 			return ret;
1331a308466cSMark Brown 		}
1332fa94e48eSDouglas Anderson 	} else if (rdev->constraints->system_load) {
1333fa94e48eSDouglas Anderson 		/*
1334fa94e48eSDouglas Anderson 		 * We'll only apply the initial system load if an
1335fa94e48eSDouglas Anderson 		 * initial mode wasn't specified.
1336fa94e48eSDouglas Anderson 		 */
1337fa94e48eSDouglas Anderson 		drms_uA_update(rdev);
1338a308466cSMark Brown 	}
1339a308466cSMark Brown 
13401653ccf4SYadwinder Singh Brar 	if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
13411653ccf4SYadwinder Singh Brar 		&& ops->set_ramp_delay) {
13426f0b2c69SYadwinder Singh Brar 		ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
13436f0b2c69SYadwinder Singh Brar 		if (ret < 0) {
13446f0b2c69SYadwinder Singh Brar 			rdev_err(rdev, "failed to set ramp_delay\n");
13456333ef46SCharles Keepax 			return ret;
13466f0b2c69SYadwinder Singh Brar 		}
13476f0b2c69SYadwinder Singh Brar 	}
13486f0b2c69SYadwinder Singh Brar 
134923c779b9SStephen Boyd 	if (rdev->constraints->pull_down && ops->set_pull_down) {
135023c779b9SStephen Boyd 		ret = ops->set_pull_down(rdev);
135123c779b9SStephen Boyd 		if (ret < 0) {
135223c779b9SStephen Boyd 			rdev_err(rdev, "failed to set pull down\n");
13536333ef46SCharles Keepax 			return ret;
135423c779b9SStephen Boyd 		}
135523c779b9SStephen Boyd 	}
135623c779b9SStephen Boyd 
135757f66b78SStephen Boyd 	if (rdev->constraints->soft_start && ops->set_soft_start) {
135857f66b78SStephen Boyd 		ret = ops->set_soft_start(rdev);
135957f66b78SStephen Boyd 		if (ret < 0) {
136057f66b78SStephen Boyd 			rdev_err(rdev, "failed to set soft start\n");
13616333ef46SCharles Keepax 			return ret;
136257f66b78SStephen Boyd 		}
136357f66b78SStephen Boyd 	}
136457f66b78SStephen Boyd 
13653a003baeSStephen Boyd 	if (rdev->constraints->over_current_protection
13663a003baeSStephen Boyd 		&& ops->set_over_current_protection) {
13673a003baeSStephen Boyd 		ret = ops->set_over_current_protection(rdev);
13683a003baeSStephen Boyd 		if (ret < 0) {
13693a003baeSStephen Boyd 			rdev_err(rdev, "failed to set over current protection\n");
13706333ef46SCharles Keepax 			return ret;
13713a003baeSStephen Boyd 		}
13723a003baeSStephen Boyd 	}
13733a003baeSStephen Boyd 
1374670666b9SLaxman Dewangan 	if (rdev->constraints->active_discharge && ops->set_active_discharge) {
1375670666b9SLaxman Dewangan 		bool ad_state = (rdev->constraints->active_discharge ==
1376670666b9SLaxman Dewangan 			      REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;
1377670666b9SLaxman Dewangan 
1378670666b9SLaxman Dewangan 		ret = ops->set_active_discharge(rdev, ad_state);
1379670666b9SLaxman Dewangan 		if (ret < 0) {
1380670666b9SLaxman Dewangan 			rdev_err(rdev, "failed to set active discharge\n");
1381670666b9SLaxman Dewangan 			return ret;
1382670666b9SLaxman Dewangan 		}
1383670666b9SLaxman Dewangan 	}
1384670666b9SLaxman Dewangan 
13852bb16663SOlliver Schinagl 	/* If the constraints say the regulator should be on at this point
13862bb16663SOlliver Schinagl 	 * and we have control then make sure it is enabled.
13872bb16663SOlliver Schinagl 	 */
13882bb16663SOlliver Schinagl 	if (rdev->constraints->always_on || rdev->constraints->boot_on) {
138905f224caSDouglas Anderson 		if (rdev->supply) {
139005f224caSDouglas Anderson 			ret = regulator_enable(rdev->supply);
139105f224caSDouglas Anderson 			if (ret < 0) {
139205f224caSDouglas Anderson 				_regulator_put(rdev->supply);
139305f224caSDouglas Anderson 				rdev->supply = NULL;
139405f224caSDouglas Anderson 				return ret;
139505f224caSDouglas Anderson 			}
139605f224caSDouglas Anderson 		}
139705f224caSDouglas Anderson 
13982bb16663SOlliver Schinagl 		ret = _regulator_do_enable(rdev);
13992bb16663SOlliver Schinagl 		if (ret < 0 && ret != -EINVAL) {
14002bb16663SOlliver Schinagl 			rdev_err(rdev, "failed to enable\n");
14012bb16663SOlliver Schinagl 			return ret;
14022bb16663SOlliver Schinagl 		}
140305f224caSDouglas Anderson 		rdev->use_count++;
14042bb16663SOlliver Schinagl 	}
14052bb16663SOlliver Schinagl 
1406a5766f11SLiam Girdwood 	print_constraints(rdev);
14071a6958e7SAxel Lin 	return 0;
1408a5766f11SLiam Girdwood }
1409a5766f11SLiam Girdwood 
1410a5766f11SLiam Girdwood /**
1411a5766f11SLiam Girdwood  * set_supply - set regulator supply regulator
141269279fb9SMark Brown  * @rdev: regulator name
141369279fb9SMark Brown  * @supply_rdev: supply regulator name
1414a5766f11SLiam Girdwood  *
1415a5766f11SLiam Girdwood  * Called by platform initialisation code to set the supply regulator for this
1416a5766f11SLiam Girdwood  * regulator. This ensures that a regulators supply will also be enabled by the
1417a5766f11SLiam Girdwood  * core if it's child is enabled.
1418a5766f11SLiam Girdwood  */
1419a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev,
1420a5766f11SLiam Girdwood 		      struct regulator_dev *supply_rdev)
1421a5766f11SLiam Girdwood {
1422a5766f11SLiam Girdwood 	int err;
1423a5766f11SLiam Girdwood 
14243801b86aSMark Brown 	rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
14253801b86aSMark Brown 
1426e2c09ae7SJavier Martinez Canillas 	if (!try_module_get(supply_rdev->owner))
1427e2c09ae7SJavier Martinez Canillas 		return -ENODEV;
1428e2c09ae7SJavier Martinez Canillas 
14293801b86aSMark Brown 	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
143032c78de8SAxel Lin 	if (rdev->supply == NULL) {
143132c78de8SAxel Lin 		err = -ENOMEM;
1432a5766f11SLiam Girdwood 		return err;
1433a5766f11SLiam Girdwood 	}
143457ad526aSLaxman Dewangan 	supply_rdev->open_count++;
1435a5766f11SLiam Girdwood 
14363801b86aSMark Brown 	return 0;
14373801b86aSMark Brown }
14383801b86aSMark Brown 
1439a5766f11SLiam Girdwood /**
144006c63f93SRandy Dunlap  * set_consumer_device_supply - Bind a regulator to a symbolic supply
144169279fb9SMark Brown  * @rdev:         regulator source
144240f9244fSMark Brown  * @consumer_dev_name: dev_name() string for device supply applies to
1443a5766f11SLiam Girdwood  * @supply:       symbolic name for supply
1444a5766f11SLiam Girdwood  *
1445a5766f11SLiam Girdwood  * Allows platform initialisation code to map physical regulator
1446a5766f11SLiam Girdwood  * sources to symbolic names for supplies for use by devices.  Devices
1447a5766f11SLiam Girdwood  * should use these symbolic names to request regulators, avoiding the
1448a5766f11SLiam Girdwood  * need to provide board-specific regulator names as platform data.
1449a5766f11SLiam Girdwood  */
1450a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev,
1451737f360dSMark Brown 				      const char *consumer_dev_name,
145240f9244fSMark Brown 				      const char *supply)
1453a5766f11SLiam Girdwood {
1454a5766f11SLiam Girdwood 	struct regulator_map *node;
14559ed2099eSMark Brown 	int has_dev;
1456a5766f11SLiam Girdwood 
1457a5766f11SLiam Girdwood 	if (supply == NULL)
1458a5766f11SLiam Girdwood 		return -EINVAL;
1459a5766f11SLiam Girdwood 
14609ed2099eSMark Brown 	if (consumer_dev_name != NULL)
14619ed2099eSMark Brown 		has_dev = 1;
14629ed2099eSMark Brown 	else
14639ed2099eSMark Brown 		has_dev = 0;
14649ed2099eSMark Brown 
14656001e13cSDavid Brownell 	list_for_each_entry(node, &regulator_map_list, list) {
146623b5cc2aSJani Nikula 		if (node->dev_name && consumer_dev_name) {
146723b5cc2aSJani Nikula 			if (strcmp(node->dev_name, consumer_dev_name) != 0)
14686001e13cSDavid Brownell 				continue;
146923b5cc2aSJani Nikula 		} else if (node->dev_name || consumer_dev_name) {
147023b5cc2aSJani Nikula 			continue;
147123b5cc2aSJani Nikula 		}
147223b5cc2aSJani Nikula 
14736001e13cSDavid Brownell 		if (strcmp(node->supply, supply) != 0)
14746001e13cSDavid Brownell 			continue;
14756001e13cSDavid Brownell 
1476737f360dSMark Brown 		pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n",
1477737f360dSMark Brown 			 consumer_dev_name,
14786001e13cSDavid Brownell 			 dev_name(&node->regulator->dev),
14796001e13cSDavid Brownell 			 node->regulator->desc->name,
14806001e13cSDavid Brownell 			 supply,
14811083c393SMark Brown 			 dev_name(&rdev->dev), rdev_get_name(rdev));
14826001e13cSDavid Brownell 		return -EBUSY;
14836001e13cSDavid Brownell 	}
14846001e13cSDavid Brownell 
14859ed2099eSMark Brown 	node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
1486a5766f11SLiam Girdwood 	if (node == NULL)
1487a5766f11SLiam Girdwood 		return -ENOMEM;
1488a5766f11SLiam Girdwood 
1489a5766f11SLiam Girdwood 	node->regulator = rdev;
1490a5766f11SLiam Girdwood 	node->supply = supply;
1491a5766f11SLiam Girdwood 
14929ed2099eSMark Brown 	if (has_dev) {
14939ed2099eSMark Brown 		node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
149440f9244fSMark Brown 		if (node->dev_name == NULL) {
149540f9244fSMark Brown 			kfree(node);
149640f9244fSMark Brown 			return -ENOMEM;
149740f9244fSMark Brown 		}
14989ed2099eSMark Brown 	}
149940f9244fSMark Brown 
1500a5766f11SLiam Girdwood 	list_add(&node->list, &regulator_map_list);
1501a5766f11SLiam Girdwood 	return 0;
1502a5766f11SLiam Girdwood }
1503a5766f11SLiam Girdwood 
15040f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev)
15050f1d747bSMike Rapoport {
15060f1d747bSMike Rapoport 	struct regulator_map *node, *n;
15070f1d747bSMike Rapoport 
15080f1d747bSMike Rapoport 	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
15090f1d747bSMike Rapoport 		if (rdev == node->regulator) {
15100f1d747bSMike Rapoport 			list_del(&node->list);
151140f9244fSMark Brown 			kfree(node->dev_name);
15120f1d747bSMike Rapoport 			kfree(node);
15130f1d747bSMike Rapoport 		}
15140f1d747bSMike Rapoport 	}
15150f1d747bSMike Rapoport }
15160f1d747bSMike Rapoport 
15172d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS
15182d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file,
15192d80a91bSRichard Fitzgerald 					  char __user *user_buf,
15202d80a91bSRichard Fitzgerald 					  size_t count, loff_t *ppos)
15212d80a91bSRichard Fitzgerald {
15222d80a91bSRichard Fitzgerald 	const struct regulator *regulator = file->private_data;
15232d80a91bSRichard Fitzgerald 	const struct regulation_constraints *c = regulator->rdev->constraints;
15242d80a91bSRichard Fitzgerald 	char *buf;
15252d80a91bSRichard Fitzgerald 	ssize_t ret;
15262d80a91bSRichard Fitzgerald 
15272d80a91bSRichard Fitzgerald 	if (!c)
15282d80a91bSRichard Fitzgerald 		return 0;
15292d80a91bSRichard Fitzgerald 
15302d80a91bSRichard Fitzgerald 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
15312d80a91bSRichard Fitzgerald 	if (!buf)
15322d80a91bSRichard Fitzgerald 		return -ENOMEM;
15332d80a91bSRichard Fitzgerald 
15342d80a91bSRichard Fitzgerald 	ret = snprintf(buf, PAGE_SIZE,
15352d80a91bSRichard Fitzgerald 			"always_on: %u\n"
15362d80a91bSRichard Fitzgerald 			"boot_on: %u\n"
15372d80a91bSRichard Fitzgerald 			"apply_uV: %u\n"
15382d80a91bSRichard Fitzgerald 			"ramp_disable: %u\n"
15392d80a91bSRichard Fitzgerald 			"soft_start: %u\n"
15402d80a91bSRichard Fitzgerald 			"pull_down: %u\n"
15412d80a91bSRichard Fitzgerald 			"over_current_protection: %u\n",
15422d80a91bSRichard Fitzgerald 			c->always_on,
15432d80a91bSRichard Fitzgerald 			c->boot_on,
15442d80a91bSRichard Fitzgerald 			c->apply_uV,
15452d80a91bSRichard Fitzgerald 			c->ramp_disable,
15462d80a91bSRichard Fitzgerald 			c->soft_start,
15472d80a91bSRichard Fitzgerald 			c->pull_down,
15482d80a91bSRichard Fitzgerald 			c->over_current_protection);
15492d80a91bSRichard Fitzgerald 
15502d80a91bSRichard Fitzgerald 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
15512d80a91bSRichard Fitzgerald 	kfree(buf);
15522d80a91bSRichard Fitzgerald 
15532d80a91bSRichard Fitzgerald 	return ret;
15542d80a91bSRichard Fitzgerald }
15552d80a91bSRichard Fitzgerald 
15562d80a91bSRichard Fitzgerald #endif
15572d80a91bSRichard Fitzgerald 
15582d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = {
15592d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS
15602d80a91bSRichard Fitzgerald 	.open = simple_open,
15612d80a91bSRichard Fitzgerald 	.read = constraint_flags_read_file,
15622d80a91bSRichard Fitzgerald 	.llseek = default_llseek,
15632d80a91bSRichard Fitzgerald #endif
15642d80a91bSRichard Fitzgerald };
15652d80a91bSRichard Fitzgerald 
1566f5726ae3SMark Brown #define REG_STR_SIZE	64
1567414c70cbSLiam Girdwood 
1568414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev,
1569414c70cbSLiam Girdwood 					  struct device *dev,
1570414c70cbSLiam Girdwood 					  const char *supply_name)
1571414c70cbSLiam Girdwood {
1572414c70cbSLiam Girdwood 	struct regulator *regulator;
1573414c70cbSLiam Girdwood 	char buf[REG_STR_SIZE];
1574414c70cbSLiam Girdwood 	int err, size;
1575414c70cbSLiam Girdwood 
1576414c70cbSLiam Girdwood 	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
1577414c70cbSLiam Girdwood 	if (regulator == NULL)
1578414c70cbSLiam Girdwood 		return NULL;
1579414c70cbSLiam Girdwood 
158066cf9a7eSMaciej Purski 	regulator_lock(rdev);
1581414c70cbSLiam Girdwood 	regulator->rdev = rdev;
1582414c70cbSLiam Girdwood 	list_add(&regulator->list, &rdev->consumer_list);
1583414c70cbSLiam Girdwood 
1584414c70cbSLiam Girdwood 	if (dev) {
1585e2c98eafSShawn Guo 		regulator->dev = dev;
1586e2c98eafSShawn Guo 
1587222cc7b1SMark Brown 		/* Add a link to the device sysfs entry */
1588b7cd1b13SBartosz Golaszewski 		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
1589414c70cbSLiam Girdwood 				dev->kobj.name, supply_name);
1590414c70cbSLiam Girdwood 		if (size >= REG_STR_SIZE)
1591222cc7b1SMark Brown 			goto overflow_err;
1592414c70cbSLiam Girdwood 
1593414c70cbSLiam Girdwood 		regulator->supply_name = kstrdup(buf, GFP_KERNEL);
1594414c70cbSLiam Girdwood 		if (regulator->supply_name == NULL)
1595222cc7b1SMark Brown 			goto overflow_err;
1596414c70cbSLiam Girdwood 
1597ff268b56SStephen Boyd 		err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
1598414c70cbSLiam Girdwood 					buf);
1599414c70cbSLiam Girdwood 		if (err) {
1600ff268b56SStephen Boyd 			rdev_dbg(rdev, "could not add device link %s err %d\n",
16011d7372e1SDaniel Walker 				  dev->kobj.name, err);
1602222cc7b1SMark Brown 			/* non-fatal */
1603414c70cbSLiam Girdwood 		}
16045de70519SMark Brown 	} else {
16050630b614SStephen Boyd 		regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL);
16065de70519SMark Brown 		if (regulator->supply_name == NULL)
1607222cc7b1SMark Brown 			goto overflow_err;
1608414c70cbSLiam Girdwood 	}
16095de70519SMark Brown 
16105de70519SMark Brown 	regulator->debugfs = debugfs_create_dir(regulator->supply_name,
16115de70519SMark Brown 						rdev->debugfs);
161224751434SStephen Boyd 	if (!regulator->debugfs) {
1613ad3a942bSStephen Boyd 		rdev_dbg(rdev, "Failed to create debugfs directory\n");
16145de70519SMark Brown 	} else {
16155de70519SMark Brown 		debugfs_create_u32("uA_load", 0444, regulator->debugfs,
16165de70519SMark Brown 				   &regulator->uA_load);
16175de70519SMark Brown 		debugfs_create_u32("min_uV", 0444, regulator->debugfs,
1618c360a6dfSChunyan Zhang 				   &regulator->voltage[PM_SUSPEND_ON].min_uV);
16195de70519SMark Brown 		debugfs_create_u32("max_uV", 0444, regulator->debugfs,
1620c360a6dfSChunyan Zhang 				   &regulator->voltage[PM_SUSPEND_ON].max_uV);
16212d80a91bSRichard Fitzgerald 		debugfs_create_file("constraint_flags", 0444,
16222d80a91bSRichard Fitzgerald 				    regulator->debugfs, regulator,
16232d80a91bSRichard Fitzgerald 				    &constraint_flags_fops);
16245de70519SMark Brown 	}
16255de70519SMark Brown 
16266492bc1bSMark Brown 	/*
16276492bc1bSMark Brown 	 * Check now if the regulator is an always on regulator - if
16286492bc1bSMark Brown 	 * it is then we don't need to do nearly so much work for
16296492bc1bSMark Brown 	 * enable/disable calls.
16306492bc1bSMark Brown 	 */
16318a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) &&
16326492bc1bSMark Brown 	    _regulator_is_enabled(rdev))
16336492bc1bSMark Brown 		regulator->always_on = true;
16346492bc1bSMark Brown 
163566cf9a7eSMaciej Purski 	regulator_unlock(rdev);
1636414c70cbSLiam Girdwood 	return regulator;
1637414c70cbSLiam Girdwood overflow_err:
1638414c70cbSLiam Girdwood 	list_del(&regulator->list);
1639414c70cbSLiam Girdwood 	kfree(regulator);
164066cf9a7eSMaciej Purski 	regulator_unlock(rdev);
1641414c70cbSLiam Girdwood 	return NULL;
1642414c70cbSLiam Girdwood }
1643414c70cbSLiam Girdwood 
164431aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev)
164531aae2beSMark Brown {
164600c877c6SLaxman Dewangan 	if (rdev->constraints && rdev->constraints->enable_time)
164700c877c6SLaxman Dewangan 		return rdev->constraints->enable_time;
164831aae2beSMark Brown 	if (!rdev->desc->ops->enable_time)
164979511ed3SMark Brown 		return rdev->desc->enable_time;
165031aae2beSMark Brown 	return rdev->desc->ops->enable_time(rdev);
165131aae2beSMark Brown }
165231aae2beSMark Brown 
1653a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias(
1654a06ccd9cSCharles Keepax 		struct device *dev, const char *supply)
1655a06ccd9cSCharles Keepax {
1656a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
1657a06ccd9cSCharles Keepax 
1658a06ccd9cSCharles Keepax 	list_for_each_entry(map, &regulator_supply_alias_list, list)
1659a06ccd9cSCharles Keepax 		if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
1660a06ccd9cSCharles Keepax 			return map;
1661a06ccd9cSCharles Keepax 
1662a06ccd9cSCharles Keepax 	return NULL;
1663a06ccd9cSCharles Keepax }
1664a06ccd9cSCharles Keepax 
1665a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply)
1666a06ccd9cSCharles Keepax {
1667a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
1668a06ccd9cSCharles Keepax 
1669a06ccd9cSCharles Keepax 	map = regulator_find_supply_alias(*dev, *supply);
1670a06ccd9cSCharles Keepax 	if (map) {
1671a06ccd9cSCharles Keepax 		dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
1672a06ccd9cSCharles Keepax 				*supply, map->alias_supply,
1673a06ccd9cSCharles Keepax 				dev_name(map->alias_dev));
1674a06ccd9cSCharles Keepax 		*dev = map->alias_dev;
1675a06ccd9cSCharles Keepax 		*supply = map->alias_supply;
1676a06ccd9cSCharles Keepax 	}
1677a06ccd9cSCharles Keepax }
1678a06ccd9cSCharles Keepax 
167985f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data)
168085f3b431STomeu Vizoso {
168185f3b431STomeu Vizoso 	struct regulator_dev *r = dev_to_rdev(dev);
168285f3b431STomeu Vizoso 
168385f3b431STomeu Vizoso 	return strcmp(rdev_get_name(r), data) == 0;
168485f3b431STomeu Vizoso }
168585f3b431STomeu Vizoso 
168685f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name)
168785f3b431STomeu Vizoso {
168885f3b431STomeu Vizoso 	struct device *dev;
168985f3b431STomeu Vizoso 
169085f3b431STomeu Vizoso 	dev = class_find_device(&regulator_class, NULL, name, regulator_match);
169185f3b431STomeu Vizoso 
169285f3b431STomeu Vizoso 	return dev ? dev_to_rdev(dev) : NULL;
169385f3b431STomeu Vizoso }
169485f3b431STomeu Vizoso 
169585f3b431STomeu Vizoso /**
169685f3b431STomeu Vizoso  * regulator_dev_lookup - lookup a regulator device.
169785f3b431STomeu Vizoso  * @dev: device for regulator "consumer".
169885f3b431STomeu Vizoso  * @supply: Supply name or regulator ID.
169985f3b431STomeu Vizoso  *
170085f3b431STomeu Vizoso  * If successful, returns a struct regulator_dev that corresponds to the name
1701163478daSDmitry Torokhov  * @supply and with the embedded struct device refcount incremented by one.
1702163478daSDmitry Torokhov  * The refcount must be dropped by calling put_device().
1703163478daSDmitry Torokhov  * On failure one of the following ERR-PTR-encoded values is returned:
1704163478daSDmitry Torokhov  * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed
1705163478daSDmitry Torokhov  * in the future.
170685f3b431STomeu Vizoso  */
170769511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev,
1708163478daSDmitry Torokhov 						  const char *supply)
170969511a45SRajendra Nayak {
171006217197SCharles Keepax 	struct regulator_dev *r = NULL;
171169511a45SRajendra Nayak 	struct device_node *node;
1712576ca436SMark Brown 	struct regulator_map *map;
1713576ca436SMark Brown 	const char *devname = NULL;
171469511a45SRajendra Nayak 
1715a06ccd9cSCharles Keepax 	regulator_supply_alias(&dev, &supply);
1716a06ccd9cSCharles Keepax 
171769511a45SRajendra Nayak 	/* first do a dt based lookup */
171869511a45SRajendra Nayak 	if (dev && dev->of_node) {
171969511a45SRajendra Nayak 		node = of_get_regulator(dev, supply);
17206d191a5fSMark Brown 		if (node) {
172185f3b431STomeu Vizoso 			r = of_find_regulator_by_node(node);
172285f3b431STomeu Vizoso 			if (r)
172369511a45SRajendra Nayak 				return r;
1724163478daSDmitry Torokhov 
17256d191a5fSMark Brown 			/*
1726163478daSDmitry Torokhov 			 * We have a node, but there is no device.
1727163478daSDmitry Torokhov 			 * assume it has not registered yet.
17286d191a5fSMark Brown 			 */
1729163478daSDmitry Torokhov 			return ERR_PTR(-EPROBE_DEFER);
17306d191a5fSMark Brown 		}
173169511a45SRajendra Nayak 	}
173269511a45SRajendra Nayak 
173369511a45SRajendra Nayak 	/* if not found, try doing it non-dt way */
1734576ca436SMark Brown 	if (dev)
1735576ca436SMark Brown 		devname = dev_name(dev);
1736576ca436SMark Brown 
173785f3b431STomeu Vizoso 	mutex_lock(&regulator_list_mutex);
1738576ca436SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
1739576ca436SMark Brown 		/* If the mapping has a device set up it must match */
1740576ca436SMark Brown 		if (map->dev_name &&
1741576ca436SMark Brown 		    (!devname || strcmp(map->dev_name, devname)))
1742576ca436SMark Brown 			continue;
1743576ca436SMark Brown 
174485f3b431STomeu Vizoso 		if (strcmp(map->supply, supply) == 0 &&
174585f3b431STomeu Vizoso 		    get_device(&map->regulator->dev)) {
1746163478daSDmitry Torokhov 			r = map->regulator;
1747163478daSDmitry Torokhov 			break;
1748576ca436SMark Brown 		}
174985f3b431STomeu Vizoso 	}
175085f3b431STomeu Vizoso 	mutex_unlock(&regulator_list_mutex);
1751576ca436SMark Brown 
1752163478daSDmitry Torokhov 	if (r)
1753163478daSDmitry Torokhov 		return r;
1754163478daSDmitry Torokhov 
175506217197SCharles Keepax 	r = regulator_lookup_by_name(supply);
175606217197SCharles Keepax 	if (r)
175706217197SCharles Keepax 		return r;
175806217197SCharles Keepax 
1759163478daSDmitry Torokhov 	return ERR_PTR(-ENODEV);
176069511a45SRajendra Nayak }
176169511a45SRajendra Nayak 
17626261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev)
17636261b06dSBjorn Andersson {
17646261b06dSBjorn Andersson 	struct regulator_dev *r;
17656261b06dSBjorn Andersson 	struct device *dev = rdev->dev.parent;
17666261b06dSBjorn Andersson 	int ret;
17676261b06dSBjorn Andersson 
176848f1b4efSKrzysztof Kozlowski 	/* No supply to resolve? */
17696261b06dSBjorn Andersson 	if (!rdev->supply_name)
17706261b06dSBjorn Andersson 		return 0;
17716261b06dSBjorn Andersson 
17726261b06dSBjorn Andersson 	/* Supply already resolved? */
17736261b06dSBjorn Andersson 	if (rdev->supply)
17746261b06dSBjorn Andersson 		return 0;
17756261b06dSBjorn Andersson 
1776163478daSDmitry Torokhov 	r = regulator_dev_lookup(dev, rdev->supply_name);
1777163478daSDmitry Torokhov 	if (IS_ERR(r)) {
1778163478daSDmitry Torokhov 		ret = PTR_ERR(r);
1779163478daSDmitry Torokhov 
178006423121SMark Brown 		/* Did the lookup explicitly defer for us? */
178106423121SMark Brown 		if (ret == -EPROBE_DEFER)
178206423121SMark Brown 			return ret;
178306423121SMark Brown 
17849f7e25edSMark Brown 		if (have_full_constraints()) {
17859f7e25edSMark Brown 			r = dummy_regulator_rdev;
178685f3b431STomeu Vizoso 			get_device(&r->dev);
17879f7e25edSMark Brown 		} else {
17886261b06dSBjorn Andersson 			dev_err(dev, "Failed to resolve %s-supply for %s\n",
17896261b06dSBjorn Andersson 				rdev->supply_name, rdev->desc->name);
17906261b06dSBjorn Andersson 			return -EPROBE_DEFER;
17916261b06dSBjorn Andersson 		}
17929f7e25edSMark Brown 	}
17936261b06dSBjorn Andersson 
179466d228a2SJon Hunter 	/*
179566d228a2SJon Hunter 	 * If the supply's parent device is not the same as the
179666d228a2SJon Hunter 	 * regulator's parent device, then ensure the parent device
179766d228a2SJon Hunter 	 * is bound before we resolve the supply, in case the parent
179866d228a2SJon Hunter 	 * device get probe deferred and unregisters the supply.
179966d228a2SJon Hunter 	 */
180066d228a2SJon Hunter 	if (r->dev.parent && r->dev.parent != rdev->dev.parent) {
180166d228a2SJon Hunter 		if (!device_is_bound(r->dev.parent)) {
180266d228a2SJon Hunter 			put_device(&r->dev);
180366d228a2SJon Hunter 			return -EPROBE_DEFER;
180466d228a2SJon Hunter 		}
180566d228a2SJon Hunter 	}
180666d228a2SJon Hunter 
18076261b06dSBjorn Andersson 	/* Recursively resolve the supply of the supply */
18086261b06dSBjorn Andersson 	ret = regulator_resolve_supply(r);
180985f3b431STomeu Vizoso 	if (ret < 0) {
181085f3b431STomeu Vizoso 		put_device(&r->dev);
18116261b06dSBjorn Andersson 		return ret;
181285f3b431STomeu Vizoso 	}
18136261b06dSBjorn Andersson 
18146261b06dSBjorn Andersson 	ret = set_supply(rdev, r);
181585f3b431STomeu Vizoso 	if (ret < 0) {
181685f3b431STomeu Vizoso 		put_device(&r->dev);
18176261b06dSBjorn Andersson 		return ret;
181885f3b431STomeu Vizoso 	}
18196261b06dSBjorn Andersson 
182005f224caSDouglas Anderson 	/*
182105f224caSDouglas Anderson 	 * In set_machine_constraints() we may have turned this regulator on
182205f224caSDouglas Anderson 	 * but we couldn't propagate to the supply if it hadn't been resolved
182305f224caSDouglas Anderson 	 * yet.  Do it now.
182405f224caSDouglas Anderson 	 */
182505f224caSDouglas Anderson 	if (rdev->use_count) {
18266261b06dSBjorn Andersson 		ret = regulator_enable(rdev->supply);
182736a1f1b6SJavier Martinez Canillas 		if (ret < 0) {
182836a1f1b6SJavier Martinez Canillas 			_regulator_put(rdev->supply);
18298e5356a7SJon Hunter 			rdev->supply = NULL;
18306261b06dSBjorn Andersson 			return ret;
18316261b06dSBjorn Andersson 		}
183236a1f1b6SJavier Martinez Canillas 	}
18336261b06dSBjorn Andersson 
18346261b06dSBjorn Andersson 	return 0;
18356261b06dSBjorn Andersson }
18366261b06dSBjorn Andersson 
18375ffbd136SMark Brown /* Internal regulator request function */
1838a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id,
1839a8bd42a9SDmitry Torokhov 				 enum regulator_get_type get_type)
1840414c70cbSLiam Girdwood {
1841414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
18427d245afaSDmitry Torokhov 	struct regulator *regulator;
1843a4d7641fSDmitry Torokhov 	const char *devname = dev ? dev_name(dev) : "deviceless";
1844317b5684SMark Brown 	int ret;
1845414c70cbSLiam Girdwood 
1846a8bd42a9SDmitry Torokhov 	if (get_type >= MAX_GET_TYPE) {
1847a8bd42a9SDmitry Torokhov 		dev_err(dev, "invalid type %d in %s\n", get_type, __func__);
1848a8bd42a9SDmitry Torokhov 		return ERR_PTR(-EINVAL);
1849a8bd42a9SDmitry Torokhov 	}
1850a8bd42a9SDmitry Torokhov 
1851414c70cbSLiam Girdwood 	if (id == NULL) {
18525da84fd9SJoe Perches 		pr_err("get() with no identifier\n");
1853043c998fSMark Brown 		return ERR_PTR(-EINVAL);
1854414c70cbSLiam Girdwood 	}
1855414c70cbSLiam Girdwood 
1856163478daSDmitry Torokhov 	rdev = regulator_dev_lookup(dev, id);
1857a4d7641fSDmitry Torokhov 	if (IS_ERR(rdev)) {
1858163478daSDmitry Torokhov 		ret = PTR_ERR(rdev);
1859ef60abbbSMark Brown 
18601e4b545cSNishanth Menon 		/*
1861a4d7641fSDmitry Torokhov 		 * If regulator_dev_lookup() fails with error other
1862a4d7641fSDmitry Torokhov 		 * than -ENODEV our job here is done, we simply return it.
18631e4b545cSNishanth Menon 		 */
1864a4d7641fSDmitry Torokhov 		if (ret != -ENODEV)
1865a4d7641fSDmitry Torokhov 			return ERR_PTR(ret);
18661e4b545cSNishanth Menon 
1867a4d7641fSDmitry Torokhov 		if (!have_full_constraints()) {
1868a4d7641fSDmitry Torokhov 			dev_warn(dev,
1869a4d7641fSDmitry Torokhov 				 "incomplete constraints, dummy supplies not allowed\n");
1870a4d7641fSDmitry Torokhov 			return ERR_PTR(-ENODEV);
187134abbd68SMark Brown 		}
187234abbd68SMark Brown 
1873a4d7641fSDmitry Torokhov 		switch (get_type) {
1874a4d7641fSDmitry Torokhov 		case NORMAL_GET:
1875a4d7641fSDmitry Torokhov 			/*
1876a4d7641fSDmitry Torokhov 			 * Assume that a regulator is physically present and
1877a4d7641fSDmitry Torokhov 			 * enabled, even if it isn't hooked up, and just
1878a4d7641fSDmitry Torokhov 			 * provide a dummy.
1879a4d7641fSDmitry Torokhov 			 */
1880a4d7641fSDmitry Torokhov 			dev_warn(dev,
1881a4d7641fSDmitry Torokhov 				 "%s supply %s not found, using dummy regulator\n",
1882a4d7641fSDmitry Torokhov 				 devname, id);
1883a4d7641fSDmitry Torokhov 			rdev = dummy_regulator_rdev;
1884a4d7641fSDmitry Torokhov 			get_device(&rdev->dev);
1885a4d7641fSDmitry Torokhov 			break;
1886414c70cbSLiam Girdwood 
1887a4d7641fSDmitry Torokhov 		case EXCLUSIVE_GET:
1888a4d7641fSDmitry Torokhov 			dev_warn(dev,
1889a4d7641fSDmitry Torokhov 				 "dummy supplies not allowed for exclusive requests\n");
1890a4d7641fSDmitry Torokhov 			/* fall through */
1891a4d7641fSDmitry Torokhov 
1892a4d7641fSDmitry Torokhov 		default:
1893a4d7641fSDmitry Torokhov 			return ERR_PTR(-ENODEV);
1894a4d7641fSDmitry Torokhov 		}
1895a4d7641fSDmitry Torokhov 	}
1896a4d7641fSDmitry Torokhov 
18975ffbd136SMark Brown 	if (rdev->exclusive) {
18985ffbd136SMark Brown 		regulator = ERR_PTR(-EPERM);
189985f3b431STomeu Vizoso 		put_device(&rdev->dev);
190085f3b431STomeu Vizoso 		return regulator;
19015ffbd136SMark Brown 	}
19025ffbd136SMark Brown 
1903a8bd42a9SDmitry Torokhov 	if (get_type == EXCLUSIVE_GET && rdev->open_count) {
19045ffbd136SMark Brown 		regulator = ERR_PTR(-EBUSY);
190585f3b431STomeu Vizoso 		put_device(&rdev->dev);
190685f3b431STomeu Vizoso 		return regulator;
19075ffbd136SMark Brown 	}
19085ffbd136SMark Brown 
190979d6f049SDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
191079d6f049SDmitry Osipenko 	ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled);
191179d6f049SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
191279d6f049SDmitry Osipenko 
191379d6f049SDmitry Osipenko 	if (ret != 0) {
191479d6f049SDmitry Osipenko 		regulator = ERR_PTR(-EPROBE_DEFER);
191579d6f049SDmitry Osipenko 		put_device(&rdev->dev);
191679d6f049SDmitry Osipenko 		return regulator;
191779d6f049SDmitry Osipenko 	}
191879d6f049SDmitry Osipenko 
19196261b06dSBjorn Andersson 	ret = regulator_resolve_supply(rdev);
19206261b06dSBjorn Andersson 	if (ret < 0) {
19216261b06dSBjorn Andersson 		regulator = ERR_PTR(ret);
192285f3b431STomeu Vizoso 		put_device(&rdev->dev);
192385f3b431STomeu Vizoso 		return regulator;
19246261b06dSBjorn Andersson 	}
19256261b06dSBjorn Andersson 
192685f3b431STomeu Vizoso 	if (!try_module_get(rdev->owner)) {
19277d245afaSDmitry Torokhov 		regulator = ERR_PTR(-EPROBE_DEFER);
192885f3b431STomeu Vizoso 		put_device(&rdev->dev);
192985f3b431STomeu Vizoso 		return regulator;
193085f3b431STomeu Vizoso 	}
1931a5766f11SLiam Girdwood 
1932414c70cbSLiam Girdwood 	regulator = create_regulator(rdev, dev, id);
1933414c70cbSLiam Girdwood 	if (regulator == NULL) {
1934414c70cbSLiam Girdwood 		regulator = ERR_PTR(-ENOMEM);
193585f3b431STomeu Vizoso 		put_device(&rdev->dev);
1936414c70cbSLiam Girdwood 		module_put(rdev->owner);
193785f3b431STomeu Vizoso 		return regulator;
1938414c70cbSLiam Girdwood 	}
1939414c70cbSLiam Girdwood 
19405ffbd136SMark Brown 	rdev->open_count++;
1941a8bd42a9SDmitry Torokhov 	if (get_type == EXCLUSIVE_GET) {
19425ffbd136SMark Brown 		rdev->exclusive = 1;
19435ffbd136SMark Brown 
19445ffbd136SMark Brown 		ret = _regulator_is_enabled(rdev);
19455ffbd136SMark Brown 		if (ret > 0)
19465ffbd136SMark Brown 			rdev->use_count = 1;
19475ffbd136SMark Brown 		else
19485ffbd136SMark Brown 			rdev->use_count = 0;
19495ffbd136SMark Brown 	}
19505ffbd136SMark Brown 
1951ed1ae2ddSpascal paillet 	device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
1952ed1ae2ddSpascal paillet 
1953414c70cbSLiam Girdwood 	return regulator;
1954414c70cbSLiam Girdwood }
19555ffbd136SMark Brown 
19565ffbd136SMark Brown /**
19575ffbd136SMark Brown  * regulator_get - lookup and obtain a reference to a regulator.
19585ffbd136SMark Brown  * @dev: device for regulator "consumer"
19595ffbd136SMark Brown  * @id: Supply name or regulator ID.
19605ffbd136SMark Brown  *
19615ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
19625ffbd136SMark Brown  * or IS_ERR() condition containing errno.
19635ffbd136SMark Brown  *
19645ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
19655ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
19665ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
19675ffbd136SMark Brown  * device pins in the datasheet.
19685ffbd136SMark Brown  */
19695ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id)
19705ffbd136SMark Brown {
1971a8bd42a9SDmitry Torokhov 	return _regulator_get(dev, id, NORMAL_GET);
19725ffbd136SMark Brown }
1973414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get);
1974414c70cbSLiam Girdwood 
1975070b9079SStephen Boyd /**
19765ffbd136SMark Brown  * regulator_get_exclusive - obtain exclusive access to a regulator.
19775ffbd136SMark Brown  * @dev: device for regulator "consumer"
19785ffbd136SMark Brown  * @id: Supply name or regulator ID.
19795ffbd136SMark Brown  *
19805ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
19815ffbd136SMark Brown  * or IS_ERR() condition containing errno.  Other consumers will be
198269c3f723SStephen Boyd  * unable to obtain this regulator while this reference is held and the
198369c3f723SStephen Boyd  * use count for the regulator will be initialised to reflect the current
198469c3f723SStephen Boyd  * state of the regulator.
19855ffbd136SMark Brown  *
19865ffbd136SMark Brown  * This is intended for use by consumers which cannot tolerate shared
19875ffbd136SMark Brown  * use of the regulator such as those which need to force the
19885ffbd136SMark Brown  * regulator off for correct operation of the hardware they are
19895ffbd136SMark Brown  * controlling.
19905ffbd136SMark Brown  *
19915ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
19925ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
19935ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
19945ffbd136SMark Brown  * device pins in the datasheet.
19955ffbd136SMark Brown  */
19965ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
19975ffbd136SMark Brown {
1998a8bd42a9SDmitry Torokhov 	return _regulator_get(dev, id, EXCLUSIVE_GET);
19995ffbd136SMark Brown }
20005ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive);
20015ffbd136SMark Brown 
2002de1dd9fdSMark Brown /**
2003de1dd9fdSMark Brown  * regulator_get_optional - obtain optional access to a regulator.
2004de1dd9fdSMark Brown  * @dev: device for regulator "consumer"
2005de1dd9fdSMark Brown  * @id: Supply name or regulator ID.
2006de1dd9fdSMark Brown  *
2007de1dd9fdSMark Brown  * Returns a struct regulator corresponding to the regulator producer,
200869c3f723SStephen Boyd  * or IS_ERR() condition containing errno.
2009de1dd9fdSMark Brown  *
2010de1dd9fdSMark Brown  * This is intended for use by consumers for devices which can have
2011de1dd9fdSMark Brown  * some supplies unconnected in normal use, such as some MMC devices.
2012de1dd9fdSMark Brown  * It can allow the regulator core to provide stub supplies for other
2013de1dd9fdSMark Brown  * supplies requested using normal regulator_get() calls without
2014de1dd9fdSMark Brown  * disrupting the operation of drivers that can handle absent
2015de1dd9fdSMark Brown  * supplies.
2016de1dd9fdSMark Brown  *
2017de1dd9fdSMark Brown  * Use of supply names configured via regulator_set_device_supply() is
2018de1dd9fdSMark Brown  * strongly encouraged.  It is recommended that the supply name used
2019de1dd9fdSMark Brown  * should match the name used for the supply and/or the relevant
2020de1dd9fdSMark Brown  * device pins in the datasheet.
2021de1dd9fdSMark Brown  */
2022de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id)
2023de1dd9fdSMark Brown {
2024a8bd42a9SDmitry Torokhov 	return _regulator_get(dev, id, OPTIONAL_GET);
2025de1dd9fdSMark Brown }
2026de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional);
2027de1dd9fdSMark Brown 
202883b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */
202923ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator)
2030414c70cbSLiam Girdwood {
2031414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
2032414c70cbSLiam Girdwood 
203393576842SViresh Kumar 	if (IS_ERR_OR_NULL(regulator))
2034414c70cbSLiam Girdwood 		return;
2035414c70cbSLiam Girdwood 
203670cfef26SKrzysztof Kozlowski 	lockdep_assert_held_once(&regulator_list_mutex);
203770cfef26SKrzysztof Kozlowski 
20385451781dSDouglas Anderson 	/* Docs say you must disable before calling regulator_put() */
20395451781dSDouglas Anderson 	WARN_ON(regulator->enable_count);
20405451781dSDouglas Anderson 
2041414c70cbSLiam Girdwood 	rdev = regulator->rdev;
2042414c70cbSLiam Girdwood 
20435de70519SMark Brown 	debugfs_remove_recursive(regulator->debugfs);
20445de70519SMark Brown 
2045ed1ae2ddSpascal paillet 	if (regulator->dev) {
2046ed1ae2ddSpascal paillet 		device_link_remove(regulator->dev, &rdev->dev);
2047ed1ae2ddSpascal paillet 
2048414c70cbSLiam Girdwood 		/* remove any sysfs entries */
2049414c70cbSLiam Girdwood 		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
2050ed1ae2ddSpascal paillet 	}
2051ed1ae2ddSpascal paillet 
205266cf9a7eSMaciej Purski 	regulator_lock(rdev);
2053414c70cbSLiam Girdwood 	list_del(&regulator->list);
2054414c70cbSLiam Girdwood 
20555ffbd136SMark Brown 	rdev->open_count--;
20565ffbd136SMark Brown 	rdev->exclusive = 0;
205785f3b431STomeu Vizoso 	put_device(&rdev->dev);
205866cf9a7eSMaciej Purski 	regulator_unlock(rdev);
20595ffbd136SMark Brown 
20600630b614SStephen Boyd 	kfree_const(regulator->supply_name);
20611768514eSMark Brown 	kfree(regulator);
20621768514eSMark Brown 
2063414c70cbSLiam Girdwood 	module_put(rdev->owner);
206423ff2f0fSCharles Keepax }
206523ff2f0fSCharles Keepax 
206623ff2f0fSCharles Keepax /**
206723ff2f0fSCharles Keepax  * regulator_put - "free" the regulator source
206823ff2f0fSCharles Keepax  * @regulator: regulator source
206923ff2f0fSCharles Keepax  *
207023ff2f0fSCharles Keepax  * Note: drivers must ensure that all regulator_enable calls made on this
207123ff2f0fSCharles Keepax  * regulator source are balanced by regulator_disable calls prior to calling
207223ff2f0fSCharles Keepax  * this function.
207323ff2f0fSCharles Keepax  */
207423ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator)
207523ff2f0fSCharles Keepax {
207623ff2f0fSCharles Keepax 	mutex_lock(&regulator_list_mutex);
207723ff2f0fSCharles Keepax 	_regulator_put(regulator);
2078414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2079414c70cbSLiam Girdwood }
2080414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put);
2081414c70cbSLiam Girdwood 
2082a06ccd9cSCharles Keepax /**
2083a06ccd9cSCharles Keepax  * regulator_register_supply_alias - Provide device alias for supply lookup
2084a06ccd9cSCharles Keepax  *
2085a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2086a06ccd9cSCharles Keepax  * @id: Supply name or regulator ID
2087a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
2088a06ccd9cSCharles Keepax  * @alias_id: Supply name or regulator ID that should be used to lookup the
2089a06ccd9cSCharles Keepax  * supply
2090a06ccd9cSCharles Keepax  *
2091a06ccd9cSCharles Keepax  * All lookups for id on dev will instead be conducted for alias_id on
2092a06ccd9cSCharles Keepax  * alias_dev.
2093a06ccd9cSCharles Keepax  */
2094a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id,
2095a06ccd9cSCharles Keepax 				    struct device *alias_dev,
2096a06ccd9cSCharles Keepax 				    const char *alias_id)
2097a06ccd9cSCharles Keepax {
2098a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
2099a06ccd9cSCharles Keepax 
2100a06ccd9cSCharles Keepax 	map = regulator_find_supply_alias(dev, id);
2101a06ccd9cSCharles Keepax 	if (map)
2102a06ccd9cSCharles Keepax 		return -EEXIST;
2103a06ccd9cSCharles Keepax 
2104a06ccd9cSCharles Keepax 	map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
2105a06ccd9cSCharles Keepax 	if (!map)
2106a06ccd9cSCharles Keepax 		return -ENOMEM;
2107a06ccd9cSCharles Keepax 
2108a06ccd9cSCharles Keepax 	map->src_dev = dev;
2109a06ccd9cSCharles Keepax 	map->src_supply = id;
2110a06ccd9cSCharles Keepax 	map->alias_dev = alias_dev;
2111a06ccd9cSCharles Keepax 	map->alias_supply = alias_id;
2112a06ccd9cSCharles Keepax 
2113a06ccd9cSCharles Keepax 	list_add(&map->list, &regulator_supply_alias_list);
2114a06ccd9cSCharles Keepax 
2115a06ccd9cSCharles Keepax 	pr_info("Adding alias for supply %s,%s -> %s,%s\n",
2116a06ccd9cSCharles Keepax 		id, dev_name(dev), alias_id, dev_name(alias_dev));
2117a06ccd9cSCharles Keepax 
2118a06ccd9cSCharles Keepax 	return 0;
2119a06ccd9cSCharles Keepax }
2120a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias);
2121a06ccd9cSCharles Keepax 
2122a06ccd9cSCharles Keepax /**
2123a06ccd9cSCharles Keepax  * regulator_unregister_supply_alias - Remove device alias
2124a06ccd9cSCharles Keepax  *
2125a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2126a06ccd9cSCharles Keepax  * @id: Supply name or regulator ID
2127a06ccd9cSCharles Keepax  *
2128a06ccd9cSCharles Keepax  * Remove a lookup alias if one exists for id on dev.
2129a06ccd9cSCharles Keepax  */
2130a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id)
2131a06ccd9cSCharles Keepax {
2132a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
2133a06ccd9cSCharles Keepax 
2134a06ccd9cSCharles Keepax 	map = regulator_find_supply_alias(dev, id);
2135a06ccd9cSCharles Keepax 	if (map) {
2136a06ccd9cSCharles Keepax 		list_del(&map->list);
2137a06ccd9cSCharles Keepax 		kfree(map);
2138a06ccd9cSCharles Keepax 	}
2139a06ccd9cSCharles Keepax }
2140a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
2141a06ccd9cSCharles Keepax 
2142a06ccd9cSCharles Keepax /**
2143a06ccd9cSCharles Keepax  * regulator_bulk_register_supply_alias - register multiple aliases
2144a06ccd9cSCharles Keepax  *
2145a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2146a06ccd9cSCharles Keepax  * @id: List of supply names or regulator IDs
2147a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
2148a06ccd9cSCharles Keepax  * @alias_id: List of supply names or regulator IDs that should be used to
2149a06ccd9cSCharles Keepax  * lookup the supply
2150a06ccd9cSCharles Keepax  * @num_id: Number of aliases to register
2151a06ccd9cSCharles Keepax  *
2152a06ccd9cSCharles Keepax  * @return 0 on success, an errno on failure.
2153a06ccd9cSCharles Keepax  *
2154a06ccd9cSCharles Keepax  * This helper function allows drivers to register several supply
2155a06ccd9cSCharles Keepax  * aliases in one operation.  If any of the aliases cannot be
2156a06ccd9cSCharles Keepax  * registered any aliases that were registered will be removed
2157a06ccd9cSCharles Keepax  * before returning to the caller.
2158a06ccd9cSCharles Keepax  */
21599f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev,
21609f8c0fe9SLee Jones 					 const char *const *id,
2161a06ccd9cSCharles Keepax 					 struct device *alias_dev,
21629f8c0fe9SLee Jones 					 const char *const *alias_id,
2163a06ccd9cSCharles Keepax 					 int num_id)
2164a06ccd9cSCharles Keepax {
2165a06ccd9cSCharles Keepax 	int i;
2166a06ccd9cSCharles Keepax 	int ret;
2167a06ccd9cSCharles Keepax 
2168a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i) {
2169a06ccd9cSCharles Keepax 		ret = regulator_register_supply_alias(dev, id[i], alias_dev,
2170a06ccd9cSCharles Keepax 						      alias_id[i]);
2171a06ccd9cSCharles Keepax 		if (ret < 0)
2172a06ccd9cSCharles Keepax 			goto err;
2173a06ccd9cSCharles Keepax 	}
2174a06ccd9cSCharles Keepax 
2175a06ccd9cSCharles Keepax 	return 0;
2176a06ccd9cSCharles Keepax 
2177a06ccd9cSCharles Keepax err:
2178a06ccd9cSCharles Keepax 	dev_err(dev,
2179a06ccd9cSCharles Keepax 		"Failed to create supply alias %s,%s -> %s,%s\n",
2180a06ccd9cSCharles Keepax 		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
2181a06ccd9cSCharles Keepax 
2182a06ccd9cSCharles Keepax 	while (--i >= 0)
2183a06ccd9cSCharles Keepax 		regulator_unregister_supply_alias(dev, id[i]);
2184a06ccd9cSCharles Keepax 
2185a06ccd9cSCharles Keepax 	return ret;
2186a06ccd9cSCharles Keepax }
2187a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
2188a06ccd9cSCharles Keepax 
2189a06ccd9cSCharles Keepax /**
2190a06ccd9cSCharles Keepax  * regulator_bulk_unregister_supply_alias - unregister multiple aliases
2191a06ccd9cSCharles Keepax  *
2192a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2193a06ccd9cSCharles Keepax  * @id: List of supply names or regulator IDs
2194a06ccd9cSCharles Keepax  * @num_id: Number of aliases to unregister
2195a06ccd9cSCharles Keepax  *
2196a06ccd9cSCharles Keepax  * This helper function allows drivers to unregister several supply
2197a06ccd9cSCharles Keepax  * aliases in one operation.
2198a06ccd9cSCharles Keepax  */
2199a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev,
22009f8c0fe9SLee Jones 					    const char *const *id,
2201a06ccd9cSCharles Keepax 					    int num_id)
2202a06ccd9cSCharles Keepax {
2203a06ccd9cSCharles Keepax 	int i;
2204a06ccd9cSCharles Keepax 
2205a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i)
2206a06ccd9cSCharles Keepax 		regulator_unregister_supply_alias(dev, id[i]);
2207a06ccd9cSCharles Keepax }
2208a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
2209a06ccd9cSCharles Keepax 
2210a06ccd9cSCharles Keepax 
2211f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
2212f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev,
2213f19b00daSKim, Milo 				const struct regulator_config *config)
2214f19b00daSKim, Milo {
2215f19b00daSKim, Milo 	struct regulator_enable_gpio *pin;
2216778b28b4SRussell King 	struct gpio_desc *gpiod;
2217f19b00daSKim, Milo 
2218e45e290aSLinus Walleij 	gpiod = config->ena_gpiod;
2219778b28b4SRussell King 
2220f19b00daSKim, Milo 	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
2221778b28b4SRussell King 		if (pin->gpiod == gpiod) {
2222541d052dSLinus Walleij 			rdev_dbg(rdev, "GPIO is already used\n");
2223f19b00daSKim, Milo 			goto update_ena_gpio_to_rdev;
2224f19b00daSKim, Milo 		}
2225f19b00daSKim, Milo 	}
2226f19b00daSKim, Milo 
2227f19b00daSKim, Milo 	pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
2228541d052dSLinus Walleij 	if (pin == NULL)
2229f19b00daSKim, Milo 		return -ENOMEM;
2230f19b00daSKim, Milo 
2231778b28b4SRussell King 	pin->gpiod = gpiod;
2232f19b00daSKim, Milo 	list_add(&pin->list, &regulator_ena_gpio_list);
2233f19b00daSKim, Milo 
2234f19b00daSKim, Milo update_ena_gpio_to_rdev:
2235f19b00daSKim, Milo 	pin->request_count++;
2236f19b00daSKim, Milo 	rdev->ena_pin = pin;
2237f19b00daSKim, Milo 	return 0;
2238f19b00daSKim, Milo }
2239f19b00daSKim, Milo 
2240f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev)
2241f19b00daSKim, Milo {
2242f19b00daSKim, Milo 	struct regulator_enable_gpio *pin, *n;
2243f19b00daSKim, Milo 
2244f19b00daSKim, Milo 	if (!rdev->ena_pin)
2245f19b00daSKim, Milo 		return;
2246f19b00daSKim, Milo 
2247f19b00daSKim, Milo 	/* Free the GPIO only in case of no use */
2248f19b00daSKim, Milo 	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
2249778b28b4SRussell King 		if (pin->gpiod == rdev->ena_pin->gpiod) {
2250f19b00daSKim, Milo 			if (pin->request_count <= 1) {
2251f19b00daSKim, Milo 				pin->request_count = 0;
225278927aa4SLinus Walleij 				gpiod_put(pin->gpiod);
2253f19b00daSKim, Milo 				list_del(&pin->list);
2254f19b00daSKim, Milo 				kfree(pin);
225560a2362fSSeung-Woo Kim 				rdev->ena_pin = NULL;
225660a2362fSSeung-Woo Kim 				return;
2257f19b00daSKim, Milo 			} else {
2258f19b00daSKim, Milo 				pin->request_count--;
2259f19b00daSKim, Milo 			}
2260f19b00daSKim, Milo 		}
2261f19b00daSKim, Milo 	}
2262f19b00daSKim, Milo }
2263f19b00daSKim, Milo 
2264967cfb18SKim, Milo /**
226531d6eebfSRobert P. J. Day  * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control
226631d6eebfSRobert P. J. Day  * @rdev: regulator_dev structure
226731d6eebfSRobert P. J. Day  * @enable: enable GPIO at initial use?
226831d6eebfSRobert P. J. Day  *
2269967cfb18SKim, Milo  * GPIO is enabled in case of initial use. (enable_count is 0)
2270967cfb18SKim, Milo  * GPIO is disabled when it is not shared any more. (enable_count <= 1)
2271967cfb18SKim, Milo  */
2272967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
2273967cfb18SKim, Milo {
2274967cfb18SKim, Milo 	struct regulator_enable_gpio *pin = rdev->ena_pin;
2275967cfb18SKim, Milo 
2276967cfb18SKim, Milo 	if (!pin)
2277967cfb18SKim, Milo 		return -EINVAL;
2278967cfb18SKim, Milo 
2279967cfb18SKim, Milo 	if (enable) {
2280967cfb18SKim, Milo 		/* Enable GPIO at initial use */
2281967cfb18SKim, Milo 		if (pin->enable_count == 0)
228201dc79cdSLinus Walleij 			gpiod_set_value_cansleep(pin->gpiod, 1);
2283967cfb18SKim, Milo 
2284967cfb18SKim, Milo 		pin->enable_count++;
2285967cfb18SKim, Milo 	} else {
2286967cfb18SKim, Milo 		if (pin->enable_count > 1) {
2287967cfb18SKim, Milo 			pin->enable_count--;
2288967cfb18SKim, Milo 			return 0;
2289967cfb18SKim, Milo 		}
2290967cfb18SKim, Milo 
2291967cfb18SKim, Milo 		/* Disable GPIO if not used */
2292967cfb18SKim, Milo 		if (pin->enable_count <= 1) {
229301dc79cdSLinus Walleij 			gpiod_set_value_cansleep(pin->gpiod, 0);
2294967cfb18SKim, Milo 			pin->enable_count = 0;
2295967cfb18SKim, Milo 		}
2296967cfb18SKim, Milo 	}
2297967cfb18SKim, Milo 
2298967cfb18SKim, Milo 	return 0;
2299967cfb18SKim, Milo }
2300967cfb18SKim, Milo 
230179fd1141SGuodong Xu /**
230279fd1141SGuodong Xu  * _regulator_enable_delay - a delay helper function
230379fd1141SGuodong Xu  * @delay: time to delay in microseconds
230479fd1141SGuodong Xu  *
23055df529d4SThierry Reding  * Delay for the requested amount of time as per the guidelines in:
23065df529d4SThierry Reding  *
23075df529d4SThierry Reding  *     Documentation/timers/timers-howto.txt
23085df529d4SThierry Reding  *
23095df529d4SThierry Reding  * The assumption here is that regulators will never be enabled in
23105df529d4SThierry Reding  * atomic context and therefore sleeping functions can be used.
23115df529d4SThierry Reding  */
231279fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay)
231379fd1141SGuodong Xu {
23145df529d4SThierry Reding 	unsigned int ms = delay / 1000;
23155df529d4SThierry Reding 	unsigned int us = delay % 1000;
23165df529d4SThierry Reding 
23175df529d4SThierry Reding 	if (ms > 0) {
23185df529d4SThierry Reding 		/*
23195df529d4SThierry Reding 		 * For small enough values, handle super-millisecond
23205df529d4SThierry Reding 		 * delays in the usleep_range() call below.
23215df529d4SThierry Reding 		 */
23225df529d4SThierry Reding 		if (ms < 20)
23235df529d4SThierry Reding 			us += ms * 1000;
23245df529d4SThierry Reding 		else
23255df529d4SThierry Reding 			msleep(ms);
23265df529d4SThierry Reding 	}
23275df529d4SThierry Reding 
23285df529d4SThierry Reding 	/*
23295df529d4SThierry Reding 	 * Give the scheduler some room to coalesce with any other
23305df529d4SThierry Reding 	 * wakeup sources. For delays shorter than 10 us, don't even
23315df529d4SThierry Reding 	 * bother setting up high-resolution timers and just busy-
23325df529d4SThierry Reding 	 * loop.
23335df529d4SThierry Reding 	 */
23345df529d4SThierry Reding 	if (us >= 10)
23355df529d4SThierry Reding 		usleep_range(us, us + 100);
23365df529d4SThierry Reding 	else
23375df529d4SThierry Reding 		udelay(us);
23385c5659d0SMark Brown }
23395c5659d0SMark Brown 
23405c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev)
23415c5659d0SMark Brown {
23425c5659d0SMark Brown 	int ret, delay;
23435c5659d0SMark Brown 
23445c5659d0SMark Brown 	/* Query before enabling in case configuration dependent.  */
23455c5659d0SMark Brown 	ret = _regulator_get_enable_time(rdev);
23465c5659d0SMark Brown 	if (ret >= 0) {
23475c5659d0SMark Brown 		delay = ret;
23485c5659d0SMark Brown 	} else {
2349414c70cbSLiam Girdwood 		rdev_warn(rdev, "enable_time() failed: %d\n", ret);
2350414c70cbSLiam Girdwood 		delay = 0;
2351414c70cbSLiam Girdwood 	}
23525c5659d0SMark Brown 
2353414c70cbSLiam Girdwood 	trace_regulator_enable(rdev_get_name(rdev));
2354414c70cbSLiam Girdwood 
2355871f5650SGuodong Xu 	if (rdev->desc->off_on_delay) {
2356871f5650SGuodong Xu 		/* if needed, keep a distance of off_on_delay from last time
2357871f5650SGuodong Xu 		 * this regulator was disabled.
2358871f5650SGuodong Xu 		 */
2359871f5650SGuodong Xu 		unsigned long start_jiffy = jiffies;
2360871f5650SGuodong Xu 		unsigned long intended, max_delay, remaining;
2361871f5650SGuodong Xu 
2362871f5650SGuodong Xu 		max_delay = usecs_to_jiffies(rdev->desc->off_on_delay);
2363871f5650SGuodong Xu 		intended = rdev->last_off_jiffy + max_delay;
2364871f5650SGuodong Xu 
2365871f5650SGuodong Xu 		if (time_before(start_jiffy, intended)) {
2366871f5650SGuodong Xu 			/* calc remaining jiffies to deal with one-time
2367871f5650SGuodong Xu 			 * timer wrapping.
2368871f5650SGuodong Xu 			 * in case of multiple timer wrapping, either it can be
2369871f5650SGuodong Xu 			 * detected by out-of-range remaining, or it cannot be
237048f1b4efSKrzysztof Kozlowski 			 * detected and we get a penalty of
2371871f5650SGuodong Xu 			 * _regulator_enable_delay().
2372871f5650SGuodong Xu 			 */
2373871f5650SGuodong Xu 			remaining = intended - start_jiffy;
2374871f5650SGuodong Xu 			if (remaining <= max_delay)
2375871f5650SGuodong Xu 				_regulator_enable_delay(
2376871f5650SGuodong Xu 						jiffies_to_usecs(remaining));
2377871f5650SGuodong Xu 		}
2378871f5650SGuodong Xu 	}
2379871f5650SGuodong Xu 
2380414c70cbSLiam Girdwood 	if (rdev->ena_pin) {
238129d62ec5SDoug Anderson 		if (!rdev->ena_gpio_state) {
23829a2372faSMark Brown 			ret = regulator_ena_gpio_ctrl(rdev, true);
2383414c70cbSLiam Girdwood 			if (ret < 0)
2384414c70cbSLiam Girdwood 				return ret;
23859a2372faSMark Brown 			rdev->ena_gpio_state = 1;
238629d62ec5SDoug Anderson 		}
23879a2372faSMark Brown 	} else if (rdev->desc->ops->enable) {
23889a2372faSMark Brown 		ret = rdev->desc->ops->enable(rdev);
23899a2372faSMark Brown 		if (ret < 0)
23909a2372faSMark Brown 			return ret;
23919a2372faSMark Brown 	} else {
23929a2372faSMark Brown 		return -EINVAL;
23935c5659d0SMark Brown 	}
23949a2372faSMark Brown 
23959a2372faSMark Brown 	/* Allow the regulator to ramp; it would be useful to extend
239631aae2beSMark Brown 	 * this for bulk operations so that the regulators can ramp
2397a7433cffSLinus Walleij 	 * together.  */
23985da84fd9SJoe Perches 	trace_regulator_enable_delay(rdev_get_name(rdev));
2399414c70cbSLiam Girdwood 
240079fd1141SGuodong Xu 	_regulator_enable_delay(delay);
2401a7433cffSLinus Walleij 
2402414c70cbSLiam Girdwood 	trace_regulator_enable_complete(rdev_get_name(rdev));
2403414c70cbSLiam Girdwood 
24049a2372faSMark Brown 	return 0;
24059a2372faSMark Brown }
24069a2372faSMark Brown 
24075451781dSDouglas Anderson /**
24085451781dSDouglas Anderson  * _regulator_handle_consumer_enable - handle that a consumer enabled
24095451781dSDouglas Anderson  * @regulator: regulator source
24105451781dSDouglas Anderson  *
24115451781dSDouglas Anderson  * Some things on a regulator consumer (like the contribution towards total
24125451781dSDouglas Anderson  * load on the regulator) only have an effect when the consumer wants the
24135451781dSDouglas Anderson  * regulator enabled.  Explained in example with two consumers of the same
24145451781dSDouglas Anderson  * regulator:
24155451781dSDouglas Anderson  *   consumer A: set_load(100);       => total load = 0
24165451781dSDouglas Anderson  *   consumer A: regulator_enable();  => total load = 100
24175451781dSDouglas Anderson  *   consumer B: set_load(1000);      => total load = 100
24185451781dSDouglas Anderson  *   consumer B: regulator_enable();  => total load = 1100
24195451781dSDouglas Anderson  *   consumer A: regulator_disable(); => total_load = 1000
24205451781dSDouglas Anderson  *
24215451781dSDouglas Anderson  * This function (together with _regulator_handle_consumer_disable) is
24225451781dSDouglas Anderson  * responsible for keeping track of the refcount for a given regulator consumer
24235451781dSDouglas Anderson  * and applying / unapplying these things.
24245451781dSDouglas Anderson  *
24255451781dSDouglas Anderson  * Returns 0 upon no error; -error upon error.
24265451781dSDouglas Anderson  */
24275451781dSDouglas Anderson static int _regulator_handle_consumer_enable(struct regulator *regulator)
2428414c70cbSLiam Girdwood {
24295451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
24305451781dSDouglas Anderson 
24315451781dSDouglas Anderson 	lockdep_assert_held_once(&rdev->mutex.base);
24325451781dSDouglas Anderson 
24335451781dSDouglas Anderson 	regulator->enable_count++;
24345451781dSDouglas Anderson 	if (regulator->uA_load && regulator->enable_count == 1)
24355451781dSDouglas Anderson 		return drms_uA_update(rdev);
24365451781dSDouglas Anderson 
24375451781dSDouglas Anderson 	return 0;
24385451781dSDouglas Anderson }
24395451781dSDouglas Anderson 
24405451781dSDouglas Anderson /**
24415451781dSDouglas Anderson  * _regulator_handle_consumer_disable - handle that a consumer disabled
24425451781dSDouglas Anderson  * @regulator: regulator source
24435451781dSDouglas Anderson  *
24445451781dSDouglas Anderson  * The opposite of _regulator_handle_consumer_enable().
24455451781dSDouglas Anderson  *
24465451781dSDouglas Anderson  * Returns 0 upon no error; -error upon error.
24475451781dSDouglas Anderson  */
24485451781dSDouglas Anderson static int _regulator_handle_consumer_disable(struct regulator *regulator)
24495451781dSDouglas Anderson {
24505451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
24515451781dSDouglas Anderson 
24525451781dSDouglas Anderson 	lockdep_assert_held_once(&rdev->mutex.base);
24535451781dSDouglas Anderson 
24545451781dSDouglas Anderson 	if (!regulator->enable_count) {
24555451781dSDouglas Anderson 		rdev_err(rdev, "Underflow of regulator enable count\n");
24565451781dSDouglas Anderson 		return -EINVAL;
24575451781dSDouglas Anderson 	}
24585451781dSDouglas Anderson 
24595451781dSDouglas Anderson 	regulator->enable_count--;
24605451781dSDouglas Anderson 	if (regulator->uA_load && regulator->enable_count == 0)
24615451781dSDouglas Anderson 		return drms_uA_update(rdev);
24625451781dSDouglas Anderson 
24635451781dSDouglas Anderson 	return 0;
24645451781dSDouglas Anderson }
24655451781dSDouglas Anderson 
24665451781dSDouglas Anderson /* locks held by regulator_enable() */
24675451781dSDouglas Anderson static int _regulator_enable(struct regulator *regulator)
24685451781dSDouglas Anderson {
24695451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
2470414c70cbSLiam Girdwood 	int ret;
2471414c70cbSLiam Girdwood 
2472f8702f9eSDmitry Osipenko 	lockdep_assert_held_once(&rdev->mutex.base);
2473f8702f9eSDmitry Osipenko 
24741fc12b05SDouglas Anderson 	if (rdev->use_count == 0 && rdev->supply) {
24755451781dSDouglas Anderson 		ret = _regulator_enable(rdev->supply);
2476f8702f9eSDmitry Osipenko 		if (ret < 0)
2477f8702f9eSDmitry Osipenko 			return ret;
2478f8702f9eSDmitry Osipenko 	}
2479f8702f9eSDmitry Osipenko 
2480f8702f9eSDmitry Osipenko 	/* balance only if there are regulators coupled */
2481f8702f9eSDmitry Osipenko 	if (rdev->coupling_desc.n_coupled > 1) {
2482f8702f9eSDmitry Osipenko 		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
2483f8702f9eSDmitry Osipenko 		if (ret < 0)
2484f8702f9eSDmitry Osipenko 			goto err_disable_supply;
2485f8702f9eSDmitry Osipenko 	}
248670cfef26SKrzysztof Kozlowski 
24875451781dSDouglas Anderson 	ret = _regulator_handle_consumer_enable(regulator);
24885451781dSDouglas Anderson 	if (ret < 0)
24895451781dSDouglas Anderson 		goto err_disable_supply;
2490cf7bbcdfSMark Brown 
2491414c70cbSLiam Girdwood 	if (rdev->use_count == 0) {
2492cf7bbcdfSMark Brown 		/* The regulator may on if it's not switchable or left on */
2493414c70cbSLiam Girdwood 		ret = _regulator_is_enabled(rdev);
2494414c70cbSLiam Girdwood 		if (ret == -EINVAL || ret == 0) {
24958a34e979SWEN Pingbo 			if (!regulator_ops_is_valid(rdev,
2496f8702f9eSDmitry Osipenko 					REGULATOR_CHANGE_STATUS)) {
2497f8702f9eSDmitry Osipenko 				ret = -EPERM;
24985451781dSDouglas Anderson 				goto err_consumer_disable;
2499f8702f9eSDmitry Osipenko 			}
2500412aec61SDavid Brownell 
2501414c70cbSLiam Girdwood 			ret = _regulator_do_enable(rdev);
2502412aec61SDavid Brownell 			if (ret < 0)
25035451781dSDouglas Anderson 				goto err_consumer_disable;
2504414c70cbSLiam Girdwood 
2505264b88c9SHarald Geyer 			_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,
2506264b88c9SHarald Geyer 					     NULL);
2507414c70cbSLiam Girdwood 		} else if (ret < 0) {
2508414c70cbSLiam Girdwood 			rdev_err(rdev, "is_enabled() failed: %d\n", ret);
25095451781dSDouglas Anderson 			goto err_consumer_disable;
2510414c70cbSLiam Girdwood 		}
2511414c70cbSLiam Girdwood 		/* Fallthrough on positive return values - already enabled */
2512414c70cbSLiam Girdwood 	}
2513414c70cbSLiam Girdwood 
2514414c70cbSLiam Girdwood 	rdev->use_count++;
2515414c70cbSLiam Girdwood 
2516414c70cbSLiam Girdwood 	return 0;
2517f8702f9eSDmitry Osipenko 
25185451781dSDouglas Anderson err_consumer_disable:
25195451781dSDouglas Anderson 	_regulator_handle_consumer_disable(regulator);
25205451781dSDouglas Anderson 
2521f8702f9eSDmitry Osipenko err_disable_supply:
25221fc12b05SDouglas Anderson 	if (rdev->use_count == 0 && rdev->supply)
25235451781dSDouglas Anderson 		_regulator_disable(rdev->supply);
2524f8702f9eSDmitry Osipenko 
2525f8702f9eSDmitry Osipenko 	return ret;
2526414c70cbSLiam Girdwood }
2527414c70cbSLiam Girdwood 
2528414c70cbSLiam Girdwood /**
2529414c70cbSLiam Girdwood  * regulator_enable - enable regulator output
2530414c70cbSLiam Girdwood  * @regulator: regulator source
2531414c70cbSLiam Girdwood  *
2532414c70cbSLiam Girdwood  * Request that the regulator be enabled with the regulator output at
2533414c70cbSLiam Girdwood  * the predefined voltage or current value.  Calls to regulator_enable()
2534414c70cbSLiam Girdwood  * must be balanced with calls to regulator_disable().
2535414c70cbSLiam Girdwood  *
2536414c70cbSLiam Girdwood  * NOTE: the output value can be set by other drivers, boot loader or may be
2537414c70cbSLiam Girdwood  * hardwired in the regulator.
2538414c70cbSLiam Girdwood  */
2539414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator)
2540414c70cbSLiam Girdwood {
2541414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2542f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
25435451781dSDouglas Anderson 	int ret;
25446492bc1bSMark Brown 
2545f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
25465451781dSDouglas Anderson 	ret = _regulator_enable(regulator);
2547f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(rdev, &ww_ctx);
25483801b86aSMark Brown 
2549414c70cbSLiam Girdwood 	return ret;
2550414c70cbSLiam Girdwood }
2551414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable);
2552414c70cbSLiam Girdwood 
25535c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev)
25545c5659d0SMark Brown {
25555c5659d0SMark Brown 	int ret;
25565c5659d0SMark Brown 
25575c5659d0SMark Brown 	trace_regulator_disable(rdev_get_name(rdev));
25585c5659d0SMark Brown 
2559967cfb18SKim, Milo 	if (rdev->ena_pin) {
256029d62ec5SDoug Anderson 		if (rdev->ena_gpio_state) {
2561967cfb18SKim, Milo 			ret = regulator_ena_gpio_ctrl(rdev, false);
2562967cfb18SKim, Milo 			if (ret < 0)
2563967cfb18SKim, Milo 				return ret;
25645c5659d0SMark Brown 			rdev->ena_gpio_state = 0;
256529d62ec5SDoug Anderson 		}
25665c5659d0SMark Brown 
25675c5659d0SMark Brown 	} else if (rdev->desc->ops->disable) {
25685c5659d0SMark Brown 		ret = rdev->desc->ops->disable(rdev);
25695c5659d0SMark Brown 		if (ret != 0)
25705c5659d0SMark Brown 			return ret;
25715c5659d0SMark Brown 	}
25725c5659d0SMark Brown 
2573871f5650SGuodong Xu 	/* cares about last_off_jiffy only if off_on_delay is required by
2574871f5650SGuodong Xu 	 * device.
2575871f5650SGuodong Xu 	 */
2576871f5650SGuodong Xu 	if (rdev->desc->off_on_delay)
2577871f5650SGuodong Xu 		rdev->last_off_jiffy = jiffies;
2578871f5650SGuodong Xu 
25795c5659d0SMark Brown 	trace_regulator_disable_complete(rdev_get_name(rdev));
25805c5659d0SMark Brown 
25815c5659d0SMark Brown 	return 0;
25825c5659d0SMark Brown }
25835c5659d0SMark Brown 
2584414c70cbSLiam Girdwood /* locks held by regulator_disable() */
25855451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator)
2586414c70cbSLiam Girdwood {
25875451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
2588414c70cbSLiam Girdwood 	int ret = 0;
2589414c70cbSLiam Girdwood 
2590f8702f9eSDmitry Osipenko 	lockdep_assert_held_once(&rdev->mutex.base);
259170cfef26SKrzysztof Kozlowski 
2592cd94b505SDavid Brownell 	if (WARN(rdev->use_count <= 0,
259343e7ee33SJoe Perches 		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
2594cd94b505SDavid Brownell 		return -EIO;
2595cd94b505SDavid Brownell 
2596414c70cbSLiam Girdwood 	/* are we the last user and permitted to disable ? */
259760ef66fcSMark Brown 	if (rdev->use_count == 1 &&
259860ef66fcSMark Brown 	    (rdev->constraints && !rdev->constraints->always_on)) {
2599414c70cbSLiam Girdwood 
2600414c70cbSLiam Girdwood 		/* we are last user */
26018a34e979SWEN Pingbo 		if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
2602a1c8a551SRichard Fitzgerald 			ret = _notifier_call_chain(rdev,
2603a1c8a551SRichard Fitzgerald 						   REGULATOR_EVENT_PRE_DISABLE,
2604a1c8a551SRichard Fitzgerald 						   NULL);
2605a1c8a551SRichard Fitzgerald 			if (ret & NOTIFY_STOP_MASK)
2606a1c8a551SRichard Fitzgerald 				return -EINVAL;
2607a1c8a551SRichard Fitzgerald 
26085c5659d0SMark Brown 			ret = _regulator_do_disable(rdev);
2609414c70cbSLiam Girdwood 			if (ret < 0) {
26105da84fd9SJoe Perches 				rdev_err(rdev, "failed to disable\n");
2611a1c8a551SRichard Fitzgerald 				_notifier_call_chain(rdev,
2612a1c8a551SRichard Fitzgerald 						REGULATOR_EVENT_ABORT_DISABLE,
2613a1c8a551SRichard Fitzgerald 						NULL);
2614414c70cbSLiam Girdwood 				return ret;
2615414c70cbSLiam Girdwood 			}
261666fda75fSMarkus Pargmann 			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
261766fda75fSMarkus Pargmann 					NULL);
2618414c70cbSLiam Girdwood 		}
2619414c70cbSLiam Girdwood 
2620414c70cbSLiam Girdwood 		rdev->use_count = 0;
2621414c70cbSLiam Girdwood 	} else if (rdev->use_count > 1) {
2622414c70cbSLiam Girdwood 		rdev->use_count--;
2623414c70cbSLiam Girdwood 	}
26243801b86aSMark Brown 
26255451781dSDouglas Anderson 	if (ret == 0)
26265451781dSDouglas Anderson 		ret = _regulator_handle_consumer_disable(regulator);
26275451781dSDouglas Anderson 
2628f8702f9eSDmitry Osipenko 	if (ret == 0 && rdev->coupling_desc.n_coupled > 1)
2629f8702f9eSDmitry Osipenko 		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
2630f8702f9eSDmitry Osipenko 
26311fc12b05SDouglas Anderson 	if (ret == 0 && rdev->use_count == 0 && rdev->supply)
26325451781dSDouglas Anderson 		ret = _regulator_disable(rdev->supply);
2633f8702f9eSDmitry Osipenko 
2634414c70cbSLiam Girdwood 	return ret;
2635414c70cbSLiam Girdwood }
2636414c70cbSLiam Girdwood 
2637414c70cbSLiam Girdwood /**
2638414c70cbSLiam Girdwood  * regulator_disable - disable regulator output
2639414c70cbSLiam Girdwood  * @regulator: regulator source
2640414c70cbSLiam Girdwood  *
2641cf7bbcdfSMark Brown  * Disable the regulator output voltage or current.  Calls to
2642cf7bbcdfSMark Brown  * regulator_enable() must be balanced with calls to
2643cf7bbcdfSMark Brown  * regulator_disable().
264469279fb9SMark Brown  *
2645414c70cbSLiam Girdwood  * NOTE: this will only disable the regulator output if no other consumer
2646cf7bbcdfSMark Brown  * devices have it enabled, the regulator device supports disabling and
2647cf7bbcdfSMark Brown  * machine constraints permit this operation.
2648414c70cbSLiam Girdwood  */
2649414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator)
2650414c70cbSLiam Girdwood {
2651412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
2652f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
26535451781dSDouglas Anderson 	int ret;
26546492bc1bSMark Brown 
2655f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
26565451781dSDouglas Anderson 	ret = _regulator_disable(regulator);
2657f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(rdev, &ww_ctx);
26588cbf811dSJeffrey Carlyle 
2659414c70cbSLiam Girdwood 	return ret;
2660414c70cbSLiam Girdwood }
2661414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable);
2662414c70cbSLiam Girdwood 
2663414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */
26643801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev)
2665414c70cbSLiam Girdwood {
2666414c70cbSLiam Girdwood 	int ret = 0;
2667414c70cbSLiam Girdwood 
2668f8702f9eSDmitry Osipenko 	lockdep_assert_held_once(&rdev->mutex.base);
266970cfef26SKrzysztof Kozlowski 
2670a1c8a551SRichard Fitzgerald 	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
2671a1c8a551SRichard Fitzgerald 			REGULATOR_EVENT_PRE_DISABLE, NULL);
2672a1c8a551SRichard Fitzgerald 	if (ret & NOTIFY_STOP_MASK)
2673a1c8a551SRichard Fitzgerald 		return -EINVAL;
2674a1c8a551SRichard Fitzgerald 
267566fda75fSMarkus Pargmann 	ret = _regulator_do_disable(rdev);
2676414c70cbSLiam Girdwood 	if (ret < 0) {
26775da84fd9SJoe Perches 		rdev_err(rdev, "failed to force disable\n");
2678a1c8a551SRichard Fitzgerald 		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
2679a1c8a551SRichard Fitzgerald 				REGULATOR_EVENT_ABORT_DISABLE, NULL);
2680414c70cbSLiam Girdwood 		return ret;
2681414c70cbSLiam Girdwood 	}
268266fda75fSMarkus Pargmann 
268384b68263SMark Brown 	_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
268484b68263SMark Brown 			REGULATOR_EVENT_DISABLE, NULL);
2685414c70cbSLiam Girdwood 
268666fda75fSMarkus Pargmann 	return 0;
2687414c70cbSLiam Girdwood }
2688414c70cbSLiam Girdwood 
2689414c70cbSLiam Girdwood /**
2690414c70cbSLiam Girdwood  * regulator_force_disable - force disable regulator output
2691414c70cbSLiam Girdwood  * @regulator: regulator source
2692414c70cbSLiam Girdwood  *
2693414c70cbSLiam Girdwood  * Forcibly disable the regulator output voltage or current.
2694414c70cbSLiam Girdwood  * NOTE: this *will* disable the regulator output even if other consumer
2695414c70cbSLiam Girdwood  * devices have it enabled. This should be used for situations when device
2696414c70cbSLiam Girdwood  * damage will likely occur if the regulator is not disabled (e.g. over temp).
2697414c70cbSLiam Girdwood  */
2698414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator)
2699414c70cbSLiam Girdwood {
270082d15839SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
2701f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
2702414c70cbSLiam Girdwood 	int ret;
2703414c70cbSLiam Girdwood 
2704f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
27055451781dSDouglas Anderson 
27063801b86aSMark Brown 	ret = _regulator_force_disable(regulator->rdev);
27075451781dSDouglas Anderson 
27089243a195SMaciej Purski 	if (rdev->coupling_desc.n_coupled > 1)
27099243a195SMaciej Purski 		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
27105451781dSDouglas Anderson 
27115451781dSDouglas Anderson 	if (regulator->uA_load) {
27125451781dSDouglas Anderson 		regulator->uA_load = 0;
27135451781dSDouglas Anderson 		ret = drms_uA_update(rdev);
27145451781dSDouglas Anderson 	}
27155451781dSDouglas Anderson 
27161fc12b05SDouglas Anderson 	if (rdev->use_count != 0 && rdev->supply)
27171fc12b05SDouglas Anderson 		_regulator_disable(rdev->supply);
27188cbf811dSJeffrey Carlyle 
27191fc12b05SDouglas Anderson 	regulator_unlock_dependent(rdev, &ww_ctx);
27208cbf811dSJeffrey Carlyle 
2721414c70cbSLiam Girdwood 	return ret;
2722414c70cbSLiam Girdwood }
2723414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable);
2724414c70cbSLiam Girdwood 
2725da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work)
2726da07ecd9SMark Brown {
2727da07ecd9SMark Brown 	struct regulator_dev *rdev = container_of(work, struct regulator_dev,
2728da07ecd9SMark Brown 						  disable_work.work);
2729f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
2730da07ecd9SMark Brown 	int count, i, ret;
27315451781dSDouglas Anderson 	struct regulator *regulator;
27325451781dSDouglas Anderson 	int total_count = 0;
2733da07ecd9SMark Brown 
2734f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
2735da07ecd9SMark Brown 
2736c9ccaa0cSTirupathi Reddy 	/*
2737c9ccaa0cSTirupathi Reddy 	 * Workqueue functions queue the new work instance while the previous
2738c9ccaa0cSTirupathi Reddy 	 * work instance is being processed. Cancel the queued work instance
2739c9ccaa0cSTirupathi Reddy 	 * as the work instance under processing does the job of the queued
2740c9ccaa0cSTirupathi Reddy 	 * work instance.
2741c9ccaa0cSTirupathi Reddy 	 */
2742c9ccaa0cSTirupathi Reddy 	cancel_delayed_work(&rdev->disable_work);
2743c9ccaa0cSTirupathi Reddy 
27445451781dSDouglas Anderson 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
27455451781dSDouglas Anderson 		count = regulator->deferred_disables;
27465451781dSDouglas Anderson 
27475451781dSDouglas Anderson 		if (!count)
27485451781dSDouglas Anderson 			continue;
27495451781dSDouglas Anderson 
27505451781dSDouglas Anderson 		total_count += count;
27515451781dSDouglas Anderson 		regulator->deferred_disables = 0;
27525451781dSDouglas Anderson 
2753da07ecd9SMark Brown 		for (i = 0; i < count; i++) {
27545451781dSDouglas Anderson 			ret = _regulator_disable(regulator);
2755da07ecd9SMark Brown 			if (ret != 0)
2756da07ecd9SMark Brown 				rdev_err(rdev, "Deferred disable failed: %d\n", ret);
2757da07ecd9SMark Brown 		}
27585451781dSDouglas Anderson 	}
27595451781dSDouglas Anderson 	WARN_ON(!total_count);
2760da07ecd9SMark Brown 
2761f8702f9eSDmitry Osipenko 	if (rdev->coupling_desc.n_coupled > 1)
2762f8702f9eSDmitry Osipenko 		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
2763f8702f9eSDmitry Osipenko 
2764f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(rdev, &ww_ctx);
2765da07ecd9SMark Brown }
2766da07ecd9SMark Brown 
2767da07ecd9SMark Brown /**
2768da07ecd9SMark Brown  * regulator_disable_deferred - disable regulator output with delay
2769da07ecd9SMark Brown  * @regulator: regulator source
277048f1b4efSKrzysztof Kozlowski  * @ms: milliseconds until the regulator is disabled
2771da07ecd9SMark Brown  *
2772da07ecd9SMark Brown  * Execute regulator_disable() on the regulator after a delay.  This
2773da07ecd9SMark Brown  * is intended for use with devices that require some time to quiesce.
2774da07ecd9SMark Brown  *
2775da07ecd9SMark Brown  * NOTE: this will only disable the regulator output if no other consumer
2776da07ecd9SMark Brown  * devices have it enabled, the regulator device supports disabling and
2777da07ecd9SMark Brown  * machine constraints permit this operation.
2778da07ecd9SMark Brown  */
2779da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms)
2780da07ecd9SMark Brown {
2781da07ecd9SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
2782da07ecd9SMark Brown 
27832b5a24a0SMark Brown 	if (!ms)
27842b5a24a0SMark Brown 		return regulator_disable(regulator);
27852b5a24a0SMark Brown 
278666cf9a7eSMaciej Purski 	regulator_lock(rdev);
27875451781dSDouglas Anderson 	regulator->deferred_disables++;
2788c9ccaa0cSTirupathi Reddy 	mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
2789c9ccaa0cSTirupathi Reddy 			 msecs_to_jiffies(ms));
279066cf9a7eSMaciej Purski 	regulator_unlock(rdev);
2791da07ecd9SMark Brown 
2792aa59802dSMark Brown 	return 0;
2793da07ecd9SMark Brown }
2794da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred);
2795da07ecd9SMark Brown 
2796414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev)
2797414c70cbSLiam Girdwood {
279865f73508SMark Brown 	/* A GPIO control always takes precedence */
27997b74d149SKim, Milo 	if (rdev->ena_pin)
280065f73508SMark Brown 		return rdev->ena_gpio_state;
280165f73508SMark Brown 
28029a7f6a4cSMark Brown 	/* If we don't know then assume that the regulator is always on */
28039332546fSMark Brown 	if (!rdev->desc->ops->is_enabled)
28049a7f6a4cSMark Brown 		return 1;
2805414c70cbSLiam Girdwood 
28069332546fSMark Brown 	return rdev->desc->ops->is_enabled(rdev);
2807414c70cbSLiam Girdwood }
2808414c70cbSLiam Girdwood 
28093d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev,
28103a40cfc3SSascha Hauer 				   unsigned selector, int lock)
28113a40cfc3SSascha Hauer {
28123a40cfc3SSascha Hauer 	const struct regulator_ops *ops = rdev->desc->ops;
28133a40cfc3SSascha Hauer 	int ret;
28143a40cfc3SSascha Hauer 
28153a40cfc3SSascha Hauer 	if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
28163a40cfc3SSascha Hauer 		return rdev->desc->fixed_uV;
28173a40cfc3SSascha Hauer 
28183a40cfc3SSascha Hauer 	if (ops->list_voltage) {
28193a40cfc3SSascha Hauer 		if (selector >= rdev->desc->n_voltages)
28203a40cfc3SSascha Hauer 			return -EINVAL;
28213a40cfc3SSascha Hauer 		if (lock)
282266cf9a7eSMaciej Purski 			regulator_lock(rdev);
28233a40cfc3SSascha Hauer 		ret = ops->list_voltage(rdev, selector);
28243a40cfc3SSascha Hauer 		if (lock)
282566cf9a7eSMaciej Purski 			regulator_unlock(rdev);
2826fd086045SMatthias Kaehlcke 	} else if (rdev->is_switch && rdev->supply) {
28273d67fe95SMaciej Purski 		ret = _regulator_list_voltage(rdev->supply->rdev,
28283d67fe95SMaciej Purski 					      selector, lock);
28293a40cfc3SSascha Hauer 	} else {
28303a40cfc3SSascha Hauer 		return -EINVAL;
28313a40cfc3SSascha Hauer 	}
28323a40cfc3SSascha Hauer 
28333a40cfc3SSascha Hauer 	if (ret > 0) {
28343a40cfc3SSascha Hauer 		if (ret < rdev->constraints->min_uV)
28353a40cfc3SSascha Hauer 			ret = 0;
28363a40cfc3SSascha Hauer 		else if (ret > rdev->constraints->max_uV)
28373a40cfc3SSascha Hauer 			ret = 0;
28383a40cfc3SSascha Hauer 	}
28393a40cfc3SSascha Hauer 
28403a40cfc3SSascha Hauer 	return ret;
28413a40cfc3SSascha Hauer }
28423a40cfc3SSascha Hauer 
2843414c70cbSLiam Girdwood /**
2844414c70cbSLiam Girdwood  * regulator_is_enabled - is the regulator output enabled
2845414c70cbSLiam Girdwood  * @regulator: regulator source
2846414c70cbSLiam Girdwood  *
2847412aec61SDavid Brownell  * Returns positive if the regulator driver backing the source/client
2848412aec61SDavid Brownell  * has requested that the device be enabled, zero if it hasn't, else a
2849412aec61SDavid Brownell  * negative errno code.
2850412aec61SDavid Brownell  *
2851412aec61SDavid Brownell  * Note that the device backing this regulator handle can have multiple
2852412aec61SDavid Brownell  * users, so it might be enabled even if regulator_enable() was never
2853412aec61SDavid Brownell  * called for this particular source.
2854414c70cbSLiam Girdwood  */
2855414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator)
2856414c70cbSLiam Girdwood {
28579332546fSMark Brown 	int ret;
28589332546fSMark Brown 
28596492bc1bSMark Brown 	if (regulator->always_on)
28606492bc1bSMark Brown 		return 1;
28616492bc1bSMark Brown 
2862f8702f9eSDmitry Osipenko 	regulator_lock(regulator->rdev);
28639332546fSMark Brown 	ret = _regulator_is_enabled(regulator->rdev);
2864f8702f9eSDmitry Osipenko 	regulator_unlock(regulator->rdev);
28659332546fSMark Brown 
28669332546fSMark Brown 	return ret;
2867414c70cbSLiam Girdwood }
2868414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled);
2869414c70cbSLiam Girdwood 
2870414c70cbSLiam Girdwood /**
28714367cfdcSDavid Brownell  * regulator_count_voltages - count regulator_list_voltage() selectors
28724367cfdcSDavid Brownell  * @regulator: regulator source
28734367cfdcSDavid Brownell  *
28744367cfdcSDavid Brownell  * Returns number of selectors, or negative errno.  Selectors are
28754367cfdcSDavid Brownell  * numbered starting at zero, and typically correspond to bitfields
28764367cfdcSDavid Brownell  * in hardware registers.
28774367cfdcSDavid Brownell  */
28784367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator)
28794367cfdcSDavid Brownell {
28804367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
28814367cfdcSDavid Brownell 
288226988efeSJavier Martinez Canillas 	if (rdev->desc->n_voltages)
288326988efeSJavier Martinez Canillas 		return rdev->desc->n_voltages;
288426988efeSJavier Martinez Canillas 
2885fd086045SMatthias Kaehlcke 	if (!rdev->is_switch || !rdev->supply)
288626988efeSJavier Martinez Canillas 		return -EINVAL;
288726988efeSJavier Martinez Canillas 
288826988efeSJavier Martinez Canillas 	return regulator_count_voltages(rdev->supply);
28894367cfdcSDavid Brownell }
28904367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages);
28914367cfdcSDavid Brownell 
28924367cfdcSDavid Brownell /**
28934367cfdcSDavid Brownell  * regulator_list_voltage - enumerate supported voltages
28944367cfdcSDavid Brownell  * @regulator: regulator source
28954367cfdcSDavid Brownell  * @selector: identify voltage to list
28964367cfdcSDavid Brownell  * Context: can sleep
28974367cfdcSDavid Brownell  *
28984367cfdcSDavid Brownell  * Returns a voltage that can be passed to @regulator_set_voltage(),
289988393161SThomas Weber  * zero if this selector code can't be used on this system, or a
29004367cfdcSDavid Brownell  * negative errno.
29014367cfdcSDavid Brownell  */
29024367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector)
29034367cfdcSDavid Brownell {
29043d67fe95SMaciej Purski 	return _regulator_list_voltage(regulator->rdev, selector, 1);
29054367cfdcSDavid Brownell }
29064367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage);
29074367cfdcSDavid Brownell 
29084367cfdcSDavid Brownell /**
290904eca28cSTuomas Tynkkynen  * regulator_get_regmap - get the regulator's register map
291004eca28cSTuomas Tynkkynen  * @regulator: regulator source
291104eca28cSTuomas Tynkkynen  *
291204eca28cSTuomas Tynkkynen  * Returns the register map for the given regulator, or an ERR_PTR value
291304eca28cSTuomas Tynkkynen  * if the regulator doesn't use regmap.
291404eca28cSTuomas Tynkkynen  */
291504eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator)
291604eca28cSTuomas Tynkkynen {
291704eca28cSTuomas Tynkkynen 	struct regmap *map = regulator->rdev->regmap;
291804eca28cSTuomas Tynkkynen 
291904eca28cSTuomas Tynkkynen 	return map ? map : ERR_PTR(-EOPNOTSUPP);
292004eca28cSTuomas Tynkkynen }
292104eca28cSTuomas Tynkkynen 
292204eca28cSTuomas Tynkkynen /**
292304eca28cSTuomas Tynkkynen  * regulator_get_hardware_vsel_register - get the HW voltage selector register
292404eca28cSTuomas Tynkkynen  * @regulator: regulator source
292504eca28cSTuomas Tynkkynen  * @vsel_reg: voltage selector register, output parameter
292604eca28cSTuomas Tynkkynen  * @vsel_mask: mask for voltage selector bitfield, output parameter
292704eca28cSTuomas Tynkkynen  *
292804eca28cSTuomas Tynkkynen  * Returns the hardware register offset and bitmask used for setting the
292904eca28cSTuomas Tynkkynen  * regulator voltage. This might be useful when configuring voltage-scaling
293004eca28cSTuomas Tynkkynen  * hardware or firmware that can make I2C requests behind the kernel's back,
293104eca28cSTuomas Tynkkynen  * for example.
293204eca28cSTuomas Tynkkynen  *
293304eca28cSTuomas Tynkkynen  * On success, the output parameters @vsel_reg and @vsel_mask are filled in
293404eca28cSTuomas Tynkkynen  * and 0 is returned, otherwise a negative errno is returned.
293504eca28cSTuomas Tynkkynen  */
293604eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator,
293704eca28cSTuomas Tynkkynen 					 unsigned *vsel_reg,
293804eca28cSTuomas Tynkkynen 					 unsigned *vsel_mask)
293904eca28cSTuomas Tynkkynen {
294004eca28cSTuomas Tynkkynen 	struct regulator_dev *rdev = regulator->rdev;
294139f5460dSGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
294204eca28cSTuomas Tynkkynen 
294304eca28cSTuomas Tynkkynen 	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
294404eca28cSTuomas Tynkkynen 		return -EOPNOTSUPP;
294504eca28cSTuomas Tynkkynen 
294604eca28cSTuomas Tynkkynen 	*vsel_reg = rdev->desc->vsel_reg;
294704eca28cSTuomas Tynkkynen 	*vsel_mask = rdev->desc->vsel_mask;
294804eca28cSTuomas Tynkkynen 
294904eca28cSTuomas Tynkkynen 	 return 0;
295004eca28cSTuomas Tynkkynen }
295104eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
295204eca28cSTuomas Tynkkynen 
295304eca28cSTuomas Tynkkynen /**
295404eca28cSTuomas Tynkkynen  * regulator_list_hardware_vsel - get the HW-specific register value for a selector
295504eca28cSTuomas Tynkkynen  * @regulator: regulator source
295604eca28cSTuomas Tynkkynen  * @selector: identify voltage to list
295704eca28cSTuomas Tynkkynen  *
295804eca28cSTuomas Tynkkynen  * Converts the selector to a hardware-specific voltage selector that can be
295904eca28cSTuomas Tynkkynen  * directly written to the regulator registers. The address of the voltage
296004eca28cSTuomas Tynkkynen  * register can be determined by calling @regulator_get_hardware_vsel_register.
296104eca28cSTuomas Tynkkynen  *
296204eca28cSTuomas Tynkkynen  * On error a negative errno is returned.
296304eca28cSTuomas Tynkkynen  */
296404eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator,
296504eca28cSTuomas Tynkkynen 				 unsigned selector)
296604eca28cSTuomas Tynkkynen {
296704eca28cSTuomas Tynkkynen 	struct regulator_dev *rdev = regulator->rdev;
296839f5460dSGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
296904eca28cSTuomas Tynkkynen 
297004eca28cSTuomas Tynkkynen 	if (selector >= rdev->desc->n_voltages)
297104eca28cSTuomas Tynkkynen 		return -EINVAL;
297204eca28cSTuomas Tynkkynen 	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
297304eca28cSTuomas Tynkkynen 		return -EOPNOTSUPP;
297404eca28cSTuomas Tynkkynen 
297504eca28cSTuomas Tynkkynen 	return selector;
297604eca28cSTuomas Tynkkynen }
297704eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
297804eca28cSTuomas Tynkkynen 
297904eca28cSTuomas Tynkkynen /**
29802a668a8bSPaul Walmsley  * regulator_get_linear_step - return the voltage step size between VSEL values
29812a668a8bSPaul Walmsley  * @regulator: regulator source
29822a668a8bSPaul Walmsley  *
29832a668a8bSPaul Walmsley  * Returns the voltage step size between VSEL values for linear
29842a668a8bSPaul Walmsley  * regulators, or return 0 if the regulator isn't a linear regulator.
29852a668a8bSPaul Walmsley  */
29862a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator)
29872a668a8bSPaul Walmsley {
29882a668a8bSPaul Walmsley 	struct regulator_dev *rdev = regulator->rdev;
29892a668a8bSPaul Walmsley 
29902a668a8bSPaul Walmsley 	return rdev->desc->uV_step;
29912a668a8bSPaul Walmsley }
29922a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step);
29932a668a8bSPaul Walmsley 
29942a668a8bSPaul Walmsley /**
2995a7a1ad90SMark Brown  * regulator_is_supported_voltage - check if a voltage range can be supported
2996a7a1ad90SMark Brown  *
2997a7a1ad90SMark Brown  * @regulator: Regulator to check.
2998a7a1ad90SMark Brown  * @min_uV: Minimum required voltage in uV.
2999a7a1ad90SMark Brown  * @max_uV: Maximum required voltage in uV.
3000a7a1ad90SMark Brown  *
300149820944SJorge Ramirez-Ortiz  * Returns a boolean.
3002a7a1ad90SMark Brown  */
3003a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator,
3004a7a1ad90SMark Brown 				   int min_uV, int max_uV)
3005a7a1ad90SMark Brown {
3006c5f3939bSMark Brown 	struct regulator_dev *rdev = regulator->rdev;
3007a7a1ad90SMark Brown 	int i, voltages, ret;
3008a7a1ad90SMark Brown 
3009c5f3939bSMark Brown 	/* If we can't change voltage check the current voltage */
30108a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
3011c5f3939bSMark Brown 		ret = regulator_get_voltage(regulator);
3012c5f3939bSMark Brown 		if (ret >= 0)
30130d25d09dSJingoo Han 			return min_uV <= ret && ret <= max_uV;
3014c5f3939bSMark Brown 		else
3015c5f3939bSMark Brown 			return ret;
3016c5f3939bSMark Brown 	}
3017c5f3939bSMark Brown 
3018bd7a2b60SPawel Moll 	/* Any voltage within constrains range is fine? */
3019bd7a2b60SPawel Moll 	if (rdev->desc->continuous_voltage_range)
3020bd7a2b60SPawel Moll 		return min_uV >= rdev->constraints->min_uV &&
3021bd7a2b60SPawel Moll 				max_uV <= rdev->constraints->max_uV;
3022bd7a2b60SPawel Moll 
3023a7a1ad90SMark Brown 	ret = regulator_count_voltages(regulator);
3024a7a1ad90SMark Brown 	if (ret < 0)
302549820944SJorge Ramirez-Ortiz 		return 0;
3026a7a1ad90SMark Brown 	voltages = ret;
3027a7a1ad90SMark Brown 
3028a7a1ad90SMark Brown 	for (i = 0; i < voltages; i++) {
3029a7a1ad90SMark Brown 		ret = regulator_list_voltage(regulator, i);
3030a7a1ad90SMark Brown 
3031a7a1ad90SMark Brown 		if (ret >= min_uV && ret <= max_uV)
3032a7a1ad90SMark Brown 			return 1;
3033a7a1ad90SMark Brown 	}
3034a7a1ad90SMark Brown 
3035a7a1ad90SMark Brown 	return 0;
3036a7a1ad90SMark Brown }
3037a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
3038a7a1ad90SMark Brown 
3039a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV,
3040a204f41eSSascha Hauer 				 int max_uV)
3041a204f41eSSascha Hauer {
3042a204f41eSSascha Hauer 	const struct regulator_desc *desc = rdev->desc;
3043a204f41eSSascha Hauer 
3044a204f41eSSascha Hauer 	if (desc->ops->map_voltage)
3045a204f41eSSascha Hauer 		return desc->ops->map_voltage(rdev, min_uV, max_uV);
3046a204f41eSSascha Hauer 
3047a204f41eSSascha Hauer 	if (desc->ops->list_voltage == regulator_list_voltage_linear)
3048a204f41eSSascha Hauer 		return regulator_map_voltage_linear(rdev, min_uV, max_uV);
3049a204f41eSSascha Hauer 
3050a204f41eSSascha Hauer 	if (desc->ops->list_voltage == regulator_list_voltage_linear_range)
3051a204f41eSSascha Hauer 		return regulator_map_voltage_linear_range(rdev, min_uV, max_uV);
3052a204f41eSSascha Hauer 
305318e4b55fSMatti Vaittinen 	if (desc->ops->list_voltage ==
305418e4b55fSMatti Vaittinen 		regulator_list_voltage_pickable_linear_range)
305518e4b55fSMatti Vaittinen 		return regulator_map_voltage_pickable_linear_range(rdev,
305618e4b55fSMatti Vaittinen 							min_uV, max_uV);
305718e4b55fSMatti Vaittinen 
3058a204f41eSSascha Hauer 	return regulator_map_voltage_iterate(rdev, min_uV, max_uV);
3059a204f41eSSascha Hauer }
3060a204f41eSSascha Hauer 
30617179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev,
30627179569aSHeiko Stübner 				       int min_uV, int max_uV,
30637179569aSHeiko Stübner 				       unsigned *selector)
30647179569aSHeiko Stübner {
30657179569aSHeiko Stübner 	struct pre_voltage_change_data data;
30667179569aSHeiko Stübner 	int ret;
30677179569aSHeiko Stübner 
30687179569aSHeiko Stübner 	data.old_uV = _regulator_get_voltage(rdev);
30697179569aSHeiko Stübner 	data.min_uV = min_uV;
30707179569aSHeiko Stübner 	data.max_uV = max_uV;
30717179569aSHeiko Stübner 	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
30727179569aSHeiko Stübner 				   &data);
30737179569aSHeiko Stübner 	if (ret & NOTIFY_STOP_MASK)
30747179569aSHeiko Stübner 		return -EINVAL;
30757179569aSHeiko Stübner 
30767179569aSHeiko Stübner 	ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector);
30777179569aSHeiko Stübner 	if (ret >= 0)
30787179569aSHeiko Stübner 		return ret;
30797179569aSHeiko Stübner 
30807179569aSHeiko Stübner 	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
30817179569aSHeiko Stübner 			     (void *)data.old_uV);
30827179569aSHeiko Stübner 
30837179569aSHeiko Stübner 	return ret;
30847179569aSHeiko Stübner }
30857179569aSHeiko Stübner 
30867179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
30877179569aSHeiko Stübner 					   int uV, unsigned selector)
30887179569aSHeiko Stübner {
30897179569aSHeiko Stübner 	struct pre_voltage_change_data data;
30907179569aSHeiko Stübner 	int ret;
30917179569aSHeiko Stübner 
30927179569aSHeiko Stübner 	data.old_uV = _regulator_get_voltage(rdev);
30937179569aSHeiko Stübner 	data.min_uV = uV;
30947179569aSHeiko Stübner 	data.max_uV = uV;
30957179569aSHeiko Stübner 	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
30967179569aSHeiko Stübner 				   &data);
30977179569aSHeiko Stübner 	if (ret & NOTIFY_STOP_MASK)
30987179569aSHeiko Stübner 		return -EINVAL;
30997179569aSHeiko Stübner 
31007179569aSHeiko Stübner 	ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
31017179569aSHeiko Stübner 	if (ret >= 0)
31027179569aSHeiko Stübner 		return ret;
31037179569aSHeiko Stübner 
31047179569aSHeiko Stübner 	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
31057179569aSHeiko Stübner 			     (void *)data.old_uV);
31067179569aSHeiko Stübner 
31077179569aSHeiko Stübner 	return ret;
31087179569aSHeiko Stübner }
31097179569aSHeiko Stübner 
311073e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev,
311173e705bfSMatthias Kaehlcke 				       int old_uV, int new_uV)
311273e705bfSMatthias Kaehlcke {
311373e705bfSMatthias Kaehlcke 	unsigned int ramp_delay = 0;
311473e705bfSMatthias Kaehlcke 
311573e705bfSMatthias Kaehlcke 	if (rdev->constraints->ramp_delay)
311673e705bfSMatthias Kaehlcke 		ramp_delay = rdev->constraints->ramp_delay;
311773e705bfSMatthias Kaehlcke 	else if (rdev->desc->ramp_delay)
311873e705bfSMatthias Kaehlcke 		ramp_delay = rdev->desc->ramp_delay;
3119d6c1dc3fSLaxman Dewangan 	else if (rdev->constraints->settling_time)
3120d6c1dc3fSLaxman Dewangan 		return rdev->constraints->settling_time;
31213ffad468SMatthias Kaehlcke 	else if (rdev->constraints->settling_time_up &&
31223ffad468SMatthias Kaehlcke 		 (new_uV > old_uV))
31233ffad468SMatthias Kaehlcke 		return rdev->constraints->settling_time_up;
31243ffad468SMatthias Kaehlcke 	else if (rdev->constraints->settling_time_down &&
31253ffad468SMatthias Kaehlcke 		 (new_uV < old_uV))
31263ffad468SMatthias Kaehlcke 		return rdev->constraints->settling_time_down;
312773e705bfSMatthias Kaehlcke 
312873e705bfSMatthias Kaehlcke 	if (ramp_delay == 0) {
3129ba14fa1aSH. Nikolaus Schaller 		rdev_dbg(rdev, "ramp_delay not set\n");
313073e705bfSMatthias Kaehlcke 		return 0;
313173e705bfSMatthias Kaehlcke 	}
313273e705bfSMatthias Kaehlcke 
313373e705bfSMatthias Kaehlcke 	return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
313473e705bfSMatthias Kaehlcke }
313573e705bfSMatthias Kaehlcke 
313675790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
313775790251SMark Brown 				     int min_uV, int max_uV)
313875790251SMark Brown {
313975790251SMark Brown 	int ret;
314077af1b26SLinus Walleij 	int delay = 0;
3141e113d792SMark Brown 	int best_val = 0;
314275790251SMark Brown 	unsigned int selector;
3143eba41a5eSAxel Lin 	int old_selector = -1;
314457995a48SMatthias Kaehlcke 	const struct regulator_ops *ops = rdev->desc->ops;
314573e705bfSMatthias Kaehlcke 	int old_uV = _regulator_get_voltage(rdev);
314675790251SMark Brown 
314775790251SMark Brown 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
314875790251SMark Brown 
3149bf5892a8SMark Brown 	min_uV += rdev->constraints->uV_offset;
3150bf5892a8SMark Brown 	max_uV += rdev->constraints->uV_offset;
3151bf5892a8SMark Brown 
315277af1b26SLinus Walleij 	/*
315377af1b26SLinus Walleij 	 * If we can't obtain the old selector there is not enough
315477af1b26SLinus Walleij 	 * info to call set_voltage_time_sel().
315577af1b26SLinus Walleij 	 */
31568b7485efSAxel Lin 	if (_regulator_is_enabled(rdev) &&
315757995a48SMatthias Kaehlcke 	    ops->set_voltage_time_sel && ops->get_voltage_sel) {
315857995a48SMatthias Kaehlcke 		old_selector = ops->get_voltage_sel(rdev);
3159eba41a5eSAxel Lin 		if (old_selector < 0)
3160eba41a5eSAxel Lin 			return old_selector;
3161eba41a5eSAxel Lin 	}
316277af1b26SLinus Walleij 
316357995a48SMatthias Kaehlcke 	if (ops->set_voltage) {
31647179569aSHeiko Stübner 		ret = _regulator_call_set_voltage(rdev, min_uV, max_uV,
316575790251SMark Brown 						  &selector);
3166e113d792SMark Brown 
3167e113d792SMark Brown 		if (ret >= 0) {
316857995a48SMatthias Kaehlcke 			if (ops->list_voltage)
316957995a48SMatthias Kaehlcke 				best_val = ops->list_voltage(rdev,
3170e113d792SMark Brown 							     selector);
3171e113d792SMark Brown 			else
3172e113d792SMark Brown 				best_val = _regulator_get_voltage(rdev);
3173e113d792SMark Brown 		}
3174e113d792SMark Brown 
317557995a48SMatthias Kaehlcke 	} else if (ops->set_voltage_sel) {
3176a204f41eSSascha Hauer 		ret = regulator_map_voltage(rdev, min_uV, max_uV);
3177e843fc46SMark Brown 		if (ret >= 0) {
317857995a48SMatthias Kaehlcke 			best_val = ops->list_voltage(rdev, ret);
3179e113d792SMark Brown 			if (min_uV <= best_val && max_uV >= best_val) {
3180e843fc46SMark Brown 				selector = ret;
3181c66a566aSAxel Lin 				if (old_selector == selector)
3182c66a566aSAxel Lin 					ret = 0;
3183c66a566aSAxel Lin 				else
31847179569aSHeiko Stübner 					ret = _regulator_call_set_voltage_sel(
31857179569aSHeiko Stübner 						rdev, best_val, selector);
3186e113d792SMark Brown 			} else {
3187e113d792SMark Brown 				ret = -EINVAL;
3188e113d792SMark Brown 			}
3189e843fc46SMark Brown 		}
3190e8eef82bSMark Brown 	} else {
3191e8eef82bSMark Brown 		ret = -EINVAL;
3192e8eef82bSMark Brown 	}
3193e8eef82bSMark Brown 
319431dfe686SMatthias Kaehlcke 	if (ret)
319531dfe686SMatthias Kaehlcke 		goto out;
3196eba41a5eSAxel Lin 
319773e705bfSMatthias Kaehlcke 	if (ops->set_voltage_time_sel) {
319873e705bfSMatthias Kaehlcke 		/*
319973e705bfSMatthias Kaehlcke 		 * Call set_voltage_time_sel if successfully obtained
320073e705bfSMatthias Kaehlcke 		 * old_selector
320173e705bfSMatthias Kaehlcke 		 */
320273e705bfSMatthias Kaehlcke 		if (old_selector >= 0 && old_selector != selector)
320373e705bfSMatthias Kaehlcke 			delay = ops->set_voltage_time_sel(rdev, old_selector,
320473e705bfSMatthias Kaehlcke 							  selector);
320573e705bfSMatthias Kaehlcke 	} else {
320673e705bfSMatthias Kaehlcke 		if (old_uV != best_val) {
320773e705bfSMatthias Kaehlcke 			if (ops->set_voltage_time)
320873e705bfSMatthias Kaehlcke 				delay = ops->set_voltage_time(rdev, old_uV,
320973e705bfSMatthias Kaehlcke 							      best_val);
321073e705bfSMatthias Kaehlcke 			else
321173e705bfSMatthias Kaehlcke 				delay = _regulator_set_voltage_time(rdev,
321273e705bfSMatthias Kaehlcke 								    old_uV,
321373e705bfSMatthias Kaehlcke 								    best_val);
321473e705bfSMatthias Kaehlcke 		}
321573e705bfSMatthias Kaehlcke 	}
321673e705bfSMatthias Kaehlcke 
3217eba41a5eSAxel Lin 	if (delay < 0) {
321873e705bfSMatthias Kaehlcke 		rdev_warn(rdev, "failed to get delay: %d\n", delay);
3219eba41a5eSAxel Lin 		delay = 0;
3220e8eef82bSMark Brown 	}
322175790251SMark Brown 
322277af1b26SLinus Walleij 	/* Insert any necessary delays */
322377af1b26SLinus Walleij 	if (delay >= 1000) {
322477af1b26SLinus Walleij 		mdelay(delay / 1000);
322577af1b26SLinus Walleij 		udelay(delay % 1000);
322677af1b26SLinus Walleij 	} else if (delay) {
322777af1b26SLinus Walleij 		udelay(delay);
322877af1b26SLinus Walleij 	}
322977af1b26SLinus Walleij 
323031dfe686SMatthias Kaehlcke 	if (best_val >= 0) {
32312f6c797fSAxel Lin 		unsigned long data = best_val;
32322f6c797fSAxel Lin 
3233ded06a52SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
32342f6c797fSAxel Lin 				     (void *)data);
32352f6c797fSAxel Lin 	}
3236ded06a52SMark Brown 
323731dfe686SMatthias Kaehlcke out:
3238eba41a5eSAxel Lin 	trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
323975790251SMark Brown 
324075790251SMark Brown 	return ret;
324175790251SMark Brown }
324275790251SMark Brown 
3243f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev,
3244f7efad10SChunyan Zhang 				  int min_uV, int max_uV, suspend_state_t state)
3245f7efad10SChunyan Zhang {
3246f7efad10SChunyan Zhang 	struct regulator_state *rstate;
3247f7efad10SChunyan Zhang 	int uV, sel;
3248f7efad10SChunyan Zhang 
3249f7efad10SChunyan Zhang 	rstate = regulator_get_suspend_state(rdev, state);
3250f7efad10SChunyan Zhang 	if (rstate == NULL)
3251f7efad10SChunyan Zhang 		return -EINVAL;
3252f7efad10SChunyan Zhang 
3253f7efad10SChunyan Zhang 	if (min_uV < rstate->min_uV)
3254f7efad10SChunyan Zhang 		min_uV = rstate->min_uV;
3255f7efad10SChunyan Zhang 	if (max_uV > rstate->max_uV)
3256f7efad10SChunyan Zhang 		max_uV = rstate->max_uV;
3257f7efad10SChunyan Zhang 
3258f7efad10SChunyan Zhang 	sel = regulator_map_voltage(rdev, min_uV, max_uV);
3259f7efad10SChunyan Zhang 	if (sel < 0)
3260f7efad10SChunyan Zhang 		return sel;
3261f7efad10SChunyan Zhang 
3262f7efad10SChunyan Zhang 	uV = rdev->desc->ops->list_voltage(rdev, sel);
3263f7efad10SChunyan Zhang 	if (uV >= min_uV && uV <= max_uV)
3264f7efad10SChunyan Zhang 		rstate->uV = uV;
3265f7efad10SChunyan Zhang 
3266f7efad10SChunyan Zhang 	return 0;
3267f7efad10SChunyan Zhang }
3268f7efad10SChunyan Zhang 
3269a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator,
3270c360a6dfSChunyan Zhang 					  int min_uV, int max_uV,
3271c360a6dfSChunyan Zhang 					  suspend_state_t state)
3272414c70cbSLiam Girdwood {
3273414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
3274c360a6dfSChunyan Zhang 	struct regulator_voltage *voltage = &regulator->voltage[state];
327595a3c23aSMark Brown 	int ret = 0;
327692d7a558SPaolo Pisati 	int old_min_uV, old_max_uV;
3277c00dc359SBjorn Andersson 	int current_uV;
3278414c70cbSLiam Girdwood 
327995a3c23aSMark Brown 	/* If we're setting the same range as last time the change
328095a3c23aSMark Brown 	 * should be a noop (some cpufreq implementations use the same
328195a3c23aSMark Brown 	 * voltage for multiple frequencies, for example).
328295a3c23aSMark Brown 	 */
3283c360a6dfSChunyan Zhang 	if (voltage->min_uV == min_uV && voltage->max_uV == max_uV)
328495a3c23aSMark Brown 		goto out;
328595a3c23aSMark Brown 
3286c00dc359SBjorn Andersson 	/* If we're trying to set a range that overlaps the current voltage,
3287d3fb9800SViresh Kumar 	 * return successfully even though the regulator does not support
3288c00dc359SBjorn Andersson 	 * changing the voltage.
3289c00dc359SBjorn Andersson 	 */
32908a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
3291c00dc359SBjorn Andersson 		current_uV = _regulator_get_voltage(rdev);
3292c00dc359SBjorn Andersson 		if (min_uV <= current_uV && current_uV <= max_uV) {
3293c360a6dfSChunyan Zhang 			voltage->min_uV = min_uV;
3294c360a6dfSChunyan Zhang 			voltage->max_uV = max_uV;
3295c00dc359SBjorn Andersson 			goto out;
3296c00dc359SBjorn Andersson 		}
3297c00dc359SBjorn Andersson 	}
3298c00dc359SBjorn Andersson 
3299414c70cbSLiam Girdwood 	/* sanity check */
3300e8eef82bSMark Brown 	if (!rdev->desc->ops->set_voltage &&
3301e8eef82bSMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
3302414c70cbSLiam Girdwood 		ret = -EINVAL;
3303414c70cbSLiam Girdwood 		goto out;
3304414c70cbSLiam Girdwood 	}
3305414c70cbSLiam Girdwood 
3306414c70cbSLiam Girdwood 	/* constraints check */
3307414c70cbSLiam Girdwood 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
3308414c70cbSLiam Girdwood 	if (ret < 0)
3309414c70cbSLiam Girdwood 		goto out;
331092d7a558SPaolo Pisati 
331192d7a558SPaolo Pisati 	/* restore original values in case of error */
3312c360a6dfSChunyan Zhang 	old_min_uV = voltage->min_uV;
3313c360a6dfSChunyan Zhang 	old_max_uV = voltage->max_uV;
3314c360a6dfSChunyan Zhang 	voltage->min_uV = min_uV;
3315c360a6dfSChunyan Zhang 	voltage->max_uV = max_uV;
33163a93f2a9SMark Brown 
33179243a195SMaciej Purski 	/* for not coupled regulators this will just set the voltage */
33189243a195SMaciej Purski 	ret = regulator_balance_voltage(rdev, state);
331970b46491SSteve Twiss 	if (ret < 0) {
33209243a195SMaciej Purski 		voltage->min_uV = old_min_uV;
33219243a195SMaciej Purski 		voltage->max_uV = old_max_uV;
332270b46491SSteve Twiss 	}
33239243a195SMaciej Purski 
332470b46491SSteve Twiss out:
33259243a195SMaciej Purski 	return ret;
33269243a195SMaciej Purski }
33279243a195SMaciej Purski 
33289243a195SMaciej Purski static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
33299243a195SMaciej Purski 				      int max_uV, suspend_state_t state)
33309243a195SMaciej Purski {
33319243a195SMaciej Purski 	int best_supply_uV = 0;
33329243a195SMaciej Purski 	int supply_change_uV = 0;
33339243a195SMaciej Purski 	int ret;
33349243a195SMaciej Purski 
333543fc99f2SMark Brown 	if (rdev->supply &&
333643fc99f2SMark Brown 	    regulator_ops_is_valid(rdev->supply->rdev,
333743fc99f2SMark Brown 				   REGULATOR_CHANGE_VOLTAGE) &&
33382c2874b1STirupathi Reddy 	    (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage ||
33392c2874b1STirupathi Reddy 					   rdev->desc->ops->get_voltage_sel))) {
3340fc42112cSSascha Hauer 		int current_supply_uV;
3341fc42112cSSascha Hauer 		int selector;
3342fc42112cSSascha Hauer 
3343fc42112cSSascha Hauer 		selector = regulator_map_voltage(rdev, min_uV, max_uV);
3344fc42112cSSascha Hauer 		if (selector < 0) {
3345fc42112cSSascha Hauer 			ret = selector;
33469243a195SMaciej Purski 			goto out;
3347fc42112cSSascha Hauer 		}
3348fc42112cSSascha Hauer 
334900cb9f4fSMark Brown 		best_supply_uV = _regulator_list_voltage(rdev, selector, 0);
3350fc42112cSSascha Hauer 		if (best_supply_uV < 0) {
3351fc42112cSSascha Hauer 			ret = best_supply_uV;
33529243a195SMaciej Purski 			goto out;
3353fc42112cSSascha Hauer 		}
3354fc42112cSSascha Hauer 
3355fc42112cSSascha Hauer 		best_supply_uV += rdev->desc->min_dropout_uV;
3356fc42112cSSascha Hauer 
3357fc42112cSSascha Hauer 		current_supply_uV = _regulator_get_voltage(rdev->supply->rdev);
3358fc42112cSSascha Hauer 		if (current_supply_uV < 0) {
3359fc42112cSSascha Hauer 			ret = current_supply_uV;
33609243a195SMaciej Purski 			goto out;
3361fc42112cSSascha Hauer 		}
3362fc42112cSSascha Hauer 
3363fc42112cSSascha Hauer 		supply_change_uV = best_supply_uV - current_supply_uV;
3364fc42112cSSascha Hauer 	}
3365fc42112cSSascha Hauer 
3366fc42112cSSascha Hauer 	if (supply_change_uV > 0) {
3367fc42112cSSascha Hauer 		ret = regulator_set_voltage_unlocked(rdev->supply,
3368c360a6dfSChunyan Zhang 				best_supply_uV, INT_MAX, state);
3369fc42112cSSascha Hauer 		if (ret) {
3370fc42112cSSascha Hauer 			dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
3371fc42112cSSascha Hauer 					ret);
33729243a195SMaciej Purski 			goto out;
3373fc42112cSSascha Hauer 		}
3374fc42112cSSascha Hauer 	}
3375fc42112cSSascha Hauer 
3376f7efad10SChunyan Zhang 	if (state == PM_SUSPEND_ON)
337775790251SMark Brown 		ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
3378f7efad10SChunyan Zhang 	else
3379f7efad10SChunyan Zhang 		ret = _regulator_do_set_suspend_voltage(rdev, min_uV,
3380f7efad10SChunyan Zhang 							max_uV, state);
338192d7a558SPaolo Pisati 	if (ret < 0)
33829243a195SMaciej Purski 		goto out;
338302fa3ec0SMark Brown 
3384fc42112cSSascha Hauer 	if (supply_change_uV < 0) {
3385fc42112cSSascha Hauer 		ret = regulator_set_voltage_unlocked(rdev->supply,
3386c360a6dfSChunyan Zhang 				best_supply_uV, INT_MAX, state);
3387fc42112cSSascha Hauer 		if (ret)
3388fc42112cSSascha Hauer 			dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n",
3389fc42112cSSascha Hauer 					ret);
3390fc42112cSSascha Hauer 		/* No need to fail here */
3391fc42112cSSascha Hauer 		ret = 0;
3392fc42112cSSascha Hauer 	}
3393fc42112cSSascha Hauer 
3394414c70cbSLiam Girdwood out:
3395414c70cbSLiam Girdwood 	return ret;
339669686176SMaciej Purski }
339769686176SMaciej Purski 
339885254bcfSDmitry Osipenko static int regulator_limit_voltage_step(struct regulator_dev *rdev,
339985254bcfSDmitry Osipenko 					int *current_uV, int *min_uV)
340085254bcfSDmitry Osipenko {
340185254bcfSDmitry Osipenko 	struct regulation_constraints *constraints = rdev->constraints;
340285254bcfSDmitry Osipenko 
340385254bcfSDmitry Osipenko 	/* Limit voltage change only if necessary */
340485254bcfSDmitry Osipenko 	if (!constraints->max_uV_step || !_regulator_is_enabled(rdev))
340585254bcfSDmitry Osipenko 		return 1;
340685254bcfSDmitry Osipenko 
340785254bcfSDmitry Osipenko 	if (*current_uV < 0) {
340885254bcfSDmitry Osipenko 		*current_uV = _regulator_get_voltage(rdev);
340985254bcfSDmitry Osipenko 
341085254bcfSDmitry Osipenko 		if (*current_uV < 0)
341185254bcfSDmitry Osipenko 			return *current_uV;
341285254bcfSDmitry Osipenko 	}
341385254bcfSDmitry Osipenko 
341485254bcfSDmitry Osipenko 	if (abs(*current_uV - *min_uV) <= constraints->max_uV_step)
341585254bcfSDmitry Osipenko 		return 1;
341685254bcfSDmitry Osipenko 
341785254bcfSDmitry Osipenko 	/* Clamp target voltage within the given step */
341885254bcfSDmitry Osipenko 	if (*current_uV < *min_uV)
341985254bcfSDmitry Osipenko 		*min_uV = min(*current_uV + constraints->max_uV_step,
342085254bcfSDmitry Osipenko 			      *min_uV);
342185254bcfSDmitry Osipenko 	else
342285254bcfSDmitry Osipenko 		*min_uV = max(*current_uV - constraints->max_uV_step,
342385254bcfSDmitry Osipenko 			      *min_uV);
342485254bcfSDmitry Osipenko 
342585254bcfSDmitry Osipenko 	return 0;
342685254bcfSDmitry Osipenko }
342785254bcfSDmitry Osipenko 
3428c054c6c7SMaciej Purski static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
3429c054c6c7SMaciej Purski 					 int *current_uV,
3430c054c6c7SMaciej Purski 					 int *min_uV, int *max_uV,
3431c054c6c7SMaciej Purski 					 suspend_state_t state,
3432c054c6c7SMaciej Purski 					 int n_coupled)
3433c054c6c7SMaciej Purski {
3434c054c6c7SMaciej Purski 	struct coupling_desc *c_desc = &rdev->coupling_desc;
3435c054c6c7SMaciej Purski 	struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
3436c054c6c7SMaciej Purski 	struct regulation_constraints *constraints = rdev->constraints;
3437c054c6c7SMaciej Purski 	int max_spread = constraints->max_spread;
3438c054c6c7SMaciej Purski 	int desired_min_uV = 0, desired_max_uV = INT_MAX;
3439c054c6c7SMaciej Purski 	int max_current_uV = 0, min_current_uV = INT_MAX;
3440c054c6c7SMaciej Purski 	int highest_min_uV = 0, target_uV, possible_uV;
3441c054c6c7SMaciej Purski 	int i, ret;
3442c054c6c7SMaciej Purski 	bool done;
3443c054c6c7SMaciej Purski 
3444c054c6c7SMaciej Purski 	*current_uV = -1;
3445c054c6c7SMaciej Purski 
3446c054c6c7SMaciej Purski 	/*
3447c054c6c7SMaciej Purski 	 * If there are no coupled regulators, simply set the voltage
3448c054c6c7SMaciej Purski 	 * demanded by consumers.
3449c054c6c7SMaciej Purski 	 */
3450c054c6c7SMaciej Purski 	if (n_coupled == 1) {
3451c054c6c7SMaciej Purski 		/*
3452c054c6c7SMaciej Purski 		 * If consumers don't provide any demands, set voltage
3453c054c6c7SMaciej Purski 		 * to min_uV
3454c054c6c7SMaciej Purski 		 */
3455c054c6c7SMaciej Purski 		desired_min_uV = constraints->min_uV;
3456c054c6c7SMaciej Purski 		desired_max_uV = constraints->max_uV;
3457c054c6c7SMaciej Purski 
3458c054c6c7SMaciej Purski 		ret = regulator_check_consumers(rdev,
3459c054c6c7SMaciej Purski 						&desired_min_uV,
3460c054c6c7SMaciej Purski 						&desired_max_uV, state);
3461c054c6c7SMaciej Purski 		if (ret < 0)
3462c054c6c7SMaciej Purski 			return ret;
3463c054c6c7SMaciej Purski 
3464c054c6c7SMaciej Purski 		possible_uV = desired_min_uV;
3465c054c6c7SMaciej Purski 		done = true;
3466c054c6c7SMaciej Purski 
3467c054c6c7SMaciej Purski 		goto finish;
3468c054c6c7SMaciej Purski 	}
3469c054c6c7SMaciej Purski 
3470c054c6c7SMaciej Purski 	/* Find highest min desired voltage */
3471c054c6c7SMaciej Purski 	for (i = 0; i < n_coupled; i++) {
3472c054c6c7SMaciej Purski 		int tmp_min = 0;
3473c054c6c7SMaciej Purski 		int tmp_max = INT_MAX;
3474c054c6c7SMaciej Purski 
3475f8702f9eSDmitry Osipenko 		lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
3476c054c6c7SMaciej Purski 
3477c054c6c7SMaciej Purski 		ret = regulator_check_consumers(c_rdevs[i],
3478c054c6c7SMaciej Purski 						&tmp_min,
3479c054c6c7SMaciej Purski 						&tmp_max, state);
3480c054c6c7SMaciej Purski 		if (ret < 0)
3481c054c6c7SMaciej Purski 			return ret;
3482c054c6c7SMaciej Purski 
3483c054c6c7SMaciej Purski 		ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max);
3484c054c6c7SMaciej Purski 		if (ret < 0)
3485c054c6c7SMaciej Purski 			return ret;
3486c054c6c7SMaciej Purski 
3487c054c6c7SMaciej Purski 		highest_min_uV = max(highest_min_uV, tmp_min);
3488c054c6c7SMaciej Purski 
3489c054c6c7SMaciej Purski 		if (i == 0) {
3490c054c6c7SMaciej Purski 			desired_min_uV = tmp_min;
3491c054c6c7SMaciej Purski 			desired_max_uV = tmp_max;
3492c054c6c7SMaciej Purski 		}
3493c054c6c7SMaciej Purski 	}
3494c054c6c7SMaciej Purski 
3495c054c6c7SMaciej Purski 	/*
3496c054c6c7SMaciej Purski 	 * Let target_uV be equal to the desired one if possible.
3497c054c6c7SMaciej Purski 	 * If not, set it to minimum voltage, allowed by other coupled
3498c054c6c7SMaciej Purski 	 * regulators.
3499c054c6c7SMaciej Purski 	 */
3500c054c6c7SMaciej Purski 	target_uV = max(desired_min_uV, highest_min_uV - max_spread);
3501c054c6c7SMaciej Purski 
3502c054c6c7SMaciej Purski 	/*
3503c054c6c7SMaciej Purski 	 * Find min and max voltages, which currently aren't violating
3504c054c6c7SMaciej Purski 	 * max_spread.
3505c054c6c7SMaciej Purski 	 */
3506c054c6c7SMaciej Purski 	for (i = 1; i < n_coupled; i++) {
3507c054c6c7SMaciej Purski 		int tmp_act;
3508c054c6c7SMaciej Purski 
3509c054c6c7SMaciej Purski 		if (!_regulator_is_enabled(c_rdevs[i]))
3510c054c6c7SMaciej Purski 			continue;
3511c054c6c7SMaciej Purski 
3512c054c6c7SMaciej Purski 		tmp_act = _regulator_get_voltage(c_rdevs[i]);
3513c054c6c7SMaciej Purski 		if (tmp_act < 0)
3514c054c6c7SMaciej Purski 			return tmp_act;
3515c054c6c7SMaciej Purski 
3516c054c6c7SMaciej Purski 		min_current_uV = min(tmp_act, min_current_uV);
3517c054c6c7SMaciej Purski 		max_current_uV = max(tmp_act, max_current_uV);
3518c054c6c7SMaciej Purski 	}
3519c054c6c7SMaciej Purski 
3520c054c6c7SMaciej Purski 	/* There aren't any other regulators enabled */
3521c054c6c7SMaciej Purski 	if (max_current_uV == 0) {
3522c054c6c7SMaciej Purski 		possible_uV = target_uV;
3523c054c6c7SMaciej Purski 	} else {
3524c054c6c7SMaciej Purski 		/*
3525c054c6c7SMaciej Purski 		 * Correct target voltage, so as it currently isn't
3526c054c6c7SMaciej Purski 		 * violating max_spread
3527c054c6c7SMaciej Purski 		 */
3528c054c6c7SMaciej Purski 		possible_uV = max(target_uV, max_current_uV - max_spread);
3529c054c6c7SMaciej Purski 		possible_uV = min(possible_uV, min_current_uV + max_spread);
3530c054c6c7SMaciej Purski 	}
3531c054c6c7SMaciej Purski 
3532c054c6c7SMaciej Purski 	if (possible_uV > desired_max_uV)
3533c054c6c7SMaciej Purski 		return -EINVAL;
3534c054c6c7SMaciej Purski 
3535c054c6c7SMaciej Purski 	done = (possible_uV == target_uV);
3536c054c6c7SMaciej Purski 	desired_min_uV = possible_uV;
3537c054c6c7SMaciej Purski 
3538c054c6c7SMaciej Purski finish:
353985254bcfSDmitry Osipenko 	/* Apply max_uV_step constraint if necessary */
354085254bcfSDmitry Osipenko 	if (state == PM_SUSPEND_ON) {
354185254bcfSDmitry Osipenko 		ret = regulator_limit_voltage_step(rdev, current_uV,
354285254bcfSDmitry Osipenko 						   &desired_min_uV);
354385254bcfSDmitry Osipenko 		if (ret < 0)
354485254bcfSDmitry Osipenko 			return ret;
354585254bcfSDmitry Osipenko 
354685254bcfSDmitry Osipenko 		if (ret == 0)
354785254bcfSDmitry Osipenko 			done = false;
354885254bcfSDmitry Osipenko 	}
354985254bcfSDmitry Osipenko 
3550c054c6c7SMaciej Purski 	/* Set current_uV if wasn't done earlier in the code and if necessary */
3551c054c6c7SMaciej Purski 	if (n_coupled > 1 && *current_uV == -1) {
3552c054c6c7SMaciej Purski 
3553c054c6c7SMaciej Purski 		if (_regulator_is_enabled(rdev)) {
3554c054c6c7SMaciej Purski 			ret = _regulator_get_voltage(rdev);
3555c054c6c7SMaciej Purski 			if (ret < 0)
3556c054c6c7SMaciej Purski 				return ret;
3557c054c6c7SMaciej Purski 
3558c054c6c7SMaciej Purski 			*current_uV = ret;
3559c054c6c7SMaciej Purski 		} else {
3560c054c6c7SMaciej Purski 			*current_uV = desired_min_uV;
3561c054c6c7SMaciej Purski 		}
3562c054c6c7SMaciej Purski 	}
3563c054c6c7SMaciej Purski 
3564c054c6c7SMaciej Purski 	*min_uV = desired_min_uV;
3565c054c6c7SMaciej Purski 	*max_uV = desired_max_uV;
3566c054c6c7SMaciej Purski 
3567c054c6c7SMaciej Purski 	return done;
3568c054c6c7SMaciej Purski }
3569c054c6c7SMaciej Purski 
3570c054c6c7SMaciej Purski static int regulator_balance_voltage(struct regulator_dev *rdev,
3571c054c6c7SMaciej Purski 				     suspend_state_t state)
3572c054c6c7SMaciej Purski {
3573c054c6c7SMaciej Purski 	struct regulator_dev **c_rdevs;
3574c054c6c7SMaciej Purski 	struct regulator_dev *best_rdev;
3575c054c6c7SMaciej Purski 	struct coupling_desc *c_desc = &rdev->coupling_desc;
3576c054c6c7SMaciej Purski 	int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
3577c054c6c7SMaciej Purski 	bool best_c_rdev_done, c_rdev_done[MAX_COUPLED];
3578c054c6c7SMaciej Purski 	unsigned int delta, best_delta;
3579c054c6c7SMaciej Purski 
3580c054c6c7SMaciej Purski 	c_rdevs = c_desc->coupled_rdevs;
3581c054c6c7SMaciej Purski 	n_coupled = c_desc->n_coupled;
3582c054c6c7SMaciej Purski 
3583c054c6c7SMaciej Purski 	/*
3584c054c6c7SMaciej Purski 	 * If system is in a state other than PM_SUSPEND_ON, don't check
3585c054c6c7SMaciej Purski 	 * other coupled regulators.
3586c054c6c7SMaciej Purski 	 */
3587c054c6c7SMaciej Purski 	if (state != PM_SUSPEND_ON)
3588c054c6c7SMaciej Purski 		n_coupled = 1;
3589c054c6c7SMaciej Purski 
3590c054c6c7SMaciej Purski 	if (c_desc->n_resolved < n_coupled) {
3591c054c6c7SMaciej Purski 		rdev_err(rdev, "Not all coupled regulators registered\n");
3592c054c6c7SMaciej Purski 		return -EPERM;
3593c054c6c7SMaciej Purski 	}
3594c054c6c7SMaciej Purski 
3595c054c6c7SMaciej Purski 	for (i = 0; i < n_coupled; i++)
3596c054c6c7SMaciej Purski 		c_rdev_done[i] = false;
3597c054c6c7SMaciej Purski 
3598c054c6c7SMaciej Purski 	/*
3599c054c6c7SMaciej Purski 	 * Find the best possible voltage change on each loop. Leave the loop
3600c054c6c7SMaciej Purski 	 * if there isn't any possible change.
3601c054c6c7SMaciej Purski 	 */
3602c054c6c7SMaciej Purski 	do {
3603c054c6c7SMaciej Purski 		best_c_rdev_done = false;
3604c054c6c7SMaciej Purski 		best_delta = 0;
3605c054c6c7SMaciej Purski 		best_min_uV = 0;
3606c054c6c7SMaciej Purski 		best_max_uV = 0;
3607c054c6c7SMaciej Purski 		best_c_rdev = 0;
3608c054c6c7SMaciej Purski 		best_rdev = NULL;
3609c054c6c7SMaciej Purski 
3610c054c6c7SMaciej Purski 		/*
3611c054c6c7SMaciej Purski 		 * Find highest difference between optimal voltage
3612c054c6c7SMaciej Purski 		 * and current voltage.
3613c054c6c7SMaciej Purski 		 */
3614c054c6c7SMaciej Purski 		for (i = 0; i < n_coupled; i++) {
3615c054c6c7SMaciej Purski 			/*
3616c054c6c7SMaciej Purski 			 * optimal_uV is the best voltage that can be set for
3617c054c6c7SMaciej Purski 			 * i-th regulator at the moment without violating
3618c054c6c7SMaciej Purski 			 * max_spread constraint in order to balance
3619c054c6c7SMaciej Purski 			 * the coupled voltages.
3620c054c6c7SMaciej Purski 			 */
3621c054c6c7SMaciej Purski 			int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
3622c054c6c7SMaciej Purski 
3623c054c6c7SMaciej Purski 			if (c_rdev_done[i])
3624c054c6c7SMaciej Purski 				continue;
3625c054c6c7SMaciej Purski 
3626c054c6c7SMaciej Purski 			ret = regulator_get_optimal_voltage(c_rdevs[i],
3627c054c6c7SMaciej Purski 							    &current_uV,
3628c054c6c7SMaciej Purski 							    &optimal_uV,
3629c054c6c7SMaciej Purski 							    &optimal_max_uV,
3630c054c6c7SMaciej Purski 							    state, n_coupled);
3631c054c6c7SMaciej Purski 			if (ret < 0)
3632c054c6c7SMaciej Purski 				goto out;
3633c054c6c7SMaciej Purski 
3634c054c6c7SMaciej Purski 			delta = abs(optimal_uV - current_uV);
3635c054c6c7SMaciej Purski 
3636c054c6c7SMaciej Purski 			if (delta && best_delta <= delta) {
3637c054c6c7SMaciej Purski 				best_c_rdev_done = ret;
3638c054c6c7SMaciej Purski 				best_delta = delta;
3639c054c6c7SMaciej Purski 				best_rdev = c_rdevs[i];
3640c054c6c7SMaciej Purski 				best_min_uV = optimal_uV;
3641c054c6c7SMaciej Purski 				best_max_uV = optimal_max_uV;
3642c054c6c7SMaciej Purski 				best_c_rdev = i;
3643c054c6c7SMaciej Purski 			}
3644c054c6c7SMaciej Purski 		}
3645c054c6c7SMaciej Purski 
3646c054c6c7SMaciej Purski 		/* Nothing to change, return successfully */
3647c054c6c7SMaciej Purski 		if (!best_rdev) {
3648c054c6c7SMaciej Purski 			ret = 0;
3649c054c6c7SMaciej Purski 			goto out;
3650c054c6c7SMaciej Purski 		}
36519243a195SMaciej Purski 
3652c054c6c7SMaciej Purski 		ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
3653c054c6c7SMaciej Purski 						 best_max_uV, state);
36549243a195SMaciej Purski 
3655c054c6c7SMaciej Purski 		if (ret < 0)
3656c054c6c7SMaciej Purski 			goto out;
3657c054c6c7SMaciej Purski 
3658c054c6c7SMaciej Purski 		c_rdev_done[best_c_rdev] = best_c_rdev_done;
3659c054c6c7SMaciej Purski 
3660c054c6c7SMaciej Purski 	} while (n_coupled > 1);
3661c054c6c7SMaciej Purski 
3662c054c6c7SMaciej Purski out:
366369686176SMaciej Purski 	return ret;
366469686176SMaciej Purski }
366569686176SMaciej Purski 
3666a9f226bcSSascha Hauer /**
3667a9f226bcSSascha Hauer  * regulator_set_voltage - set regulator output voltage
3668a9f226bcSSascha Hauer  * @regulator: regulator source
3669a9f226bcSSascha Hauer  * @min_uV: Minimum required voltage in uV
3670a9f226bcSSascha Hauer  * @max_uV: Maximum acceptable voltage in uV
3671a9f226bcSSascha Hauer  *
3672a9f226bcSSascha Hauer  * Sets a voltage regulator to the desired output voltage. This can be set
3673a9f226bcSSascha Hauer  * during any regulator state. IOW, regulator can be disabled or enabled.
3674a9f226bcSSascha Hauer  *
3675a9f226bcSSascha Hauer  * If the regulator is enabled then the voltage will change to the new value
3676a9f226bcSSascha Hauer  * immediately otherwise if the regulator is disabled the regulator will
3677a9f226bcSSascha Hauer  * output at the new voltage when enabled.
3678a9f226bcSSascha Hauer  *
3679a9f226bcSSascha Hauer  * NOTE: If the regulator is shared between several devices then the lowest
3680a9f226bcSSascha Hauer  * request voltage that meets the system constraints will be used.
3681a9f226bcSSascha Hauer  * Regulator system constraints must be set for this regulator before
3682a9f226bcSSascha Hauer  * calling this function otherwise this call will fail.
3683a9f226bcSSascha Hauer  */
3684a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
3685a9f226bcSSascha Hauer {
3686f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
3687f8702f9eSDmitry Osipenko 	int ret;
3688a9f226bcSSascha Hauer 
3689f8702f9eSDmitry Osipenko 	regulator_lock_dependent(regulator->rdev, &ww_ctx);
3690a9f226bcSSascha Hauer 
3691c360a6dfSChunyan Zhang 	ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
3692c360a6dfSChunyan Zhang 					     PM_SUSPEND_ON);
3693a9f226bcSSascha Hauer 
3694f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
3695a9f226bcSSascha Hauer 
369692d7a558SPaolo Pisati 	return ret;
3697414c70cbSLiam Girdwood }
3698414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage);
3699414c70cbSLiam Girdwood 
3700f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev,
3701f7efad10SChunyan Zhang 					   suspend_state_t state, bool en)
3702f7efad10SChunyan Zhang {
3703f7efad10SChunyan Zhang 	struct regulator_state *rstate;
3704f7efad10SChunyan Zhang 
3705f7efad10SChunyan Zhang 	rstate = regulator_get_suspend_state(rdev, state);
3706f7efad10SChunyan Zhang 	if (rstate == NULL)
3707f7efad10SChunyan Zhang 		return -EINVAL;
3708f7efad10SChunyan Zhang 
3709f7efad10SChunyan Zhang 	if (!rstate->changeable)
3710f7efad10SChunyan Zhang 		return -EPERM;
3711f7efad10SChunyan Zhang 
37123edd79cfSMarek Szyprowski 	rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND;
3713f7efad10SChunyan Zhang 
3714f7efad10SChunyan Zhang 	return 0;
3715f7efad10SChunyan Zhang }
3716f7efad10SChunyan Zhang 
3717f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev,
3718f7efad10SChunyan Zhang 				    suspend_state_t state)
3719f7efad10SChunyan Zhang {
3720f7efad10SChunyan Zhang 	return regulator_suspend_toggle(rdev, state, true);
3721f7efad10SChunyan Zhang }
3722f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable);
3723f7efad10SChunyan Zhang 
3724f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev,
3725f7efad10SChunyan Zhang 				     suspend_state_t state)
3726f7efad10SChunyan Zhang {
3727f7efad10SChunyan Zhang 	struct regulator *regulator;
3728f7efad10SChunyan Zhang 	struct regulator_voltage *voltage;
3729f7efad10SChunyan Zhang 
3730f7efad10SChunyan Zhang 	/*
3731f7efad10SChunyan Zhang 	 * if any consumer wants this regulator device keeping on in
3732f7efad10SChunyan Zhang 	 * suspend states, don't set it as disabled.
3733f7efad10SChunyan Zhang 	 */
3734f7efad10SChunyan Zhang 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
3735f7efad10SChunyan Zhang 		voltage = &regulator->voltage[state];
3736f7efad10SChunyan Zhang 		if (voltage->min_uV || voltage->max_uV)
3737f7efad10SChunyan Zhang 			return 0;
3738f7efad10SChunyan Zhang 	}
3739f7efad10SChunyan Zhang 
3740f7efad10SChunyan Zhang 	return regulator_suspend_toggle(rdev, state, false);
3741f7efad10SChunyan Zhang }
3742f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable);
3743f7efad10SChunyan Zhang 
3744f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator,
3745f7efad10SChunyan Zhang 					  int min_uV, int max_uV,
3746f7efad10SChunyan Zhang 					  suspend_state_t state)
3747f7efad10SChunyan Zhang {
3748f7efad10SChunyan Zhang 	struct regulator_dev *rdev = regulator->rdev;
3749f7efad10SChunyan Zhang 	struct regulator_state *rstate;
3750f7efad10SChunyan Zhang 
3751f7efad10SChunyan Zhang 	rstate = regulator_get_suspend_state(rdev, state);
3752f7efad10SChunyan Zhang 	if (rstate == NULL)
3753f7efad10SChunyan Zhang 		return -EINVAL;
3754f7efad10SChunyan Zhang 
3755f7efad10SChunyan Zhang 	if (rstate->min_uV == rstate->max_uV) {
3756f7efad10SChunyan Zhang 		rdev_err(rdev, "The suspend voltage can't be changed!\n");
3757f7efad10SChunyan Zhang 		return -EPERM;
3758f7efad10SChunyan Zhang 	}
3759f7efad10SChunyan Zhang 
3760f7efad10SChunyan Zhang 	return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state);
3761f7efad10SChunyan Zhang }
3762f7efad10SChunyan Zhang 
3763f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
3764f7efad10SChunyan Zhang 				  int max_uV, suspend_state_t state)
3765f7efad10SChunyan Zhang {
3766f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
3767f8702f9eSDmitry Osipenko 	int ret;
3768f7efad10SChunyan Zhang 
3769f7efad10SChunyan Zhang 	/* PM_SUSPEND_ON is handled by regulator_set_voltage() */
3770f7efad10SChunyan Zhang 	if (regulator_check_states(state) || state == PM_SUSPEND_ON)
3771f7efad10SChunyan Zhang 		return -EINVAL;
3772f7efad10SChunyan Zhang 
3773f8702f9eSDmitry Osipenko 	regulator_lock_dependent(regulator->rdev, &ww_ctx);
3774f7efad10SChunyan Zhang 
3775f7efad10SChunyan Zhang 	ret = _regulator_set_suspend_voltage(regulator, min_uV,
3776f7efad10SChunyan Zhang 					     max_uV, state);
3777f7efad10SChunyan Zhang 
3778f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
3779f7efad10SChunyan Zhang 
3780f7efad10SChunyan Zhang 	return ret;
3781f7efad10SChunyan Zhang }
3782f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage);
3783f7efad10SChunyan Zhang 
3784606a2562SMark Brown /**
378588cd222bSLinus Walleij  * regulator_set_voltage_time - get raise/fall time
378688cd222bSLinus Walleij  * @regulator: regulator source
378788cd222bSLinus Walleij  * @old_uV: starting voltage in microvolts
378888cd222bSLinus Walleij  * @new_uV: target voltage in microvolts
378988cd222bSLinus Walleij  *
379088cd222bSLinus Walleij  * Provided with the starting and ending voltage, this function attempts to
379188cd222bSLinus Walleij  * calculate the time in microseconds required to rise or fall to this new
379288cd222bSLinus Walleij  * voltage.
379388cd222bSLinus Walleij  */
379488cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator,
379588cd222bSLinus Walleij 			       int old_uV, int new_uV)
379688cd222bSLinus Walleij {
379788cd222bSLinus Walleij 	struct regulator_dev *rdev = regulator->rdev;
3798272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
379988cd222bSLinus Walleij 	int old_sel = -1;
380088cd222bSLinus Walleij 	int new_sel = -1;
380188cd222bSLinus Walleij 	int voltage;
380288cd222bSLinus Walleij 	int i;
380388cd222bSLinus Walleij 
380473e705bfSMatthias Kaehlcke 	if (ops->set_voltage_time)
380573e705bfSMatthias Kaehlcke 		return ops->set_voltage_time(rdev, old_uV, new_uV);
380673e705bfSMatthias Kaehlcke 	else if (!ops->set_voltage_time_sel)
380773e705bfSMatthias Kaehlcke 		return _regulator_set_voltage_time(rdev, old_uV, new_uV);
380873e705bfSMatthias Kaehlcke 
380988cd222bSLinus Walleij 	/* Currently requires operations to do this */
381073e705bfSMatthias Kaehlcke 	if (!ops->list_voltage || !rdev->desc->n_voltages)
381188cd222bSLinus Walleij 		return -EINVAL;
381288cd222bSLinus Walleij 
381388cd222bSLinus Walleij 	for (i = 0; i < rdev->desc->n_voltages; i++) {
381488cd222bSLinus Walleij 		/* We only look for exact voltage matches here */
381588cd222bSLinus Walleij 		voltage = regulator_list_voltage(regulator, i);
381688cd222bSLinus Walleij 		if (voltage < 0)
381788cd222bSLinus Walleij 			return -EINVAL;
381888cd222bSLinus Walleij 		if (voltage == 0)
381988cd222bSLinus Walleij 			continue;
382088cd222bSLinus Walleij 		if (voltage == old_uV)
382188cd222bSLinus Walleij 			old_sel = i;
382288cd222bSLinus Walleij 		if (voltage == new_uV)
382388cd222bSLinus Walleij 			new_sel = i;
382488cd222bSLinus Walleij 	}
382588cd222bSLinus Walleij 
382688cd222bSLinus Walleij 	if (old_sel < 0 || new_sel < 0)
382788cd222bSLinus Walleij 		return -EINVAL;
382888cd222bSLinus Walleij 
382988cd222bSLinus Walleij 	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
383088cd222bSLinus Walleij }
383188cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
383288cd222bSLinus Walleij 
383388cd222bSLinus Walleij /**
383498a175b6SYadwinder Singh Brar  * regulator_set_voltage_time_sel - get raise/fall time
3835296c6566SRandy Dunlap  * @rdev: regulator source device
383698a175b6SYadwinder Singh Brar  * @old_selector: selector for starting voltage
383798a175b6SYadwinder Singh Brar  * @new_selector: selector for target voltage
383898a175b6SYadwinder Singh Brar  *
383998a175b6SYadwinder Singh Brar  * Provided with the starting and target voltage selectors, this function
384098a175b6SYadwinder Singh Brar  * returns time in microseconds required to rise or fall to this new voltage
384198a175b6SYadwinder Singh Brar  *
3842f11d08c3SAxel Lin  * Drivers providing ramp_delay in regulation_constraints can use this as their
3843398715abSAxel Lin  * set_voltage_time_sel() operation.
384498a175b6SYadwinder Singh Brar  */
384598a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
384698a175b6SYadwinder Singh Brar 				   unsigned int old_selector,
384798a175b6SYadwinder Singh Brar 				   unsigned int new_selector)
384898a175b6SYadwinder Singh Brar {
3849f11d08c3SAxel Lin 	int old_volt, new_volt;
3850398715abSAxel Lin 
3851f11d08c3SAxel Lin 	/* sanity check */
3852f11d08c3SAxel Lin 	if (!rdev->desc->ops->list_voltage)
3853f11d08c3SAxel Lin 		return -EINVAL;
3854398715abSAxel Lin 
3855f11d08c3SAxel Lin 	old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
3856f11d08c3SAxel Lin 	new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
3857f11d08c3SAxel Lin 
385873e705bfSMatthias Kaehlcke 	if (rdev->desc->ops->set_voltage_time)
385973e705bfSMatthias Kaehlcke 		return rdev->desc->ops->set_voltage_time(rdev, old_volt,
386073e705bfSMatthias Kaehlcke 							 new_volt);
386173e705bfSMatthias Kaehlcke 	else
386273e705bfSMatthias Kaehlcke 		return _regulator_set_voltage_time(rdev, old_volt, new_volt);
386398a175b6SYadwinder Singh Brar }
3864b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
386598a175b6SYadwinder Singh Brar 
386698a175b6SYadwinder Singh Brar /**
3867606a2562SMark Brown  * regulator_sync_voltage - re-apply last regulator output voltage
3868606a2562SMark Brown  * @regulator: regulator source
3869606a2562SMark Brown  *
3870606a2562SMark Brown  * Re-apply the last configured voltage.  This is intended to be used
3871606a2562SMark Brown  * where some external control source the consumer is cooperating with
3872606a2562SMark Brown  * has caused the configured voltage to change.
3873606a2562SMark Brown  */
3874606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator)
3875606a2562SMark Brown {
3876606a2562SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
3877c360a6dfSChunyan Zhang 	struct regulator_voltage *voltage = &regulator->voltage[PM_SUSPEND_ON];
3878606a2562SMark Brown 	int ret, min_uV, max_uV;
3879606a2562SMark Brown 
388066cf9a7eSMaciej Purski 	regulator_lock(rdev);
3881606a2562SMark Brown 
3882606a2562SMark Brown 	if (!rdev->desc->ops->set_voltage &&
3883606a2562SMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
3884606a2562SMark Brown 		ret = -EINVAL;
3885606a2562SMark Brown 		goto out;
3886606a2562SMark Brown 	}
3887606a2562SMark Brown 
3888606a2562SMark Brown 	/* This is only going to work if we've had a voltage configured. */
3889c360a6dfSChunyan Zhang 	if (!voltage->min_uV && !voltage->max_uV) {
3890606a2562SMark Brown 		ret = -EINVAL;
3891606a2562SMark Brown 		goto out;
3892606a2562SMark Brown 	}
3893606a2562SMark Brown 
3894c360a6dfSChunyan Zhang 	min_uV = voltage->min_uV;
3895c360a6dfSChunyan Zhang 	max_uV = voltage->max_uV;
3896606a2562SMark Brown 
3897606a2562SMark Brown 	/* This should be a paranoia check... */
3898606a2562SMark Brown 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
3899606a2562SMark Brown 	if (ret < 0)
3900606a2562SMark Brown 		goto out;
3901606a2562SMark Brown 
3902c360a6dfSChunyan Zhang 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0);
3903606a2562SMark Brown 	if (ret < 0)
3904606a2562SMark Brown 		goto out;
3905606a2562SMark Brown 
3906606a2562SMark Brown 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
3907606a2562SMark Brown 
3908606a2562SMark Brown out:
390966cf9a7eSMaciej Purski 	regulator_unlock(rdev);
3910606a2562SMark Brown 	return ret;
3911606a2562SMark Brown }
3912606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage);
3913606a2562SMark Brown 
3914414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev)
3915414c70cbSLiam Girdwood {
3916bf5892a8SMark Brown 	int sel, ret;
3917fef95019SMark Brown 	bool bypassed;
3918fef95019SMark Brown 
3919fef95019SMark Brown 	if (rdev->desc->ops->get_bypass) {
3920fef95019SMark Brown 		ret = rdev->desc->ops->get_bypass(rdev, &bypassed);
3921fef95019SMark Brown 		if (ret < 0)
3922fef95019SMark Brown 			return ret;
3923fef95019SMark Brown 		if (bypassed) {
3924fef95019SMark Brown 			/* if bypassed the regulator must have a supply */
392545389c47SJon Hunter 			if (!rdev->supply) {
392645389c47SJon Hunter 				rdev_err(rdev,
392745389c47SJon Hunter 					 "bypassed regulator has no supply!\n");
392845389c47SJon Hunter 				return -EPROBE_DEFER;
392945389c47SJon Hunter 			}
3930fef95019SMark Brown 
3931fef95019SMark Brown 			return _regulator_get_voltage(rdev->supply->rdev);
3932fef95019SMark Brown 		}
3933fef95019SMark Brown 	}
3934476c2d83SMark Brown 
3935476c2d83SMark Brown 	if (rdev->desc->ops->get_voltage_sel) {
3936476c2d83SMark Brown 		sel = rdev->desc->ops->get_voltage_sel(rdev);
3937476c2d83SMark Brown 		if (sel < 0)
3938476c2d83SMark Brown 			return sel;
3939bf5892a8SMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, sel);
3940cb220d16SAxel Lin 	} else if (rdev->desc->ops->get_voltage) {
3941bf5892a8SMark Brown 		ret = rdev->desc->ops->get_voltage(rdev);
3942f7df20ecSMark Brown 	} else if (rdev->desc->ops->list_voltage) {
3943f7df20ecSMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, 0);
39445a523605SLaxman Dewangan 	} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
39455a523605SLaxman Dewangan 		ret = rdev->desc->fixed_uV;
3946e303996eSJavier Martinez Canillas 	} else if (rdev->supply) {
3947d9b96d35SMark Brown 		ret = _regulator_get_voltage(rdev->supply->rdev);
3948cb220d16SAxel Lin 	} else {
3949414c70cbSLiam Girdwood 		return -EINVAL;
3950cb220d16SAxel Lin 	}
3951bf5892a8SMark Brown 
3952cb220d16SAxel Lin 	if (ret < 0)
3953cb220d16SAxel Lin 		return ret;
3954bf5892a8SMark Brown 	return ret - rdev->constraints->uV_offset;
3955414c70cbSLiam Girdwood }
3956414c70cbSLiam Girdwood 
3957414c70cbSLiam Girdwood /**
3958414c70cbSLiam Girdwood  * regulator_get_voltage - get regulator output voltage
3959414c70cbSLiam Girdwood  * @regulator: regulator source
3960414c70cbSLiam Girdwood  *
3961414c70cbSLiam Girdwood  * This returns the current regulator voltage in uV.
3962414c70cbSLiam Girdwood  *
3963414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the voltage value. This
3964414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
3965414c70cbSLiam Girdwood  */
3966414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator)
3967414c70cbSLiam Girdwood {
3968f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
3969414c70cbSLiam Girdwood 	int ret;
3970414c70cbSLiam Girdwood 
3971f8702f9eSDmitry Osipenko 	regulator_lock_dependent(regulator->rdev, &ww_ctx);
3972414c70cbSLiam Girdwood 	ret = _regulator_get_voltage(regulator->rdev);
3973f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
3974414c70cbSLiam Girdwood 
3975414c70cbSLiam Girdwood 	return ret;
3976414c70cbSLiam Girdwood }
3977414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage);
3978414c70cbSLiam Girdwood 
3979414c70cbSLiam Girdwood /**
3980414c70cbSLiam Girdwood  * regulator_set_current_limit - set regulator output current limit
3981414c70cbSLiam Girdwood  * @regulator: regulator source
3982ce0d10f8SCharles Keepax  * @min_uA: Minimum supported current in uA
3983414c70cbSLiam Girdwood  * @max_uA: Maximum supported current in uA
3984414c70cbSLiam Girdwood  *
3985414c70cbSLiam Girdwood  * Sets current sink to the desired output current. This can be set during
3986414c70cbSLiam Girdwood  * any regulator state. IOW, regulator can be disabled or enabled.
3987414c70cbSLiam Girdwood  *
3988414c70cbSLiam Girdwood  * If the regulator is enabled then the current will change to the new value
3989414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
3990414c70cbSLiam Girdwood  * output at the new current when enabled.
3991414c70cbSLiam Girdwood  *
3992414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
3993414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
3994414c70cbSLiam Girdwood  */
3995414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator,
3996414c70cbSLiam Girdwood 			       int min_uA, int max_uA)
3997414c70cbSLiam Girdwood {
3998414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
3999414c70cbSLiam Girdwood 	int ret;
4000414c70cbSLiam Girdwood 
400166cf9a7eSMaciej Purski 	regulator_lock(rdev);
4002414c70cbSLiam Girdwood 
4003414c70cbSLiam Girdwood 	/* sanity check */
4004414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_current_limit) {
4005414c70cbSLiam Girdwood 		ret = -EINVAL;
4006414c70cbSLiam Girdwood 		goto out;
4007414c70cbSLiam Girdwood 	}
4008414c70cbSLiam Girdwood 
4009414c70cbSLiam Girdwood 	/* constraints check */
4010414c70cbSLiam Girdwood 	ret = regulator_check_current_limit(rdev, &min_uA, &max_uA);
4011414c70cbSLiam Girdwood 	if (ret < 0)
4012414c70cbSLiam Girdwood 		goto out;
4013414c70cbSLiam Girdwood 
4014414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
4015414c70cbSLiam Girdwood out:
401666cf9a7eSMaciej Purski 	regulator_unlock(rdev);
4017414c70cbSLiam Girdwood 	return ret;
4018414c70cbSLiam Girdwood }
4019414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit);
4020414c70cbSLiam Girdwood 
40217e4d9683SDouglas Anderson static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev)
40227e4d9683SDouglas Anderson {
40237e4d9683SDouglas Anderson 	/* sanity check */
40247e4d9683SDouglas Anderson 	if (!rdev->desc->ops->get_current_limit)
40257e4d9683SDouglas Anderson 		return -EINVAL;
40267e4d9683SDouglas Anderson 
40277e4d9683SDouglas Anderson 	return rdev->desc->ops->get_current_limit(rdev);
40287e4d9683SDouglas Anderson }
40297e4d9683SDouglas Anderson 
4030414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev)
4031414c70cbSLiam Girdwood {
4032414c70cbSLiam Girdwood 	int ret;
4033414c70cbSLiam Girdwood 
403466cf9a7eSMaciej Purski 	regulator_lock(rdev);
40357e4d9683SDouglas Anderson 	ret = _regulator_get_current_limit_unlocked(rdev);
403666cf9a7eSMaciej Purski 	regulator_unlock(rdev);
40377e4d9683SDouglas Anderson 
4038414c70cbSLiam Girdwood 	return ret;
4039414c70cbSLiam Girdwood }
4040414c70cbSLiam Girdwood 
4041414c70cbSLiam Girdwood /**
4042414c70cbSLiam Girdwood  * regulator_get_current_limit - get regulator output current
4043414c70cbSLiam Girdwood  * @regulator: regulator source
4044414c70cbSLiam Girdwood  *
4045414c70cbSLiam Girdwood  * This returns the current supplied by the specified current sink in uA.
4046414c70cbSLiam Girdwood  *
4047414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the current value. This
4048414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
4049414c70cbSLiam Girdwood  */
4050414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator)
4051414c70cbSLiam Girdwood {
4052414c70cbSLiam Girdwood 	return _regulator_get_current_limit(regulator->rdev);
4053414c70cbSLiam Girdwood }
4054414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit);
4055414c70cbSLiam Girdwood 
4056414c70cbSLiam Girdwood /**
4057414c70cbSLiam Girdwood  * regulator_set_mode - set regulator operating mode
4058414c70cbSLiam Girdwood  * @regulator: regulator source
4059414c70cbSLiam Girdwood  * @mode: operating mode - one of the REGULATOR_MODE constants
4060414c70cbSLiam Girdwood  *
4061414c70cbSLiam Girdwood  * Set regulator operating mode to increase regulator efficiency or improve
4062414c70cbSLiam Girdwood  * regulation performance.
4063414c70cbSLiam Girdwood  *
4064414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
4065414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
4066414c70cbSLiam Girdwood  */
4067414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode)
4068414c70cbSLiam Girdwood {
4069414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
4070414c70cbSLiam Girdwood 	int ret;
4071500b4ac9SSundar R Iyer 	int regulator_curr_mode;
4072414c70cbSLiam Girdwood 
407366cf9a7eSMaciej Purski 	regulator_lock(rdev);
4074414c70cbSLiam Girdwood 
4075414c70cbSLiam Girdwood 	/* sanity check */
4076414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_mode) {
4077414c70cbSLiam Girdwood 		ret = -EINVAL;
4078414c70cbSLiam Girdwood 		goto out;
4079414c70cbSLiam Girdwood 	}
4080414c70cbSLiam Girdwood 
4081500b4ac9SSundar R Iyer 	/* return if the same mode is requested */
4082500b4ac9SSundar R Iyer 	if (rdev->desc->ops->get_mode) {
4083500b4ac9SSundar R Iyer 		regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
4084500b4ac9SSundar R Iyer 		if (regulator_curr_mode == mode) {
4085500b4ac9SSundar R Iyer 			ret = 0;
4086500b4ac9SSundar R Iyer 			goto out;
4087500b4ac9SSundar R Iyer 		}
4088500b4ac9SSundar R Iyer 	}
4089500b4ac9SSundar R Iyer 
4090414c70cbSLiam Girdwood 	/* constraints check */
409122c51b47SAxel Lin 	ret = regulator_mode_constrain(rdev, &mode);
4092414c70cbSLiam Girdwood 	if (ret < 0)
4093414c70cbSLiam Girdwood 		goto out;
4094414c70cbSLiam Girdwood 
4095414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
4096414c70cbSLiam Girdwood out:
409766cf9a7eSMaciej Purski 	regulator_unlock(rdev);
4098414c70cbSLiam Girdwood 	return ret;
4099414c70cbSLiam Girdwood }
4100414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode);
4101414c70cbSLiam Girdwood 
41027e4d9683SDouglas Anderson static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev)
41037e4d9683SDouglas Anderson {
41047e4d9683SDouglas Anderson 	/* sanity check */
41057e4d9683SDouglas Anderson 	if (!rdev->desc->ops->get_mode)
41067e4d9683SDouglas Anderson 		return -EINVAL;
41077e4d9683SDouglas Anderson 
41087e4d9683SDouglas Anderson 	return rdev->desc->ops->get_mode(rdev);
41097e4d9683SDouglas Anderson }
41107e4d9683SDouglas Anderson 
4111414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
4112414c70cbSLiam Girdwood {
4113414c70cbSLiam Girdwood 	int ret;
4114414c70cbSLiam Girdwood 
411566cf9a7eSMaciej Purski 	regulator_lock(rdev);
41167e4d9683SDouglas Anderson 	ret = _regulator_get_mode_unlocked(rdev);
411766cf9a7eSMaciej Purski 	regulator_unlock(rdev);
41187e4d9683SDouglas Anderson 
4119414c70cbSLiam Girdwood 	return ret;
4120414c70cbSLiam Girdwood }
4121414c70cbSLiam Girdwood 
4122414c70cbSLiam Girdwood /**
4123414c70cbSLiam Girdwood  * regulator_get_mode - get regulator operating mode
4124414c70cbSLiam Girdwood  * @regulator: regulator source
4125414c70cbSLiam Girdwood  *
4126414c70cbSLiam Girdwood  * Get the current regulator operating mode.
4127414c70cbSLiam Girdwood  */
4128414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator)
4129414c70cbSLiam Girdwood {
4130414c70cbSLiam Girdwood 	return _regulator_get_mode(regulator->rdev);
4131414c70cbSLiam Girdwood }
4132414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode);
4133414c70cbSLiam Girdwood 
41341b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev,
41351b5b4221SAxel Haslam 					unsigned int *flags)
41361b5b4221SAxel Haslam {
41371b5b4221SAxel Haslam 	int ret;
41381b5b4221SAxel Haslam 
413966cf9a7eSMaciej Purski 	regulator_lock(rdev);
41401b5b4221SAxel Haslam 
41411b5b4221SAxel Haslam 	/* sanity check */
41421b5b4221SAxel Haslam 	if (!rdev->desc->ops->get_error_flags) {
41431b5b4221SAxel Haslam 		ret = -EINVAL;
41441b5b4221SAxel Haslam 		goto out;
41451b5b4221SAxel Haslam 	}
41461b5b4221SAxel Haslam 
41471b5b4221SAxel Haslam 	ret = rdev->desc->ops->get_error_flags(rdev, flags);
41481b5b4221SAxel Haslam out:
414966cf9a7eSMaciej Purski 	regulator_unlock(rdev);
41501b5b4221SAxel Haslam 	return ret;
41511b5b4221SAxel Haslam }
41521b5b4221SAxel Haslam 
41531b5b4221SAxel Haslam /**
41541b5b4221SAxel Haslam  * regulator_get_error_flags - get regulator error information
41551b5b4221SAxel Haslam  * @regulator: regulator source
41561b5b4221SAxel Haslam  * @flags: pointer to store error flags
41571b5b4221SAxel Haslam  *
41581b5b4221SAxel Haslam  * Get the current regulator error information.
41591b5b4221SAxel Haslam  */
41601b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator,
41611b5b4221SAxel Haslam 				unsigned int *flags)
41621b5b4221SAxel Haslam {
41631b5b4221SAxel Haslam 	return _regulator_get_error_flags(regulator->rdev, flags);
41641b5b4221SAxel Haslam }
41651b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags);
41661b5b4221SAxel Haslam 
4167414c70cbSLiam Girdwood /**
4168e39ce48fSBjorn Andersson  * regulator_set_load - set regulator load
4169414c70cbSLiam Girdwood  * @regulator: regulator source
4170414c70cbSLiam Girdwood  * @uA_load: load current
4171414c70cbSLiam Girdwood  *
4172414c70cbSLiam Girdwood  * Notifies the regulator core of a new device load. This is then used by
4173414c70cbSLiam Girdwood  * DRMS (if enabled by constraints) to set the most efficient regulator
4174414c70cbSLiam Girdwood  * operating mode for the new regulator loading.
4175414c70cbSLiam Girdwood  *
4176414c70cbSLiam Girdwood  * Consumer devices notify their supply regulator of the maximum power
4177414c70cbSLiam Girdwood  * they will require (can be taken from device datasheet in the power
4178414c70cbSLiam Girdwood  * consumption tables) when they change operational status and hence power
4179414c70cbSLiam Girdwood  * state. Examples of operational state changes that can affect power
4180414c70cbSLiam Girdwood  * consumption are :-
4181414c70cbSLiam Girdwood  *
4182414c70cbSLiam Girdwood  *    o Device is opened / closed.
4183414c70cbSLiam Girdwood  *    o Device I/O is about to begin or has just finished.
4184414c70cbSLiam Girdwood  *    o Device is idling in between work.
4185414c70cbSLiam Girdwood  *
4186414c70cbSLiam Girdwood  * This information is also exported via sysfs to userspace.
4187414c70cbSLiam Girdwood  *
4188414c70cbSLiam Girdwood  * DRMS will sum the total requested load on the regulator and change
4189414c70cbSLiam Girdwood  * to the most efficient operating mode if platform constraints allow.
4190414c70cbSLiam Girdwood  *
41915451781dSDouglas Anderson  * NOTE: when a regulator consumer requests to have a regulator
41925451781dSDouglas Anderson  * disabled then any load that consumer requested no longer counts
41935451781dSDouglas Anderson  * toward the total requested load.  If the regulator is re-enabled
41945451781dSDouglas Anderson  * then the previously requested load will start counting again.
41955451781dSDouglas Anderson  *
41965451781dSDouglas Anderson  * If a regulator is an always-on regulator then an individual consumer's
41975451781dSDouglas Anderson  * load will still be removed if that consumer is fully disabled.
41985451781dSDouglas Anderson  *
4199e39ce48fSBjorn Andersson  * On error a negative errno is returned.
4200414c70cbSLiam Girdwood  */
4201e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load)
4202414c70cbSLiam Girdwood {
4203414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
42045451781dSDouglas Anderson 	int old_uA_load;
42055451781dSDouglas Anderson 	int ret = 0;
4206d92d95b6SStephen Boyd 
420766cf9a7eSMaciej Purski 	regulator_lock(rdev);
42085451781dSDouglas Anderson 	old_uA_load = regulator->uA_load;
4209414c70cbSLiam Girdwood 	regulator->uA_load = uA_load;
42105451781dSDouglas Anderson 	if (regulator->enable_count && old_uA_load != uA_load) {
42118460ef38SBjorn Andersson 		ret = drms_uA_update(rdev);
42125451781dSDouglas Anderson 		if (ret < 0)
42135451781dSDouglas Anderson 			regulator->uA_load = old_uA_load;
42145451781dSDouglas Anderson 	}
421566cf9a7eSMaciej Purski 	regulator_unlock(rdev);
42168460ef38SBjorn Andersson 
4217414c70cbSLiam Girdwood 	return ret;
4218414c70cbSLiam Girdwood }
4219e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load);
4220414c70cbSLiam Girdwood 
4221414c70cbSLiam Girdwood /**
4222f59c8f9fSMark Brown  * regulator_allow_bypass - allow the regulator to go into bypass mode
4223f59c8f9fSMark Brown  *
4224f59c8f9fSMark Brown  * @regulator: Regulator to configure
42259345dfb8SNishanth Menon  * @enable: enable or disable bypass mode
4226f59c8f9fSMark Brown  *
4227f59c8f9fSMark Brown  * Allow the regulator to go into bypass mode if all other consumers
4228f59c8f9fSMark Brown  * for the regulator also enable bypass mode and the machine
4229f59c8f9fSMark Brown  * constraints allow this.  Bypass mode means that the regulator is
4230f59c8f9fSMark Brown  * simply passing the input directly to the output with no regulation.
4231f59c8f9fSMark Brown  */
4232f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable)
4233f59c8f9fSMark Brown {
4234f59c8f9fSMark Brown 	struct regulator_dev *rdev = regulator->rdev;
4235f59c8f9fSMark Brown 	int ret = 0;
4236f59c8f9fSMark Brown 
4237f59c8f9fSMark Brown 	if (!rdev->desc->ops->set_bypass)
4238f59c8f9fSMark Brown 		return 0;
4239f59c8f9fSMark Brown 
42408a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS))
4241f59c8f9fSMark Brown 		return 0;
4242f59c8f9fSMark Brown 
424366cf9a7eSMaciej Purski 	regulator_lock(rdev);
4244f59c8f9fSMark Brown 
4245f59c8f9fSMark Brown 	if (enable && !regulator->bypass) {
4246f59c8f9fSMark Brown 		rdev->bypass_count++;
4247f59c8f9fSMark Brown 
4248f59c8f9fSMark Brown 		if (rdev->bypass_count == rdev->open_count) {
4249f59c8f9fSMark Brown 			ret = rdev->desc->ops->set_bypass(rdev, enable);
4250f59c8f9fSMark Brown 			if (ret != 0)
4251f59c8f9fSMark Brown 				rdev->bypass_count--;
4252f59c8f9fSMark Brown 		}
4253f59c8f9fSMark Brown 
4254f59c8f9fSMark Brown 	} else if (!enable && regulator->bypass) {
4255f59c8f9fSMark Brown 		rdev->bypass_count--;
4256f59c8f9fSMark Brown 
4257f59c8f9fSMark Brown 		if (rdev->bypass_count != rdev->open_count) {
4258f59c8f9fSMark Brown 			ret = rdev->desc->ops->set_bypass(rdev, enable);
4259f59c8f9fSMark Brown 			if (ret != 0)
4260f59c8f9fSMark Brown 				rdev->bypass_count++;
4261f59c8f9fSMark Brown 		}
4262f59c8f9fSMark Brown 	}
4263f59c8f9fSMark Brown 
4264f59c8f9fSMark Brown 	if (ret == 0)
4265f59c8f9fSMark Brown 		regulator->bypass = enable;
4266f59c8f9fSMark Brown 
426766cf9a7eSMaciej Purski 	regulator_unlock(rdev);
4268f59c8f9fSMark Brown 
4269f59c8f9fSMark Brown 	return ret;
4270f59c8f9fSMark Brown }
4271f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass);
4272f59c8f9fSMark Brown 
4273f59c8f9fSMark Brown /**
4274414c70cbSLiam Girdwood  * regulator_register_notifier - register regulator event notifier
4275414c70cbSLiam Girdwood  * @regulator: regulator source
427669279fb9SMark Brown  * @nb: notifier block
4277414c70cbSLiam Girdwood  *
4278414c70cbSLiam Girdwood  * Register notifier block to receive regulator events.
4279414c70cbSLiam Girdwood  */
4280414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator,
4281414c70cbSLiam Girdwood 			      struct notifier_block *nb)
4282414c70cbSLiam Girdwood {
4283414c70cbSLiam Girdwood 	return blocking_notifier_chain_register(&regulator->rdev->notifier,
4284414c70cbSLiam Girdwood 						nb);
4285414c70cbSLiam Girdwood }
4286414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier);
4287414c70cbSLiam Girdwood 
4288414c70cbSLiam Girdwood /**
4289414c70cbSLiam Girdwood  * regulator_unregister_notifier - unregister regulator event notifier
4290414c70cbSLiam Girdwood  * @regulator: regulator source
429169279fb9SMark Brown  * @nb: notifier block
4292414c70cbSLiam Girdwood  *
4293414c70cbSLiam Girdwood  * Unregister regulator event notifier block.
4294414c70cbSLiam Girdwood  */
4295414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator,
4296414c70cbSLiam Girdwood 				struct notifier_block *nb)
4297414c70cbSLiam Girdwood {
4298414c70cbSLiam Girdwood 	return blocking_notifier_chain_unregister(&regulator->rdev->notifier,
4299414c70cbSLiam Girdwood 						  nb);
4300414c70cbSLiam Girdwood }
4301414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
4302414c70cbSLiam Girdwood 
4303b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers.
4304b136fb44SJonathan Cameron  * Note mutex must be held by caller.
4305b136fb44SJonathan Cameron  */
43067179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev,
4307414c70cbSLiam Girdwood 				  unsigned long event, void *data)
4308414c70cbSLiam Girdwood {
4309414c70cbSLiam Girdwood 	/* call rdev chain first */
43107179569aSHeiko Stübner 	return blocking_notifier_call_chain(&rdev->notifier, event, data);
4311414c70cbSLiam Girdwood }
4312414c70cbSLiam Girdwood 
4313414c70cbSLiam Girdwood /**
4314414c70cbSLiam Girdwood  * regulator_bulk_get - get multiple regulator consumers
4315414c70cbSLiam Girdwood  *
4316414c70cbSLiam Girdwood  * @dev:           Device to supply
4317414c70cbSLiam Girdwood  * @num_consumers: Number of consumers to register
4318414c70cbSLiam Girdwood  * @consumers:     Configuration of consumers; clients are stored here.
4319414c70cbSLiam Girdwood  *
4320414c70cbSLiam Girdwood  * @return 0 on success, an errno on failure.
4321414c70cbSLiam Girdwood  *
4322414c70cbSLiam Girdwood  * This helper function allows drivers to get several regulator
4323414c70cbSLiam Girdwood  * consumers in one operation.  If any of the regulators cannot be
4324414c70cbSLiam Girdwood  * acquired then any regulators that were allocated will be freed
4325414c70cbSLiam Girdwood  * before returning to the caller.
4326414c70cbSLiam Girdwood  */
4327414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers,
4328414c70cbSLiam Girdwood 		       struct regulator_bulk_data *consumers)
4329414c70cbSLiam Girdwood {
4330414c70cbSLiam Girdwood 	int i;
4331414c70cbSLiam Girdwood 	int ret;
4332414c70cbSLiam Girdwood 
4333414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++)
4334414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
4335414c70cbSLiam Girdwood 
4336414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
4337565f9b07SBjorn Andersson 		consumers[i].consumer = regulator_get(dev,
4338565f9b07SBjorn Andersson 						      consumers[i].supply);
4339414c70cbSLiam Girdwood 		if (IS_ERR(consumers[i].consumer)) {
4340414c70cbSLiam Girdwood 			ret = PTR_ERR(consumers[i].consumer);
4341414c70cbSLiam Girdwood 			consumers[i].consumer = NULL;
4342414c70cbSLiam Girdwood 			goto err;
4343414c70cbSLiam Girdwood 		}
4344414c70cbSLiam Girdwood 	}
4345414c70cbSLiam Girdwood 
4346414c70cbSLiam Girdwood 	return 0;
4347414c70cbSLiam Girdwood 
4348414c70cbSLiam Girdwood err:
4349b9816363SJorge Ramirez-Ortiz 	if (ret != -EPROBE_DEFER)
4350b9816363SJorge Ramirez-Ortiz 		dev_err(dev, "Failed to get supply '%s': %d\n",
4351b9816363SJorge Ramirez-Ortiz 			consumers[i].supply, ret);
4352b9816363SJorge Ramirez-Ortiz 	else
4353b9816363SJorge Ramirez-Ortiz 		dev_dbg(dev, "Failed to get supply '%s', deferring\n",
4354b9816363SJorge Ramirez-Ortiz 			consumers[i].supply);
4355b9816363SJorge Ramirez-Ortiz 
4356b29c7690SAxel Lin 	while (--i >= 0)
4357414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
4358414c70cbSLiam Girdwood 
4359414c70cbSLiam Girdwood 	return ret;
4360414c70cbSLiam Girdwood }
4361414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get);
4362414c70cbSLiam Girdwood 
4363f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
4364f21e0e81SMark Brown {
4365f21e0e81SMark Brown 	struct regulator_bulk_data *bulk = data;
4366f21e0e81SMark Brown 
4367f21e0e81SMark Brown 	bulk->ret = regulator_enable(bulk->consumer);
4368f21e0e81SMark Brown }
4369f21e0e81SMark Brown 
4370414c70cbSLiam Girdwood /**
4371414c70cbSLiam Girdwood  * regulator_bulk_enable - enable multiple regulator consumers
4372414c70cbSLiam Girdwood  *
4373414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
4374414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
4375414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
4376414c70cbSLiam Girdwood  *
4377414c70cbSLiam Girdwood  * This convenience API allows consumers to enable multiple regulator
4378414c70cbSLiam Girdwood  * clients in a single API call.  If any consumers cannot be enabled
4379414c70cbSLiam Girdwood  * then any others that were enabled will be disabled again prior to
4380414c70cbSLiam Girdwood  * return.
4381414c70cbSLiam Girdwood  */
4382414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers,
4383414c70cbSLiam Girdwood 			  struct regulator_bulk_data *consumers)
4384414c70cbSLiam Girdwood {
43852955b47dSDan Williams 	ASYNC_DOMAIN_EXCLUSIVE(async_domain);
4386414c70cbSLiam Girdwood 	int i;
4387f21e0e81SMark Brown 	int ret = 0;
4388414c70cbSLiam Girdwood 
43896492bc1bSMark Brown 	for (i = 0; i < num_consumers; i++) {
4390f21e0e81SMark Brown 		async_schedule_domain(regulator_bulk_enable_async,
4391f21e0e81SMark Brown 				      &consumers[i], &async_domain);
43926492bc1bSMark Brown 	}
4393f21e0e81SMark Brown 
4394f21e0e81SMark Brown 	async_synchronize_full_domain(&async_domain);
4395f21e0e81SMark Brown 
4396f21e0e81SMark Brown 	/* If any consumer failed we need to unwind any that succeeded */
4397414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
4398f21e0e81SMark Brown 		if (consumers[i].ret != 0) {
4399f21e0e81SMark Brown 			ret = consumers[i].ret;
4400414c70cbSLiam Girdwood 			goto err;
4401414c70cbSLiam Girdwood 		}
4402f21e0e81SMark Brown 	}
4403414c70cbSLiam Girdwood 
4404414c70cbSLiam Girdwood 	return 0;
4405414c70cbSLiam Girdwood 
4406414c70cbSLiam Girdwood err:
4407fbe31057SAndrzej Hajda 	for (i = 0; i < num_consumers; i++) {
4408fbe31057SAndrzej Hajda 		if (consumers[i].ret < 0)
4409fbe31057SAndrzej Hajda 			pr_err("Failed to enable %s: %d\n", consumers[i].supply,
4410fbe31057SAndrzej Hajda 			       consumers[i].ret);
4411fbe31057SAndrzej Hajda 		else
4412414c70cbSLiam Girdwood 			regulator_disable(consumers[i].consumer);
4413fbe31057SAndrzej Hajda 	}
4414414c70cbSLiam Girdwood 
4415414c70cbSLiam Girdwood 	return ret;
4416414c70cbSLiam Girdwood }
4417414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable);
4418414c70cbSLiam Girdwood 
4419414c70cbSLiam Girdwood /**
4420414c70cbSLiam Girdwood  * regulator_bulk_disable - disable multiple regulator consumers
4421414c70cbSLiam Girdwood  *
4422414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
4423414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
4424414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
4425414c70cbSLiam Girdwood  *
4426414c70cbSLiam Girdwood  * This convenience API allows consumers to disable multiple regulator
442749e22632SSylwester Nawrocki  * clients in a single API call.  If any consumers cannot be disabled
442849e22632SSylwester Nawrocki  * then any others that were disabled will be enabled again prior to
4429414c70cbSLiam Girdwood  * return.
4430414c70cbSLiam Girdwood  */
4431414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers,
4432414c70cbSLiam Girdwood 			   struct regulator_bulk_data *consumers)
4433414c70cbSLiam Girdwood {
4434414c70cbSLiam Girdwood 	int i;
443501e86f49SMark Brown 	int ret, r;
4436414c70cbSLiam Girdwood 
443749e22632SSylwester Nawrocki 	for (i = num_consumers - 1; i >= 0; --i) {
4438414c70cbSLiam Girdwood 		ret = regulator_disable(consumers[i].consumer);
4439414c70cbSLiam Girdwood 		if (ret != 0)
4440414c70cbSLiam Girdwood 			goto err;
4441414c70cbSLiam Girdwood 	}
4442414c70cbSLiam Girdwood 
4443414c70cbSLiam Girdwood 	return 0;
4444414c70cbSLiam Girdwood 
4445414c70cbSLiam Girdwood err:
44465da84fd9SJoe Perches 	pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
444701e86f49SMark Brown 	for (++i; i < num_consumers; ++i) {
444801e86f49SMark Brown 		r = regulator_enable(consumers[i].consumer);
444901e86f49SMark Brown 		if (r != 0)
4450d1642ea7SDmitry Torokhov 			pr_err("Failed to re-enable %s: %d\n",
445101e86f49SMark Brown 			       consumers[i].supply, r);
445201e86f49SMark Brown 	}
4453414c70cbSLiam Girdwood 
4454414c70cbSLiam Girdwood 	return ret;
4455414c70cbSLiam Girdwood }
4456414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable);
4457414c70cbSLiam Girdwood 
4458414c70cbSLiam Girdwood /**
4459e1de2f42SDonggeun Kim  * regulator_bulk_force_disable - force disable multiple regulator consumers
4460e1de2f42SDonggeun Kim  *
4461e1de2f42SDonggeun Kim  * @num_consumers: Number of consumers
4462e1de2f42SDonggeun Kim  * @consumers:     Consumer data; clients are stored here.
4463e1de2f42SDonggeun Kim  * @return         0 on success, an errno on failure
4464e1de2f42SDonggeun Kim  *
4465e1de2f42SDonggeun Kim  * This convenience API allows consumers to forcibly disable multiple regulator
4466e1de2f42SDonggeun Kim  * clients in a single API call.
4467e1de2f42SDonggeun Kim  * NOTE: This should be used for situations when device damage will
4468e1de2f42SDonggeun Kim  * likely occur if the regulators are not disabled (e.g. over temp).
4469e1de2f42SDonggeun Kim  * Although regulator_force_disable function call for some consumers can
4470e1de2f42SDonggeun Kim  * return error numbers, the function is called for all consumers.
4471e1de2f42SDonggeun Kim  */
4472e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers,
4473e1de2f42SDonggeun Kim 			   struct regulator_bulk_data *consumers)
4474e1de2f42SDonggeun Kim {
4475e1de2f42SDonggeun Kim 	int i;
4476b8c77ff6SDmitry Torokhov 	int ret = 0;
4477e1de2f42SDonggeun Kim 
4478b8c77ff6SDmitry Torokhov 	for (i = 0; i < num_consumers; i++) {
4479e1de2f42SDonggeun Kim 		consumers[i].ret =
4480e1de2f42SDonggeun Kim 			    regulator_force_disable(consumers[i].consumer);
4481e1de2f42SDonggeun Kim 
4482b8c77ff6SDmitry Torokhov 		/* Store first error for reporting */
4483b8c77ff6SDmitry Torokhov 		if (consumers[i].ret && !ret)
4484e1de2f42SDonggeun Kim 			ret = consumers[i].ret;
4485e1de2f42SDonggeun Kim 	}
4486e1de2f42SDonggeun Kim 
4487e1de2f42SDonggeun Kim 	return ret;
4488e1de2f42SDonggeun Kim }
4489e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
4490e1de2f42SDonggeun Kim 
4491e1de2f42SDonggeun Kim /**
4492414c70cbSLiam Girdwood  * regulator_bulk_free - free multiple regulator consumers
4493414c70cbSLiam Girdwood  *
4494414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
4495414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
4496414c70cbSLiam Girdwood  *
4497414c70cbSLiam Girdwood  * This convenience API allows consumers to free multiple regulator
4498414c70cbSLiam Girdwood  * clients in a single API call.
4499414c70cbSLiam Girdwood  */
4500414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers,
4501414c70cbSLiam Girdwood 			 struct regulator_bulk_data *consumers)
4502414c70cbSLiam Girdwood {
4503414c70cbSLiam Girdwood 	int i;
4504414c70cbSLiam Girdwood 
4505414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
4506414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
4507414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
4508414c70cbSLiam Girdwood 	}
4509414c70cbSLiam Girdwood }
4510414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free);
4511414c70cbSLiam Girdwood 
4512414c70cbSLiam Girdwood /**
4513414c70cbSLiam Girdwood  * regulator_notifier_call_chain - call regulator event notifier
451469279fb9SMark Brown  * @rdev: regulator source
4515414c70cbSLiam Girdwood  * @event: notifier block
451669279fb9SMark Brown  * @data: callback-specific data.
4517414c70cbSLiam Girdwood  *
4518414c70cbSLiam Girdwood  * Called by regulator drivers to notify clients a regulator event has
4519414c70cbSLiam Girdwood  * occurred. We also notify regulator clients downstream.
4520b136fb44SJonathan Cameron  * Note lock must be held by caller.
4521414c70cbSLiam Girdwood  */
4522414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev,
4523414c70cbSLiam Girdwood 				  unsigned long event, void *data)
4524414c70cbSLiam Girdwood {
4525f8702f9eSDmitry Osipenko 	lockdep_assert_held_once(&rdev->mutex.base);
452670cfef26SKrzysztof Kozlowski 
4527414c70cbSLiam Girdwood 	_notifier_call_chain(rdev, event, data);
4528414c70cbSLiam Girdwood 	return NOTIFY_DONE;
4529414c70cbSLiam Girdwood 
4530414c70cbSLiam Girdwood }
4531414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
4532414c70cbSLiam Girdwood 
4533be721979SMark Brown /**
4534be721979SMark Brown  * regulator_mode_to_status - convert a regulator mode into a status
4535be721979SMark Brown  *
4536be721979SMark Brown  * @mode: Mode to convert
4537be721979SMark Brown  *
4538be721979SMark Brown  * Convert a regulator mode into a status.
4539be721979SMark Brown  */
4540be721979SMark Brown int regulator_mode_to_status(unsigned int mode)
4541be721979SMark Brown {
4542be721979SMark Brown 	switch (mode) {
4543be721979SMark Brown 	case REGULATOR_MODE_FAST:
4544be721979SMark Brown 		return REGULATOR_STATUS_FAST;
4545be721979SMark Brown 	case REGULATOR_MODE_NORMAL:
4546be721979SMark Brown 		return REGULATOR_STATUS_NORMAL;
4547be721979SMark Brown 	case REGULATOR_MODE_IDLE:
4548be721979SMark Brown 		return REGULATOR_STATUS_IDLE;
454903ffcf3dSKrystian Garbaciak 	case REGULATOR_MODE_STANDBY:
4550be721979SMark Brown 		return REGULATOR_STATUS_STANDBY;
4551be721979SMark Brown 	default:
45521beaf762SKrystian Garbaciak 		return REGULATOR_STATUS_UNDEFINED;
4553be721979SMark Brown 	}
4554be721979SMark Brown }
4555be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status);
4556be721979SMark Brown 
455739f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = {
455839f802d6STakashi Iwai 	&dev_attr_name.attr,
455939f802d6STakashi Iwai 	&dev_attr_num_users.attr,
456039f802d6STakashi Iwai 	&dev_attr_type.attr,
456139f802d6STakashi Iwai 	&dev_attr_microvolts.attr,
456239f802d6STakashi Iwai 	&dev_attr_microamps.attr,
456339f802d6STakashi Iwai 	&dev_attr_opmode.attr,
456439f802d6STakashi Iwai 	&dev_attr_state.attr,
456539f802d6STakashi Iwai 	&dev_attr_status.attr,
456639f802d6STakashi Iwai 	&dev_attr_bypass.attr,
456739f802d6STakashi Iwai 	&dev_attr_requested_microamps.attr,
456839f802d6STakashi Iwai 	&dev_attr_min_microvolts.attr,
456939f802d6STakashi Iwai 	&dev_attr_max_microvolts.attr,
457039f802d6STakashi Iwai 	&dev_attr_min_microamps.attr,
457139f802d6STakashi Iwai 	&dev_attr_max_microamps.attr,
457239f802d6STakashi Iwai 	&dev_attr_suspend_standby_state.attr,
457339f802d6STakashi Iwai 	&dev_attr_suspend_mem_state.attr,
457439f802d6STakashi Iwai 	&dev_attr_suspend_disk_state.attr,
457539f802d6STakashi Iwai 	&dev_attr_suspend_standby_microvolts.attr,
457639f802d6STakashi Iwai 	&dev_attr_suspend_mem_microvolts.attr,
457739f802d6STakashi Iwai 	&dev_attr_suspend_disk_microvolts.attr,
457839f802d6STakashi Iwai 	&dev_attr_suspend_standby_mode.attr,
457939f802d6STakashi Iwai 	&dev_attr_suspend_mem_mode.attr,
458039f802d6STakashi Iwai 	&dev_attr_suspend_disk_mode.attr,
458139f802d6STakashi Iwai 	NULL
458239f802d6STakashi Iwai };
458339f802d6STakashi Iwai 
45847ad68e2fSDavid Brownell /*
45857ad68e2fSDavid Brownell  * To avoid cluttering sysfs (and memory) with useless state, only
45867ad68e2fSDavid Brownell  * create attributes that can be meaningfully displayed.
45877ad68e2fSDavid Brownell  */
458839f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj,
458939f802d6STakashi Iwai 					 struct attribute *attr, int idx)
45907ad68e2fSDavid Brownell {
459139f802d6STakashi Iwai 	struct device *dev = kobj_to_dev(kobj);
459283080a14SGeliang Tang 	struct regulator_dev *rdev = dev_to_rdev(dev);
4593272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
459439f802d6STakashi Iwai 	umode_t mode = attr->mode;
459539f802d6STakashi Iwai 
459639f802d6STakashi Iwai 	/* these three are always present */
459739f802d6STakashi Iwai 	if (attr == &dev_attr_name.attr ||
459839f802d6STakashi Iwai 	    attr == &dev_attr_num_users.attr ||
459939f802d6STakashi Iwai 	    attr == &dev_attr_type.attr)
460039f802d6STakashi Iwai 		return mode;
46017ad68e2fSDavid Brownell 
46027ad68e2fSDavid Brownell 	/* some attributes need specific methods to be displayed */
460339f802d6STakashi Iwai 	if (attr == &dev_attr_microvolts.attr) {
46044c78899bSMark Brown 		if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
4605f2889e65SMark Brown 		    (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
46065a523605SLaxman Dewangan 		    (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
460739f802d6STakashi Iwai 		    (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1))
460839f802d6STakashi Iwai 			return mode;
460939f802d6STakashi Iwai 		return 0;
4610f59c8f9fSMark Brown 	}
46117ad68e2fSDavid Brownell 
461239f802d6STakashi Iwai 	if (attr == &dev_attr_microamps.attr)
461339f802d6STakashi Iwai 		return ops->get_current_limit ? mode : 0;
461439f802d6STakashi Iwai 
461539f802d6STakashi Iwai 	if (attr == &dev_attr_opmode.attr)
461639f802d6STakashi Iwai 		return ops->get_mode ? mode : 0;
461739f802d6STakashi Iwai 
461839f802d6STakashi Iwai 	if (attr == &dev_attr_state.attr)
461939f802d6STakashi Iwai 		return (rdev->ena_pin || ops->is_enabled) ? mode : 0;
462039f802d6STakashi Iwai 
462139f802d6STakashi Iwai 	if (attr == &dev_attr_status.attr)
462239f802d6STakashi Iwai 		return ops->get_status ? mode : 0;
462339f802d6STakashi Iwai 
462439f802d6STakashi Iwai 	if (attr == &dev_attr_bypass.attr)
462539f802d6STakashi Iwai 		return ops->get_bypass ? mode : 0;
462639f802d6STakashi Iwai 
46277ad68e2fSDavid Brownell 	/* constraints need specific supporting methods */
462839f802d6STakashi Iwai 	if (attr == &dev_attr_min_microvolts.attr ||
462939f802d6STakashi Iwai 	    attr == &dev_attr_max_microvolts.attr)
463039f802d6STakashi Iwai 		return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0;
463139f802d6STakashi Iwai 
463239f802d6STakashi Iwai 	if (attr == &dev_attr_min_microamps.attr ||
463339f802d6STakashi Iwai 	    attr == &dev_attr_max_microamps.attr)
463439f802d6STakashi Iwai 		return ops->set_current_limit ? mode : 0;
463539f802d6STakashi Iwai 
463639f802d6STakashi Iwai 	if (attr == &dev_attr_suspend_standby_state.attr ||
463739f802d6STakashi Iwai 	    attr == &dev_attr_suspend_mem_state.attr ||
463839f802d6STakashi Iwai 	    attr == &dev_attr_suspend_disk_state.attr)
463939f802d6STakashi Iwai 		return mode;
464039f802d6STakashi Iwai 
464139f802d6STakashi Iwai 	if (attr == &dev_attr_suspend_standby_microvolts.attr ||
464239f802d6STakashi Iwai 	    attr == &dev_attr_suspend_mem_microvolts.attr ||
464339f802d6STakashi Iwai 	    attr == &dev_attr_suspend_disk_microvolts.attr)
464439f802d6STakashi Iwai 		return ops->set_suspend_voltage ? mode : 0;
464539f802d6STakashi Iwai 
464639f802d6STakashi Iwai 	if (attr == &dev_attr_suspend_standby_mode.attr ||
464739f802d6STakashi Iwai 	    attr == &dev_attr_suspend_mem_mode.attr ||
464839f802d6STakashi Iwai 	    attr == &dev_attr_suspend_disk_mode.attr)
464939f802d6STakashi Iwai 		return ops->set_suspend_mode ? mode : 0;
465039f802d6STakashi Iwai 
465139f802d6STakashi Iwai 	return mode;
46527ad68e2fSDavid Brownell }
46537ad68e2fSDavid Brownell 
465439f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = {
465539f802d6STakashi Iwai 	.attrs = regulator_dev_attrs,
465639f802d6STakashi Iwai 	.is_visible = regulator_attr_is_visible,
465739f802d6STakashi Iwai };
46587ad68e2fSDavid Brownell 
465939f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = {
466039f802d6STakashi Iwai 	&regulator_dev_group,
466139f802d6STakashi Iwai 	NULL
466239f802d6STakashi Iwai };
466339f802d6STakashi Iwai 
466439f802d6STakashi Iwai static void regulator_dev_release(struct device *dev)
466539f802d6STakashi Iwai {
466639f802d6STakashi Iwai 	struct regulator_dev *rdev = dev_get_drvdata(dev);
466729f5f486SMark Brown 
466829f5f486SMark Brown 	kfree(rdev->constraints);
466929f5f486SMark Brown 	of_node_put(rdev->dev.of_node);
467039f802d6STakashi Iwai 	kfree(rdev);
46717ad68e2fSDavid Brownell }
46727ad68e2fSDavid Brownell 
46731130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev)
46741130e5b3SMark Brown {
4675a9eaa813SGuenter Roeck 	struct device *parent = rdev->dev.parent;
4676a9eaa813SGuenter Roeck 	const char *rname = rdev_get_name(rdev);
4677a9eaa813SGuenter Roeck 	char name[NAME_MAX];
4678a9eaa813SGuenter Roeck 
4679a9eaa813SGuenter Roeck 	/* Avoid duplicate debugfs directory names */
4680a9eaa813SGuenter Roeck 	if (parent && rname == rdev->desc->name) {
4681a9eaa813SGuenter Roeck 		snprintf(name, sizeof(name), "%s-%s", dev_name(parent),
4682a9eaa813SGuenter Roeck 			 rname);
4683a9eaa813SGuenter Roeck 		rname = name;
4684a9eaa813SGuenter Roeck 	}
4685a9eaa813SGuenter Roeck 
4686a9eaa813SGuenter Roeck 	rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
468724751434SStephen Boyd 	if (!rdev->debugfs) {
46881130e5b3SMark Brown 		rdev_warn(rdev, "Failed to create debugfs directory\n");
46891130e5b3SMark Brown 		return;
46901130e5b3SMark Brown 	}
46911130e5b3SMark Brown 
46921130e5b3SMark Brown 	debugfs_create_u32("use_count", 0444, rdev->debugfs,
46931130e5b3SMark Brown 			   &rdev->use_count);
46941130e5b3SMark Brown 	debugfs_create_u32("open_count", 0444, rdev->debugfs,
46951130e5b3SMark Brown 			   &rdev->open_count);
4696f59c8f9fSMark Brown 	debugfs_create_u32("bypass_count", 0444, rdev->debugfs,
4697f59c8f9fSMark Brown 			   &rdev->bypass_count);
46981130e5b3SMark Brown }
46991130e5b3SMark Brown 
47005e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data)
47015e3ca2b3SJavier Martinez Canillas {
47027ddede6aSJon Hunter 	struct regulator_dev *rdev = dev_to_rdev(dev);
47037ddede6aSJon Hunter 
47047ddede6aSJon Hunter 	if (regulator_resolve_supply(rdev))
47057ddede6aSJon Hunter 		rdev_dbg(rdev, "unable to resolve supply\n");
47067ddede6aSJon Hunter 
47077ddede6aSJon Hunter 	return 0;
47085e3ca2b3SJavier Martinez Canillas }
47095e3ca2b3SJavier Martinez Canillas 
4710f9503385SDmitry Osipenko static void regulator_resolve_coupling(struct regulator_dev *rdev)
4711d3d64537SMaciej Purski {
4712d3d64537SMaciej Purski 	struct coupling_desc *c_desc = &rdev->coupling_desc;
4713d3d64537SMaciej Purski 	int n_coupled = c_desc->n_coupled;
4714d3d64537SMaciej Purski 	struct regulator_dev *c_rdev;
4715d3d64537SMaciej Purski 	int i;
4716d3d64537SMaciej Purski 
4717d3d64537SMaciej Purski 	for (i = 1; i < n_coupled; i++) {
4718d3d64537SMaciej Purski 		/* already resolved */
4719d3d64537SMaciej Purski 		if (c_desc->coupled_rdevs[i])
4720d3d64537SMaciej Purski 			continue;
4721d3d64537SMaciej Purski 
4722d3d64537SMaciej Purski 		c_rdev = of_parse_coupled_regulator(rdev, i - 1);
4723d3d64537SMaciej Purski 
4724f9503385SDmitry Osipenko 		if (!c_rdev)
4725f9503385SDmitry Osipenko 			continue;
4726f9503385SDmitry Osipenko 
4727f9503385SDmitry Osipenko 		regulator_lock(c_rdev);
4728f9503385SDmitry Osipenko 
4729d3d64537SMaciej Purski 		c_desc->coupled_rdevs[i] = c_rdev;
4730d3d64537SMaciej Purski 		c_desc->n_resolved++;
4731f9503385SDmitry Osipenko 
4732f9503385SDmitry Osipenko 		regulator_unlock(c_rdev);
4733f9503385SDmitry Osipenko 
4734f9503385SDmitry Osipenko 		regulator_resolve_coupling(c_rdev);
4735d3d64537SMaciej Purski 	}
4736d3d64537SMaciej Purski }
4737d3d64537SMaciej Purski 
47386303f3e7SDmitry Osipenko static void regulator_remove_coupling(struct regulator_dev *rdev)
4739d3d64537SMaciej Purski {
47406303f3e7SDmitry Osipenko 	struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc;
47416303f3e7SDmitry Osipenko 	struct regulator_dev *__c_rdev, *c_rdev;
47426303f3e7SDmitry Osipenko 	unsigned int __n_coupled, n_coupled;
47436303f3e7SDmitry Osipenko 	int i, k;
4744d3d64537SMaciej Purski 
47456303f3e7SDmitry Osipenko 	n_coupled = c_desc->n_coupled;
4746d3d64537SMaciej Purski 
47476303f3e7SDmitry Osipenko 	for (i = 1; i < n_coupled; i++) {
47486303f3e7SDmitry Osipenko 		c_rdev = c_desc->coupled_rdevs[i];
4749d3d64537SMaciej Purski 
47506303f3e7SDmitry Osipenko 		if (!c_rdev)
47516303f3e7SDmitry Osipenko 			continue;
47526303f3e7SDmitry Osipenko 
47536303f3e7SDmitry Osipenko 		regulator_lock(c_rdev);
47546303f3e7SDmitry Osipenko 
47556303f3e7SDmitry Osipenko 		__c_desc = &c_rdev->coupling_desc;
47566303f3e7SDmitry Osipenko 		__n_coupled = __c_desc->n_coupled;
47576303f3e7SDmitry Osipenko 
47586303f3e7SDmitry Osipenko 		for (k = 1; k < __n_coupled; k++) {
47596303f3e7SDmitry Osipenko 			__c_rdev = __c_desc->coupled_rdevs[k];
47606303f3e7SDmitry Osipenko 
47616303f3e7SDmitry Osipenko 			if (__c_rdev == rdev) {
47626303f3e7SDmitry Osipenko 				__c_desc->coupled_rdevs[k] = NULL;
47636303f3e7SDmitry Osipenko 				__c_desc->n_resolved--;
47646303f3e7SDmitry Osipenko 				break;
47656303f3e7SDmitry Osipenko 			}
4766d3d64537SMaciej Purski 		}
4767d3d64537SMaciej Purski 
47686303f3e7SDmitry Osipenko 		regulator_unlock(c_rdev);
47696303f3e7SDmitry Osipenko 
47706303f3e7SDmitry Osipenko 		c_desc->coupled_rdevs[i] = NULL;
47716303f3e7SDmitry Osipenko 		c_desc->n_resolved--;
47726303f3e7SDmitry Osipenko 	}
47736303f3e7SDmitry Osipenko }
47746303f3e7SDmitry Osipenko 
4775f9503385SDmitry Osipenko static int regulator_init_coupling(struct regulator_dev *rdev)
4776d3d64537SMaciej Purski {
4777d3d64537SMaciej Purski 	int n_phandles;
4778d3d64537SMaciej Purski 
4779d3d64537SMaciej Purski 	if (!IS_ENABLED(CONFIG_OF))
4780d3d64537SMaciej Purski 		n_phandles = 0;
4781d3d64537SMaciej Purski 	else
4782d3d64537SMaciej Purski 		n_phandles = of_get_n_coupled(rdev);
4783d3d64537SMaciej Purski 
4784d3d64537SMaciej Purski 	if (n_phandles + 1 > MAX_COUPLED) {
4785d3d64537SMaciej Purski 		rdev_err(rdev, "too many regulators coupled\n");
4786d3d64537SMaciej Purski 		return -EPERM;
4787d3d64537SMaciej Purski 	}
4788d3d64537SMaciej Purski 
4789d3d64537SMaciej Purski 	/*
4790d3d64537SMaciej Purski 	 * Every regulator should always have coupling descriptor filled with
4791d3d64537SMaciej Purski 	 * at least pointer to itself.
4792d3d64537SMaciej Purski 	 */
4793d3d64537SMaciej Purski 	rdev->coupling_desc.coupled_rdevs[0] = rdev;
4794d3d64537SMaciej Purski 	rdev->coupling_desc.n_coupled = n_phandles + 1;
4795d3d64537SMaciej Purski 	rdev->coupling_desc.n_resolved++;
4796d3d64537SMaciej Purski 
4797d3d64537SMaciej Purski 	/* regulator isn't coupled */
4798d3d64537SMaciej Purski 	if (n_phandles == 0)
4799d3d64537SMaciej Purski 		return 0;
4800d3d64537SMaciej Purski 
4801d3d64537SMaciej Purski 	/* regulator, which can't change its voltage, can't be coupled */
4802d3d64537SMaciej Purski 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
4803d3d64537SMaciej Purski 		rdev_err(rdev, "voltage operation not allowed\n");
4804d3d64537SMaciej Purski 		return -EPERM;
4805d3d64537SMaciej Purski 	}
4806d3d64537SMaciej Purski 
4807d3d64537SMaciej Purski 	if (rdev->constraints->max_spread <= 0) {
4808d3d64537SMaciej Purski 		rdev_err(rdev, "wrong max_spread value\n");
4809d3d64537SMaciej Purski 		return -EPERM;
4810d3d64537SMaciej Purski 	}
4811d3d64537SMaciej Purski 
4812d3d64537SMaciej Purski 	if (!of_check_coupling_data(rdev))
4813d3d64537SMaciej Purski 		return -EPERM;
4814d3d64537SMaciej Purski 
4815d3d64537SMaciej Purski 	return 0;
4816d3d64537SMaciej Purski }
4817d3d64537SMaciej Purski 
4818414c70cbSLiam Girdwood /**
4819414c70cbSLiam Girdwood  * regulator_register - register regulator
482069279fb9SMark Brown  * @regulator_desc: regulator to register
4821f47531b1SKrzysztof Kozlowski  * @cfg: runtime configuration for regulator
4822414c70cbSLiam Girdwood  *
4823414c70cbSLiam Girdwood  * Called by regulator drivers to register a regulator.
48240384618aSAxel Lin  * Returns a valid pointer to struct regulator_dev on success
48250384618aSAxel Lin  * or an ERR_PTR() on error.
4826414c70cbSLiam Girdwood  */
482765f26846SMark Brown struct regulator_dev *
482865f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc,
48291b3de223SKrzysztof Kozlowski 		   const struct regulator_config *cfg)
4830414c70cbSLiam Girdwood {
48319a8f5e07SMark Brown 	const struct regulation_constraints *constraints = NULL;
4832c172708dSMark Brown 	const struct regulator_init_data *init_data;
48331b3de223SKrzysztof Kozlowski 	struct regulator_config *config = NULL;
483472dca06fSAniroop Mathur 	static atomic_t regulator_no = ATOMIC_INIT(-1);
4835414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
48360edb040dSLinus Walleij 	bool dangling_cfg_gpiod = false;
48370edb040dSLinus Walleij 	bool dangling_of_gpiod = false;
483832c8fad4SMark Brown 	struct device *dev;
4839a5766f11SLiam Girdwood 	int ret, i;
4840414c70cbSLiam Girdwood 
48410edb040dSLinus Walleij 	if (cfg == NULL)
4842414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
48430edb040dSLinus Walleij 	if (cfg->ena_gpiod)
48440edb040dSLinus Walleij 		dangling_cfg_gpiod = true;
48450edb040dSLinus Walleij 	if (regulator_desc == NULL) {
48460edb040dSLinus Walleij 		ret = -EINVAL;
48470edb040dSLinus Walleij 		goto rinse;
48480edb040dSLinus Walleij 	}
4849414c70cbSLiam Girdwood 
48501b3de223SKrzysztof Kozlowski 	dev = cfg->dev;
4851dcf70112SMark Brown 	WARN_ON(!dev);
485232c8fad4SMark Brown 
48530edb040dSLinus Walleij 	if (regulator_desc->name == NULL || regulator_desc->ops == NULL) {
48540edb040dSLinus Walleij 		ret = -EINVAL;
48550edb040dSLinus Walleij 		goto rinse;
48560edb040dSLinus Walleij 	}
4857414c70cbSLiam Girdwood 
4858cd78dfc6SDiego Liziero 	if (regulator_desc->type != REGULATOR_VOLTAGE &&
48590edb040dSLinus Walleij 	    regulator_desc->type != REGULATOR_CURRENT) {
48600edb040dSLinus Walleij 		ret = -EINVAL;
48610edb040dSLinus Walleij 		goto rinse;
48620edb040dSLinus Walleij 	}
4863414c70cbSLiam Girdwood 
4864476c2d83SMark Brown 	/* Only one of each should be implemented */
4865476c2d83SMark Brown 	WARN_ON(regulator_desc->ops->get_voltage &&
4866476c2d83SMark Brown 		regulator_desc->ops->get_voltage_sel);
4867e8eef82bSMark Brown 	WARN_ON(regulator_desc->ops->set_voltage &&
4868e8eef82bSMark Brown 		regulator_desc->ops->set_voltage_sel);
4869476c2d83SMark Brown 
4870476c2d83SMark Brown 	/* If we're using selectors we must implement list_voltage. */
4871476c2d83SMark Brown 	if (regulator_desc->ops->get_voltage_sel &&
4872476c2d83SMark Brown 	    !regulator_desc->ops->list_voltage) {
48730edb040dSLinus Walleij 		ret = -EINVAL;
48740edb040dSLinus Walleij 		goto rinse;
4875476c2d83SMark Brown 	}
4876e8eef82bSMark Brown 	if (regulator_desc->ops->set_voltage_sel &&
4877e8eef82bSMark Brown 	    !regulator_desc->ops->list_voltage) {
48780edb040dSLinus Walleij 		ret = -EINVAL;
48790edb040dSLinus Walleij 		goto rinse;
4880e8eef82bSMark Brown 	}
4881476c2d83SMark Brown 
4882414c70cbSLiam Girdwood 	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
48830edb040dSLinus Walleij 	if (rdev == NULL) {
48840edb040dSLinus Walleij 		ret = -ENOMEM;
48850edb040dSLinus Walleij 		goto rinse;
48860edb040dSLinus Walleij 	}
4887414c70cbSLiam Girdwood 
48881b3de223SKrzysztof Kozlowski 	/*
48891b3de223SKrzysztof Kozlowski 	 * Duplicate the config so the driver could override it after
48901b3de223SKrzysztof Kozlowski 	 * parsing init data.
48911b3de223SKrzysztof Kozlowski 	 */
48921b3de223SKrzysztof Kozlowski 	config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
48931b3de223SKrzysztof Kozlowski 	if (config == NULL) {
48941b3de223SKrzysztof Kozlowski 		kfree(rdev);
48950edb040dSLinus Walleij 		ret = -ENOMEM;
48960edb040dSLinus Walleij 		goto rinse;
48971b3de223SKrzysztof Kozlowski 	}
48981b3de223SKrzysztof Kozlowski 
4899bfa21a0dSKrzysztof Kozlowski 	init_data = regulator_of_get_init_data(dev, regulator_desc, config,
4900a0c7b164SMark Brown 					       &rdev->dev.of_node);
49010edb040dSLinus Walleij 	/*
49020edb040dSLinus Walleij 	 * We need to keep track of any GPIO descriptor coming from the
49030edb040dSLinus Walleij 	 * device tree until we have handled it over to the core. If the
49040edb040dSLinus Walleij 	 * config that was passed in to this function DOES NOT contain
49050edb040dSLinus Walleij 	 * a descriptor, and the config after this call DOES contain
490648f1b4efSKrzysztof Kozlowski 	 * a descriptor, we definitely got one from parsing the device
49070edb040dSLinus Walleij 	 * tree.
49080edb040dSLinus Walleij 	 */
49090edb040dSLinus Walleij 	if (!cfg->ena_gpiod && config->ena_gpiod)
49100edb040dSLinus Walleij 		dangling_of_gpiod = true;
4911a0c7b164SMark Brown 	if (!init_data) {
4912a0c7b164SMark Brown 		init_data = config->init_data;
4913a0c7b164SMark Brown 		rdev->dev.of_node = of_node_get(config->of_node);
4914a0c7b164SMark Brown 	}
4915a0c7b164SMark Brown 
4916f8702f9eSDmitry Osipenko 	ww_mutex_init(&rdev->mutex, &regulator_ww_class);
4917c172708dSMark Brown 	rdev->reg_data = config->driver_data;
4918414c70cbSLiam Girdwood 	rdev->owner = regulator_desc->owner;
4919414c70cbSLiam Girdwood 	rdev->desc = regulator_desc;
49203a4b0a07SMark Brown 	if (config->regmap)
492165b19ce6SMark Brown 		rdev->regmap = config->regmap;
492252b84dacSAnilKumar Ch 	else if (dev_get_regmap(dev, NULL))
49233a4b0a07SMark Brown 		rdev->regmap = dev_get_regmap(dev, NULL);
492452b84dacSAnilKumar Ch 	else if (dev->parent)
492552b84dacSAnilKumar Ch 		rdev->regmap = dev_get_regmap(dev->parent, NULL);
4926414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->consumer_list);
4927414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->list);
4928414c70cbSLiam Girdwood 	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
4929da07ecd9SMark Brown 	INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
4930414c70cbSLiam Girdwood 
4931a5766f11SLiam Girdwood 	/* preform any regulator specific init */
49329a8f5e07SMark Brown 	if (init_data && init_data->regulator_init) {
4933a5766f11SLiam Girdwood 		ret = init_data->regulator_init(rdev->reg_data);
49344fca9545SDavid Brownell 		if (ret < 0)
49354fca9545SDavid Brownell 			goto clean;
4936a5766f11SLiam Girdwood 	}
4937a5766f11SLiam Girdwood 
4938541d052dSLinus Walleij 	if (config->ena_gpiod) {
493945389c47SJon Hunter 		mutex_lock(&regulator_list_mutex);
4940daad134dSKrzysztof Adamski 		ret = regulator_ena_gpio_request(rdev, config);
494145389c47SJon Hunter 		mutex_unlock(&regulator_list_mutex);
4942daad134dSKrzysztof Adamski 		if (ret != 0) {
4943541d052dSLinus Walleij 			rdev_err(rdev, "Failed to request enable GPIO: %d\n",
4944541d052dSLinus Walleij 				 ret);
494532165230SKrzysztof Adamski 			goto clean;
4946daad134dSKrzysztof Adamski 		}
49470edb040dSLinus Walleij 		/* The regulator core took over the GPIO descriptor */
49480edb040dSLinus Walleij 		dangling_cfg_gpiod = false;
49490edb040dSLinus Walleij 		dangling_of_gpiod = false;
4950daad134dSKrzysztof Adamski 	}
4951daad134dSKrzysztof Adamski 
4952a5766f11SLiam Girdwood 	/* register with sysfs */
4953a5766f11SLiam Girdwood 	rdev->dev.class = &regulator_class;
4954a5766f11SLiam Girdwood 	rdev->dev.parent = dev;
495572dca06fSAniroop Mathur 	dev_set_name(&rdev->dev, "regulator.%lu",
495639138818SAniroop Mathur 		    (unsigned long) atomic_inc_return(&regulator_no));
4957a5766f11SLiam Girdwood 
495874f544c1SMike Rapoport 	/* set regulator constraints */
49599a8f5e07SMark Brown 	if (init_data)
49609a8f5e07SMark Brown 		constraints = &init_data->constraints;
49619a8f5e07SMark Brown 
49629a8f5e07SMark Brown 	if (init_data && init_data->supply_regulator)
49636261b06dSBjorn Andersson 		rdev->supply_name = init_data->supply_regulator;
496469511a45SRajendra Nayak 	else if (regulator_desc->supply_name)
49656261b06dSBjorn Andersson 		rdev->supply_name = regulator_desc->supply_name;
496669511a45SRajendra Nayak 
496745389c47SJon Hunter 	/*
496845389c47SJon Hunter 	 * Attempt to resolve the regulator supply, if specified,
496945389c47SJon Hunter 	 * but don't return an error if we fail because we will try
497045389c47SJon Hunter 	 * to resolve it again later as more regulators are added.
497145389c47SJon Hunter 	 */
497245389c47SJon Hunter 	if (regulator_resolve_supply(rdev))
497345389c47SJon Hunter 		rdev_dbg(rdev, "unable to resolve supply\n");
497445389c47SJon Hunter 
497545389c47SJon Hunter 	ret = set_machine_constraints(rdev, constraints);
497645389c47SJon Hunter 	if (ret < 0)
497745389c47SJon Hunter 		goto wash;
497845389c47SJon Hunter 
4979f9503385SDmitry Osipenko 	ret = regulator_init_coupling(rdev);
4980f9503385SDmitry Osipenko 	if (ret < 0)
4981d3d64537SMaciej Purski 		goto wash;
4982d3d64537SMaciej Purski 
4983a5766f11SLiam Girdwood 	/* add consumers devices */
49849a8f5e07SMark Brown 	if (init_data) {
498545389c47SJon Hunter 		mutex_lock(&regulator_list_mutex);
4986a5766f11SLiam Girdwood 		for (i = 0; i < init_data->num_consumer_supplies; i++) {
4987a5766f11SLiam Girdwood 			ret = set_consumer_device_supply(rdev,
498840f9244fSMark Brown 				init_data->consumer_supplies[i].dev_name,
4989a5766f11SLiam Girdwood 				init_data->consumer_supplies[i].supply);
499023c2f041SMark Brown 			if (ret < 0) {
499145389c47SJon Hunter 				mutex_unlock(&regulator_list_mutex);
499223c2f041SMark Brown 				dev_err(dev, "Failed to set supply %s\n",
499323c2f041SMark Brown 					init_data->consumer_supplies[i].supply);
4994d4033b54SJani Nikula 				goto unset_supplies;
4995a5766f11SLiam Girdwood 			}
499623c2f041SMark Brown 		}
4997a2151374SJon Hunter 		mutex_unlock(&regulator_list_mutex);
49989a8f5e07SMark Brown 	}
4999a5766f11SLiam Girdwood 
5000fd086045SMatthias Kaehlcke 	if (!rdev->desc->ops->get_voltage &&
5001fd086045SMatthias Kaehlcke 	    !rdev->desc->ops->list_voltage &&
5002fd086045SMatthias Kaehlcke 	    !rdev->desc->fixed_uV)
5003fd086045SMatthias Kaehlcke 		rdev->is_switch = true;
5004fd086045SMatthias Kaehlcke 
5005fb6de923SYu Zhao 	dev_set_drvdata(&rdev->dev, rdev);
5006c438b9d0SJon Hunter 	ret = device_register(&rdev->dev);
5007c438b9d0SJon Hunter 	if (ret != 0) {
5008c438b9d0SJon Hunter 		put_device(&rdev->dev);
5009c438b9d0SJon Hunter 		goto unset_supplies;
5010c438b9d0SJon Hunter 	}
5011c438b9d0SJon Hunter 
50121130e5b3SMark Brown 	rdev_init_debugfs(rdev);
50135e3ca2b3SJavier Martinez Canillas 
5014f9503385SDmitry Osipenko 	/* try to resolve regulators coupling since a new one was registered */
5015f9503385SDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
5016f9503385SDmitry Osipenko 	regulator_resolve_coupling(rdev);
5017f9503385SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
5018f9503385SDmitry Osipenko 
50195e3ca2b3SJavier Martinez Canillas 	/* try to resolve regulators supply since a new one was registered */
50205e3ca2b3SJavier Martinez Canillas 	class_for_each_device(&regulator_class, NULL, NULL,
50215e3ca2b3SJavier Martinez Canillas 			      regulator_register_resolve_supply);
50221b3de223SKrzysztof Kozlowski 	kfree(config);
5023414c70cbSLiam Girdwood 	return rdev;
50244fca9545SDavid Brownell 
5025d4033b54SJani Nikula unset_supplies:
502645389c47SJon Hunter 	mutex_lock(&regulator_list_mutex);
5027d4033b54SJani Nikula 	unset_regulator_supplies(rdev);
502845389c47SJon Hunter 	mutex_unlock(&regulator_list_mutex);
502932165230SKrzysztof Adamski wash:
5030469b640eSBoris Brezillon 	kfree(rdev->constraints);
503145389c47SJon Hunter 	mutex_lock(&regulator_list_mutex);
503232165230SKrzysztof Adamski 	regulator_ena_gpio_free(rdev);
503345389c47SJon Hunter 	mutex_unlock(&regulator_list_mutex);
50344fca9545SDavid Brownell clean:
50350edb040dSLinus Walleij 	if (dangling_of_gpiod)
50360edb040dSLinus Walleij 		gpiod_put(config->ena_gpiod);
50374fca9545SDavid Brownell 	kfree(rdev);
5038a2151374SJon Hunter 	kfree(config);
50390edb040dSLinus Walleij rinse:
50400edb040dSLinus Walleij 	if (dangling_cfg_gpiod)
50410edb040dSLinus Walleij 		gpiod_put(cfg->ena_gpiod);
5042a2151374SJon Hunter 	return ERR_PTR(ret);
5043414c70cbSLiam Girdwood }
5044414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register);
5045414c70cbSLiam Girdwood 
5046414c70cbSLiam Girdwood /**
5047414c70cbSLiam Girdwood  * regulator_unregister - unregister regulator
504869279fb9SMark Brown  * @rdev: regulator to unregister
5049414c70cbSLiam Girdwood  *
5050414c70cbSLiam Girdwood  * Called by regulator drivers to unregister a regulator.
5051414c70cbSLiam Girdwood  */
5052414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev)
5053414c70cbSLiam Girdwood {
5054414c70cbSLiam Girdwood 	if (rdev == NULL)
5055414c70cbSLiam Girdwood 		return;
5056414c70cbSLiam Girdwood 
5057891636eaSMark Brown 	if (rdev->supply) {
5058891636eaSMark Brown 		while (rdev->use_count--)
5059891636eaSMark Brown 			regulator_disable(rdev->supply);
5060e032b376SMark Brown 		regulator_put(rdev->supply);
5061891636eaSMark Brown 	}
5062ff9b34b6SDmitry Osipenko 
506306377301SCharles Keepax 	flush_work(&rdev->disable_work.work);
506406377301SCharles Keepax 
5065414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
5066ff9b34b6SDmitry Osipenko 
50671130e5b3SMark Brown 	debugfs_remove_recursive(rdev->debugfs);
50686bf87d17SMark Brown 	WARN_ON(rdev->open_count);
50696303f3e7SDmitry Osipenko 	regulator_remove_coupling(rdev);
50700f1d747bSMike Rapoport 	unset_regulator_supplies(rdev);
5071414c70cbSLiam Girdwood 	list_del(&rdev->list);
5072f19b00daSKim, Milo 	regulator_ena_gpio_free(rdev);
507358fb5cf5SLothar Waßmann 	device_unregister(&rdev->dev);
5074ff9b34b6SDmitry Osipenko 
5075ff9b34b6SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
5076414c70cbSLiam Girdwood }
5077414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister);
5078414c70cbSLiam Girdwood 
5079f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND
5080414c70cbSLiam Girdwood /**
50810380cf7dSpascal paillet  * regulator_suspend - prepare regulators for system wide suspend
50821efef7ccSRandy Dunlap  * @dev: ``&struct device`` pointer that is passed to _regulator_suspend()
5083414c70cbSLiam Girdwood  *
5084414c70cbSLiam Girdwood  * Configure each regulator with it's suspend operating parameters for state.
5085414c70cbSLiam Girdwood  */
50860380cf7dSpascal paillet static int regulator_suspend(struct device *dev)
5087414c70cbSLiam Girdwood {
5088cd7e36abSMarek Szyprowski 	struct regulator_dev *rdev = dev_to_rdev(dev);
5089f7efad10SChunyan Zhang 	suspend_state_t state = pm_suspend_target_state;
5090cd7e36abSMarek Szyprowski 	int ret;
5091414c70cbSLiam Girdwood 
5092cd7e36abSMarek Szyprowski 	regulator_lock(rdev);
5093cd7e36abSMarek Szyprowski 	ret = suspend_set_state(rdev, state);
5094cd7e36abSMarek Szyprowski 	regulator_unlock(rdev);
5095cd7e36abSMarek Szyprowski 
5096cd7e36abSMarek Szyprowski 	return ret;
5097414c70cbSLiam Girdwood }
5098d3e4eccbSMark Brown 
5099cd7e36abSMarek Szyprowski static int regulator_resume(struct device *dev)
510085f3b431STomeu Vizoso {
5101cd7e36abSMarek Szyprowski 	suspend_state_t state = pm_suspend_target_state;
510285f3b431STomeu Vizoso 	struct regulator_dev *rdev = dev_to_rdev(dev);
5103f7efad10SChunyan Zhang 	struct regulator_state *rstate;
5104cd7e36abSMarek Szyprowski 	int ret = 0;
5105f7efad10SChunyan Zhang 
5106cd7e36abSMarek Szyprowski 	rstate = regulator_get_suspend_state(rdev, state);
5107f7efad10SChunyan Zhang 	if (rstate == NULL)
510835b5f14eSGeert Uytterhoeven 		return 0;
510985f3b431STomeu Vizoso 
511066cf9a7eSMaciej Purski 	regulator_lock(rdev);
511185f3b431STomeu Vizoso 
51120380cf7dSpascal paillet 	if (rdev->desc->ops->resume &&
5113f7efad10SChunyan Zhang 	    (rstate->enabled == ENABLE_IN_SUSPEND ||
5114f7efad10SChunyan Zhang 	     rstate->enabled == DISABLE_IN_SUSPEND))
51150380cf7dSpascal paillet 		ret = rdev->desc->ops->resume(rdev);
5116f7efad10SChunyan Zhang 
511766cf9a7eSMaciej Purski 	regulator_unlock(rdev);
511885f3b431STomeu Vizoso 
5119f7efad10SChunyan Zhang 	return ret;
512085f3b431STomeu Vizoso }
5121f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */
5122f7efad10SChunyan Zhang 
51230380cf7dSpascal paillet #define regulator_suspend	NULL
51240380cf7dSpascal paillet #define regulator_resume	NULL
5125f7efad10SChunyan Zhang 
5126f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */
5127f7efad10SChunyan Zhang 
5128f7efad10SChunyan Zhang #ifdef CONFIG_PM
5129f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = {
51300380cf7dSpascal paillet 	.suspend	= regulator_suspend,
51310380cf7dSpascal paillet 	.resume		= regulator_resume,
5132f7efad10SChunyan Zhang };
5133f7efad10SChunyan Zhang #endif
5134f7efad10SChunyan Zhang 
5135285c22deSMark Brown struct class regulator_class = {
5136f7efad10SChunyan Zhang 	.name = "regulator",
5137f7efad10SChunyan Zhang 	.dev_release = regulator_dev_release,
5138f7efad10SChunyan Zhang 	.dev_groups = regulator_dev_groups,
5139f7efad10SChunyan Zhang #ifdef CONFIG_PM
5140f7efad10SChunyan Zhang 	.pm = &regulator_pm_ops,
5141f7efad10SChunyan Zhang #endif
5142f7efad10SChunyan Zhang };
51437a32b589SMyungJoo Ham /**
5144ca725561SMark Brown  * regulator_has_full_constraints - the system has fully specified constraints
5145ca725561SMark Brown  *
5146ca725561SMark Brown  * Calling this function will cause the regulator API to disable all
5147ca725561SMark Brown  * regulators which have a zero use count and don't have an always_on
5148ca725561SMark Brown  * constraint in a late_initcall.
5149ca725561SMark Brown  *
5150ca725561SMark Brown  * The intention is that this will become the default behaviour in a
5151ca725561SMark Brown  * future kernel release so users are encouraged to use this facility
5152ca725561SMark Brown  * now.
5153ca725561SMark Brown  */
5154ca725561SMark Brown void regulator_has_full_constraints(void)
5155ca725561SMark Brown {
5156ca725561SMark Brown 	has_full_constraints = 1;
5157ca725561SMark Brown }
5158ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
5159ca725561SMark Brown 
5160ca725561SMark Brown /**
5161414c70cbSLiam Girdwood  * rdev_get_drvdata - get rdev regulator driver data
516269279fb9SMark Brown  * @rdev: regulator
5163414c70cbSLiam Girdwood  *
5164414c70cbSLiam Girdwood  * Get rdev regulator driver private data. This call can be used in the
5165414c70cbSLiam Girdwood  * regulator driver context.
5166414c70cbSLiam Girdwood  */
5167414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev)
5168414c70cbSLiam Girdwood {
5169414c70cbSLiam Girdwood 	return rdev->reg_data;
5170414c70cbSLiam Girdwood }
5171414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata);
5172414c70cbSLiam Girdwood 
5173414c70cbSLiam Girdwood /**
5174414c70cbSLiam Girdwood  * regulator_get_drvdata - get regulator driver data
5175414c70cbSLiam Girdwood  * @regulator: regulator
5176414c70cbSLiam Girdwood  *
5177414c70cbSLiam Girdwood  * Get regulator driver private data. This call can be used in the consumer
5178414c70cbSLiam Girdwood  * driver context when non API regulator specific functions need to be called.
5179414c70cbSLiam Girdwood  */
5180414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator)
5181414c70cbSLiam Girdwood {
5182414c70cbSLiam Girdwood 	return regulator->rdev->reg_data;
5183414c70cbSLiam Girdwood }
5184414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata);
5185414c70cbSLiam Girdwood 
5186414c70cbSLiam Girdwood /**
5187414c70cbSLiam Girdwood  * regulator_set_drvdata - set regulator driver data
5188414c70cbSLiam Girdwood  * @regulator: regulator
5189414c70cbSLiam Girdwood  * @data: data
5190414c70cbSLiam Girdwood  */
5191414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data)
5192414c70cbSLiam Girdwood {
5193414c70cbSLiam Girdwood 	regulator->rdev->reg_data = data;
5194414c70cbSLiam Girdwood }
5195414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata);
5196414c70cbSLiam Girdwood 
5197414c70cbSLiam Girdwood /**
5198414c70cbSLiam Girdwood  * regulator_get_id - get regulator ID
519969279fb9SMark Brown  * @rdev: regulator
5200414c70cbSLiam Girdwood  */
5201414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev)
5202414c70cbSLiam Girdwood {
5203414c70cbSLiam Girdwood 	return rdev->desc->id;
5204414c70cbSLiam Girdwood }
5205414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id);
5206414c70cbSLiam Girdwood 
5207a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev)
5208a5766f11SLiam Girdwood {
5209a5766f11SLiam Girdwood 	return &rdev->dev;
5210a5766f11SLiam Girdwood }
5211a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev);
5212a5766f11SLiam Girdwood 
521303c87b95SBartosz Golaszewski struct regmap *rdev_get_regmap(struct regulator_dev *rdev)
521403c87b95SBartosz Golaszewski {
521503c87b95SBartosz Golaszewski 	return rdev->regmap;
521603c87b95SBartosz Golaszewski }
521703c87b95SBartosz Golaszewski EXPORT_SYMBOL_GPL(rdev_get_regmap);
521803c87b95SBartosz Golaszewski 
5219a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
5220a5766f11SLiam Girdwood {
5221a5766f11SLiam Girdwood 	return reg_init_data->driver_data;
5222a5766f11SLiam Girdwood }
5223a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
5224a5766f11SLiam Girdwood 
5225ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS
5226dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data)
5227ba55a974SMark Brown {
5228ba55a974SMark Brown 	struct regulator_map *map;
5229ba55a974SMark Brown 
5230ba55a974SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
5231dbc55955SHaishan Zhou 		seq_printf(sf, "%s -> %s.%s\n",
5232ba55a974SMark Brown 				rdev_get_name(map->regulator), map->dev_name,
5233ba55a974SMark Brown 				map->supply);
5234ba55a974SMark Brown 	}
5235ba55a974SMark Brown 
5236dbc55955SHaishan Zhou 	return 0;
5237dbc55955SHaishan Zhou }
52383e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(supply_map);
5239ba55a974SMark Brown 
524085f3b431STomeu Vizoso struct summary_data {
524185f3b431STomeu Vizoso 	struct seq_file *s;
524285f3b431STomeu Vizoso 	struct regulator_dev *parent;
524385f3b431STomeu Vizoso 	int level;
524485f3b431STomeu Vizoso };
524585f3b431STomeu Vizoso 
524685f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s,
524785f3b431STomeu Vizoso 					   struct regulator_dev *rdev,
524885f3b431STomeu Vizoso 					   int level);
524985f3b431STomeu Vizoso 
525085f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data)
525185f3b431STomeu Vizoso {
525285f3b431STomeu Vizoso 	struct regulator_dev *rdev = dev_to_rdev(dev);
525385f3b431STomeu Vizoso 	struct summary_data *summary_data = data;
525485f3b431STomeu Vizoso 
525585f3b431STomeu Vizoso 	if (rdev->supply && rdev->supply->rdev == summary_data->parent)
525685f3b431STomeu Vizoso 		regulator_summary_show_subtree(summary_data->s, rdev,
525785f3b431STomeu Vizoso 					       summary_data->level + 1);
525885f3b431STomeu Vizoso 
525985f3b431STomeu Vizoso 	return 0;
526085f3b431STomeu Vizoso }
526185f3b431STomeu Vizoso 
52627c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s,
52637c225ec9SHeiko Stübner 					   struct regulator_dev *rdev,
52647c225ec9SHeiko Stübner 					   int level)
52657c225ec9SHeiko Stübner {
52667c225ec9SHeiko Stübner 	struct regulation_constraints *c;
52677c225ec9SHeiko Stübner 	struct regulator *consumer;
526885f3b431STomeu Vizoso 	struct summary_data summary_data;
52697e4d9683SDouglas Anderson 	unsigned int opmode;
52707c225ec9SHeiko Stübner 
52717c225ec9SHeiko Stübner 	if (!rdev)
52727c225ec9SHeiko Stübner 		return;
52737c225ec9SHeiko Stübner 
52747e4d9683SDouglas Anderson 	opmode = _regulator_get_mode_unlocked(rdev);
527501de19d0SDouglas Anderson 	seq_printf(s, "%*s%-*s %3d %4d %6d %7s ",
52767c225ec9SHeiko Stübner 		   level * 3 + 1, "",
52777c225ec9SHeiko Stübner 		   30 - level * 3, rdev_get_name(rdev),
527801de19d0SDouglas Anderson 		   rdev->use_count, rdev->open_count, rdev->bypass_count,
52797e4d9683SDouglas Anderson 		   regulator_opmode_to_str(opmode));
52807c225ec9SHeiko Stübner 
528123296099SHeiko Stübner 	seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000);
52827e4d9683SDouglas Anderson 	seq_printf(s, "%5dmA ",
52837e4d9683SDouglas Anderson 		   _regulator_get_current_limit_unlocked(rdev) / 1000);
52847c225ec9SHeiko Stübner 
52857c225ec9SHeiko Stübner 	c = rdev->constraints;
52867c225ec9SHeiko Stübner 	if (c) {
52877c225ec9SHeiko Stübner 		switch (rdev->desc->type) {
52887c225ec9SHeiko Stübner 		case REGULATOR_VOLTAGE:
52897c225ec9SHeiko Stübner 			seq_printf(s, "%5dmV %5dmV ",
52907c225ec9SHeiko Stübner 				   c->min_uV / 1000, c->max_uV / 1000);
52917c225ec9SHeiko Stübner 			break;
52927c225ec9SHeiko Stübner 		case REGULATOR_CURRENT:
52937c225ec9SHeiko Stübner 			seq_printf(s, "%5dmA %5dmA ",
52947c225ec9SHeiko Stübner 				   c->min_uA / 1000, c->max_uA / 1000);
52957c225ec9SHeiko Stübner 			break;
52967c225ec9SHeiko Stübner 		}
52977c225ec9SHeiko Stübner 	}
52987c225ec9SHeiko Stübner 
52997c225ec9SHeiko Stübner 	seq_puts(s, "\n");
53007c225ec9SHeiko Stübner 
53017c225ec9SHeiko Stübner 	list_for_each_entry(consumer, &rdev->consumer_list, list) {
5302e42a46b6SLeonard Crestez 		if (consumer->dev && consumer->dev->class == &regulator_class)
53037c225ec9SHeiko Stübner 			continue;
53047c225ec9SHeiko Stübner 
53057c225ec9SHeiko Stübner 		seq_printf(s, "%*s%-*s ",
53067c225ec9SHeiko Stübner 			   (level + 1) * 3 + 1, "",
5307e42a46b6SLeonard Crestez 			   30 - (level + 1) * 3,
5308e42a46b6SLeonard Crestez 			   consumer->dev ? dev_name(consumer->dev) : "deviceless");
53097c225ec9SHeiko Stübner 
53107c225ec9SHeiko Stübner 		switch (rdev->desc->type) {
53117c225ec9SHeiko Stübner 		case REGULATOR_VOLTAGE:
53125451781dSDouglas Anderson 			seq_printf(s, "%3d %33dmA%c%5dmV %5dmV",
53135451781dSDouglas Anderson 				   consumer->enable_count,
53147d3827b5SDouglas Anderson 				   consumer->uA_load / 1000,
53155451781dSDouglas Anderson 				   consumer->uA_load && !consumer->enable_count ?
53165451781dSDouglas Anderson 				   '*' : ' ',
5317c360a6dfSChunyan Zhang 				   consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
5318c360a6dfSChunyan Zhang 				   consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
53197c225ec9SHeiko Stübner 			break;
53207c225ec9SHeiko Stübner 		case REGULATOR_CURRENT:
53217c225ec9SHeiko Stübner 			break;
53227c225ec9SHeiko Stübner 		}
53237c225ec9SHeiko Stübner 
53247c225ec9SHeiko Stübner 		seq_puts(s, "\n");
53257c225ec9SHeiko Stübner 	}
53267c225ec9SHeiko Stübner 
532785f3b431STomeu Vizoso 	summary_data.s = s;
532885f3b431STomeu Vizoso 	summary_data.level = level;
532985f3b431STomeu Vizoso 	summary_data.parent = rdev;
53307c225ec9SHeiko Stübner 
533185f3b431STomeu Vizoso 	class_for_each_device(&regulator_class, NULL, &summary_data,
533285f3b431STomeu Vizoso 			      regulator_summary_show_children);
5333f8702f9eSDmitry Osipenko }
5334f8702f9eSDmitry Osipenko 
5335f8702f9eSDmitry Osipenko struct summary_lock_data {
5336f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx *ww_ctx;
5337f8702f9eSDmitry Osipenko 	struct regulator_dev **new_contended_rdev;
5338f8702f9eSDmitry Osipenko 	struct regulator_dev **old_contended_rdev;
5339f8702f9eSDmitry Osipenko };
5340f8702f9eSDmitry Osipenko 
5341f8702f9eSDmitry Osipenko static int regulator_summary_lock_one(struct device *dev, void *data)
5342f8702f9eSDmitry Osipenko {
5343f8702f9eSDmitry Osipenko 	struct regulator_dev *rdev = dev_to_rdev(dev);
5344f8702f9eSDmitry Osipenko 	struct summary_lock_data *lock_data = data;
5345f8702f9eSDmitry Osipenko 	int ret = 0;
5346f8702f9eSDmitry Osipenko 
5347f8702f9eSDmitry Osipenko 	if (rdev != *lock_data->old_contended_rdev) {
5348f8702f9eSDmitry Osipenko 		ret = regulator_lock_nested(rdev, lock_data->ww_ctx);
5349f8702f9eSDmitry Osipenko 
5350f8702f9eSDmitry Osipenko 		if (ret == -EDEADLK)
5351f8702f9eSDmitry Osipenko 			*lock_data->new_contended_rdev = rdev;
5352f8702f9eSDmitry Osipenko 		else
5353f8702f9eSDmitry Osipenko 			WARN_ON_ONCE(ret);
5354f8702f9eSDmitry Osipenko 	} else {
5355f8702f9eSDmitry Osipenko 		*lock_data->old_contended_rdev = NULL;
5356f8702f9eSDmitry Osipenko 	}
5357f8702f9eSDmitry Osipenko 
5358f8702f9eSDmitry Osipenko 	return ret;
5359f8702f9eSDmitry Osipenko }
5360f8702f9eSDmitry Osipenko 
5361f8702f9eSDmitry Osipenko static int regulator_summary_unlock_one(struct device *dev, void *data)
5362f8702f9eSDmitry Osipenko {
5363f8702f9eSDmitry Osipenko 	struct regulator_dev *rdev = dev_to_rdev(dev);
5364f8702f9eSDmitry Osipenko 	struct summary_lock_data *lock_data = data;
5365f8702f9eSDmitry Osipenko 
5366f8702f9eSDmitry Osipenko 	if (lock_data) {
5367f8702f9eSDmitry Osipenko 		if (rdev == *lock_data->new_contended_rdev)
5368f8702f9eSDmitry Osipenko 			return -EDEADLK;
5369f8702f9eSDmitry Osipenko 	}
53707e4d9683SDouglas Anderson 
53717e4d9683SDouglas Anderson 	regulator_unlock(rdev);
5372f8702f9eSDmitry Osipenko 
5373f8702f9eSDmitry Osipenko 	return 0;
5374f8702f9eSDmitry Osipenko }
5375f8702f9eSDmitry Osipenko 
5376f8702f9eSDmitry Osipenko static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx,
5377f8702f9eSDmitry Osipenko 				      struct regulator_dev **new_contended_rdev,
5378f8702f9eSDmitry Osipenko 				      struct regulator_dev **old_contended_rdev)
5379f8702f9eSDmitry Osipenko {
5380f8702f9eSDmitry Osipenko 	struct summary_lock_data lock_data;
5381f8702f9eSDmitry Osipenko 	int ret;
5382f8702f9eSDmitry Osipenko 
5383f8702f9eSDmitry Osipenko 	lock_data.ww_ctx = ww_ctx;
5384f8702f9eSDmitry Osipenko 	lock_data.new_contended_rdev = new_contended_rdev;
5385f8702f9eSDmitry Osipenko 	lock_data.old_contended_rdev = old_contended_rdev;
5386f8702f9eSDmitry Osipenko 
5387f8702f9eSDmitry Osipenko 	ret = class_for_each_device(&regulator_class, NULL, &lock_data,
5388f8702f9eSDmitry Osipenko 				    regulator_summary_lock_one);
5389f8702f9eSDmitry Osipenko 	if (ret)
5390f8702f9eSDmitry Osipenko 		class_for_each_device(&regulator_class, NULL, &lock_data,
5391f8702f9eSDmitry Osipenko 				      regulator_summary_unlock_one);
5392f8702f9eSDmitry Osipenko 
5393f8702f9eSDmitry Osipenko 	return ret;
5394f8702f9eSDmitry Osipenko }
5395f8702f9eSDmitry Osipenko 
5396f8702f9eSDmitry Osipenko static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx)
5397f8702f9eSDmitry Osipenko {
5398f8702f9eSDmitry Osipenko 	struct regulator_dev *new_contended_rdev = NULL;
5399f8702f9eSDmitry Osipenko 	struct regulator_dev *old_contended_rdev = NULL;
5400f8702f9eSDmitry Osipenko 	int err;
5401f8702f9eSDmitry Osipenko 
5402ff9b34b6SDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
5403ff9b34b6SDmitry Osipenko 
5404f8702f9eSDmitry Osipenko 	ww_acquire_init(ww_ctx, &regulator_ww_class);
5405f8702f9eSDmitry Osipenko 
5406f8702f9eSDmitry Osipenko 	do {
5407f8702f9eSDmitry Osipenko 		if (new_contended_rdev) {
5408f8702f9eSDmitry Osipenko 			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
5409f8702f9eSDmitry Osipenko 			old_contended_rdev = new_contended_rdev;
5410f8702f9eSDmitry Osipenko 			old_contended_rdev->ref_cnt++;
5411f8702f9eSDmitry Osipenko 		}
5412f8702f9eSDmitry Osipenko 
5413f8702f9eSDmitry Osipenko 		err = regulator_summary_lock_all(ww_ctx,
5414f8702f9eSDmitry Osipenko 						 &new_contended_rdev,
5415f8702f9eSDmitry Osipenko 						 &old_contended_rdev);
5416f8702f9eSDmitry Osipenko 
5417f8702f9eSDmitry Osipenko 		if (old_contended_rdev)
5418f8702f9eSDmitry Osipenko 			regulator_unlock(old_contended_rdev);
5419f8702f9eSDmitry Osipenko 
5420f8702f9eSDmitry Osipenko 	} while (err == -EDEADLK);
5421f8702f9eSDmitry Osipenko 
5422f8702f9eSDmitry Osipenko 	ww_acquire_done(ww_ctx);
5423f8702f9eSDmitry Osipenko }
5424f8702f9eSDmitry Osipenko 
5425f8702f9eSDmitry Osipenko static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx)
5426f8702f9eSDmitry Osipenko {
5427f8702f9eSDmitry Osipenko 	class_for_each_device(&regulator_class, NULL, NULL,
5428f8702f9eSDmitry Osipenko 			      regulator_summary_unlock_one);
5429f8702f9eSDmitry Osipenko 	ww_acquire_fini(ww_ctx);
5430ff9b34b6SDmitry Osipenko 
5431ff9b34b6SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
54327c225ec9SHeiko Stübner }
543385f3b431STomeu Vizoso 
543485f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data)
543585f3b431STomeu Vizoso {
543685f3b431STomeu Vizoso 	struct regulator_dev *rdev = dev_to_rdev(dev);
543785f3b431STomeu Vizoso 	struct seq_file *s = data;
543885f3b431STomeu Vizoso 
543985f3b431STomeu Vizoso 	if (!rdev->supply)
544085f3b431STomeu Vizoso 		regulator_summary_show_subtree(s, rdev, 0);
544185f3b431STomeu Vizoso 
544285f3b431STomeu Vizoso 	return 0;
54437c225ec9SHeiko Stübner }
54447c225ec9SHeiko Stübner 
54457c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data)
54467c225ec9SHeiko Stübner {
5447f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
5448f8702f9eSDmitry Osipenko 
544901de19d0SDouglas Anderson 	seq_puts(s, " regulator                      use open bypass  opmode voltage current     min     max\n");
545001de19d0SDouglas Anderson 	seq_puts(s, "---------------------------------------------------------------------------------------\n");
54517c225ec9SHeiko Stübner 
5452f8702f9eSDmitry Osipenko 	regulator_summary_lock(&ww_ctx);
5453f8702f9eSDmitry Osipenko 
545485f3b431STomeu Vizoso 	class_for_each_device(&regulator_class, NULL, s,
545585f3b431STomeu Vizoso 			      regulator_summary_show_roots);
54567c225ec9SHeiko Stübner 
5457f8702f9eSDmitry Osipenko 	regulator_summary_unlock(&ww_ctx);
5458f8702f9eSDmitry Osipenko 
54597c225ec9SHeiko Stübner 	return 0;
54607c225ec9SHeiko Stübner }
54613e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(regulator_summary);
54623e60b4fcSYangtao Li #endif /* CONFIG_DEBUG_FS */
54637c225ec9SHeiko Stübner 
5464414c70cbSLiam Girdwood static int __init regulator_init(void)
5465414c70cbSLiam Girdwood {
546634abbd68SMark Brown 	int ret;
546734abbd68SMark Brown 
546834abbd68SMark Brown 	ret = class_register(&regulator_class);
546934abbd68SMark Brown 
54701130e5b3SMark Brown 	debugfs_root = debugfs_create_dir("regulator", NULL);
547124751434SStephen Boyd 	if (!debugfs_root)
54721130e5b3SMark Brown 		pr_warn("regulator: Failed to create debugfs directory\n");
5473ba55a974SMark Brown 
54743e60b4fcSYangtao Li #ifdef CONFIG_DEBUG_FS
5475f4d562c6SMark Brown 	debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
5476f4d562c6SMark Brown 			    &supply_map_fops);
54771130e5b3SMark Brown 
54787c225ec9SHeiko Stübner 	debugfs_create_file("regulator_summary", 0444, debugfs_root,
547985f3b431STomeu Vizoso 			    NULL, &regulator_summary_fops);
54803e60b4fcSYangtao Li #endif
548134abbd68SMark Brown 	regulator_dummy_init();
548234abbd68SMark Brown 
548334abbd68SMark Brown 	return ret;
5484414c70cbSLiam Girdwood }
5485414c70cbSLiam Girdwood 
5486414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */
5487414c70cbSLiam Girdwood core_initcall(regulator_init);
5488ca725561SMark Brown 
5489609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data)
5490ca725561SMark Brown {
5491609ca5f3SMark Brown 	struct regulator_dev *rdev = dev_to_rdev(dev);
5492609ca5f3SMark Brown 	const struct regulator_ops *ops = rdev->desc->ops;
5493609ca5f3SMark Brown 	struct regulation_constraints *c = rdev->constraints;
5494ca725561SMark Brown 	int enabled, ret;
5495ca725561SMark Brown 
549666fda75fSMarkus Pargmann 	if (c && c->always_on)
5497609ca5f3SMark Brown 		return 0;
5498ca725561SMark Brown 
54998a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS))
5500609ca5f3SMark Brown 		return 0;
5501e9535834SMark Brown 
550266cf9a7eSMaciej Purski 	regulator_lock(rdev);
5503ca725561SMark Brown 
5504ca725561SMark Brown 	if (rdev->use_count)
5505ca725561SMark Brown 		goto unlock;
5506ca725561SMark Brown 
5507ca725561SMark Brown 	/* If we can't read the status assume it's on. */
5508ca725561SMark Brown 	if (ops->is_enabled)
5509ca725561SMark Brown 		enabled = ops->is_enabled(rdev);
5510ca725561SMark Brown 	else
5511ca725561SMark Brown 		enabled = 1;
5512ca725561SMark Brown 
5513ca725561SMark Brown 	if (!enabled)
5514ca725561SMark Brown 		goto unlock;
5515ca725561SMark Brown 
551687b28417SMark Brown 	if (have_full_constraints()) {
5517609ca5f3SMark Brown 		/* We log since this may kill the system if it goes
5518609ca5f3SMark Brown 		 * wrong. */
55195da84fd9SJoe Perches 		rdev_info(rdev, "disabling\n");
552066fda75fSMarkus Pargmann 		ret = _regulator_do_disable(rdev);
55210d25d09dSJingoo Han 		if (ret != 0)
55225da84fd9SJoe Perches 			rdev_err(rdev, "couldn't disable: %d\n", ret);
5523ca725561SMark Brown 	} else {
5524ca725561SMark Brown 		/* The intention is that in future we will
5525ca725561SMark Brown 		 * assume that full constraints are provided
5526ca725561SMark Brown 		 * so warn even if we aren't going to do
5527ca725561SMark Brown 		 * anything here.
5528ca725561SMark Brown 		 */
55295da84fd9SJoe Perches 		rdev_warn(rdev, "incomplete constraints, leaving on\n");
5530ca725561SMark Brown 	}
5531ca725561SMark Brown 
5532ca725561SMark Brown unlock:
553366cf9a7eSMaciej Purski 	regulator_unlock(rdev);
5534609ca5f3SMark Brown 
5535609ca5f3SMark Brown 	return 0;
5536ca725561SMark Brown }
5537ca725561SMark Brown 
5538609ca5f3SMark Brown static int __init regulator_init_complete(void)
5539609ca5f3SMark Brown {
5540609ca5f3SMark Brown 	/*
5541609ca5f3SMark Brown 	 * Since DT doesn't provide an idiomatic mechanism for
5542609ca5f3SMark Brown 	 * enabling full constraints and since it's much more natural
5543609ca5f3SMark Brown 	 * with DT to provide them just assume that a DT enabled
5544609ca5f3SMark Brown 	 * system has full constraints.
5545609ca5f3SMark Brown 	 */
5546609ca5f3SMark Brown 	if (of_have_populated_dt())
5547609ca5f3SMark Brown 		has_full_constraints = true;
5548609ca5f3SMark Brown 
55493827b64dSJavier Martinez Canillas 	/*
55503827b64dSJavier Martinez Canillas 	 * Regulators may had failed to resolve their input supplies
55513827b64dSJavier Martinez Canillas 	 * when were registered, either because the input supply was
55523827b64dSJavier Martinez Canillas 	 * not registered yet or because its parent device was not
55533827b64dSJavier Martinez Canillas 	 * bound yet. So attempt to resolve the input supplies for
55543827b64dSJavier Martinez Canillas 	 * pending regulators before trying to disable unused ones.
55553827b64dSJavier Martinez Canillas 	 */
55563827b64dSJavier Martinez Canillas 	class_for_each_device(&regulator_class, NULL, NULL,
55573827b64dSJavier Martinez Canillas 			      regulator_register_resolve_supply);
55583827b64dSJavier Martinez Canillas 
5559609ca5f3SMark Brown 	/* If we have a full configuration then disable any regulators
5560609ca5f3SMark Brown 	 * we have permission to change the status for and which are
5561609ca5f3SMark Brown 	 * not in use or always_on.  This is effectively the default
5562609ca5f3SMark Brown 	 * for DT and ACPI as they have full constraints.
5563609ca5f3SMark Brown 	 */
5564609ca5f3SMark Brown 	class_for_each_device(&regulator_class, NULL, NULL,
5565609ca5f3SMark Brown 			      regulator_late_cleanup);
5566ca725561SMark Brown 
5567ca725561SMark Brown 	return 0;
5568ca725561SMark Brown }
5569fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete);
5570