xref: /openbmc/linux/drivers/regulator/core.c (revision 186d7785)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2f2c6203fSMark Brown //
3f2c6203fSMark Brown // core.c  --  Voltage/Current Regulator framework.
4f2c6203fSMark Brown //
5f2c6203fSMark Brown // Copyright 2007, 2008 Wolfson Microelectronics PLC.
6f2c6203fSMark Brown // Copyright 2008 SlimLogic Ltd.
7f2c6203fSMark Brown //
8f2c6203fSMark Brown // Author: Liam Girdwood <lrg@slimlogic.co.uk>
9414c70cbSLiam Girdwood 
10414c70cbSLiam Girdwood #include <linux/kernel.h>
11414c70cbSLiam Girdwood #include <linux/init.h>
121130e5b3SMark Brown #include <linux/debugfs.h>
13414c70cbSLiam Girdwood #include <linux/device.h>
145a0e3ad6STejun Heo #include <linux/slab.h>
15f21e0e81SMark Brown #include <linux/async.h>
16414c70cbSLiam Girdwood #include <linux/err.h>
17414c70cbSLiam Girdwood #include <linux/mutex.h>
18414c70cbSLiam Girdwood #include <linux/suspend.h>
1931aae2beSMark Brown #include <linux/delay.h>
20778b28b4SRussell King #include <linux/gpio/consumer.h>
2169511a45SRajendra Nayak #include <linux/of.h>
2265b19ce6SMark Brown #include <linux/regmap.h>
2369511a45SRajendra Nayak #include <linux/regulator/of_regulator.h>
24414c70cbSLiam Girdwood #include <linux/regulator/consumer.h>
25d8ca7d18SDmitry Osipenko #include <linux/regulator/coupler.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 
36f8702f9eSDmitry Osipenko static DEFINE_WW_CLASS(regulator_ww_class);
37f8702f9eSDmitry Osipenko static DEFINE_MUTEX(regulator_nesting_mutex);
38414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex);
39414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list);
40f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list);
41a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list);
42d8ca7d18SDmitry Osipenko static LIST_HEAD(regulator_coupler_list);
4321cf891aSMark Brown static bool has_full_constraints;
44414c70cbSLiam Girdwood 
451130e5b3SMark Brown static struct dentry *debugfs_root;
461130e5b3SMark Brown 
478dc5390dSMark Brown /*
48414c70cbSLiam Girdwood  * struct regulator_map
49414c70cbSLiam Girdwood  *
50414c70cbSLiam Girdwood  * Used to provide symbolic supply names to devices.
51414c70cbSLiam Girdwood  */
52414c70cbSLiam Girdwood struct regulator_map {
53414c70cbSLiam Girdwood 	struct list_head list;
5440f9244fSMark Brown 	const char *dev_name;   /* The dev_name() for the consumer */
55414c70cbSLiam Girdwood 	const char *supply;
56a5766f11SLiam Girdwood 	struct regulator_dev *regulator;
57414c70cbSLiam Girdwood };
58414c70cbSLiam Girdwood 
59414c70cbSLiam Girdwood /*
60f19b00daSKim, Milo  * struct regulator_enable_gpio
61f19b00daSKim, Milo  *
62f19b00daSKim, Milo  * Management for shared enable GPIO pin
63f19b00daSKim, Milo  */
64f19b00daSKim, Milo struct regulator_enable_gpio {
65f19b00daSKim, Milo 	struct list_head list;
66778b28b4SRussell King 	struct gpio_desc *gpiod;
67f19b00daSKim, Milo 	u32 enable_count;	/* a number of enabled shared GPIO */
68f19b00daSKim, Milo 	u32 request_count;	/* a number of requested shared GPIO */
69f19b00daSKim, Milo };
70f19b00daSKim, Milo 
71a06ccd9cSCharles Keepax /*
72a06ccd9cSCharles Keepax  * struct regulator_supply_alias
73a06ccd9cSCharles Keepax  *
74a06ccd9cSCharles Keepax  * Used to map lookups for a supply onto an alternative device.
75a06ccd9cSCharles Keepax  */
76a06ccd9cSCharles Keepax struct regulator_supply_alias {
77a06ccd9cSCharles Keepax 	struct list_head list;
78a06ccd9cSCharles Keepax 	struct device *src_dev;
79a06ccd9cSCharles Keepax 	const char *src_supply;
80a06ccd9cSCharles Keepax 	struct device *alias_dev;
81a06ccd9cSCharles Keepax 	const char *alias_supply;
82a06ccd9cSCharles Keepax };
83a06ccd9cSCharles Keepax 
84414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev);
855451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator);
860f2d636eSZev Weiss static int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags);
87414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev);
88414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
897179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev,
90414c70cbSLiam Girdwood 				  unsigned long event, void *data);
9175790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
9275790251SMark Brown 				     int min_uV, int max_uV);
93c054c6c7SMaciej Purski static int regulator_balance_voltage(struct regulator_dev *rdev,
94c054c6c7SMaciej Purski 				     suspend_state_t state);
953801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev,
963801b86aSMark Brown 					  struct device *dev,
973801b86aSMark Brown 					  const char *supply_name);
98e1794aa4SSaravana Kannan static void destroy_regulator(struct regulator *regulator);
9936a1f1b6SJavier Martinez Canillas static void _regulator_put(struct regulator *regulator);
100414c70cbSLiam Girdwood 
rdev_get_name(struct regulator_dev * rdev)101d22b85a1SDmitry Osipenko const char *rdev_get_name(struct regulator_dev *rdev)
1021083c393SMark Brown {
1031083c393SMark Brown 	if (rdev->constraints && rdev->constraints->name)
1041083c393SMark Brown 		return rdev->constraints->name;
1051083c393SMark Brown 	else if (rdev->desc->name)
1061083c393SMark Brown 		return rdev->desc->name;
1071083c393SMark Brown 	else
1081083c393SMark Brown 		return "";
1091083c393SMark Brown }
110157d2230SMatti Vaittinen EXPORT_SYMBOL_GPL(rdev_get_name);
1111083c393SMark Brown 
have_full_constraints(void)11287b28417SMark Brown static bool have_full_constraints(void)
11387b28417SMark Brown {
11475bc9641SMark Brown 	return has_full_constraints || of_have_populated_dt();
11587b28417SMark Brown }
11687b28417SMark Brown 
regulator_ops_is_valid(struct regulator_dev * rdev,int ops)1178a34e979SWEN Pingbo static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops)
1188a34e979SWEN Pingbo {
1198a34e979SWEN Pingbo 	if (!rdev->constraints) {
1208a34e979SWEN Pingbo 		rdev_err(rdev, "no constraints\n");
1218a34e979SWEN Pingbo 		return false;
1228a34e979SWEN Pingbo 	}
1238a34e979SWEN Pingbo 
1248a34e979SWEN Pingbo 	if (rdev->constraints->valid_ops_mask & ops)
1258a34e979SWEN Pingbo 		return true;
1268a34e979SWEN Pingbo 
1278a34e979SWEN Pingbo 	return false;
1288a34e979SWEN Pingbo }
1298a34e979SWEN Pingbo 
13069511a45SRajendra Nayak /**
13166cf9a7eSMaciej Purski  * regulator_lock_nested - lock a single regulator
13266cf9a7eSMaciej Purski  * @rdev:		regulator source
133f8702f9eSDmitry Osipenko  * @ww_ctx:		w/w mutex acquire context
13466cf9a7eSMaciej Purski  *
13566cf9a7eSMaciej Purski  * This function can be called many times by one task on
13666cf9a7eSMaciej Purski  * a single regulator and its mutex will be locked only
13766cf9a7eSMaciej Purski  * once. If a task, which is calling this function is other
13866cf9a7eSMaciej Purski  * than the one, which initially locked the mutex, it will
13966cf9a7eSMaciej Purski  * wait on mutex.
14066cf9a7eSMaciej Purski  */
regulator_lock_nested(struct regulator_dev * rdev,struct ww_acquire_ctx * ww_ctx)141f8702f9eSDmitry Osipenko static inline int regulator_lock_nested(struct regulator_dev *rdev,
142f8702f9eSDmitry Osipenko 					struct ww_acquire_ctx *ww_ctx)
14366cf9a7eSMaciej Purski {
144f8702f9eSDmitry Osipenko 	bool lock = false;
145f8702f9eSDmitry Osipenko 	int ret = 0;
146f8702f9eSDmitry Osipenko 
147f8702f9eSDmitry Osipenko 	mutex_lock(&regulator_nesting_mutex);
148f8702f9eSDmitry Osipenko 
14912235da8SMaarten Lankhorst 	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
150f8702f9eSDmitry Osipenko 		if (rdev->mutex_owner == current)
15166cf9a7eSMaciej Purski 			rdev->ref_cnt++;
152f8702f9eSDmitry Osipenko 		else
153f8702f9eSDmitry Osipenko 			lock = true;
154f8702f9eSDmitry Osipenko 
155f8702f9eSDmitry Osipenko 		if (lock) {
156f8702f9eSDmitry Osipenko 			mutex_unlock(&regulator_nesting_mutex);
157f8702f9eSDmitry Osipenko 			ret = ww_mutex_lock(&rdev->mutex, ww_ctx);
158f8702f9eSDmitry Osipenko 			mutex_lock(&regulator_nesting_mutex);
15966cf9a7eSMaciej Purski 		}
160f8702f9eSDmitry Osipenko 	} else {
161f8702f9eSDmitry Osipenko 		lock = true;
16266cf9a7eSMaciej Purski 	}
16366cf9a7eSMaciej Purski 
164f8702f9eSDmitry Osipenko 	if (lock && ret != -EDEADLK) {
165f8702f9eSDmitry Osipenko 		rdev->ref_cnt++;
16666cf9a7eSMaciej Purski 		rdev->mutex_owner = current;
16766cf9a7eSMaciej Purski 	}
16866cf9a7eSMaciej Purski 
169f8702f9eSDmitry Osipenko 	mutex_unlock(&regulator_nesting_mutex);
170f8702f9eSDmitry Osipenko 
171f8702f9eSDmitry Osipenko 	return ret;
172f8702f9eSDmitry Osipenko }
173f8702f9eSDmitry Osipenko 
174f8702f9eSDmitry Osipenko /**
175f8702f9eSDmitry Osipenko  * regulator_lock - lock a single regulator
176f8702f9eSDmitry Osipenko  * @rdev:		regulator source
177f8702f9eSDmitry Osipenko  *
178f8702f9eSDmitry Osipenko  * This function can be called many times by one task on
179f8702f9eSDmitry Osipenko  * a single regulator and its mutex will be locked only
180f8702f9eSDmitry Osipenko  * once. If a task, which is calling this function is other
181f8702f9eSDmitry Osipenko  * than the one, which initially locked the mutex, it will
182f8702f9eSDmitry Osipenko  * wait on mutex.
183f8702f9eSDmitry Osipenko  */
regulator_lock(struct regulator_dev * rdev)1844c9db393SMichał Mirosław static void regulator_lock(struct regulator_dev *rdev)
18566cf9a7eSMaciej Purski {
186f8702f9eSDmitry Osipenko 	regulator_lock_nested(rdev, NULL);
18766cf9a7eSMaciej Purski }
18866cf9a7eSMaciej Purski 
18966cf9a7eSMaciej Purski /**
19066cf9a7eSMaciej Purski  * regulator_unlock - unlock a single regulator
19166cf9a7eSMaciej Purski  * @rdev:		regulator_source
19266cf9a7eSMaciej Purski  *
19366cf9a7eSMaciej Purski  * This function unlocks the mutex when the
19466cf9a7eSMaciej Purski  * reference counter reaches 0.
19566cf9a7eSMaciej Purski  */
regulator_unlock(struct regulator_dev * rdev)1964c9db393SMichał Mirosław static void regulator_unlock(struct regulator_dev *rdev)
19766cf9a7eSMaciej Purski {
198f8702f9eSDmitry Osipenko 	mutex_lock(&regulator_nesting_mutex);
19966cf9a7eSMaciej Purski 
200f8702f9eSDmitry Osipenko 	if (--rdev->ref_cnt == 0) {
20166cf9a7eSMaciej Purski 		rdev->mutex_owner = NULL;
202f8702f9eSDmitry Osipenko 		ww_mutex_unlock(&rdev->mutex);
20366cf9a7eSMaciej Purski 	}
20466cf9a7eSMaciej Purski 
205f8702f9eSDmitry Osipenko 	WARN_ON_ONCE(rdev->ref_cnt < 0);
206f8702f9eSDmitry Osipenko 
207f8702f9eSDmitry Osipenko 	mutex_unlock(&regulator_nesting_mutex);
208f8702f9eSDmitry Osipenko }
209f8702f9eSDmitry Osipenko 
210cba6cfdcSDouglas Anderson /**
211cba6cfdcSDouglas Anderson  * regulator_lock_two - lock two regulators
212cba6cfdcSDouglas Anderson  * @rdev1:		first regulator
213cba6cfdcSDouglas Anderson  * @rdev2:		second regulator
214cba6cfdcSDouglas Anderson  * @ww_ctx:		w/w mutex acquire context
215cba6cfdcSDouglas Anderson  *
216cba6cfdcSDouglas Anderson  * Locks both rdevs using the regulator_ww_class.
217cba6cfdcSDouglas Anderson  */
regulator_lock_two(struct regulator_dev * rdev1,struct regulator_dev * rdev2,struct ww_acquire_ctx * ww_ctx)218cba6cfdcSDouglas Anderson static void regulator_lock_two(struct regulator_dev *rdev1,
219cba6cfdcSDouglas Anderson 			       struct regulator_dev *rdev2,
220cba6cfdcSDouglas Anderson 			       struct ww_acquire_ctx *ww_ctx)
221cba6cfdcSDouglas Anderson {
22237473397SDouglas Anderson 	struct regulator_dev *held, *contended;
223cba6cfdcSDouglas Anderson 	int ret;
224cba6cfdcSDouglas Anderson 
225cba6cfdcSDouglas Anderson 	ww_acquire_init(ww_ctx, &regulator_ww_class);
226cba6cfdcSDouglas Anderson 
227cba6cfdcSDouglas Anderson 	/* Try to just grab both of them */
228cba6cfdcSDouglas Anderson 	ret = regulator_lock_nested(rdev1, ww_ctx);
229cba6cfdcSDouglas Anderson 	WARN_ON(ret);
230cba6cfdcSDouglas Anderson 	ret = regulator_lock_nested(rdev2, ww_ctx);
231cba6cfdcSDouglas Anderson 	if (ret != -EDEADLOCK) {
232cba6cfdcSDouglas Anderson 		WARN_ON(ret);
233cba6cfdcSDouglas Anderson 		goto exit;
234cba6cfdcSDouglas Anderson 	}
235cba6cfdcSDouglas Anderson 
23637473397SDouglas Anderson 	held = rdev1;
23737473397SDouglas Anderson 	contended = rdev2;
238cba6cfdcSDouglas Anderson 	while (true) {
23937473397SDouglas Anderson 		regulator_unlock(held);
240cba6cfdcSDouglas Anderson 
24137473397SDouglas Anderson 		ww_mutex_lock_slow(&contended->mutex, ww_ctx);
24237473397SDouglas Anderson 		contended->ref_cnt++;
24337473397SDouglas Anderson 		contended->mutex_owner = current;
24437473397SDouglas Anderson 		swap(held, contended);
24537473397SDouglas Anderson 		ret = regulator_lock_nested(contended, ww_ctx);
246cba6cfdcSDouglas Anderson 
24737473397SDouglas Anderson 		if (ret != -EDEADLOCK) {
248cba6cfdcSDouglas Anderson 			WARN_ON(ret);
249cba6cfdcSDouglas Anderson 			break;
250cba6cfdcSDouglas Anderson 		}
251cba6cfdcSDouglas Anderson 	}
252cba6cfdcSDouglas Anderson 
253cba6cfdcSDouglas Anderson exit:
254cba6cfdcSDouglas Anderson 	ww_acquire_done(ww_ctx);
255cba6cfdcSDouglas Anderson }
256cba6cfdcSDouglas Anderson 
257cba6cfdcSDouglas Anderson /**
258cba6cfdcSDouglas Anderson  * regulator_unlock_two - unlock two regulators
259cba6cfdcSDouglas Anderson  * @rdev1:		first regulator
260cba6cfdcSDouglas Anderson  * @rdev2:		second regulator
261cba6cfdcSDouglas Anderson  * @ww_ctx:		w/w mutex acquire context
262cba6cfdcSDouglas Anderson  *
263cba6cfdcSDouglas Anderson  * The inverse of regulator_lock_two().
264cba6cfdcSDouglas Anderson  */
265cba6cfdcSDouglas Anderson 
regulator_unlock_two(struct regulator_dev * rdev1,struct regulator_dev * rdev2,struct ww_acquire_ctx * ww_ctx)266cba6cfdcSDouglas Anderson static void regulator_unlock_two(struct regulator_dev *rdev1,
267cba6cfdcSDouglas Anderson 				 struct regulator_dev *rdev2,
268cba6cfdcSDouglas Anderson 				 struct ww_acquire_ctx *ww_ctx)
269cba6cfdcSDouglas Anderson {
270cba6cfdcSDouglas Anderson 	regulator_unlock(rdev2);
271cba6cfdcSDouglas Anderson 	regulator_unlock(rdev1);
272cba6cfdcSDouglas Anderson 	ww_acquire_fini(ww_ctx);
273cba6cfdcSDouglas Anderson }
274cba6cfdcSDouglas Anderson 
regulator_supply_is_couple(struct regulator_dev * rdev)275089e2cc2SDmitry Osipenko static bool regulator_supply_is_couple(struct regulator_dev *rdev)
2769f01cd4aSSascha Hauer {
277089e2cc2SDmitry Osipenko 	struct regulator_dev *c_rdev;
278fa731ac7SArnd Bergmann 	int i;
2799f01cd4aSSascha Hauer 
280089e2cc2SDmitry Osipenko 	for (i = 1; i < rdev->coupling_desc.n_coupled; i++) {
281089e2cc2SDmitry Osipenko 		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
282089e2cc2SDmitry Osipenko 
283089e2cc2SDmitry Osipenko 		if (rdev->supply->rdev == c_rdev)
284089e2cc2SDmitry Osipenko 			return true;
285089e2cc2SDmitry Osipenko 	}
286089e2cc2SDmitry Osipenko 
287089e2cc2SDmitry Osipenko 	return false;
288089e2cc2SDmitry Osipenko }
289089e2cc2SDmitry Osipenko 
regulator_unlock_recursive(struct regulator_dev * rdev,unsigned int n_coupled)290f8702f9eSDmitry Osipenko static void regulator_unlock_recursive(struct regulator_dev *rdev,
291f8702f9eSDmitry Osipenko 				       unsigned int n_coupled)
292f8702f9eSDmitry Osipenko {
2930a7416f9SDmitry Osipenko 	struct regulator_dev *c_rdev, *supply_rdev;
2940a7416f9SDmitry Osipenko 	int i, supply_n_coupled;
295f8702f9eSDmitry Osipenko 
296f8702f9eSDmitry Osipenko 	for (i = n_coupled; i > 0; i--) {
297f8702f9eSDmitry Osipenko 		c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
298f8702f9eSDmitry Osipenko 
299f8702f9eSDmitry Osipenko 		if (!c_rdev)
300f8702f9eSDmitry Osipenko 			continue;
301f8702f9eSDmitry Osipenko 
3020a7416f9SDmitry Osipenko 		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
3030a7416f9SDmitry Osipenko 			supply_rdev = c_rdev->supply->rdev;
3040a7416f9SDmitry Osipenko 			supply_n_coupled = supply_rdev->coupling_desc.n_coupled;
3050a7416f9SDmitry Osipenko 
3060a7416f9SDmitry Osipenko 			regulator_unlock_recursive(supply_rdev,
3070a7416f9SDmitry Osipenko 						   supply_n_coupled);
3080a7416f9SDmitry Osipenko 		}
309f8702f9eSDmitry Osipenko 
310f8702f9eSDmitry Osipenko 		regulator_unlock(c_rdev);
311414c70cbSLiam Girdwood 	}
312414c70cbSLiam Girdwood }
313414c70cbSLiam Girdwood 
regulator_lock_recursive(struct regulator_dev * rdev,struct regulator_dev ** new_contended_rdev,struct regulator_dev ** old_contended_rdev,struct ww_acquire_ctx * ww_ctx)3149243a195SMaciej Purski static int regulator_lock_recursive(struct regulator_dev *rdev,
315f8702f9eSDmitry Osipenko 				    struct regulator_dev **new_contended_rdev,
316f8702f9eSDmitry Osipenko 				    struct regulator_dev **old_contended_rdev,
317f8702f9eSDmitry Osipenko 				    struct ww_acquire_ctx *ww_ctx)
3189f01cd4aSSascha Hauer {
3199243a195SMaciej Purski 	struct regulator_dev *c_rdev;
320f8702f9eSDmitry Osipenko 	int i, err;
3219f01cd4aSSascha Hauer 
3229243a195SMaciej Purski 	for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
3239243a195SMaciej Purski 		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
3249243a195SMaciej Purski 
3259243a195SMaciej Purski 		if (!c_rdev)
3269243a195SMaciej Purski 			continue;
3279243a195SMaciej Purski 
328f8702f9eSDmitry Osipenko 		if (c_rdev != *old_contended_rdev) {
329f8702f9eSDmitry Osipenko 			err = regulator_lock_nested(c_rdev, ww_ctx);
330f8702f9eSDmitry Osipenko 			if (err) {
331f8702f9eSDmitry Osipenko 				if (err == -EDEADLK) {
332f8702f9eSDmitry Osipenko 					*new_contended_rdev = c_rdev;
333f8702f9eSDmitry Osipenko 					goto err_unlock;
3349243a195SMaciej Purski 				}
3359243a195SMaciej Purski 
336f8702f9eSDmitry Osipenko 				/* shouldn't happen */
337f8702f9eSDmitry Osipenko 				WARN_ON_ONCE(err != -EALREADY);
338f8702f9eSDmitry Osipenko 			}
339f8702f9eSDmitry Osipenko 		} else {
340f8702f9eSDmitry Osipenko 			*old_contended_rdev = NULL;
341f8702f9eSDmitry Osipenko 		}
342f8702f9eSDmitry Osipenko 
343089e2cc2SDmitry Osipenko 		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
344f8702f9eSDmitry Osipenko 			err = regulator_lock_recursive(c_rdev->supply->rdev,
345f8702f9eSDmitry Osipenko 						       new_contended_rdev,
346f8702f9eSDmitry Osipenko 						       old_contended_rdev,
347f8702f9eSDmitry Osipenko 						       ww_ctx);
348f8702f9eSDmitry Osipenko 			if (err) {
349f8702f9eSDmitry Osipenko 				regulator_unlock(c_rdev);
350f8702f9eSDmitry Osipenko 				goto err_unlock;
351f8702f9eSDmitry Osipenko 			}
352f8702f9eSDmitry Osipenko 		}
353f8702f9eSDmitry Osipenko 	}
354f8702f9eSDmitry Osipenko 
355f8702f9eSDmitry Osipenko 	return 0;
356f8702f9eSDmitry Osipenko 
357f8702f9eSDmitry Osipenko err_unlock:
358f8702f9eSDmitry Osipenko 	regulator_unlock_recursive(rdev, i);
359f8702f9eSDmitry Osipenko 
360f8702f9eSDmitry Osipenko 	return err;
3619f01cd4aSSascha Hauer }
3629f01cd4aSSascha Hauer 
3639f01cd4aSSascha Hauer /**
3649243a195SMaciej Purski  * regulator_unlock_dependent - unlock regulator's suppliers and coupled
3659243a195SMaciej Purski  *				regulators
3669f01cd4aSSascha Hauer  * @rdev:			regulator source
367f8702f9eSDmitry Osipenko  * @ww_ctx:			w/w mutex acquire context
3689243a195SMaciej Purski  *
36948f1b4efSKrzysztof Kozlowski  * Unlock all regulators related with rdev by coupling or supplying.
3709f01cd4aSSascha Hauer  */
regulator_unlock_dependent(struct regulator_dev * rdev,struct ww_acquire_ctx * ww_ctx)371f8702f9eSDmitry Osipenko static void regulator_unlock_dependent(struct regulator_dev *rdev,
372f8702f9eSDmitry Osipenko 				       struct ww_acquire_ctx *ww_ctx)
3739f01cd4aSSascha Hauer {
374f8702f9eSDmitry Osipenko 	regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled);
375f8702f9eSDmitry Osipenko 	ww_acquire_fini(ww_ctx);
3769f01cd4aSSascha Hauer }
3779f01cd4aSSascha Hauer 
3789f01cd4aSSascha Hauer /**
3799243a195SMaciej Purski  * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
3809243a195SMaciej Purski  * @rdev:			regulator source
381f8702f9eSDmitry Osipenko  * @ww_ctx:			w/w mutex acquire context
3829243a195SMaciej Purski  *
3839243a195SMaciej Purski  * This function as a wrapper on regulator_lock_recursive(), which locks
38448f1b4efSKrzysztof Kozlowski  * all regulators related with rdev by coupling or supplying.
3859243a195SMaciej Purski  */
regulator_lock_dependent(struct regulator_dev * rdev,struct ww_acquire_ctx * ww_ctx)386f8702f9eSDmitry Osipenko static void regulator_lock_dependent(struct regulator_dev *rdev,
387f8702f9eSDmitry Osipenko 				     struct ww_acquire_ctx *ww_ctx)
3889243a195SMaciej Purski {
389f8702f9eSDmitry Osipenko 	struct regulator_dev *new_contended_rdev = NULL;
390f8702f9eSDmitry Osipenko 	struct regulator_dev *old_contended_rdev = NULL;
391f8702f9eSDmitry Osipenko 	int err;
392f8702f9eSDmitry Osipenko 
393f8702f9eSDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
394f8702f9eSDmitry Osipenko 
395f8702f9eSDmitry Osipenko 	ww_acquire_init(ww_ctx, &regulator_ww_class);
396f8702f9eSDmitry Osipenko 
397f8702f9eSDmitry Osipenko 	do {
398f8702f9eSDmitry Osipenko 		if (new_contended_rdev) {
399f8702f9eSDmitry Osipenko 			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
400f8702f9eSDmitry Osipenko 			old_contended_rdev = new_contended_rdev;
401f8702f9eSDmitry Osipenko 			old_contended_rdev->ref_cnt++;
402b83a1772SDouglas Anderson 			old_contended_rdev->mutex_owner = current;
403f8702f9eSDmitry Osipenko 		}
404f8702f9eSDmitry Osipenko 
405f8702f9eSDmitry Osipenko 		err = regulator_lock_recursive(rdev,
406f8702f9eSDmitry Osipenko 					       &new_contended_rdev,
407f8702f9eSDmitry Osipenko 					       &old_contended_rdev,
408f8702f9eSDmitry Osipenko 					       ww_ctx);
409f8702f9eSDmitry Osipenko 
410f8702f9eSDmitry Osipenko 		if (old_contended_rdev)
411f8702f9eSDmitry Osipenko 			regulator_unlock(old_contended_rdev);
412f8702f9eSDmitry Osipenko 
413f8702f9eSDmitry Osipenko 	} while (err == -EDEADLK);
414f8702f9eSDmitry Osipenko 
415f8702f9eSDmitry Osipenko 	ww_acquire_done(ww_ctx);
416f8702f9eSDmitry Osipenko 
417f8702f9eSDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
418414c70cbSLiam Girdwood }
419414c70cbSLiam Girdwood 
420414c70cbSLiam Girdwood /**
421fe06051dSzoro  * of_get_child_regulator - get a child regulator device node
422fe06051dSzoro  * based on supply name
423fe06051dSzoro  * @parent: Parent device node
424fe06051dSzoro  * @prop_name: Combination regulator supply name and "-supply"
425fe06051dSzoro  *
426fe06051dSzoro  * Traverse all child nodes.
427fe06051dSzoro  * Extract the child regulator device node corresponding to the supply name.
428fe06051dSzoro  * returns the device node corresponding to the regulator if found, else
429fe06051dSzoro  * returns NULL.
430fe06051dSzoro  */
of_get_child_regulator(struct device_node * parent,const char * prop_name)431fe06051dSzoro static struct device_node *of_get_child_regulator(struct device_node *parent,
432fe06051dSzoro 						  const char *prop_name)
433fe06051dSzoro {
434fe06051dSzoro 	struct device_node *regnode = NULL;
435fe06051dSzoro 	struct device_node *child = NULL;
436fe06051dSzoro 
437fe06051dSzoro 	for_each_child_of_node(parent, child) {
438fe06051dSzoro 		regnode = of_parse_phandle(child, prop_name, 0);
439fe06051dSzoro 
440fe06051dSzoro 		if (!regnode) {
441fe06051dSzoro 			regnode = of_get_child_regulator(child, prop_name);
44281eeb0a3SNishka Dasgupta 			if (regnode)
44381eeb0a3SNishka Dasgupta 				goto err_node_put;
444fe06051dSzoro 		} else {
44581eeb0a3SNishka Dasgupta 			goto err_node_put;
446fe06051dSzoro 		}
447fe06051dSzoro 	}
448fe06051dSzoro 	return NULL;
44981eeb0a3SNishka Dasgupta 
45081eeb0a3SNishka Dasgupta err_node_put:
45181eeb0a3SNishka Dasgupta 	of_node_put(child);
45281eeb0a3SNishka Dasgupta 	return regnode;
453fe06051dSzoro }
454fe06051dSzoro 
455fe06051dSzoro /**
45669511a45SRajendra Nayak  * of_get_regulator - get a regulator device node based on supply name
45769511a45SRajendra Nayak  * @dev: Device pointer for the consumer (of regulator) device
45869511a45SRajendra Nayak  * @supply: regulator supply name
45969511a45SRajendra Nayak  *
46069511a45SRajendra Nayak  * Extract the regulator device node corresponding to the supply name.
461167d41dcSMaxime Ripard  * returns the device node corresponding to the regulator if found, else
46269511a45SRajendra Nayak  * returns NULL.
46369511a45SRajendra Nayak  */
of_get_regulator(struct device * dev,const char * supply)46469511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply)
46569511a45SRajendra Nayak {
46669511a45SRajendra Nayak 	struct device_node *regnode = NULL;
467e9bb4a06SAngeloGioacchino Del Regno 	char prop_name[64]; /* 64 is max size of property name */
46869511a45SRajendra Nayak 
46969511a45SRajendra Nayak 	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
47069511a45SRajendra Nayak 
471e9bb4a06SAngeloGioacchino Del Regno 	snprintf(prop_name, 64, "%s-supply", supply);
47269511a45SRajendra Nayak 	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
47369511a45SRajendra Nayak 
47469511a45SRajendra Nayak 	if (!regnode) {
475fe06051dSzoro 		regnode = of_get_child_regulator(dev->of_node, prop_name);
476fe06051dSzoro 		if (regnode)
477fe06051dSzoro 			return regnode;
478fe06051dSzoro 
4797799167bSRob Herring 		dev_dbg(dev, "Looking up %s property in node %pOF failed\n",
4807799167bSRob Herring 				prop_name, dev->of_node);
48169511a45SRajendra Nayak 		return NULL;
48269511a45SRajendra Nayak 	}
48369511a45SRajendra Nayak 	return regnode;
48469511a45SRajendra Nayak }
48569511a45SRajendra Nayak 
486414c70cbSLiam Girdwood /* Platform voltage constraint check */
regulator_check_voltage(struct regulator_dev * rdev,int * min_uV,int * max_uV)487d22b85a1SDmitry Osipenko int regulator_check_voltage(struct regulator_dev *rdev,
488414c70cbSLiam Girdwood 			    int *min_uV, int *max_uV)
489414c70cbSLiam Girdwood {
490414c70cbSLiam Girdwood 	BUG_ON(*min_uV > *max_uV);
491414c70cbSLiam Girdwood 
4928a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
4937ebcf26cSStephen Boyd 		rdev_err(rdev, "voltage operation not allowed\n");
494414c70cbSLiam Girdwood 		return -EPERM;
495414c70cbSLiam Girdwood 	}
496414c70cbSLiam Girdwood 
497414c70cbSLiam Girdwood 	if (*max_uV > rdev->constraints->max_uV)
498414c70cbSLiam Girdwood 		*max_uV = rdev->constraints->max_uV;
499414c70cbSLiam Girdwood 	if (*min_uV < rdev->constraints->min_uV)
500414c70cbSLiam Girdwood 		*min_uV = rdev->constraints->min_uV;
501414c70cbSLiam Girdwood 
50289f425edSMark Brown 	if (*min_uV > *max_uV) {
50389f425edSMark Brown 		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
50454abd335SMark Brown 			 *min_uV, *max_uV);
505414c70cbSLiam Girdwood 		return -EINVAL;
50689f425edSMark Brown 	}
507414c70cbSLiam Girdwood 
508414c70cbSLiam Girdwood 	return 0;
509414c70cbSLiam Girdwood }
510414c70cbSLiam Girdwood 
511f7efad10SChunyan Zhang /* return 0 if the state is valid */
regulator_check_states(suspend_state_t state)512f7efad10SChunyan Zhang static int regulator_check_states(suspend_state_t state)
513f7efad10SChunyan Zhang {
514f7efad10SChunyan Zhang 	return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE);
515f7efad10SChunyan Zhang }
516f7efad10SChunyan Zhang 
51705fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all
51805fda3b1SThomas Petazzoni  * regulator consumers
51905fda3b1SThomas Petazzoni  */
regulator_check_consumers(struct regulator_dev * rdev,int * min_uV,int * max_uV,suspend_state_t state)520d22b85a1SDmitry Osipenko int regulator_check_consumers(struct regulator_dev *rdev,
521c360a6dfSChunyan Zhang 			      int *min_uV, int *max_uV,
522c360a6dfSChunyan Zhang 			      suspend_state_t state)
52305fda3b1SThomas Petazzoni {
52405fda3b1SThomas Petazzoni 	struct regulator *regulator;
525c360a6dfSChunyan Zhang 	struct regulator_voltage *voltage;
52605fda3b1SThomas Petazzoni 
52705fda3b1SThomas Petazzoni 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
528c360a6dfSChunyan Zhang 		voltage = &regulator->voltage[state];
5294aa922c0SMark Brown 		/*
5304aa922c0SMark Brown 		 * Assume consumers that didn't say anything are OK
5314aa922c0SMark Brown 		 * with anything in the constraint range.
5324aa922c0SMark Brown 		 */
533c360a6dfSChunyan Zhang 		if (!voltage->min_uV && !voltage->max_uV)
5344aa922c0SMark Brown 			continue;
5354aa922c0SMark Brown 
536c360a6dfSChunyan Zhang 		if (*max_uV > voltage->max_uV)
537c360a6dfSChunyan Zhang 			*max_uV = voltage->max_uV;
538c360a6dfSChunyan Zhang 		if (*min_uV < voltage->min_uV)
539c360a6dfSChunyan Zhang 			*min_uV = voltage->min_uV;
54005fda3b1SThomas Petazzoni 	}
54105fda3b1SThomas Petazzoni 
542dd8004afSMark Brown 	if (*min_uV > *max_uV) {
5439c7b4e8aSRuss Dill 		rdev_err(rdev, "Restricting voltage, %u-%uuV\n",
5449c7b4e8aSRuss Dill 			*min_uV, *max_uV);
54505fda3b1SThomas Petazzoni 		return -EINVAL;
546dd8004afSMark Brown 	}
54705fda3b1SThomas Petazzoni 
54805fda3b1SThomas Petazzoni 	return 0;
54905fda3b1SThomas Petazzoni }
55005fda3b1SThomas Petazzoni 
551414c70cbSLiam Girdwood /* current constraint check */
regulator_check_current_limit(struct regulator_dev * rdev,int * min_uA,int * max_uA)552414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev,
553414c70cbSLiam Girdwood 					int *min_uA, int *max_uA)
554414c70cbSLiam Girdwood {
555414c70cbSLiam Girdwood 	BUG_ON(*min_uA > *max_uA);
556414c70cbSLiam Girdwood 
5578a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) {
5587ebcf26cSStephen Boyd 		rdev_err(rdev, "current operation not allowed\n");
559414c70cbSLiam Girdwood 		return -EPERM;
560414c70cbSLiam Girdwood 	}
561414c70cbSLiam Girdwood 
562414c70cbSLiam Girdwood 	if (*max_uA > rdev->constraints->max_uA)
563414c70cbSLiam Girdwood 		*max_uA = rdev->constraints->max_uA;
564414c70cbSLiam Girdwood 	if (*min_uA < rdev->constraints->min_uA)
565414c70cbSLiam Girdwood 		*min_uA = rdev->constraints->min_uA;
566414c70cbSLiam Girdwood 
56789f425edSMark Brown 	if (*min_uA > *max_uA) {
56889f425edSMark Brown 		rdev_err(rdev, "unsupportable current range: %d-%duA\n",
56954abd335SMark Brown 			 *min_uA, *max_uA);
570414c70cbSLiam Girdwood 		return -EINVAL;
57189f425edSMark Brown 	}
572414c70cbSLiam Girdwood 
573414c70cbSLiam Girdwood 	return 0;
574414c70cbSLiam Girdwood }
575414c70cbSLiam Girdwood 
576414c70cbSLiam Girdwood /* operating mode constraint check */
regulator_mode_constrain(struct regulator_dev * rdev,unsigned int * mode)577109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev,
578109c75afSCharles Keepax 				    unsigned int *mode)
579414c70cbSLiam Girdwood {
5802c608234SMark Brown 	switch (*mode) {
581e573520bSDavid Brownell 	case REGULATOR_MODE_FAST:
582e573520bSDavid Brownell 	case REGULATOR_MODE_NORMAL:
583e573520bSDavid Brownell 	case REGULATOR_MODE_IDLE:
584e573520bSDavid Brownell 	case REGULATOR_MODE_STANDBY:
585e573520bSDavid Brownell 		break;
586e573520bSDavid Brownell 	default:
58789f425edSMark Brown 		rdev_err(rdev, "invalid mode %x specified\n", *mode);
588e573520bSDavid Brownell 		return -EINVAL;
589e573520bSDavid Brownell 	}
590e573520bSDavid Brownell 
5918a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) {
5927ebcf26cSStephen Boyd 		rdev_err(rdev, "mode operation not allowed\n");
593414c70cbSLiam Girdwood 		return -EPERM;
594414c70cbSLiam Girdwood 	}
5952c608234SMark Brown 
5962c608234SMark Brown 	/* The modes are bitmasks, the most power hungry modes having
5972c608234SMark Brown 	 * the lowest values. If the requested mode isn't supported
59869b8821eSShubhankar Kuranagatti 	 * try higher modes.
59969b8821eSShubhankar Kuranagatti 	 */
6002c608234SMark Brown 	while (*mode) {
6012c608234SMark Brown 		if (rdev->constraints->valid_modes_mask & *mode)
602414c70cbSLiam Girdwood 			return 0;
6032c608234SMark Brown 		*mode /= 2;
6042c608234SMark Brown 	}
6052c608234SMark Brown 
6062c608234SMark Brown 	return -EINVAL;
607414c70cbSLiam Girdwood }
608414c70cbSLiam Girdwood 
609f7efad10SChunyan Zhang static inline struct regulator_state *
regulator_get_suspend_state(struct regulator_dev * rdev,suspend_state_t state)610f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state)
611f7efad10SChunyan Zhang {
612f7efad10SChunyan Zhang 	if (rdev->constraints == NULL)
613f7efad10SChunyan Zhang 		return NULL;
614f7efad10SChunyan Zhang 
615f7efad10SChunyan Zhang 	switch (state) {
616f7efad10SChunyan Zhang 	case PM_SUSPEND_STANDBY:
617f7efad10SChunyan Zhang 		return &rdev->constraints->state_standby;
618f7efad10SChunyan Zhang 	case PM_SUSPEND_MEM:
619f7efad10SChunyan Zhang 		return &rdev->constraints->state_mem;
620f7efad10SChunyan Zhang 	case PM_SUSPEND_MAX:
621f7efad10SChunyan Zhang 		return &rdev->constraints->state_disk;
622f7efad10SChunyan Zhang 	default:
623f7efad10SChunyan Zhang 		return NULL;
624f7efad10SChunyan Zhang 	}
625f7efad10SChunyan Zhang }
626f7efad10SChunyan Zhang 
6270955f5beSStephen Boyd static const struct regulator_state *
regulator_get_suspend_state_check(struct regulator_dev * rdev,suspend_state_t state)6280955f5beSStephen Boyd regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state)
6290955f5beSStephen Boyd {
6300955f5beSStephen Boyd 	const struct regulator_state *rstate;
6310955f5beSStephen Boyd 
6320955f5beSStephen Boyd 	rstate = regulator_get_suspend_state(rdev, state);
6330955f5beSStephen Boyd 	if (rstate == NULL)
6340955f5beSStephen Boyd 		return NULL;
6350955f5beSStephen Boyd 
6360955f5beSStephen Boyd 	/* If we have no suspend mode configuration don't set anything;
6370955f5beSStephen Boyd 	 * only warn if the driver implements set_suspend_voltage or
6380955f5beSStephen Boyd 	 * set_suspend_mode callback.
6390955f5beSStephen Boyd 	 */
6400955f5beSStephen Boyd 	if (rstate->enabled != ENABLE_IN_SUSPEND &&
6410955f5beSStephen Boyd 	    rstate->enabled != DISABLE_IN_SUSPEND) {
6420955f5beSStephen Boyd 		if (rdev->desc->ops->set_suspend_voltage ||
6430955f5beSStephen Boyd 		    rdev->desc->ops->set_suspend_mode)
6440955f5beSStephen Boyd 			rdev_warn(rdev, "No configuration\n");
6450955f5beSStephen Boyd 		return NULL;
6460955f5beSStephen Boyd 	}
6470955f5beSStephen Boyd 
6480955f5beSStephen Boyd 	return rstate;
6490955f5beSStephen Boyd }
6500955f5beSStephen Boyd 
microvolts_show(struct device * dev,struct device_attribute * attr,char * buf)651a277a262SYueHaibing static ssize_t microvolts_show(struct device *dev,
652414c70cbSLiam Girdwood 			       struct device_attribute *attr, char *buf)
653414c70cbSLiam Girdwood {
654a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
655c82f27dfSH. Nikolaus Schaller 	int uV;
656414c70cbSLiam Girdwood 
65766cf9a7eSMaciej Purski 	regulator_lock(rdev);
658c82f27dfSH. Nikolaus Schaller 	uV = regulator_get_voltage_rdev(rdev);
65966cf9a7eSMaciej Purski 	regulator_unlock(rdev);
660414c70cbSLiam Girdwood 
661c82f27dfSH. Nikolaus Schaller 	if (uV < 0)
662c82f27dfSH. Nikolaus Schaller 		return uV;
663c82f27dfSH. Nikolaus Schaller 	return sprintf(buf, "%d\n", uV);
664414c70cbSLiam Girdwood }
665a277a262SYueHaibing static DEVICE_ATTR_RO(microvolts);
666414c70cbSLiam Girdwood 
microamps_show(struct device * dev,struct device_attribute * attr,char * buf)667a277a262SYueHaibing static ssize_t microamps_show(struct device *dev,
668414c70cbSLiam Girdwood 			      struct device_attribute *attr, char *buf)
669414c70cbSLiam Girdwood {
670a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
671414c70cbSLiam Girdwood 
672414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
673414c70cbSLiam Girdwood }
674a277a262SYueHaibing static DEVICE_ATTR_RO(microamps);
675414c70cbSLiam Girdwood 
name_show(struct device * dev,struct device_attribute * attr,char * buf)676587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr,
677587cea27SGreg Kroah-Hartman 			 char *buf)
678bc558a60SMark Brown {
679bc558a60SMark Brown 	struct regulator_dev *rdev = dev_get_drvdata(dev);
680bc558a60SMark Brown 
6811083c393SMark Brown 	return sprintf(buf, "%s\n", rdev_get_name(rdev));
682bc558a60SMark Brown }
683587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name);
684bc558a60SMark Brown 
regulator_opmode_to_str(int mode)68501de19d0SDouglas Anderson static const char *regulator_opmode_to_str(int mode)
686414c70cbSLiam Girdwood {
687414c70cbSLiam Girdwood 	switch (mode) {
688414c70cbSLiam Girdwood 	case REGULATOR_MODE_FAST:
68901de19d0SDouglas Anderson 		return "fast";
690414c70cbSLiam Girdwood 	case REGULATOR_MODE_NORMAL:
69101de19d0SDouglas Anderson 		return "normal";
692414c70cbSLiam Girdwood 	case REGULATOR_MODE_IDLE:
69301de19d0SDouglas Anderson 		return "idle";
694414c70cbSLiam Girdwood 	case REGULATOR_MODE_STANDBY:
69501de19d0SDouglas Anderson 		return "standby";
696414c70cbSLiam Girdwood 	}
69701de19d0SDouglas Anderson 	return "unknown";
69801de19d0SDouglas Anderson }
69901de19d0SDouglas Anderson 
regulator_print_opmode(char * buf,int mode)70001de19d0SDouglas Anderson static ssize_t regulator_print_opmode(char *buf, int mode)
70101de19d0SDouglas Anderson {
70201de19d0SDouglas Anderson 	return sprintf(buf, "%s\n", regulator_opmode_to_str(mode));
703414c70cbSLiam Girdwood }
704414c70cbSLiam Girdwood 
opmode_show(struct device * dev,struct device_attribute * attr,char * buf)705a277a262SYueHaibing static ssize_t opmode_show(struct device *dev,
706414c70cbSLiam Girdwood 			   struct device_attribute *attr, char *buf)
707414c70cbSLiam Girdwood {
708a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
709414c70cbSLiam Girdwood 
7104fca9545SDavid Brownell 	return regulator_print_opmode(buf, _regulator_get_mode(rdev));
7114fca9545SDavid Brownell }
712a277a262SYueHaibing static DEVICE_ATTR_RO(opmode);
7134fca9545SDavid Brownell 
regulator_print_state(char * buf,int state)7144fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state)
7154fca9545SDavid Brownell {
716414c70cbSLiam Girdwood 	if (state > 0)
717414c70cbSLiam Girdwood 		return sprintf(buf, "enabled\n");
718414c70cbSLiam Girdwood 	else if (state == 0)
719414c70cbSLiam Girdwood 		return sprintf(buf, "disabled\n");
720414c70cbSLiam Girdwood 	else
721414c70cbSLiam Girdwood 		return sprintf(buf, "unknown\n");
722414c70cbSLiam Girdwood }
723414c70cbSLiam Girdwood 
state_show(struct device * dev,struct device_attribute * attr,char * buf)724a277a262SYueHaibing static ssize_t state_show(struct device *dev,
7254fca9545SDavid Brownell 			  struct device_attribute *attr, char *buf)
7264fca9545SDavid Brownell {
7274fca9545SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
7289332546fSMark Brown 	ssize_t ret;
7294fca9545SDavid Brownell 
73066cf9a7eSMaciej Purski 	regulator_lock(rdev);
7319332546fSMark Brown 	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
73266cf9a7eSMaciej Purski 	regulator_unlock(rdev);
7339332546fSMark Brown 
7349332546fSMark Brown 	return ret;
7354fca9545SDavid Brownell }
736a277a262SYueHaibing static DEVICE_ATTR_RO(state);
7374fca9545SDavid Brownell 
status_show(struct device * dev,struct device_attribute * attr,char * buf)738a277a262SYueHaibing static ssize_t status_show(struct device *dev,
739853116a1SDavid Brownell 			   struct device_attribute *attr, char *buf)
740853116a1SDavid Brownell {
741853116a1SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
742853116a1SDavid Brownell 	int status;
743853116a1SDavid Brownell 	char *label;
744853116a1SDavid Brownell 
745853116a1SDavid Brownell 	status = rdev->desc->ops->get_status(rdev);
746853116a1SDavid Brownell 	if (status < 0)
747853116a1SDavid Brownell 		return status;
748853116a1SDavid Brownell 
749853116a1SDavid Brownell 	switch (status) {
750853116a1SDavid Brownell 	case REGULATOR_STATUS_OFF:
751853116a1SDavid Brownell 		label = "off";
752853116a1SDavid Brownell 		break;
753853116a1SDavid Brownell 	case REGULATOR_STATUS_ON:
754853116a1SDavid Brownell 		label = "on";
755853116a1SDavid Brownell 		break;
756853116a1SDavid Brownell 	case REGULATOR_STATUS_ERROR:
757853116a1SDavid Brownell 		label = "error";
758853116a1SDavid Brownell 		break;
759853116a1SDavid Brownell 	case REGULATOR_STATUS_FAST:
760853116a1SDavid Brownell 		label = "fast";
761853116a1SDavid Brownell 		break;
762853116a1SDavid Brownell 	case REGULATOR_STATUS_NORMAL:
763853116a1SDavid Brownell 		label = "normal";
764853116a1SDavid Brownell 		break;
765853116a1SDavid Brownell 	case REGULATOR_STATUS_IDLE:
766853116a1SDavid Brownell 		label = "idle";
767853116a1SDavid Brownell 		break;
768853116a1SDavid Brownell 	case REGULATOR_STATUS_STANDBY:
769853116a1SDavid Brownell 		label = "standby";
770853116a1SDavid Brownell 		break;
771f59c8f9fSMark Brown 	case REGULATOR_STATUS_BYPASS:
772f59c8f9fSMark Brown 		label = "bypass";
773f59c8f9fSMark Brown 		break;
7741beaf762SKrystian Garbaciak 	case REGULATOR_STATUS_UNDEFINED:
7751beaf762SKrystian Garbaciak 		label = "undefined";
7761beaf762SKrystian Garbaciak 		break;
777853116a1SDavid Brownell 	default:
778853116a1SDavid Brownell 		return -ERANGE;
779853116a1SDavid Brownell 	}
780853116a1SDavid Brownell 
781853116a1SDavid Brownell 	return sprintf(buf, "%s\n", label);
782853116a1SDavid Brownell }
783a277a262SYueHaibing static DEVICE_ATTR_RO(status);
784853116a1SDavid Brownell 
min_microamps_show(struct device * dev,struct device_attribute * attr,char * buf)785a277a262SYueHaibing static ssize_t min_microamps_show(struct device *dev,
786414c70cbSLiam Girdwood 				  struct device_attribute *attr, char *buf)
787414c70cbSLiam Girdwood {
788a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
789414c70cbSLiam Girdwood 
790414c70cbSLiam Girdwood 	if (!rdev->constraints)
791414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
792414c70cbSLiam Girdwood 
793414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uA);
794414c70cbSLiam Girdwood }
795a277a262SYueHaibing static DEVICE_ATTR_RO(min_microamps);
796414c70cbSLiam Girdwood 
max_microamps_show(struct device * dev,struct device_attribute * attr,char * buf)797a277a262SYueHaibing static ssize_t max_microamps_show(struct device *dev,
798414c70cbSLiam Girdwood 				  struct device_attribute *attr, char *buf)
799414c70cbSLiam Girdwood {
800a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
801414c70cbSLiam Girdwood 
802414c70cbSLiam Girdwood 	if (!rdev->constraints)
803414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
804414c70cbSLiam Girdwood 
805414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uA);
806414c70cbSLiam Girdwood }
807a277a262SYueHaibing static DEVICE_ATTR_RO(max_microamps);
808414c70cbSLiam Girdwood 
min_microvolts_show(struct device * dev,struct device_attribute * attr,char * buf)809a277a262SYueHaibing static ssize_t min_microvolts_show(struct device *dev,
810414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
811414c70cbSLiam Girdwood {
812a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
813414c70cbSLiam Girdwood 
814414c70cbSLiam Girdwood 	if (!rdev->constraints)
815414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
816414c70cbSLiam Girdwood 
817414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uV);
818414c70cbSLiam Girdwood }
819a277a262SYueHaibing static DEVICE_ATTR_RO(min_microvolts);
820414c70cbSLiam Girdwood 
max_microvolts_show(struct device * dev,struct device_attribute * attr,char * buf)821a277a262SYueHaibing static ssize_t max_microvolts_show(struct device *dev,
822414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
823414c70cbSLiam Girdwood {
824a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
825414c70cbSLiam Girdwood 
826414c70cbSLiam Girdwood 	if (!rdev->constraints)
827414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
828414c70cbSLiam Girdwood 
829414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uV);
830414c70cbSLiam Girdwood }
831a277a262SYueHaibing static DEVICE_ATTR_RO(max_microvolts);
832414c70cbSLiam Girdwood 
requested_microamps_show(struct device * dev,struct device_attribute * attr,char * buf)833a277a262SYueHaibing static ssize_t requested_microamps_show(struct device *dev,
834414c70cbSLiam Girdwood 					struct device_attribute *attr, char *buf)
835414c70cbSLiam Girdwood {
836a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
837414c70cbSLiam Girdwood 	struct regulator *regulator;
838414c70cbSLiam Girdwood 	int uA = 0;
839414c70cbSLiam Girdwood 
84066cf9a7eSMaciej Purski 	regulator_lock(rdev);
8415451781dSDouglas Anderson 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
8425451781dSDouglas Anderson 		if (regulator->enable_count)
843414c70cbSLiam Girdwood 			uA += regulator->uA_load;
8445451781dSDouglas Anderson 	}
84566cf9a7eSMaciej Purski 	regulator_unlock(rdev);
846414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", uA);
847414c70cbSLiam Girdwood }
848a277a262SYueHaibing static DEVICE_ATTR_RO(requested_microamps);
849414c70cbSLiam Girdwood 
num_users_show(struct device * dev,struct device_attribute * attr,char * buf)850587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr,
851587cea27SGreg Kroah-Hartman 			      char *buf)
852414c70cbSLiam Girdwood {
853a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
854414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->use_count);
855414c70cbSLiam Girdwood }
856587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users);
857414c70cbSLiam Girdwood 
type_show(struct device * dev,struct device_attribute * attr,char * buf)858587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr,
859587cea27SGreg Kroah-Hartman 			 char *buf)
860414c70cbSLiam Girdwood {
861a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
862414c70cbSLiam Girdwood 
863414c70cbSLiam Girdwood 	switch (rdev->desc->type) {
864414c70cbSLiam Girdwood 	case REGULATOR_VOLTAGE:
865414c70cbSLiam Girdwood 		return sprintf(buf, "voltage\n");
866414c70cbSLiam Girdwood 	case REGULATOR_CURRENT:
867414c70cbSLiam Girdwood 		return sprintf(buf, "current\n");
868414c70cbSLiam Girdwood 	}
869414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
870414c70cbSLiam Girdwood }
871587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type);
872414c70cbSLiam Girdwood 
suspend_mem_microvolts_show(struct device * dev,struct device_attribute * attr,char * buf)873a277a262SYueHaibing static ssize_t suspend_mem_microvolts_show(struct device *dev,
874414c70cbSLiam Girdwood 					   struct device_attribute *attr, char *buf)
875414c70cbSLiam Girdwood {
876a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
877414c70cbSLiam Girdwood 
878414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
879414c70cbSLiam Girdwood }
880a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_mem_microvolts);
881414c70cbSLiam Girdwood 
suspend_disk_microvolts_show(struct device * dev,struct device_attribute * attr,char * buf)882a277a262SYueHaibing static ssize_t suspend_disk_microvolts_show(struct device *dev,
883414c70cbSLiam Girdwood 					    struct device_attribute *attr, char *buf)
884414c70cbSLiam Girdwood {
885a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
886414c70cbSLiam Girdwood 
887414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
888414c70cbSLiam Girdwood }
889a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_disk_microvolts);
890414c70cbSLiam Girdwood 
suspend_standby_microvolts_show(struct device * dev,struct device_attribute * attr,char * buf)891a277a262SYueHaibing static ssize_t suspend_standby_microvolts_show(struct device *dev,
892414c70cbSLiam Girdwood 					       struct device_attribute *attr, char *buf)
893414c70cbSLiam Girdwood {
894a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
895414c70cbSLiam Girdwood 
896414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
897414c70cbSLiam Girdwood }
898a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_standby_microvolts);
899414c70cbSLiam Girdwood 
suspend_mem_mode_show(struct device * dev,struct device_attribute * attr,char * buf)900a277a262SYueHaibing static ssize_t suspend_mem_mode_show(struct device *dev,
901414c70cbSLiam Girdwood 				     struct device_attribute *attr, char *buf)
902414c70cbSLiam Girdwood {
903a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
904414c70cbSLiam Girdwood 
9054fca9545SDavid Brownell 	return regulator_print_opmode(buf,
9064fca9545SDavid Brownell 		rdev->constraints->state_mem.mode);
907414c70cbSLiam Girdwood }
908a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_mem_mode);
909414c70cbSLiam Girdwood 
suspend_disk_mode_show(struct device * dev,struct device_attribute * attr,char * buf)910a277a262SYueHaibing static ssize_t suspend_disk_mode_show(struct device *dev,
911414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
912414c70cbSLiam Girdwood {
913a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
914414c70cbSLiam Girdwood 
9154fca9545SDavid Brownell 	return regulator_print_opmode(buf,
9164fca9545SDavid Brownell 		rdev->constraints->state_disk.mode);
917414c70cbSLiam Girdwood }
918a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_disk_mode);
919414c70cbSLiam Girdwood 
suspend_standby_mode_show(struct device * dev,struct device_attribute * attr,char * buf)920a277a262SYueHaibing static ssize_t suspend_standby_mode_show(struct device *dev,
921414c70cbSLiam Girdwood 					 struct device_attribute *attr, char *buf)
922414c70cbSLiam Girdwood {
923a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
924414c70cbSLiam Girdwood 
9254fca9545SDavid Brownell 	return regulator_print_opmode(buf,
9264fca9545SDavid Brownell 		rdev->constraints->state_standby.mode);
927414c70cbSLiam Girdwood }
928a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_standby_mode);
929414c70cbSLiam Girdwood 
suspend_mem_state_show(struct device * dev,struct device_attribute * attr,char * buf)930a277a262SYueHaibing static ssize_t suspend_mem_state_show(struct device *dev,
931414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
932414c70cbSLiam Girdwood {
933a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
934414c70cbSLiam Girdwood 
9354fca9545SDavid Brownell 	return regulator_print_state(buf,
9364fca9545SDavid Brownell 			rdev->constraints->state_mem.enabled);
937414c70cbSLiam Girdwood }
938a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_mem_state);
939414c70cbSLiam Girdwood 
suspend_disk_state_show(struct device * dev,struct device_attribute * attr,char * buf)940a277a262SYueHaibing static ssize_t suspend_disk_state_show(struct device *dev,
941414c70cbSLiam Girdwood 				       struct device_attribute *attr, char *buf)
942414c70cbSLiam Girdwood {
943a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
944414c70cbSLiam Girdwood 
9454fca9545SDavid Brownell 	return regulator_print_state(buf,
9464fca9545SDavid Brownell 			rdev->constraints->state_disk.enabled);
947414c70cbSLiam Girdwood }
948a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_disk_state);
949414c70cbSLiam Girdwood 
suspend_standby_state_show(struct device * dev,struct device_attribute * attr,char * buf)950a277a262SYueHaibing static ssize_t suspend_standby_state_show(struct device *dev,
951414c70cbSLiam Girdwood 					  struct device_attribute *attr, char *buf)
952414c70cbSLiam Girdwood {
953a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
954414c70cbSLiam Girdwood 
9554fca9545SDavid Brownell 	return regulator_print_state(buf,
9564fca9545SDavid Brownell 			rdev->constraints->state_standby.enabled);
957414c70cbSLiam Girdwood }
958a277a262SYueHaibing static DEVICE_ATTR_RO(suspend_standby_state);
959bc558a60SMark Brown 
bypass_show(struct device * dev,struct device_attribute * attr,char * buf)960a277a262SYueHaibing static ssize_t bypass_show(struct device *dev,
961f59c8f9fSMark Brown 			   struct device_attribute *attr, char *buf)
962f59c8f9fSMark Brown {
963f59c8f9fSMark Brown 	struct regulator_dev *rdev = dev_get_drvdata(dev);
964f59c8f9fSMark Brown 	const char *report;
965f59c8f9fSMark Brown 	bool bypass;
966f59c8f9fSMark Brown 	int ret;
967f59c8f9fSMark Brown 
968f59c8f9fSMark Brown 	ret = rdev->desc->ops->get_bypass(rdev, &bypass);
969f59c8f9fSMark Brown 
970f59c8f9fSMark Brown 	if (ret != 0)
971f59c8f9fSMark Brown 		report = "unknown";
972f59c8f9fSMark Brown 	else if (bypass)
973f59c8f9fSMark Brown 		report = "enabled";
974f59c8f9fSMark Brown 	else
975f59c8f9fSMark Brown 		report = "disabled";
976f59c8f9fSMark Brown 
977f59c8f9fSMark Brown 	return sprintf(buf, "%s\n", report);
978f59c8f9fSMark Brown }
979a277a262SYueHaibing static DEVICE_ATTR_RO(bypass);
9807ad68e2fSDavid Brownell 
9810f2d636eSZev Weiss #define REGULATOR_ERROR_ATTR(name, bit)							\
9820f2d636eSZev Weiss 	static ssize_t name##_show(struct device *dev, struct device_attribute *attr,	\
9830f2d636eSZev Weiss 				   char *buf)						\
9840f2d636eSZev Weiss 	{										\
9850f2d636eSZev Weiss 		int ret;								\
9860f2d636eSZev Weiss 		unsigned int flags;							\
9870f2d636eSZev Weiss 		struct regulator_dev *rdev = dev_get_drvdata(dev);			\
9880f2d636eSZev Weiss 		ret = _regulator_get_error_flags(rdev, &flags);				\
9890f2d636eSZev Weiss 		if (ret)								\
9900f2d636eSZev Weiss 			return ret;							\
9910f2d636eSZev Weiss 		return sysfs_emit(buf, "%d\n", !!(flags & (bit)));			\
9920f2d636eSZev Weiss 	}										\
9930f2d636eSZev Weiss 	static DEVICE_ATTR_RO(name)
9940f2d636eSZev Weiss 
9950f2d636eSZev Weiss REGULATOR_ERROR_ATTR(under_voltage, REGULATOR_ERROR_UNDER_VOLTAGE);
9960f2d636eSZev Weiss REGULATOR_ERROR_ATTR(over_current, REGULATOR_ERROR_OVER_CURRENT);
9970f2d636eSZev Weiss REGULATOR_ERROR_ATTR(regulation_out, REGULATOR_ERROR_REGULATION_OUT);
9980f2d636eSZev Weiss REGULATOR_ERROR_ATTR(fail, REGULATOR_ERROR_FAIL);
9990f2d636eSZev Weiss REGULATOR_ERROR_ATTR(over_temp, REGULATOR_ERROR_OVER_TEMP);
10000f2d636eSZev Weiss REGULATOR_ERROR_ATTR(under_voltage_warn, REGULATOR_ERROR_UNDER_VOLTAGE_WARN);
10010f2d636eSZev Weiss REGULATOR_ERROR_ATTR(over_current_warn, REGULATOR_ERROR_OVER_CURRENT_WARN);
10020f2d636eSZev Weiss REGULATOR_ERROR_ATTR(over_voltage_warn, REGULATOR_ERROR_OVER_VOLTAGE_WARN);
10030f2d636eSZev Weiss REGULATOR_ERROR_ATTR(over_temp_warn, REGULATOR_ERROR_OVER_TEMP_WARN);
10040f2d636eSZev Weiss 
1005414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total
100669b8821eSShubhankar Kuranagatti  * consumer load. All locks held by caller
100769b8821eSShubhankar Kuranagatti  */
drms_uA_update(struct regulator_dev * rdev)10088460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev)
1009414c70cbSLiam Girdwood {
1010414c70cbSLiam Girdwood 	struct regulator *sibling;
1011414c70cbSLiam Girdwood 	int current_uA = 0, output_uV, input_uV, err;
1012414c70cbSLiam Girdwood 	unsigned int mode;
1013414c70cbSLiam Girdwood 
10148460ef38SBjorn Andersson 	/*
10158460ef38SBjorn Andersson 	 * first check to see if we can set modes at all, otherwise just
10168460ef38SBjorn Andersson 	 * tell the consumer everything is OK.
10178460ef38SBjorn Andersson 	 */
101874a569eeSMarc Gonzalez 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) {
101974a569eeSMarc Gonzalez 		rdev_dbg(rdev, "DRMS operation not allowed\n");
10208460ef38SBjorn Andersson 		return 0;
102174a569eeSMarc Gonzalez 	}
10228460ef38SBjorn Andersson 
10238f4490e0SBjorn Andersson 	if (!rdev->desc->ops->get_optimum_mode &&
10248f4490e0SBjorn Andersson 	    !rdev->desc->ops->set_load)
10258460ef38SBjorn Andersson 		return 0;
10268460ef38SBjorn Andersson 
10278f4490e0SBjorn Andersson 	if (!rdev->desc->ops->set_mode &&
10288f4490e0SBjorn Andersson 	    !rdev->desc->ops->set_load)
10298460ef38SBjorn Andersson 		return -EINVAL;
1030414c70cbSLiam Girdwood 
103157776617SJoonwoo Park 	/* calc total requested load */
10325451781dSDouglas Anderson 	list_for_each_entry(sibling, &rdev->consumer_list, list) {
10335451781dSDouglas Anderson 		if (sibling->enable_count)
103457776617SJoonwoo Park 			current_uA += sibling->uA_load;
10355451781dSDouglas Anderson 	}
103657776617SJoonwoo Park 
103757776617SJoonwoo Park 	current_uA += rdev->constraints->system_load;
103857776617SJoonwoo Park 
103957776617SJoonwoo Park 	if (rdev->desc->ops->set_load) {
104057776617SJoonwoo Park 		/* set the optimum mode for our new total regulator load */
104157776617SJoonwoo Park 		err = rdev->desc->ops->set_load(rdev, current_uA);
104257776617SJoonwoo Park 		if (err < 0)
104361aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set load %d: %pe\n",
104461aab5adSMichał Mirosław 				 current_uA, ERR_PTR(err));
104557776617SJoonwoo Park 	} else {
104657919f4aSDouglas Anderson 		/*
104757919f4aSDouglas Anderson 		 * Unfortunately in some cases the constraints->valid_ops has
104857919f4aSDouglas Anderson 		 * REGULATOR_CHANGE_DRMS but there are no valid modes listed.
104957919f4aSDouglas Anderson 		 * That's not really legit but we won't consider it a fatal
105057919f4aSDouglas Anderson 		 * error here. We'll treat it as if REGULATOR_CHANGE_DRMS
105157919f4aSDouglas Anderson 		 * wasn't set.
105257919f4aSDouglas Anderson 		 */
105357919f4aSDouglas Anderson 		if (!rdev->constraints->valid_modes_mask) {
105457919f4aSDouglas Anderson 			rdev_dbg(rdev, "Can change modes; but no valid mode\n");
105557919f4aSDouglas Anderson 			return 0;
105657919f4aSDouglas Anderson 		}
105757919f4aSDouglas Anderson 
1058414c70cbSLiam Girdwood 		/* get output voltage */
1059d22b85a1SDmitry Osipenko 		output_uV = regulator_get_voltage_rdev(rdev);
106055841199SDouglas Anderson 
106155841199SDouglas Anderson 		/*
106255841199SDouglas Anderson 		 * Don't return an error; if regulator driver cares about
106355841199SDouglas Anderson 		 * output_uV then it's up to the driver to validate.
106455841199SDouglas Anderson 		 */
106555841199SDouglas Anderson 		if (output_uV <= 0)
106655841199SDouglas Anderson 			rdev_dbg(rdev, "invalid output voltage found\n");
1067414c70cbSLiam Girdwood 
1068414c70cbSLiam Girdwood 		/* get input voltage */
10691bf5a1f8SMark Brown 		input_uV = 0;
10701bf5a1f8SMark Brown 		if (rdev->supply)
1071cb3543cfSJohan Hovold 			input_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
10721bf5a1f8SMark Brown 		if (input_uV <= 0)
1073414c70cbSLiam Girdwood 			input_uV = rdev->constraints->input_uV;
107455841199SDouglas Anderson 
107555841199SDouglas Anderson 		/*
107655841199SDouglas Anderson 		 * Don't return an error; if regulator driver cares about
107755841199SDouglas Anderson 		 * input_uV then it's up to the driver to validate.
107855841199SDouglas Anderson 		 */
107955841199SDouglas Anderson 		if (input_uV <= 0)
108055841199SDouglas Anderson 			rdev_dbg(rdev, "invalid input voltage found\n");
1081414c70cbSLiam Girdwood 
1082414c70cbSLiam Girdwood 		/* now get the optimum mode for our new total regulator load */
1083414c70cbSLiam Girdwood 		mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
1084414c70cbSLiam Girdwood 							 output_uV, current_uA);
1085414c70cbSLiam Girdwood 
1086414c70cbSLiam Girdwood 		/* check the new mode is allowed */
10872c608234SMark Brown 		err = regulator_mode_constrain(rdev, &mode);
10888460ef38SBjorn Andersson 		if (err < 0) {
108961aab5adSMichał Mirosław 			rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n",
109061aab5adSMichał Mirosław 				 current_uA, input_uV, output_uV, ERR_PTR(err));
10918460ef38SBjorn Andersson 			return err;
10928460ef38SBjorn Andersson 		}
10938460ef38SBjorn Andersson 
10948460ef38SBjorn Andersson 		err = rdev->desc->ops->set_mode(rdev, mode);
10958460ef38SBjorn Andersson 		if (err < 0)
109661aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set optimum mode %x: %pe\n",
109761aab5adSMichał Mirosław 				 mode, ERR_PTR(err));
10988f4490e0SBjorn Andersson 	}
10998460ef38SBjorn Andersson 
11008460ef38SBjorn Andersson 	return err;
1101414c70cbSLiam Girdwood }
1102414c70cbSLiam Girdwood 
__suspend_set_state(struct regulator_dev * rdev,const struct regulator_state * rstate)11030955f5beSStephen Boyd static int __suspend_set_state(struct regulator_dev *rdev,
11040955f5beSStephen Boyd 			       const struct regulator_state *rstate)
1105414c70cbSLiam Girdwood {
1106414c70cbSLiam Girdwood 	int ret = 0;
1107638f85c5SMark Brown 
110872069f99SChunyan Zhang 	if (rstate->enabled == ENABLE_IN_SUSPEND &&
110972069f99SChunyan Zhang 		rdev->desc->ops->set_suspend_enable)
1110414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_enable(rdev);
111172069f99SChunyan Zhang 	else if (rstate->enabled == DISABLE_IN_SUSPEND &&
111272069f99SChunyan Zhang 		rdev->desc->ops->set_suspend_disable)
1113414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_disable(rdev);
11148ac0e95dSAxel Lin 	else /* OK if set_suspend_enable or set_suspend_disable is NULL */
11158ac0e95dSAxel Lin 		ret = 0;
11168ac0e95dSAxel Lin 
1117414c70cbSLiam Girdwood 	if (ret < 0) {
111861aab5adSMichał Mirosław 		rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret));
1119414c70cbSLiam Girdwood 		return ret;
1120414c70cbSLiam Girdwood 	}
1121414c70cbSLiam Girdwood 
1122414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
1123414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
1124414c70cbSLiam Girdwood 		if (ret < 0) {
112561aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret));
1126414c70cbSLiam Girdwood 			return ret;
1127414c70cbSLiam Girdwood 		}
1128414c70cbSLiam Girdwood 	}
1129414c70cbSLiam Girdwood 
1130414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
1131414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
1132414c70cbSLiam Girdwood 		if (ret < 0) {
113361aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret));
1134414c70cbSLiam Girdwood 			return ret;
1135414c70cbSLiam Girdwood 		}
1136414c70cbSLiam Girdwood 	}
1137f7efad10SChunyan Zhang 
1138414c70cbSLiam Girdwood 	return ret;
1139414c70cbSLiam Girdwood }
1140414c70cbSLiam Girdwood 
suspend_set_initial_state(struct regulator_dev * rdev)11410955f5beSStephen Boyd static int suspend_set_initial_state(struct regulator_dev *rdev)
11420955f5beSStephen Boyd {
11430955f5beSStephen Boyd 	const struct regulator_state *rstate;
11440955f5beSStephen Boyd 
11450955f5beSStephen Boyd 	rstate = regulator_get_suspend_state_check(rdev,
11460955f5beSStephen Boyd 			rdev->constraints->initial_state);
11470955f5beSStephen Boyd 	if (!rstate)
11480955f5beSStephen Boyd 		return 0;
11490955f5beSStephen Boyd 
11500955f5beSStephen Boyd 	return __suspend_set_state(rdev, rstate);
11510955f5beSStephen Boyd }
11520955f5beSStephen Boyd 
1153c845f21aSGeert Uytterhoeven #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
print_constraints_debug(struct regulator_dev * rdev)1154c845f21aSGeert Uytterhoeven static void print_constraints_debug(struct regulator_dev *rdev)
1155414c70cbSLiam Girdwood {
1156414c70cbSLiam Girdwood 	struct regulation_constraints *constraints = rdev->constraints;
1157a7068e39SStefan Wahren 	char buf[160] = "";
11585751a99fSStefan Wahren 	size_t len = sizeof(buf) - 1;
11598f031b48SMark Brown 	int count = 0;
11608f031b48SMark Brown 	int ret;
1161414c70cbSLiam Girdwood 
11628f031b48SMark Brown 	if (constraints->min_uV && constraints->max_uV) {
1163414c70cbSLiam Girdwood 		if (constraints->min_uV == constraints->max_uV)
11645751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count, "%d mV ",
1165414c70cbSLiam Girdwood 					   constraints->min_uV / 1000);
1166414c70cbSLiam Girdwood 		else
11675751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
11685751a99fSStefan Wahren 					   "%d <--> %d mV ",
1169414c70cbSLiam Girdwood 					   constraints->min_uV / 1000,
1170414c70cbSLiam Girdwood 					   constraints->max_uV / 1000);
11718f031b48SMark Brown 	}
11728f031b48SMark Brown 
11738f031b48SMark Brown 	if (!constraints->min_uV ||
11748f031b48SMark Brown 	    constraints->min_uV != constraints->max_uV) {
1175d22b85a1SDmitry Osipenko 		ret = regulator_get_voltage_rdev(rdev);
11768f031b48SMark Brown 		if (ret > 0)
11775751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
11785751a99fSStefan Wahren 					   "at %d mV ", ret / 1000);
11798f031b48SMark Brown 	}
11808f031b48SMark Brown 
1181bf5892a8SMark Brown 	if (constraints->uV_offset)
11825751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "%dmV offset ",
1183bf5892a8SMark Brown 				   constraints->uV_offset / 1000);
1184bf5892a8SMark Brown 
11858f031b48SMark Brown 	if (constraints->min_uA && constraints->max_uA) {
1186414c70cbSLiam Girdwood 		if (constraints->min_uA == constraints->max_uA)
11875751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count, "%d mA ",
1188414c70cbSLiam Girdwood 					   constraints->min_uA / 1000);
1189414c70cbSLiam Girdwood 		else
11905751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
11915751a99fSStefan Wahren 					   "%d <--> %d mA ",
1192414c70cbSLiam Girdwood 					   constraints->min_uA / 1000,
1193414c70cbSLiam Girdwood 					   constraints->max_uA / 1000);
1194414c70cbSLiam Girdwood 	}
11958f031b48SMark Brown 
11968f031b48SMark Brown 	if (!constraints->min_uA ||
11978f031b48SMark Brown 	    constraints->min_uA != constraints->max_uA) {
11988f031b48SMark Brown 		ret = _regulator_get_current_limit(rdev);
11998f031b48SMark Brown 		if (ret > 0)
12005751a99fSStefan Wahren 			count += scnprintf(buf + count, len - count,
12015751a99fSStefan Wahren 					   "at %d mA ", ret / 1000);
12028f031b48SMark Brown 	}
12038f031b48SMark Brown 
1204414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
12055751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "fast ");
1206414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
12075751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "normal ");
1208414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
12095751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "idle ");
1210414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
12115751a99fSStefan Wahren 		count += scnprintf(buf + count, len - count, "standby ");
1212414c70cbSLiam Girdwood 
1213215b8b05SUwe Kleine-König 	if (!count)
121499ad5f6eSMichał Mirosław 		count = scnprintf(buf, len, "no parameters");
121599ad5f6eSMichał Mirosław 	else
121699ad5f6eSMichał Mirosław 		--count;
121799ad5f6eSMichał Mirosław 
121899ad5f6eSMichał Mirosław 	count += scnprintf(buf + count, len - count, ", %s",
121999ad5f6eSMichał Mirosław 		_regulator_is_enabled(rdev) ? "enabled" : "disabled");
1220215b8b05SUwe Kleine-König 
1221194dbaefSMark Brown 	rdev_dbg(rdev, "%s\n", buf);
1222c845f21aSGeert Uytterhoeven }
1223c845f21aSGeert Uytterhoeven #else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
print_constraints_debug(struct regulator_dev * rdev)1224c845f21aSGeert Uytterhoeven static inline void print_constraints_debug(struct regulator_dev *rdev) {}
1225c845f21aSGeert Uytterhoeven #endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
1226c845f21aSGeert Uytterhoeven 
print_constraints(struct regulator_dev * rdev)1227c845f21aSGeert Uytterhoeven static void print_constraints(struct regulator_dev *rdev)
1228c845f21aSGeert Uytterhoeven {
1229c845f21aSGeert Uytterhoeven 	struct regulation_constraints *constraints = rdev->constraints;
1230c845f21aSGeert Uytterhoeven 
1231c845f21aSGeert Uytterhoeven 	print_constraints_debug(rdev);
12324a682922SMark Brown 
12334a682922SMark Brown 	if ((constraints->min_uV != constraints->max_uV) &&
12348a34e979SWEN Pingbo 	    !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
12354a682922SMark Brown 		rdev_warn(rdev,
12364a682922SMark Brown 			  "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
1237414c70cbSLiam Girdwood }
1238414c70cbSLiam Girdwood 
machine_constraints_voltage(struct regulator_dev * rdev,struct regulation_constraints * constraints)1239e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev,
12401083c393SMark Brown 	struct regulation_constraints *constraints)
1241e79055d6SMark Brown {
1242272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
1243af5866c9SMark Brown 	int ret;
1244af5866c9SMark Brown 
1245af5866c9SMark Brown 	/* do we need to apply the constraint voltage */
1246af5866c9SMark Brown 	if (rdev->constraints->apply_uV &&
1247fa93fd4eSMark Brown 	    rdev->constraints->min_uV && rdev->constraints->max_uV) {
1248fa93fd4eSMark Brown 		int target_min, target_max;
1249d22b85a1SDmitry Osipenko 		int current_uV = regulator_get_voltage_rdev(rdev);
125084b3a7c9SDouglas Anderson 
125184b3a7c9SDouglas Anderson 		if (current_uV == -ENOTRECOVERABLE) {
125248f1b4efSKrzysztof Kozlowski 			/* This regulator can't be read and must be initialized */
125384b3a7c9SDouglas Anderson 			rdev_info(rdev, "Setting %d-%duV\n",
125484b3a7c9SDouglas Anderson 				  rdev->constraints->min_uV,
125584b3a7c9SDouglas Anderson 				  rdev->constraints->max_uV);
125684b3a7c9SDouglas Anderson 			_regulator_do_set_voltage(rdev,
125784b3a7c9SDouglas Anderson 						  rdev->constraints->min_uV,
125884b3a7c9SDouglas Anderson 						  rdev->constraints->max_uV);
1259d22b85a1SDmitry Osipenko 			current_uV = regulator_get_voltage_rdev(rdev);
126084b3a7c9SDouglas Anderson 		}
126184b3a7c9SDouglas Anderson 
1262064d5cd1SAlban Bedel 		if (current_uV < 0) {
1263adea2831SBrian Norris 			if (current_uV != -EPROBE_DEFER)
126469d58839SNishanth Menon 				rdev_err(rdev,
126561aab5adSMichał Mirosław 					 "failed to get the current voltage: %pe\n",
126661aab5adSMichał Mirosław 					 ERR_PTR(current_uV));
1267064d5cd1SAlban Bedel 			return current_uV;
1268064d5cd1SAlban Bedel 		}
1269fa93fd4eSMark Brown 
1270fa93fd4eSMark Brown 		/*
1271fa93fd4eSMark Brown 		 * If we're below the minimum voltage move up to the
1272fa93fd4eSMark Brown 		 * minimum voltage, if we're above the maximum voltage
1273fa93fd4eSMark Brown 		 * then move down to the maximum.
1274fa93fd4eSMark Brown 		 */
1275fa93fd4eSMark Brown 		target_min = current_uV;
1276fa93fd4eSMark Brown 		target_max = current_uV;
1277fa93fd4eSMark Brown 
1278fa93fd4eSMark Brown 		if (current_uV < rdev->constraints->min_uV) {
1279fa93fd4eSMark Brown 			target_min = rdev->constraints->min_uV;
1280fa93fd4eSMark Brown 			target_max = rdev->constraints->min_uV;
1281fa93fd4eSMark Brown 		}
1282fa93fd4eSMark Brown 
1283fa93fd4eSMark Brown 		if (current_uV > rdev->constraints->max_uV) {
1284fa93fd4eSMark Brown 			target_min = rdev->constraints->max_uV;
1285fa93fd4eSMark Brown 			target_max = rdev->constraints->max_uV;
1286fa93fd4eSMark Brown 		}
1287fa93fd4eSMark Brown 
1288fa93fd4eSMark Brown 		if (target_min != current_uV || target_max != current_uV) {
128945a91e8fSMark Brown 			rdev_info(rdev, "Bringing %duV into %d-%duV\n",
129045a91e8fSMark Brown 				  current_uV, target_min, target_max);
1291064d5cd1SAlban Bedel 			ret = _regulator_do_set_voltage(
1292fa93fd4eSMark Brown 				rdev, target_min, target_max);
1293af5866c9SMark Brown 			if (ret < 0) {
1294064d5cd1SAlban Bedel 				rdev_err(rdev,
129561aab5adSMichał Mirosław 					"failed to apply %d-%duV constraint: %pe\n",
129661aab5adSMichał Mirosław 					target_min, target_max, ERR_PTR(ret));
1297af5866c9SMark Brown 				return ret;
1298af5866c9SMark Brown 			}
1299af5866c9SMark Brown 		}
1300064d5cd1SAlban Bedel 	}
1301e79055d6SMark Brown 
1302e79055d6SMark Brown 	/* constrain machine-level voltage specs to fit
1303e79055d6SMark Brown 	 * the actual range supported by this regulator.
1304e79055d6SMark Brown 	 */
1305e79055d6SMark Brown 	if (ops->list_voltage && rdev->desc->n_voltages) {
1306e79055d6SMark Brown 		int	count = rdev->desc->n_voltages;
1307e79055d6SMark Brown 		int	i;
1308e79055d6SMark Brown 		int	min_uV = INT_MAX;
1309e79055d6SMark Brown 		int	max_uV = INT_MIN;
1310e79055d6SMark Brown 		int	cmin = constraints->min_uV;
1311e79055d6SMark Brown 		int	cmax = constraints->max_uV;
1312e79055d6SMark Brown 
1313e79055d6SMark Brown 		/* it's safe to autoconfigure fixed-voltage supplies
131469b8821eSShubhankar Kuranagatti 		 * and the constraints are used by list_voltage.
131569b8821eSShubhankar Kuranagatti 		 */
1316e79055d6SMark Brown 		if (count == 1 && !cmin) {
1317e79055d6SMark Brown 			cmin = 1;
1318e79055d6SMark Brown 			cmax = INT_MAX;
1319e79055d6SMark Brown 			constraints->min_uV = cmin;
1320e79055d6SMark Brown 			constraints->max_uV = cmax;
1321e79055d6SMark Brown 		}
1322e79055d6SMark Brown 
1323e79055d6SMark Brown 		/* voltage constraints are optional */
1324e79055d6SMark Brown 		if ((cmin == 0) && (cmax == 0))
1325e79055d6SMark Brown 			return 0;
1326e79055d6SMark Brown 
1327e79055d6SMark Brown 		/* else require explicit machine-level constraints */
1328e79055d6SMark Brown 		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
13295da84fd9SJoe Perches 			rdev_err(rdev, "invalid voltage constraints\n");
1330e79055d6SMark Brown 			return -EINVAL;
1331e79055d6SMark Brown 		}
1332e79055d6SMark Brown 
13336d30fc51SCristian Marussi 		/* no need to loop voltages if range is continuous */
13346d30fc51SCristian Marussi 		if (rdev->desc->continuous_voltage_range)
13356d30fc51SCristian Marussi 			return 0;
13366d30fc51SCristian Marussi 
1337e79055d6SMark Brown 		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
1338e79055d6SMark Brown 		for (i = 0; i < count; i++) {
1339e79055d6SMark Brown 			int	value;
1340e79055d6SMark Brown 
1341e79055d6SMark Brown 			value = ops->list_voltage(rdev, i);
1342e79055d6SMark Brown 			if (value <= 0)
1343e79055d6SMark Brown 				continue;
1344e79055d6SMark Brown 
1345e79055d6SMark Brown 			/* maybe adjust [min_uV..max_uV] */
1346e79055d6SMark Brown 			if (value >= cmin && value < min_uV)
1347e79055d6SMark Brown 				min_uV = value;
1348e79055d6SMark Brown 			if (value <= cmax && value > max_uV)
1349e79055d6SMark Brown 				max_uV = value;
1350e79055d6SMark Brown 		}
1351e79055d6SMark Brown 
1352e79055d6SMark Brown 		/* final: [min_uV..max_uV] valid iff constraints valid */
1353e79055d6SMark Brown 		if (max_uV < min_uV) {
1354fff15befSMark Brown 			rdev_err(rdev,
1355fff15befSMark Brown 				 "unsupportable voltage constraints %u-%uuV\n",
1356fff15befSMark Brown 				 min_uV, max_uV);
1357e79055d6SMark Brown 			return -EINVAL;
1358e79055d6SMark Brown 		}
1359e79055d6SMark Brown 
1360e79055d6SMark Brown 		/* use regulator's subset of machine constraints */
1361e79055d6SMark Brown 		if (constraints->min_uV < min_uV) {
13625da84fd9SJoe Perches 			rdev_dbg(rdev, "override min_uV, %d -> %d\n",
13635da84fd9SJoe Perches 				 constraints->min_uV, min_uV);
1364e79055d6SMark Brown 			constraints->min_uV = min_uV;
1365e79055d6SMark Brown 		}
1366e79055d6SMark Brown 		if (constraints->max_uV > max_uV) {
13675da84fd9SJoe Perches 			rdev_dbg(rdev, "override max_uV, %d -> %d\n",
13685da84fd9SJoe Perches 				 constraints->max_uV, max_uV);
1369e79055d6SMark Brown 			constraints->max_uV = max_uV;
1370e79055d6SMark Brown 		}
1371e79055d6SMark Brown 	}
1372e79055d6SMark Brown 
1373e79055d6SMark Brown 	return 0;
1374e79055d6SMark Brown }
1375e79055d6SMark Brown 
machine_constraints_current(struct regulator_dev * rdev,struct regulation_constraints * constraints)1376f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev,
1377f8c1700dSLaxman Dewangan 	struct regulation_constraints *constraints)
1378f8c1700dSLaxman Dewangan {
1379272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
1380f8c1700dSLaxman Dewangan 	int ret;
1381f8c1700dSLaxman Dewangan 
1382f8c1700dSLaxman Dewangan 	if (!constraints->min_uA && !constraints->max_uA)
1383f8c1700dSLaxman Dewangan 		return 0;
1384f8c1700dSLaxman Dewangan 
1385f8c1700dSLaxman Dewangan 	if (constraints->min_uA > constraints->max_uA) {
1386f8c1700dSLaxman Dewangan 		rdev_err(rdev, "Invalid current constraints\n");
1387f8c1700dSLaxman Dewangan 		return -EINVAL;
1388f8c1700dSLaxman Dewangan 	}
1389f8c1700dSLaxman Dewangan 
1390f8c1700dSLaxman Dewangan 	if (!ops->set_current_limit || !ops->get_current_limit) {
1391f8c1700dSLaxman Dewangan 		rdev_warn(rdev, "Operation of current configuration missing\n");
1392f8c1700dSLaxman Dewangan 		return 0;
1393f8c1700dSLaxman Dewangan 	}
1394f8c1700dSLaxman Dewangan 
1395f8c1700dSLaxman Dewangan 	/* Set regulator current in constraints range */
1396f8c1700dSLaxman Dewangan 	ret = ops->set_current_limit(rdev, constraints->min_uA,
1397f8c1700dSLaxman Dewangan 			constraints->max_uA);
1398f8c1700dSLaxman Dewangan 	if (ret < 0) {
1399f8c1700dSLaxman Dewangan 		rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
1400f8c1700dSLaxman Dewangan 		return ret;
1401f8c1700dSLaxman Dewangan 	}
1402f8c1700dSLaxman Dewangan 
1403f8c1700dSLaxman Dewangan 	return 0;
1404f8c1700dSLaxman Dewangan }
1405f8c1700dSLaxman Dewangan 
140630c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev);
140730c21971SMarkus Pargmann 
notif_set_limit(struct regulator_dev * rdev,int (* set)(struct regulator_dev *,int,int,bool),int limit,int severity)140889a6a5e5SMatti Vaittinen static int notif_set_limit(struct regulator_dev *rdev,
140989a6a5e5SMatti Vaittinen 			   int (*set)(struct regulator_dev *, int, int, bool),
141089a6a5e5SMatti Vaittinen 			   int limit, int severity)
141189a6a5e5SMatti Vaittinen {
141289a6a5e5SMatti Vaittinen 	bool enable;
141389a6a5e5SMatti Vaittinen 
141489a6a5e5SMatti Vaittinen 	if (limit == REGULATOR_NOTIF_LIMIT_DISABLE) {
141589a6a5e5SMatti Vaittinen 		enable = false;
141689a6a5e5SMatti Vaittinen 		limit = 0;
141789a6a5e5SMatti Vaittinen 	} else {
141889a6a5e5SMatti Vaittinen 		enable = true;
141989a6a5e5SMatti Vaittinen 	}
142089a6a5e5SMatti Vaittinen 
142189a6a5e5SMatti Vaittinen 	if (limit == REGULATOR_NOTIF_LIMIT_ENABLE)
142289a6a5e5SMatti Vaittinen 		limit = 0;
142389a6a5e5SMatti Vaittinen 
142489a6a5e5SMatti Vaittinen 	return set(rdev, limit, severity, enable);
142589a6a5e5SMatti Vaittinen }
142689a6a5e5SMatti Vaittinen 
handle_notify_limits(struct regulator_dev * rdev,int (* set)(struct regulator_dev *,int,int,bool),struct notification_limit * limits)142789a6a5e5SMatti Vaittinen static int handle_notify_limits(struct regulator_dev *rdev,
142889a6a5e5SMatti Vaittinen 			int (*set)(struct regulator_dev *, int, int, bool),
142989a6a5e5SMatti Vaittinen 			struct notification_limit *limits)
143089a6a5e5SMatti Vaittinen {
143189a6a5e5SMatti Vaittinen 	int ret = 0;
143289a6a5e5SMatti Vaittinen 
143389a6a5e5SMatti Vaittinen 	if (!set)
143489a6a5e5SMatti Vaittinen 		return -EOPNOTSUPP;
143589a6a5e5SMatti Vaittinen 
143689a6a5e5SMatti Vaittinen 	if (limits->prot)
143789a6a5e5SMatti Vaittinen 		ret = notif_set_limit(rdev, set, limits->prot,
143889a6a5e5SMatti Vaittinen 				      REGULATOR_SEVERITY_PROT);
143989a6a5e5SMatti Vaittinen 	if (ret)
144089a6a5e5SMatti Vaittinen 		return ret;
144189a6a5e5SMatti Vaittinen 
144289a6a5e5SMatti Vaittinen 	if (limits->err)
144389a6a5e5SMatti Vaittinen 		ret = notif_set_limit(rdev, set, limits->err,
144489a6a5e5SMatti Vaittinen 				      REGULATOR_SEVERITY_ERR);
144589a6a5e5SMatti Vaittinen 	if (ret)
144689a6a5e5SMatti Vaittinen 		return ret;
144789a6a5e5SMatti Vaittinen 
144889a6a5e5SMatti Vaittinen 	if (limits->warn)
144989a6a5e5SMatti Vaittinen 		ret = notif_set_limit(rdev, set, limits->warn,
145089a6a5e5SMatti Vaittinen 				      REGULATOR_SEVERITY_WARN);
145189a6a5e5SMatti Vaittinen 
145289a6a5e5SMatti Vaittinen 	return ret;
145389a6a5e5SMatti Vaittinen }
1454a5766f11SLiam Girdwood /**
1455a5766f11SLiam Girdwood  * set_machine_constraints - sets regulator constraints
145669279fb9SMark Brown  * @rdev: regulator source
1457a5766f11SLiam Girdwood  *
1458a5766f11SLiam Girdwood  * Allows platform initialisation code to define and constrain
1459a5766f11SLiam Girdwood  * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
1460a5766f11SLiam Girdwood  * Constraints *must* be set by platform code in order for some
1461a5766f11SLiam Girdwood  * regulator operations to proceed i.e. set_voltage, set_current_limit,
1462a5766f11SLiam Girdwood  * set_mode.
1463a5766f11SLiam Girdwood  */
set_machine_constraints(struct regulator_dev * rdev)146457a6ad48SMichał Mirosław static int set_machine_constraints(struct regulator_dev *rdev)
1465a5766f11SLiam Girdwood {
1466a5766f11SLiam Girdwood 	int ret = 0;
1467272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
1468e06f5b4fSMark Brown 
1469f8c12fe3SMark Brown 	ret = machine_constraints_voltage(rdev, rdev->constraints);
1470e79055d6SMark Brown 	if (ret != 0)
14716333ef46SCharles Keepax 		return ret;
14723e2b9abdSMark Brown 
1473f8c1700dSLaxman Dewangan 	ret = machine_constraints_current(rdev, rdev->constraints);
1474f8c1700dSLaxman Dewangan 	if (ret != 0)
14756333ef46SCharles Keepax 		return ret;
1476f8c1700dSLaxman Dewangan 
147736e4f839SStephen Boyd 	if (rdev->constraints->ilim_uA && ops->set_input_current_limit) {
147836e4f839SStephen Boyd 		ret = ops->set_input_current_limit(rdev,
147936e4f839SStephen Boyd 						   rdev->constraints->ilim_uA);
148036e4f839SStephen Boyd 		if (ret < 0) {
148161aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret));
14826333ef46SCharles Keepax 			return ret;
148336e4f839SStephen Boyd 		}
148436e4f839SStephen Boyd 	}
148536e4f839SStephen Boyd 
1486a5766f11SLiam Girdwood 	/* do we need to setup our suspend state */
14879a8f5e07SMark Brown 	if (rdev->constraints->initial_state) {
14880955f5beSStephen Boyd 		ret = suspend_set_initial_state(rdev);
1489e06f5b4fSMark Brown 		if (ret < 0) {
149061aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret));
14916333ef46SCharles Keepax 			return ret;
1492e06f5b4fSMark Brown 		}
1493e06f5b4fSMark Brown 	}
1494a5766f11SLiam Girdwood 
14959a8f5e07SMark Brown 	if (rdev->constraints->initial_mode) {
1496a308466cSMark Brown 		if (!ops->set_mode) {
14975da84fd9SJoe Perches 			rdev_err(rdev, "no set_mode operation\n");
14986333ef46SCharles Keepax 			return -EINVAL;
1499a308466cSMark Brown 		}
1500a308466cSMark Brown 
1501f8c12fe3SMark Brown 		ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
1502a308466cSMark Brown 		if (ret < 0) {
150361aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret));
15046333ef46SCharles Keepax 			return ret;
1505a308466cSMark Brown 		}
1506fa94e48eSDouglas Anderson 	} else if (rdev->constraints->system_load) {
1507fa94e48eSDouglas Anderson 		/*
1508fa94e48eSDouglas Anderson 		 * We'll only apply the initial system load if an
1509fa94e48eSDouglas Anderson 		 * initial mode wasn't specified.
1510fa94e48eSDouglas Anderson 		 */
1511fa94e48eSDouglas Anderson 		drms_uA_update(rdev);
1512a308466cSMark Brown 	}
1513a308466cSMark Brown 
15141653ccf4SYadwinder Singh Brar 	if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
15151653ccf4SYadwinder Singh Brar 		&& ops->set_ramp_delay) {
15166f0b2c69SYadwinder Singh Brar 		ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
15176f0b2c69SYadwinder Singh Brar 		if (ret < 0) {
151861aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret));
15196333ef46SCharles Keepax 			return ret;
15206f0b2c69SYadwinder Singh Brar 		}
15216f0b2c69SYadwinder Singh Brar 	}
15226f0b2c69SYadwinder Singh Brar 
152323c779b9SStephen Boyd 	if (rdev->constraints->pull_down && ops->set_pull_down) {
152423c779b9SStephen Boyd 		ret = ops->set_pull_down(rdev);
152523c779b9SStephen Boyd 		if (ret < 0) {
152661aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret));
15276333ef46SCharles Keepax 			return ret;
152823c779b9SStephen Boyd 		}
152923c779b9SStephen Boyd 	}
153023c779b9SStephen Boyd 
153157f66b78SStephen Boyd 	if (rdev->constraints->soft_start && ops->set_soft_start) {
153257f66b78SStephen Boyd 		ret = ops->set_soft_start(rdev);
153357f66b78SStephen Boyd 		if (ret < 0) {
153461aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret));
15356333ef46SCharles Keepax 			return ret;
153657f66b78SStephen Boyd 		}
153757f66b78SStephen Boyd 	}
153857f66b78SStephen Boyd 
153989a6a5e5SMatti Vaittinen 	/*
154089a6a5e5SMatti Vaittinen 	 * Existing logic does not warn if over_current_protection is given as
154189a6a5e5SMatti Vaittinen 	 * a constraint but driver does not support that. I think we should
154289a6a5e5SMatti Vaittinen 	 * warn about this type of issues as it is possible someone changes
154389a6a5e5SMatti Vaittinen 	 * PMIC on board to another type - and the another PMIC's driver does
154489a6a5e5SMatti Vaittinen 	 * not support setting protection. Board composer may happily believe
154589a6a5e5SMatti Vaittinen 	 * the DT limits are respected - especially if the new PMIC HW also
154689a6a5e5SMatti Vaittinen 	 * supports protection but the driver does not. I won't change the logic
154789a6a5e5SMatti Vaittinen 	 * without hearing more experienced opinion on this though.
154889a6a5e5SMatti Vaittinen 	 *
154989a6a5e5SMatti Vaittinen 	 * If warning is seen as a good idea then we can merge handling the
155089a6a5e5SMatti Vaittinen 	 * over-curret protection and detection and get rid of this special
155189a6a5e5SMatti Vaittinen 	 * handling.
155289a6a5e5SMatti Vaittinen 	 */
15533a003baeSStephen Boyd 	if (rdev->constraints->over_current_protection
15543a003baeSStephen Boyd 		&& ops->set_over_current_protection) {
155589a6a5e5SMatti Vaittinen 		int lim = rdev->constraints->over_curr_limits.prot;
155689a6a5e5SMatti Vaittinen 
155789a6a5e5SMatti Vaittinen 		ret = ops->set_over_current_protection(rdev, lim,
155889a6a5e5SMatti Vaittinen 						       REGULATOR_SEVERITY_PROT,
155989a6a5e5SMatti Vaittinen 						       true);
15603a003baeSStephen Boyd 		if (ret < 0) {
156161aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set over current protection: %pe\n",
156261aab5adSMichał Mirosław 				 ERR_PTR(ret));
15636333ef46SCharles Keepax 			return ret;
15643a003baeSStephen Boyd 		}
15653a003baeSStephen Boyd 	}
15663a003baeSStephen Boyd 
156789a6a5e5SMatti Vaittinen 	if (rdev->constraints->over_current_detection)
156889a6a5e5SMatti Vaittinen 		ret = handle_notify_limits(rdev,
156989a6a5e5SMatti Vaittinen 					   ops->set_over_current_protection,
157089a6a5e5SMatti Vaittinen 					   &rdev->constraints->over_curr_limits);
157189a6a5e5SMatti Vaittinen 	if (ret) {
157289a6a5e5SMatti Vaittinen 		if (ret != -EOPNOTSUPP) {
157389a6a5e5SMatti Vaittinen 			rdev_err(rdev, "failed to set over current limits: %pe\n",
157489a6a5e5SMatti Vaittinen 				 ERR_PTR(ret));
157589a6a5e5SMatti Vaittinen 			return ret;
157689a6a5e5SMatti Vaittinen 		}
157789a6a5e5SMatti Vaittinen 		rdev_warn(rdev,
157889a6a5e5SMatti Vaittinen 			  "IC does not support requested over-current limits\n");
157989a6a5e5SMatti Vaittinen 	}
158089a6a5e5SMatti Vaittinen 
158189a6a5e5SMatti Vaittinen 	if (rdev->constraints->over_voltage_detection)
158289a6a5e5SMatti Vaittinen 		ret = handle_notify_limits(rdev,
158389a6a5e5SMatti Vaittinen 					   ops->set_over_voltage_protection,
158489a6a5e5SMatti Vaittinen 					   &rdev->constraints->over_voltage_limits);
158589a6a5e5SMatti Vaittinen 	if (ret) {
158689a6a5e5SMatti Vaittinen 		if (ret != -EOPNOTSUPP) {
158789a6a5e5SMatti Vaittinen 			rdev_err(rdev, "failed to set over voltage limits %pe\n",
158889a6a5e5SMatti Vaittinen 				 ERR_PTR(ret));
158989a6a5e5SMatti Vaittinen 			return ret;
159089a6a5e5SMatti Vaittinen 		}
159189a6a5e5SMatti Vaittinen 		rdev_warn(rdev,
159289a6a5e5SMatti Vaittinen 			  "IC does not support requested over voltage limits\n");
159389a6a5e5SMatti Vaittinen 	}
159489a6a5e5SMatti Vaittinen 
159589a6a5e5SMatti Vaittinen 	if (rdev->constraints->under_voltage_detection)
159689a6a5e5SMatti Vaittinen 		ret = handle_notify_limits(rdev,
159789a6a5e5SMatti Vaittinen 					   ops->set_under_voltage_protection,
159889a6a5e5SMatti Vaittinen 					   &rdev->constraints->under_voltage_limits);
159989a6a5e5SMatti Vaittinen 	if (ret) {
160089a6a5e5SMatti Vaittinen 		if (ret != -EOPNOTSUPP) {
160189a6a5e5SMatti Vaittinen 			rdev_err(rdev, "failed to set under voltage limits %pe\n",
160289a6a5e5SMatti Vaittinen 				 ERR_PTR(ret));
160389a6a5e5SMatti Vaittinen 			return ret;
160489a6a5e5SMatti Vaittinen 		}
160589a6a5e5SMatti Vaittinen 		rdev_warn(rdev,
160689a6a5e5SMatti Vaittinen 			  "IC does not support requested under voltage limits\n");
160789a6a5e5SMatti Vaittinen 	}
160889a6a5e5SMatti Vaittinen 
160989a6a5e5SMatti Vaittinen 	if (rdev->constraints->over_temp_detection)
161089a6a5e5SMatti Vaittinen 		ret = handle_notify_limits(rdev,
161189a6a5e5SMatti Vaittinen 					   ops->set_thermal_protection,
161289a6a5e5SMatti Vaittinen 					   &rdev->constraints->temp_limits);
161389a6a5e5SMatti Vaittinen 	if (ret) {
161489a6a5e5SMatti Vaittinen 		if (ret != -EOPNOTSUPP) {
161589a6a5e5SMatti Vaittinen 			rdev_err(rdev, "failed to set temperature limits %pe\n",
161689a6a5e5SMatti Vaittinen 				 ERR_PTR(ret));
161789a6a5e5SMatti Vaittinen 			return ret;
161889a6a5e5SMatti Vaittinen 		}
161989a6a5e5SMatti Vaittinen 		rdev_warn(rdev,
162089a6a5e5SMatti Vaittinen 			  "IC does not support requested temperature limits\n");
162189a6a5e5SMatti Vaittinen 	}
162289a6a5e5SMatti Vaittinen 
1623670666b9SLaxman Dewangan 	if (rdev->constraints->active_discharge && ops->set_active_discharge) {
1624670666b9SLaxman Dewangan 		bool ad_state = (rdev->constraints->active_discharge ==
1625670666b9SLaxman Dewangan 			      REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;
1626670666b9SLaxman Dewangan 
1627670666b9SLaxman Dewangan 		ret = ops->set_active_discharge(rdev, ad_state);
1628670666b9SLaxman Dewangan 		if (ret < 0) {
162961aab5adSMichał Mirosław 			rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret));
1630670666b9SLaxman Dewangan 			return ret;
1631670666b9SLaxman Dewangan 		}
1632670666b9SLaxman Dewangan 	}
1633670666b9SLaxman Dewangan 
1634261f0631SMark Brown 	/*
1635261f0631SMark Brown 	 * If there is no mechanism for controlling the regulator then
1636261f0631SMark Brown 	 * flag it as always_on so we don't end up duplicating checks
1637261f0631SMark Brown 	 * for this so much.  Note that we could control the state of
1638261f0631SMark Brown 	 * a supply to control the output on a regulator that has no
1639261f0631SMark Brown 	 * direct control.
1640261f0631SMark Brown 	 */
1641261f0631SMark Brown 	if (!rdev->ena_pin && !ops->enable) {
1642261f0631SMark Brown 		if (rdev->supply_name && !rdev->supply)
1643261f0631SMark Brown 			return -EPROBE_DEFER;
1644261f0631SMark Brown 
1645261f0631SMark Brown 		if (rdev->supply)
1646261f0631SMark Brown 			rdev->constraints->always_on =
1647261f0631SMark Brown 				rdev->supply->rdev->constraints->always_on;
1648261f0631SMark Brown 		else
1649261f0631SMark Brown 			rdev->constraints->always_on = true;
1650261f0631SMark Brown 	}
1651261f0631SMark Brown 
16522bb16663SOlliver Schinagl 	/* If the constraints say the regulator should be on at this point
16532bb16663SOlliver Schinagl 	 * and we have control then make sure it is enabled.
16542bb16663SOlliver Schinagl 	 */
16552bb16663SOlliver Schinagl 	if (rdev->constraints->always_on || rdev->constraints->boot_on) {
165698e48cd9SDmitry Baryshkov 		/* If we want to enable this regulator, make sure that we know
165798e48cd9SDmitry Baryshkov 		 * the supplying regulator.
165898e48cd9SDmitry Baryshkov 		 */
165998e48cd9SDmitry Baryshkov 		if (rdev->supply_name && !rdev->supply)
166098e48cd9SDmitry Baryshkov 			return -EPROBE_DEFER;
166198e48cd9SDmitry Baryshkov 
16620591b14cSRui Zhang 		/* If supplying regulator has already been enabled,
16630591b14cSRui Zhang 		 * it's not intended to have use_count increment
16640591b14cSRui Zhang 		 * when rdev is only boot-on.
16650591b14cSRui Zhang 		 */
16660591b14cSRui Zhang 		if (rdev->supply &&
16670591b14cSRui Zhang 		    (rdev->constraints->always_on ||
16680591b14cSRui Zhang 		     !regulator_is_enabled(rdev->supply))) {
166905f224caSDouglas Anderson 			ret = regulator_enable(rdev->supply);
167005f224caSDouglas Anderson 			if (ret < 0) {
167105f224caSDouglas Anderson 				_regulator_put(rdev->supply);
167205f224caSDouglas Anderson 				rdev->supply = NULL;
167305f224caSDouglas Anderson 				return ret;
167405f224caSDouglas Anderson 			}
167505f224caSDouglas Anderson 		}
167605f224caSDouglas Anderson 
16772bb16663SOlliver Schinagl 		ret = _regulator_do_enable(rdev);
16782bb16663SOlliver Schinagl 		if (ret < 0 && ret != -EINVAL) {
167961aab5adSMichał Mirosław 			rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret));
16802bb16663SOlliver Schinagl 			return ret;
16812bb16663SOlliver Schinagl 		}
1682089b3f61SPascal Paillet 
1683089b3f61SPascal Paillet 		if (rdev->constraints->always_on)
168405f224caSDouglas Anderson 			rdev->use_count++;
1685691c1fcdSDouglas Anderson 	} else if (rdev->desc->off_on_delay) {
1686691c1fcdSDouglas Anderson 		rdev->last_off = ktime_get();
16872bb16663SOlliver Schinagl 	}
16882bb16663SOlliver Schinagl 
1689a5766f11SLiam Girdwood 	print_constraints(rdev);
16901a6958e7SAxel Lin 	return 0;
1691a5766f11SLiam Girdwood }
1692a5766f11SLiam Girdwood 
1693a5766f11SLiam Girdwood /**
1694a5766f11SLiam Girdwood  * set_supply - set regulator supply regulator
1695cba6cfdcSDouglas Anderson  * @rdev: regulator (locked)
1696cba6cfdcSDouglas Anderson  * @supply_rdev: supply regulator (locked))
1697a5766f11SLiam Girdwood  *
1698a5766f11SLiam Girdwood  * Called by platform initialisation code to set the supply regulator for this
1699a5766f11SLiam Girdwood  * regulator. This ensures that a regulators supply will also be enabled by the
1700a5766f11SLiam Girdwood  * core if it's child is enabled.
1701a5766f11SLiam Girdwood  */
set_supply(struct regulator_dev * rdev,struct regulator_dev * supply_rdev)1702a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev,
1703a5766f11SLiam Girdwood 		      struct regulator_dev *supply_rdev)
1704a5766f11SLiam Girdwood {
1705a5766f11SLiam Girdwood 	int err;
1706a5766f11SLiam Girdwood 
170735d11469SMark Brown 	rdev_dbg(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
17083801b86aSMark Brown 
1709e2c09ae7SJavier Martinez Canillas 	if (!try_module_get(supply_rdev->owner))
1710e2c09ae7SJavier Martinez Canillas 		return -ENODEV;
1711e2c09ae7SJavier Martinez Canillas 
17123801b86aSMark Brown 	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
171332c78de8SAxel Lin 	if (rdev->supply == NULL) {
1714da46ee19SYang Yingliang 		module_put(supply_rdev->owner);
171532c78de8SAxel Lin 		err = -ENOMEM;
1716a5766f11SLiam Girdwood 		return err;
1717a5766f11SLiam Girdwood 	}
171857ad526aSLaxman Dewangan 	supply_rdev->open_count++;
1719a5766f11SLiam Girdwood 
17203801b86aSMark Brown 	return 0;
17213801b86aSMark Brown }
17223801b86aSMark Brown 
1723a5766f11SLiam Girdwood /**
172406c63f93SRandy Dunlap  * set_consumer_device_supply - Bind a regulator to a symbolic supply
172569279fb9SMark Brown  * @rdev:         regulator source
172640f9244fSMark Brown  * @consumer_dev_name: dev_name() string for device supply applies to
1727a5766f11SLiam Girdwood  * @supply:       symbolic name for supply
1728a5766f11SLiam Girdwood  *
1729a5766f11SLiam Girdwood  * Allows platform initialisation code to map physical regulator
1730a5766f11SLiam Girdwood  * sources to symbolic names for supplies for use by devices.  Devices
1731a5766f11SLiam Girdwood  * should use these symbolic names to request regulators, avoiding the
1732a5766f11SLiam Girdwood  * need to provide board-specific regulator names as platform data.
1733a5766f11SLiam Girdwood  */
set_consumer_device_supply(struct regulator_dev * rdev,const char * consumer_dev_name,const char * supply)1734a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev,
1735737f360dSMark Brown 				      const char *consumer_dev_name,
173640f9244fSMark Brown 				      const char *supply)
1737a5766f11SLiam Girdwood {
17385c065401SMichał Mirosław 	struct regulator_map *node, *new_node;
17399ed2099eSMark Brown 	int has_dev;
1740a5766f11SLiam Girdwood 
1741a5766f11SLiam Girdwood 	if (supply == NULL)
1742a5766f11SLiam Girdwood 		return -EINVAL;
1743a5766f11SLiam Girdwood 
17449ed2099eSMark Brown 	if (consumer_dev_name != NULL)
17459ed2099eSMark Brown 		has_dev = 1;
17469ed2099eSMark Brown 	else
17479ed2099eSMark Brown 		has_dev = 0;
17489ed2099eSMark Brown 
17495c065401SMichał Mirosław 	new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
17505c065401SMichał Mirosław 	if (new_node == NULL)
17515c065401SMichał Mirosław 		return -ENOMEM;
17525c065401SMichał Mirosław 
17535c065401SMichał Mirosław 	new_node->regulator = rdev;
17545c065401SMichał Mirosław 	new_node->supply = supply;
17555c065401SMichał Mirosław 
17565c065401SMichał Mirosław 	if (has_dev) {
17575c065401SMichał Mirosław 		new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
17585c065401SMichał Mirosław 		if (new_node->dev_name == NULL) {
17595c065401SMichał Mirosław 			kfree(new_node);
17605c065401SMichał Mirosław 			return -ENOMEM;
17615c065401SMichał Mirosław 		}
17625c065401SMichał Mirosław 	}
17635c065401SMichał Mirosław 
17645c065401SMichał Mirosław 	mutex_lock(&regulator_list_mutex);
17656001e13cSDavid Brownell 	list_for_each_entry(node, &regulator_map_list, list) {
176623b5cc2aSJani Nikula 		if (node->dev_name && consumer_dev_name) {
176723b5cc2aSJani Nikula 			if (strcmp(node->dev_name, consumer_dev_name) != 0)
17686001e13cSDavid Brownell 				continue;
176923b5cc2aSJani Nikula 		} else if (node->dev_name || consumer_dev_name) {
177023b5cc2aSJani Nikula 			continue;
177123b5cc2aSJani Nikula 		}
177223b5cc2aSJani Nikula 
17736001e13cSDavid Brownell 		if (strcmp(node->supply, supply) != 0)
17746001e13cSDavid Brownell 			continue;
17756001e13cSDavid Brownell 
1776737f360dSMark Brown 		pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n",
1777737f360dSMark Brown 			 consumer_dev_name,
17786001e13cSDavid Brownell 			 dev_name(&node->regulator->dev),
17796001e13cSDavid Brownell 			 node->regulator->desc->name,
17806001e13cSDavid Brownell 			 supply,
17811083c393SMark Brown 			 dev_name(&rdev->dev), rdev_get_name(rdev));
17825c065401SMichał Mirosław 		goto fail;
17836001e13cSDavid Brownell 	}
17846001e13cSDavid Brownell 
17855c065401SMichał Mirosław 	list_add(&new_node->list, &regulator_map_list);
17865c065401SMichał Mirosław 	mutex_unlock(&regulator_list_mutex);
1787a5766f11SLiam Girdwood 
1788a5766f11SLiam Girdwood 	return 0;
17895c065401SMichał Mirosław 
17905c065401SMichał Mirosław fail:
17915c065401SMichał Mirosław 	mutex_unlock(&regulator_list_mutex);
17925c065401SMichał Mirosław 	kfree(new_node->dev_name);
17935c065401SMichał Mirosław 	kfree(new_node);
17945c065401SMichał Mirosław 	return -EBUSY;
1795a5766f11SLiam Girdwood }
1796a5766f11SLiam Girdwood 
unset_regulator_supplies(struct regulator_dev * rdev)17970f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev)
17980f1d747bSMike Rapoport {
17990f1d747bSMike Rapoport 	struct regulator_map *node, *n;
18000f1d747bSMike Rapoport 
18010f1d747bSMike Rapoport 	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
18020f1d747bSMike Rapoport 		if (rdev == node->regulator) {
18030f1d747bSMike Rapoport 			list_del(&node->list);
180440f9244fSMark Brown 			kfree(node->dev_name);
18050f1d747bSMike Rapoport 			kfree(node);
18060f1d747bSMike Rapoport 		}
18070f1d747bSMike Rapoport 	}
18080f1d747bSMike Rapoport }
18090f1d747bSMike Rapoport 
18102d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS
constraint_flags_read_file(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)18112d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file,
18122d80a91bSRichard Fitzgerald 					  char __user *user_buf,
18132d80a91bSRichard Fitzgerald 					  size_t count, loff_t *ppos)
18142d80a91bSRichard Fitzgerald {
18152d80a91bSRichard Fitzgerald 	const struct regulator *regulator = file->private_data;
18162d80a91bSRichard Fitzgerald 	const struct regulation_constraints *c = regulator->rdev->constraints;
18172d80a91bSRichard Fitzgerald 	char *buf;
18182d80a91bSRichard Fitzgerald 	ssize_t ret;
18192d80a91bSRichard Fitzgerald 
18202d80a91bSRichard Fitzgerald 	if (!c)
18212d80a91bSRichard Fitzgerald 		return 0;
18222d80a91bSRichard Fitzgerald 
18232d80a91bSRichard Fitzgerald 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
18242d80a91bSRichard Fitzgerald 	if (!buf)
18252d80a91bSRichard Fitzgerald 		return -ENOMEM;
18262d80a91bSRichard Fitzgerald 
18272d80a91bSRichard Fitzgerald 	ret = snprintf(buf, PAGE_SIZE,
18282d80a91bSRichard Fitzgerald 			"always_on: %u\n"
18292d80a91bSRichard Fitzgerald 			"boot_on: %u\n"
18302d80a91bSRichard Fitzgerald 			"apply_uV: %u\n"
18312d80a91bSRichard Fitzgerald 			"ramp_disable: %u\n"
18322d80a91bSRichard Fitzgerald 			"soft_start: %u\n"
18332d80a91bSRichard Fitzgerald 			"pull_down: %u\n"
18342d80a91bSRichard Fitzgerald 			"over_current_protection: %u\n",
18352d80a91bSRichard Fitzgerald 			c->always_on,
18362d80a91bSRichard Fitzgerald 			c->boot_on,
18372d80a91bSRichard Fitzgerald 			c->apply_uV,
18382d80a91bSRichard Fitzgerald 			c->ramp_disable,
18392d80a91bSRichard Fitzgerald 			c->soft_start,
18402d80a91bSRichard Fitzgerald 			c->pull_down,
18412d80a91bSRichard Fitzgerald 			c->over_current_protection);
18422d80a91bSRichard Fitzgerald 
18432d80a91bSRichard Fitzgerald 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
18442d80a91bSRichard Fitzgerald 	kfree(buf);
18452d80a91bSRichard Fitzgerald 
18462d80a91bSRichard Fitzgerald 	return ret;
18472d80a91bSRichard Fitzgerald }
18482d80a91bSRichard Fitzgerald 
18492d80a91bSRichard Fitzgerald #endif
18502d80a91bSRichard Fitzgerald 
18512d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = {
18522d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS
18532d80a91bSRichard Fitzgerald 	.open = simple_open,
18542d80a91bSRichard Fitzgerald 	.read = constraint_flags_read_file,
18552d80a91bSRichard Fitzgerald 	.llseek = default_llseek,
18562d80a91bSRichard Fitzgerald #endif
18572d80a91bSRichard Fitzgerald };
18582d80a91bSRichard Fitzgerald 
1859f5726ae3SMark Brown #define REG_STR_SIZE	64
1860414c70cbSLiam Girdwood 
create_regulator(struct regulator_dev * rdev,struct device * dev,const char * supply_name)1861414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev,
1862414c70cbSLiam Girdwood 					  struct device *dev,
1863414c70cbSLiam Girdwood 					  const char *supply_name)
1864414c70cbSLiam Girdwood {
1865414c70cbSLiam Girdwood 	struct regulator *regulator;
1866dbe954d8SHans de Goede 	int err = 0;
1867414c70cbSLiam Girdwood 
1868cba6cfdcSDouglas Anderson 	lockdep_assert_held_once(&rdev->mutex.base);
1869cba6cfdcSDouglas Anderson 
187087fe29b6SMichał Mirosław 	if (dev) {
187187fe29b6SMichał Mirosław 		char buf[REG_STR_SIZE];
187287fe29b6SMichał Mirosław 		int size;
187387fe29b6SMichał Mirosław 
187487fe29b6SMichał Mirosław 		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
187587fe29b6SMichał Mirosław 				dev->kobj.name, supply_name);
187687fe29b6SMichał Mirosław 		if (size >= REG_STR_SIZE)
1877414c70cbSLiam Girdwood 			return NULL;
1878414c70cbSLiam Girdwood 
187987fe29b6SMichał Mirosław 		supply_name = kstrdup(buf, GFP_KERNEL);
188087fe29b6SMichał Mirosław 		if (supply_name == NULL)
188187fe29b6SMichał Mirosław 			return NULL;
188287fe29b6SMichał Mirosław 	} else {
188387fe29b6SMichał Mirosław 		supply_name = kstrdup_const(supply_name, GFP_KERNEL);
188487fe29b6SMichał Mirosław 		if (supply_name == NULL)
188587fe29b6SMichał Mirosław 			return NULL;
188687fe29b6SMichał Mirosław 	}
188787fe29b6SMichał Mirosław 
188887fe29b6SMichał Mirosław 	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
188987fe29b6SMichał Mirosław 	if (regulator == NULL) {
1890dc8d006dSWang ShaoBo 		kfree_const(supply_name);
189187fe29b6SMichał Mirosław 		return NULL;
189287fe29b6SMichał Mirosław 	}
189387fe29b6SMichał Mirosław 
1894414c70cbSLiam Girdwood 	regulator->rdev = rdev;
189587fe29b6SMichał Mirosław 	regulator->supply_name = supply_name;
189687fe29b6SMichał Mirosław 
1897414c70cbSLiam Girdwood 	list_add(&regulator->list, &rdev->consumer_list);
1898414c70cbSLiam Girdwood 
1899414c70cbSLiam Girdwood 	if (dev) {
1900e2c98eafSShawn Guo 		regulator->dev = dev;
1901e2c98eafSShawn Guo 
1902222cc7b1SMark Brown 		/* Add a link to the device sysfs entry */
1903ff268b56SStephen Boyd 		err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
190487fe29b6SMichał Mirosław 					       supply_name);
1905414c70cbSLiam Girdwood 		if (err) {
190661aab5adSMichał Mirosław 			rdev_dbg(rdev, "could not add device link %s: %pe\n",
190761aab5adSMichał Mirosław 				  dev->kobj.name, ERR_PTR(err));
1908222cc7b1SMark Brown 			/* non-fatal */
1909414c70cbSLiam Girdwood 		}
1910414c70cbSLiam Girdwood 	}
19115de70519SMark Brown 
1912e9f86773SJohan Hovold 	if (err != -EEXIST) {
1913dbe954d8SHans de Goede 		regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs);
1914e9f86773SJohan Hovold 		if (IS_ERR(regulator->debugfs)) {
1915ad3a942bSStephen Boyd 			rdev_dbg(rdev, "Failed to create debugfs directory\n");
1916e9f86773SJohan Hovold 			regulator->debugfs = NULL;
1917e9f86773SJohan Hovold 		}
1918e9f86773SJohan Hovold 	}
191908880713SGeert Uytterhoeven 
1920e9f86773SJohan Hovold 	if (regulator->debugfs) {
19215de70519SMark Brown 		debugfs_create_u32("uA_load", 0444, regulator->debugfs,
19225de70519SMark Brown 				   &regulator->uA_load);
19235de70519SMark Brown 		debugfs_create_u32("min_uV", 0444, regulator->debugfs,
1924c360a6dfSChunyan Zhang 				   &regulator->voltage[PM_SUSPEND_ON].min_uV);
19255de70519SMark Brown 		debugfs_create_u32("max_uV", 0444, regulator->debugfs,
1926c360a6dfSChunyan Zhang 				   &regulator->voltage[PM_SUSPEND_ON].max_uV);
192708880713SGeert Uytterhoeven 		debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
192808880713SGeert Uytterhoeven 				    regulator, &constraint_flags_fops);
1929e9f86773SJohan Hovold 	}
19305de70519SMark Brown 
19316492bc1bSMark Brown 	/*
19326492bc1bSMark Brown 	 * Check now if the regulator is an always on regulator - if
19336492bc1bSMark Brown 	 * it is then we don't need to do nearly so much work for
19346492bc1bSMark Brown 	 * enable/disable calls.
19356492bc1bSMark Brown 	 */
19368a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) &&
19376492bc1bSMark Brown 	    _regulator_is_enabled(rdev))
19386492bc1bSMark Brown 		regulator->always_on = true;
19396492bc1bSMark Brown 
1940414c70cbSLiam Girdwood 	return regulator;
1941414c70cbSLiam Girdwood }
1942414c70cbSLiam Girdwood 
_regulator_get_enable_time(struct regulator_dev * rdev)194331aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev)
194431aae2beSMark Brown {
194500c877c6SLaxman Dewangan 	if (rdev->constraints && rdev->constraints->enable_time)
194600c877c6SLaxman Dewangan 		return rdev->constraints->enable_time;
194768ce3a44SAxel Lin 	if (rdev->desc->ops->enable_time)
194831aae2beSMark Brown 		return rdev->desc->ops->enable_time(rdev);
194968ce3a44SAxel Lin 	return rdev->desc->enable_time;
195031aae2beSMark Brown }
195131aae2beSMark Brown 
regulator_find_supply_alias(struct device * dev,const char * supply)1952a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias(
1953a06ccd9cSCharles Keepax 		struct device *dev, const char *supply)
1954a06ccd9cSCharles Keepax {
1955a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
1956a06ccd9cSCharles Keepax 
1957a06ccd9cSCharles Keepax 	list_for_each_entry(map, &regulator_supply_alias_list, list)
1958a06ccd9cSCharles Keepax 		if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
1959a06ccd9cSCharles Keepax 			return map;
1960a06ccd9cSCharles Keepax 
1961a06ccd9cSCharles Keepax 	return NULL;
1962a06ccd9cSCharles Keepax }
1963a06ccd9cSCharles Keepax 
regulator_supply_alias(struct device ** dev,const char ** supply)1964a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply)
1965a06ccd9cSCharles Keepax {
1966a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
1967a06ccd9cSCharles Keepax 
1968a06ccd9cSCharles Keepax 	map = regulator_find_supply_alias(*dev, *supply);
1969a06ccd9cSCharles Keepax 	if (map) {
1970a06ccd9cSCharles Keepax 		dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
1971a06ccd9cSCharles Keepax 				*supply, map->alias_supply,
1972a06ccd9cSCharles Keepax 				dev_name(map->alias_dev));
1973a06ccd9cSCharles Keepax 		*dev = map->alias_dev;
1974a06ccd9cSCharles Keepax 		*supply = map->alias_supply;
1975a06ccd9cSCharles Keepax 	}
1976a06ccd9cSCharles Keepax }
1977a06ccd9cSCharles Keepax 
regulator_match(struct device * dev,const void * data)197885f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data)
197985f3b431STomeu Vizoso {
198085f3b431STomeu Vizoso 	struct regulator_dev *r = dev_to_rdev(dev);
198185f3b431STomeu Vizoso 
198285f3b431STomeu Vizoso 	return strcmp(rdev_get_name(r), data) == 0;
198385f3b431STomeu Vizoso }
198485f3b431STomeu Vizoso 
regulator_lookup_by_name(const char * name)198585f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name)
198685f3b431STomeu Vizoso {
198785f3b431STomeu Vizoso 	struct device *dev;
198885f3b431STomeu Vizoso 
198985f3b431STomeu Vizoso 	dev = class_find_device(&regulator_class, NULL, name, regulator_match);
199085f3b431STomeu Vizoso 
199185f3b431STomeu Vizoso 	return dev ? dev_to_rdev(dev) : NULL;
199285f3b431STomeu Vizoso }
199385f3b431STomeu Vizoso 
199485f3b431STomeu Vizoso /**
199585f3b431STomeu Vizoso  * regulator_dev_lookup - lookup a regulator device.
199685f3b431STomeu Vizoso  * @dev: device for regulator "consumer".
199785f3b431STomeu Vizoso  * @supply: Supply name or regulator ID.
199885f3b431STomeu Vizoso  *
199985f3b431STomeu Vizoso  * If successful, returns a struct regulator_dev that corresponds to the name
2000163478daSDmitry Torokhov  * @supply and with the embedded struct device refcount incremented by one.
2001163478daSDmitry Torokhov  * The refcount must be dropped by calling put_device().
2002163478daSDmitry Torokhov  * On failure one of the following ERR-PTR-encoded values is returned:
2003163478daSDmitry Torokhov  * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed
2004163478daSDmitry Torokhov  * in the future.
200585f3b431STomeu Vizoso  */
regulator_dev_lookup(struct device * dev,const char * supply)200669511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev,
2007163478daSDmitry Torokhov 						  const char *supply)
200869511a45SRajendra Nayak {
200906217197SCharles Keepax 	struct regulator_dev *r = NULL;
201069511a45SRajendra Nayak 	struct device_node *node;
2011576ca436SMark Brown 	struct regulator_map *map;
2012576ca436SMark Brown 	const char *devname = NULL;
201369511a45SRajendra Nayak 
2014a06ccd9cSCharles Keepax 	regulator_supply_alias(&dev, &supply);
2015a06ccd9cSCharles Keepax 
201669511a45SRajendra Nayak 	/* first do a dt based lookup */
201769511a45SRajendra Nayak 	if (dev && dev->of_node) {
201869511a45SRajendra Nayak 		node = of_get_regulator(dev, supply);
20196d191a5fSMark Brown 		if (node) {
202085f3b431STomeu Vizoso 			r = of_find_regulator_by_node(node);
2021f2b41b74SYang Yingliang 			of_node_put(node);
202285f3b431STomeu Vizoso 			if (r)
202369511a45SRajendra Nayak 				return r;
2024163478daSDmitry Torokhov 
20256d191a5fSMark Brown 			/*
2026163478daSDmitry Torokhov 			 * We have a node, but there is no device.
2027163478daSDmitry Torokhov 			 * assume it has not registered yet.
20286d191a5fSMark Brown 			 */
2029163478daSDmitry Torokhov 			return ERR_PTR(-EPROBE_DEFER);
20306d191a5fSMark Brown 		}
203169511a45SRajendra Nayak 	}
203269511a45SRajendra Nayak 
203369511a45SRajendra Nayak 	/* if not found, try doing it non-dt way */
2034576ca436SMark Brown 	if (dev)
2035576ca436SMark Brown 		devname = dev_name(dev);
2036576ca436SMark Brown 
203785f3b431STomeu Vizoso 	mutex_lock(&regulator_list_mutex);
2038576ca436SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
2039576ca436SMark Brown 		/* If the mapping has a device set up it must match */
2040576ca436SMark Brown 		if (map->dev_name &&
2041576ca436SMark Brown 		    (!devname || strcmp(map->dev_name, devname)))
2042576ca436SMark Brown 			continue;
2043576ca436SMark Brown 
204485f3b431STomeu Vizoso 		if (strcmp(map->supply, supply) == 0 &&
204585f3b431STomeu Vizoso 		    get_device(&map->regulator->dev)) {
2046163478daSDmitry Torokhov 			r = map->regulator;
2047163478daSDmitry Torokhov 			break;
2048576ca436SMark Brown 		}
204985f3b431STomeu Vizoso 	}
205085f3b431STomeu Vizoso 	mutex_unlock(&regulator_list_mutex);
2051576ca436SMark Brown 
2052163478daSDmitry Torokhov 	if (r)
2053163478daSDmitry Torokhov 		return r;
2054163478daSDmitry Torokhov 
205506217197SCharles Keepax 	r = regulator_lookup_by_name(supply);
205606217197SCharles Keepax 	if (r)
205706217197SCharles Keepax 		return r;
205806217197SCharles Keepax 
2059163478daSDmitry Torokhov 	return ERR_PTR(-ENODEV);
206069511a45SRajendra Nayak }
206169511a45SRajendra Nayak 
regulator_resolve_supply(struct regulator_dev * rdev)20626261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev)
20636261b06dSBjorn Andersson {
20646261b06dSBjorn Andersson 	struct regulator_dev *r;
20656261b06dSBjorn Andersson 	struct device *dev = rdev->dev.parent;
2066cba6cfdcSDouglas Anderson 	struct ww_acquire_ctx ww_ctx;
2067eaa7995cSDavid Collins 	int ret = 0;
20686261b06dSBjorn Andersson 
206948f1b4efSKrzysztof Kozlowski 	/* No supply to resolve? */
20706261b06dSBjorn Andersson 	if (!rdev->supply_name)
20716261b06dSBjorn Andersson 		return 0;
20726261b06dSBjorn Andersson 
2073eaa7995cSDavid Collins 	/* Supply already resolved? (fast-path without locking contention) */
20746261b06dSBjorn Andersson 	if (rdev->supply)
20756261b06dSBjorn Andersson 		return 0;
20766261b06dSBjorn Andersson 
2077163478daSDmitry Torokhov 	r = regulator_dev_lookup(dev, rdev->supply_name);
2078163478daSDmitry Torokhov 	if (IS_ERR(r)) {
2079163478daSDmitry Torokhov 		ret = PTR_ERR(r);
2080163478daSDmitry Torokhov 
208106423121SMark Brown 		/* Did the lookup explicitly defer for us? */
208206423121SMark Brown 		if (ret == -EPROBE_DEFER)
2083eaa7995cSDavid Collins 			goto out;
208406423121SMark Brown 
20859f7e25edSMark Brown 		if (have_full_constraints()) {
20869f7e25edSMark Brown 			r = dummy_regulator_rdev;
208785f3b431STomeu Vizoso 			get_device(&r->dev);
20889f7e25edSMark Brown 		} else {
20896261b06dSBjorn Andersson 			dev_err(dev, "Failed to resolve %s-supply for %s\n",
20906261b06dSBjorn Andersson 				rdev->supply_name, rdev->desc->name);
2091eaa7995cSDavid Collins 			ret = -EPROBE_DEFER;
2092eaa7995cSDavid Collins 			goto out;
20936261b06dSBjorn Andersson 		}
20949f7e25edSMark Brown 	}
20956261b06dSBjorn Andersson 
20964b639e25SMichał Mirosław 	if (r == rdev) {
20974b639e25SMichał Mirosław 		dev_err(dev, "Supply for %s (%s) resolved to itself\n",
20984b639e25SMichał Mirosław 			rdev->desc->name, rdev->supply_name);
2099eaa7995cSDavid Collins 		if (!have_full_constraints()) {
2100eaa7995cSDavid Collins 			ret = -EINVAL;
2101eaa7995cSDavid Collins 			goto out;
2102eaa7995cSDavid Collins 		}
2103f5c042b2SMichał Mirosław 		r = dummy_regulator_rdev;
2104f5c042b2SMichał Mirosław 		get_device(&r->dev);
21054b639e25SMichał Mirosław 	}
21064b639e25SMichał Mirosław 
210766d228a2SJon Hunter 	/*
210866d228a2SJon Hunter 	 * If the supply's parent device is not the same as the
210966d228a2SJon Hunter 	 * regulator's parent device, then ensure the parent device
211066d228a2SJon Hunter 	 * is bound before we resolve the supply, in case the parent
211166d228a2SJon Hunter 	 * device get probe deferred and unregisters the supply.
211266d228a2SJon Hunter 	 */
211366d228a2SJon Hunter 	if (r->dev.parent && r->dev.parent != rdev->dev.parent) {
211466d228a2SJon Hunter 		if (!device_is_bound(r->dev.parent)) {
211566d228a2SJon Hunter 			put_device(&r->dev);
2116eaa7995cSDavid Collins 			ret = -EPROBE_DEFER;
2117eaa7995cSDavid Collins 			goto out;
211866d228a2SJon Hunter 		}
211966d228a2SJon Hunter 	}
212066d228a2SJon Hunter 
21216261b06dSBjorn Andersson 	/* Recursively resolve the supply of the supply */
21226261b06dSBjorn Andersson 	ret = regulator_resolve_supply(r);
212385f3b431STomeu Vizoso 	if (ret < 0) {
212485f3b431STomeu Vizoso 		put_device(&r->dev);
2125eaa7995cSDavid Collins 		goto out;
212685f3b431STomeu Vizoso 	}
21276261b06dSBjorn Andersson 
212814a71d50SMark Brown 	/*
212914a71d50SMark Brown 	 * Recheck rdev->supply with rdev->mutex lock held to avoid a race
213014a71d50SMark Brown 	 * between rdev->supply null check and setting rdev->supply in
213114a71d50SMark Brown 	 * set_supply() from concurrent tasks.
213214a71d50SMark Brown 	 */
2133cba6cfdcSDouglas Anderson 	regulator_lock_two(rdev, r, &ww_ctx);
213414a71d50SMark Brown 
213514a71d50SMark Brown 	/* Supply just resolved by a concurrent task? */
213614a71d50SMark Brown 	if (rdev->supply) {
2137cba6cfdcSDouglas Anderson 		regulator_unlock_two(rdev, r, &ww_ctx);
213885f3b431STomeu Vizoso 		put_device(&r->dev);
2139eaa7995cSDavid Collins 		goto out;
214085f3b431STomeu Vizoso 	}
21416261b06dSBjorn Andersson 
214214a71d50SMark Brown 	ret = set_supply(rdev, r);
214314a71d50SMark Brown 	if (ret < 0) {
2144cba6cfdcSDouglas Anderson 		regulator_unlock_two(rdev, r, &ww_ctx);
214514a71d50SMark Brown 		put_device(&r->dev);
214614a71d50SMark Brown 		goto out;
214714a71d50SMark Brown 	}
214814a71d50SMark Brown 
2149cba6cfdcSDouglas Anderson 	regulator_unlock_two(rdev, r, &ww_ctx);
215014a71d50SMark Brown 
215105f224caSDouglas Anderson 	/*
215205f224caSDouglas Anderson 	 * In set_machine_constraints() we may have turned this regulator on
215305f224caSDouglas Anderson 	 * but we couldn't propagate to the supply if it hadn't been resolved
215405f224caSDouglas Anderson 	 * yet.  Do it now.
215505f224caSDouglas Anderson 	 */
215605f224caSDouglas Anderson 	if (rdev->use_count) {
21576261b06dSBjorn Andersson 		ret = regulator_enable(rdev->supply);
215836a1f1b6SJavier Martinez Canillas 		if (ret < 0) {
215936a1f1b6SJavier Martinez Canillas 			_regulator_put(rdev->supply);
21608e5356a7SJon Hunter 			rdev->supply = NULL;
2161eaa7995cSDavid Collins 			goto out;
21626261b06dSBjorn Andersson 		}
216336a1f1b6SJavier Martinez Canillas 	}
21646261b06dSBjorn Andersson 
2165eaa7995cSDavid Collins out:
2166eaa7995cSDavid Collins 	return ret;
21676261b06dSBjorn Andersson }
21686261b06dSBjorn Andersson 
21695ffbd136SMark Brown /* Internal regulator request function */
_regulator_get(struct device * dev,const char * id,enum regulator_get_type get_type)2170a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id,
2171a8bd42a9SDmitry Torokhov 				 enum regulator_get_type get_type)
2172414c70cbSLiam Girdwood {
2173414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
21747d245afaSDmitry Torokhov 	struct regulator *regulator;
2175b59b6544SSaravana Kannan 	struct device_link *link;
2176317b5684SMark Brown 	int ret;
2177414c70cbSLiam Girdwood 
2178a8bd42a9SDmitry Torokhov 	if (get_type >= MAX_GET_TYPE) {
2179a8bd42a9SDmitry Torokhov 		dev_err(dev, "invalid type %d in %s\n", get_type, __func__);
2180a8bd42a9SDmitry Torokhov 		return ERR_PTR(-EINVAL);
2181a8bd42a9SDmitry Torokhov 	}
2182a8bd42a9SDmitry Torokhov 
2183414c70cbSLiam Girdwood 	if (id == NULL) {
21845da84fd9SJoe Perches 		pr_err("get() with no identifier\n");
2185043c998fSMark Brown 		return ERR_PTR(-EINVAL);
2186414c70cbSLiam Girdwood 	}
2187414c70cbSLiam Girdwood 
2188163478daSDmitry Torokhov 	rdev = regulator_dev_lookup(dev, id);
2189a4d7641fSDmitry Torokhov 	if (IS_ERR(rdev)) {
2190163478daSDmitry Torokhov 		ret = PTR_ERR(rdev);
2191ef60abbbSMark Brown 
21921e4b545cSNishanth Menon 		/*
2193a4d7641fSDmitry Torokhov 		 * If regulator_dev_lookup() fails with error other
2194a4d7641fSDmitry Torokhov 		 * than -ENODEV our job here is done, we simply return it.
21951e4b545cSNishanth Menon 		 */
2196a4d7641fSDmitry Torokhov 		if (ret != -ENODEV)
2197a4d7641fSDmitry Torokhov 			return ERR_PTR(ret);
21981e4b545cSNishanth Menon 
2199a4d7641fSDmitry Torokhov 		if (!have_full_constraints()) {
2200a4d7641fSDmitry Torokhov 			dev_warn(dev,
2201a4d7641fSDmitry Torokhov 				 "incomplete constraints, dummy supplies not allowed\n");
2202a4d7641fSDmitry Torokhov 			return ERR_PTR(-ENODEV);
220334abbd68SMark Brown 		}
220434abbd68SMark Brown 
2205a4d7641fSDmitry Torokhov 		switch (get_type) {
2206a4d7641fSDmitry Torokhov 		case NORMAL_GET:
2207a4d7641fSDmitry Torokhov 			/*
2208a4d7641fSDmitry Torokhov 			 * Assume that a regulator is physically present and
2209a4d7641fSDmitry Torokhov 			 * enabled, even if it isn't hooked up, and just
2210a4d7641fSDmitry Torokhov 			 * provide a dummy.
2211a4d7641fSDmitry Torokhov 			 */
22126e5505cfSAndy Shevchenko 			dev_warn(dev, "supply %s not found, using dummy regulator\n", id);
2213a4d7641fSDmitry Torokhov 			rdev = dummy_regulator_rdev;
2214a4d7641fSDmitry Torokhov 			get_device(&rdev->dev);
2215a4d7641fSDmitry Torokhov 			break;
2216414c70cbSLiam Girdwood 
2217a4d7641fSDmitry Torokhov 		case EXCLUSIVE_GET:
2218a4d7641fSDmitry Torokhov 			dev_warn(dev,
2219a4d7641fSDmitry Torokhov 				 "dummy supplies not allowed for exclusive requests\n");
2220df561f66SGustavo A. R. Silva 			fallthrough;
2221a4d7641fSDmitry Torokhov 
2222a4d7641fSDmitry Torokhov 		default:
2223a4d7641fSDmitry Torokhov 			return ERR_PTR(-ENODEV);
2224a4d7641fSDmitry Torokhov 		}
2225a4d7641fSDmitry Torokhov 	}
2226a4d7641fSDmitry Torokhov 
22275ffbd136SMark Brown 	if (rdev->exclusive) {
22285ffbd136SMark Brown 		regulator = ERR_PTR(-EPERM);
222985f3b431STomeu Vizoso 		put_device(&rdev->dev);
223085f3b431STomeu Vizoso 		return regulator;
22315ffbd136SMark Brown 	}
22325ffbd136SMark Brown 
2233a8bd42a9SDmitry Torokhov 	if (get_type == EXCLUSIVE_GET && rdev->open_count) {
22345ffbd136SMark Brown 		regulator = ERR_PTR(-EBUSY);
223585f3b431STomeu Vizoso 		put_device(&rdev->dev);
223685f3b431STomeu Vizoso 		return regulator;
22375ffbd136SMark Brown 	}
22385ffbd136SMark Brown 
223979d6f049SDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
224079d6f049SDmitry Osipenko 	ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled);
224179d6f049SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
224279d6f049SDmitry Osipenko 
224379d6f049SDmitry Osipenko 	if (ret != 0) {
224479d6f049SDmitry Osipenko 		regulator = ERR_PTR(-EPROBE_DEFER);
224579d6f049SDmitry Osipenko 		put_device(&rdev->dev);
224679d6f049SDmitry Osipenko 		return regulator;
224779d6f049SDmitry Osipenko 	}
224879d6f049SDmitry Osipenko 
22496261b06dSBjorn Andersson 	ret = regulator_resolve_supply(rdev);
22506261b06dSBjorn Andersson 	if (ret < 0) {
22516261b06dSBjorn Andersson 		regulator = ERR_PTR(ret);
225285f3b431STomeu Vizoso 		put_device(&rdev->dev);
225385f3b431STomeu Vizoso 		return regulator;
22546261b06dSBjorn Andersson 	}
22556261b06dSBjorn Andersson 
225685f3b431STomeu Vizoso 	if (!try_module_get(rdev->owner)) {
22577d245afaSDmitry Torokhov 		regulator = ERR_PTR(-EPROBE_DEFER);
225885f3b431STomeu Vizoso 		put_device(&rdev->dev);
225985f3b431STomeu Vizoso 		return regulator;
226085f3b431STomeu Vizoso 	}
2261a5766f11SLiam Girdwood 
2262cba6cfdcSDouglas Anderson 	regulator_lock(rdev);
2263414c70cbSLiam Girdwood 	regulator = create_regulator(rdev, dev, id);
2264cba6cfdcSDouglas Anderson 	regulator_unlock(rdev);
2265414c70cbSLiam Girdwood 	if (regulator == NULL) {
2266414c70cbSLiam Girdwood 		regulator = ERR_PTR(-ENOMEM);
2267414c70cbSLiam Girdwood 		module_put(rdev->owner);
22684affd79aSWen Yang 		put_device(&rdev->dev);
226985f3b431STomeu Vizoso 		return regulator;
2270414c70cbSLiam Girdwood 	}
2271414c70cbSLiam Girdwood 
22725ffbd136SMark Brown 	rdev->open_count++;
2273a8bd42a9SDmitry Torokhov 	if (get_type == EXCLUSIVE_GET) {
22745ffbd136SMark Brown 		rdev->exclusive = 1;
22755ffbd136SMark Brown 
22765ffbd136SMark Brown 		ret = _regulator_is_enabled(rdev);
2277c3e3ca05SZev Weiss 		if (ret > 0) {
22785ffbd136SMark Brown 			rdev->use_count = 1;
2279c3e3ca05SZev Weiss 			regulator->enable_count = 1;
2280c3e3ca05SZev Weiss 		} else {
22815ffbd136SMark Brown 			rdev->use_count = 0;
2282c3e3ca05SZev Weiss 			regulator->enable_count = 0;
2283c3e3ca05SZev Weiss 		}
22845ffbd136SMark Brown 	}
22855ffbd136SMark Brown 
2286b59b6544SSaravana Kannan 	link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
2287b59b6544SSaravana Kannan 	if (!IS_ERR_OR_NULL(link))
2288b59b6544SSaravana Kannan 		regulator->device_link = true;
2289ed1ae2ddSpascal paillet 
2290414c70cbSLiam Girdwood 	return regulator;
2291414c70cbSLiam Girdwood }
22925ffbd136SMark Brown 
22935ffbd136SMark Brown /**
22945ffbd136SMark Brown  * regulator_get - lookup and obtain a reference to a regulator.
22955ffbd136SMark Brown  * @dev: device for regulator "consumer"
22965ffbd136SMark Brown  * @id: Supply name or regulator ID.
22975ffbd136SMark Brown  *
22985ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
22995ffbd136SMark Brown  * or IS_ERR() condition containing errno.
23005ffbd136SMark Brown  *
230190cf443dSDaniel Scally  * Use of supply names configured via set_consumer_device_supply() is
23025ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
23035ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
23045ffbd136SMark Brown  * device pins in the datasheet.
23055ffbd136SMark Brown  */
regulator_get(struct device * dev,const char * id)23065ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id)
23075ffbd136SMark Brown {
2308a8bd42a9SDmitry Torokhov 	return _regulator_get(dev, id, NORMAL_GET);
23095ffbd136SMark Brown }
2310414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get);
2311414c70cbSLiam Girdwood 
2312070b9079SStephen Boyd /**
23135ffbd136SMark Brown  * regulator_get_exclusive - obtain exclusive access to a regulator.
23145ffbd136SMark Brown  * @dev: device for regulator "consumer"
23155ffbd136SMark Brown  * @id: Supply name or regulator ID.
23165ffbd136SMark Brown  *
23175ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
23185ffbd136SMark Brown  * or IS_ERR() condition containing errno.  Other consumers will be
231969c3f723SStephen Boyd  * unable to obtain this regulator while this reference is held and the
232069c3f723SStephen Boyd  * use count for the regulator will be initialised to reflect the current
232169c3f723SStephen Boyd  * state of the regulator.
23225ffbd136SMark Brown  *
23235ffbd136SMark Brown  * This is intended for use by consumers which cannot tolerate shared
23245ffbd136SMark Brown  * use of the regulator such as those which need to force the
23255ffbd136SMark Brown  * regulator off for correct operation of the hardware they are
23265ffbd136SMark Brown  * controlling.
23275ffbd136SMark Brown  *
232890cf443dSDaniel Scally  * Use of supply names configured via set_consumer_device_supply() is
23295ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
23305ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
23315ffbd136SMark Brown  * device pins in the datasheet.
23325ffbd136SMark Brown  */
regulator_get_exclusive(struct device * dev,const char * id)23335ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
23345ffbd136SMark Brown {
2335a8bd42a9SDmitry Torokhov 	return _regulator_get(dev, id, EXCLUSIVE_GET);
23365ffbd136SMark Brown }
23375ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive);
23385ffbd136SMark Brown 
2339de1dd9fdSMark Brown /**
2340de1dd9fdSMark Brown  * regulator_get_optional - obtain optional access to a regulator.
2341de1dd9fdSMark Brown  * @dev: device for regulator "consumer"
2342de1dd9fdSMark Brown  * @id: Supply name or regulator ID.
2343de1dd9fdSMark Brown  *
2344de1dd9fdSMark Brown  * Returns a struct regulator corresponding to the regulator producer,
234569c3f723SStephen Boyd  * or IS_ERR() condition containing errno.
2346de1dd9fdSMark Brown  *
2347de1dd9fdSMark Brown  * This is intended for use by consumers for devices which can have
2348de1dd9fdSMark Brown  * some supplies unconnected in normal use, such as some MMC devices.
2349de1dd9fdSMark Brown  * It can allow the regulator core to provide stub supplies for other
2350de1dd9fdSMark Brown  * supplies requested using normal regulator_get() calls without
2351de1dd9fdSMark Brown  * disrupting the operation of drivers that can handle absent
2352de1dd9fdSMark Brown  * supplies.
2353de1dd9fdSMark Brown  *
235490cf443dSDaniel Scally  * Use of supply names configured via set_consumer_device_supply() is
2355de1dd9fdSMark Brown  * strongly encouraged.  It is recommended that the supply name used
2356de1dd9fdSMark Brown  * should match the name used for the supply and/or the relevant
2357de1dd9fdSMark Brown  * device pins in the datasheet.
2358de1dd9fdSMark Brown  */
regulator_get_optional(struct device * dev,const char * id)2359de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id)
2360de1dd9fdSMark Brown {
2361a8bd42a9SDmitry Torokhov 	return _regulator_get(dev, id, OPTIONAL_GET);
2362de1dd9fdSMark Brown }
2363de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional);
2364de1dd9fdSMark Brown 
destroy_regulator(struct regulator * regulator)2365e1794aa4SSaravana Kannan static void destroy_regulator(struct regulator *regulator)
2366414c70cbSLiam Girdwood {
2367e1794aa4SSaravana Kannan 	struct regulator_dev *rdev = regulator->rdev;
2368414c70cbSLiam Girdwood 
23695de70519SMark Brown 	debugfs_remove_recursive(regulator->debugfs);
23705de70519SMark Brown 
2371ed1ae2ddSpascal paillet 	if (regulator->dev) {
2372b59b6544SSaravana Kannan 		if (regulator->device_link)
2373ed1ae2ddSpascal paillet 			device_link_remove(regulator->dev, &rdev->dev);
2374ed1ae2ddSpascal paillet 
2375414c70cbSLiam Girdwood 		/* remove any sysfs entries */
2376414c70cbSLiam Girdwood 		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
2377ed1ae2ddSpascal paillet 	}
2378ed1ae2ddSpascal paillet 
237966cf9a7eSMaciej Purski 	regulator_lock(rdev);
2380414c70cbSLiam Girdwood 	list_del(&regulator->list);
2381414c70cbSLiam Girdwood 
23825ffbd136SMark Brown 	rdev->open_count--;
23835ffbd136SMark Brown 	rdev->exclusive = 0;
238466cf9a7eSMaciej Purski 	regulator_unlock(rdev);
23855ffbd136SMark Brown 
23860630b614SStephen Boyd 	kfree_const(regulator->supply_name);
23871768514eSMark Brown 	kfree(regulator);
2388e1794aa4SSaravana Kannan }
2389e1794aa4SSaravana Kannan 
2390e1794aa4SSaravana Kannan /* regulator_list_mutex lock held by regulator_put() */
_regulator_put(struct regulator * regulator)2391e1794aa4SSaravana Kannan static void _regulator_put(struct regulator *regulator)
2392e1794aa4SSaravana Kannan {
2393e1794aa4SSaravana Kannan 	struct regulator_dev *rdev;
2394e1794aa4SSaravana Kannan 
2395e1794aa4SSaravana Kannan 	if (IS_ERR_OR_NULL(regulator))
2396e1794aa4SSaravana Kannan 		return;
2397e1794aa4SSaravana Kannan 
2398e1794aa4SSaravana Kannan 	lockdep_assert_held_once(&regulator_list_mutex);
2399e1794aa4SSaravana Kannan 
2400e1794aa4SSaravana Kannan 	/* Docs say you must disable before calling regulator_put() */
2401e1794aa4SSaravana Kannan 	WARN_ON(regulator->enable_count);
2402e1794aa4SSaravana Kannan 
2403e1794aa4SSaravana Kannan 	rdev = regulator->rdev;
2404e1794aa4SSaravana Kannan 
2405e1794aa4SSaravana Kannan 	destroy_regulator(regulator);
24061768514eSMark Brown 
2407414c70cbSLiam Girdwood 	module_put(rdev->owner);
24084affd79aSWen Yang 	put_device(&rdev->dev);
240923ff2f0fSCharles Keepax }
241023ff2f0fSCharles Keepax 
241123ff2f0fSCharles Keepax /**
241223ff2f0fSCharles Keepax  * regulator_put - "free" the regulator source
241323ff2f0fSCharles Keepax  * @regulator: regulator source
241423ff2f0fSCharles Keepax  *
241523ff2f0fSCharles Keepax  * Note: drivers must ensure that all regulator_enable calls made on this
241623ff2f0fSCharles Keepax  * regulator source are balanced by regulator_disable calls prior to calling
241723ff2f0fSCharles Keepax  * this function.
241823ff2f0fSCharles Keepax  */
regulator_put(struct regulator * regulator)241923ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator)
242023ff2f0fSCharles Keepax {
242123ff2f0fSCharles Keepax 	mutex_lock(&regulator_list_mutex);
242223ff2f0fSCharles Keepax 	_regulator_put(regulator);
2423414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2424414c70cbSLiam Girdwood }
2425414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put);
2426414c70cbSLiam Girdwood 
2427a06ccd9cSCharles Keepax /**
2428a06ccd9cSCharles Keepax  * regulator_register_supply_alias - Provide device alias for supply lookup
2429a06ccd9cSCharles Keepax  *
2430a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2431a06ccd9cSCharles Keepax  * @id: Supply name or regulator ID
2432a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
2433a06ccd9cSCharles Keepax  * @alias_id: Supply name or regulator ID that should be used to lookup the
2434a06ccd9cSCharles Keepax  * supply
2435a06ccd9cSCharles Keepax  *
2436a06ccd9cSCharles Keepax  * All lookups for id on dev will instead be conducted for alias_id on
2437a06ccd9cSCharles Keepax  * alias_dev.
2438a06ccd9cSCharles Keepax  */
regulator_register_supply_alias(struct device * dev,const char * id,struct device * alias_dev,const char * alias_id)2439a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id,
2440a06ccd9cSCharles Keepax 				    struct device *alias_dev,
2441a06ccd9cSCharles Keepax 				    const char *alias_id)
2442a06ccd9cSCharles Keepax {
2443a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
2444a06ccd9cSCharles Keepax 
2445a06ccd9cSCharles Keepax 	map = regulator_find_supply_alias(dev, id);
2446a06ccd9cSCharles Keepax 	if (map)
2447a06ccd9cSCharles Keepax 		return -EEXIST;
2448a06ccd9cSCharles Keepax 
2449a06ccd9cSCharles Keepax 	map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
2450a06ccd9cSCharles Keepax 	if (!map)
2451a06ccd9cSCharles Keepax 		return -ENOMEM;
2452a06ccd9cSCharles Keepax 
2453a06ccd9cSCharles Keepax 	map->src_dev = dev;
2454a06ccd9cSCharles Keepax 	map->src_supply = id;
2455a06ccd9cSCharles Keepax 	map->alias_dev = alias_dev;
2456a06ccd9cSCharles Keepax 	map->alias_supply = alias_id;
2457a06ccd9cSCharles Keepax 
2458a06ccd9cSCharles Keepax 	list_add(&map->list, &regulator_supply_alias_list);
2459a06ccd9cSCharles Keepax 
2460a06ccd9cSCharles Keepax 	pr_info("Adding alias for supply %s,%s -> %s,%s\n",
2461a06ccd9cSCharles Keepax 		id, dev_name(dev), alias_id, dev_name(alias_dev));
2462a06ccd9cSCharles Keepax 
2463a06ccd9cSCharles Keepax 	return 0;
2464a06ccd9cSCharles Keepax }
2465a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias);
2466a06ccd9cSCharles Keepax 
2467a06ccd9cSCharles Keepax /**
2468a06ccd9cSCharles Keepax  * regulator_unregister_supply_alias - Remove device alias
2469a06ccd9cSCharles Keepax  *
2470a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2471a06ccd9cSCharles Keepax  * @id: Supply name or regulator ID
2472a06ccd9cSCharles Keepax  *
2473a06ccd9cSCharles Keepax  * Remove a lookup alias if one exists for id on dev.
2474a06ccd9cSCharles Keepax  */
regulator_unregister_supply_alias(struct device * dev,const char * id)2475a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id)
2476a06ccd9cSCharles Keepax {
2477a06ccd9cSCharles Keepax 	struct regulator_supply_alias *map;
2478a06ccd9cSCharles Keepax 
2479a06ccd9cSCharles Keepax 	map = regulator_find_supply_alias(dev, id);
2480a06ccd9cSCharles Keepax 	if (map) {
2481a06ccd9cSCharles Keepax 		list_del(&map->list);
2482a06ccd9cSCharles Keepax 		kfree(map);
2483a06ccd9cSCharles Keepax 	}
2484a06ccd9cSCharles Keepax }
2485a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
2486a06ccd9cSCharles Keepax 
2487a06ccd9cSCharles Keepax /**
2488a06ccd9cSCharles Keepax  * regulator_bulk_register_supply_alias - register multiple aliases
2489a06ccd9cSCharles Keepax  *
2490a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2491a06ccd9cSCharles Keepax  * @id: List of supply names or regulator IDs
2492a06ccd9cSCharles Keepax  * @alias_dev: device that should be used to lookup the supply
2493a06ccd9cSCharles Keepax  * @alias_id: List of supply names or regulator IDs that should be used to
2494a06ccd9cSCharles Keepax  * lookup the supply
2495a06ccd9cSCharles Keepax  * @num_id: Number of aliases to register
2496a06ccd9cSCharles Keepax  *
2497a06ccd9cSCharles Keepax  * @return 0 on success, an errno on failure.
2498a06ccd9cSCharles Keepax  *
2499a06ccd9cSCharles Keepax  * This helper function allows drivers to register several supply
2500a06ccd9cSCharles Keepax  * aliases in one operation.  If any of the aliases cannot be
2501a06ccd9cSCharles Keepax  * registered any aliases that were registered will be removed
2502a06ccd9cSCharles Keepax  * before returning to the caller.
2503a06ccd9cSCharles Keepax  */
regulator_bulk_register_supply_alias(struct device * dev,const char * const * id,struct device * alias_dev,const char * const * alias_id,int num_id)25049f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev,
25059f8c0fe9SLee Jones 					 const char *const *id,
2506a06ccd9cSCharles Keepax 					 struct device *alias_dev,
25079f8c0fe9SLee Jones 					 const char *const *alias_id,
2508a06ccd9cSCharles Keepax 					 int num_id)
2509a06ccd9cSCharles Keepax {
2510a06ccd9cSCharles Keepax 	int i;
2511a06ccd9cSCharles Keepax 	int ret;
2512a06ccd9cSCharles Keepax 
2513a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i) {
2514a06ccd9cSCharles Keepax 		ret = regulator_register_supply_alias(dev, id[i], alias_dev,
2515a06ccd9cSCharles Keepax 						      alias_id[i]);
2516a06ccd9cSCharles Keepax 		if (ret < 0)
2517a06ccd9cSCharles Keepax 			goto err;
2518a06ccd9cSCharles Keepax 	}
2519a06ccd9cSCharles Keepax 
2520a06ccd9cSCharles Keepax 	return 0;
2521a06ccd9cSCharles Keepax 
2522a06ccd9cSCharles Keepax err:
2523a06ccd9cSCharles Keepax 	dev_err(dev,
2524a06ccd9cSCharles Keepax 		"Failed to create supply alias %s,%s -> %s,%s\n",
2525a06ccd9cSCharles Keepax 		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
2526a06ccd9cSCharles Keepax 
2527a06ccd9cSCharles Keepax 	while (--i >= 0)
2528a06ccd9cSCharles Keepax 		regulator_unregister_supply_alias(dev, id[i]);
2529a06ccd9cSCharles Keepax 
2530a06ccd9cSCharles Keepax 	return ret;
2531a06ccd9cSCharles Keepax }
2532a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
2533a06ccd9cSCharles Keepax 
2534a06ccd9cSCharles Keepax /**
2535a06ccd9cSCharles Keepax  * regulator_bulk_unregister_supply_alias - unregister multiple aliases
2536a06ccd9cSCharles Keepax  *
2537a06ccd9cSCharles Keepax  * @dev: device that will be given as the regulator "consumer"
2538a06ccd9cSCharles Keepax  * @id: List of supply names or regulator IDs
2539a06ccd9cSCharles Keepax  * @num_id: Number of aliases to unregister
2540a06ccd9cSCharles Keepax  *
2541a06ccd9cSCharles Keepax  * This helper function allows drivers to unregister several supply
2542a06ccd9cSCharles Keepax  * aliases in one operation.
2543a06ccd9cSCharles Keepax  */
regulator_bulk_unregister_supply_alias(struct device * dev,const char * const * id,int num_id)2544a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev,
25459f8c0fe9SLee Jones 					    const char *const *id,
2546a06ccd9cSCharles Keepax 					    int num_id)
2547a06ccd9cSCharles Keepax {
2548a06ccd9cSCharles Keepax 	int i;
2549a06ccd9cSCharles Keepax 
2550a06ccd9cSCharles Keepax 	for (i = 0; i < num_id; ++i)
2551a06ccd9cSCharles Keepax 		regulator_unregister_supply_alias(dev, id[i]);
2552a06ccd9cSCharles Keepax }
2553a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
2554a06ccd9cSCharles Keepax 
2555a06ccd9cSCharles Keepax 
2556f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
regulator_ena_gpio_request(struct regulator_dev * rdev,const struct regulator_config * config)2557f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev,
2558f19b00daSKim, Milo 				const struct regulator_config *config)
2559f19b00daSKim, Milo {
2560467bf301SMichał Mirosław 	struct regulator_enable_gpio *pin, *new_pin;
2561778b28b4SRussell King 	struct gpio_desc *gpiod;
2562f19b00daSKim, Milo 
2563e45e290aSLinus Walleij 	gpiod = config->ena_gpiod;
2564467bf301SMichał Mirosław 	new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);
2565467bf301SMichał Mirosław 
2566467bf301SMichał Mirosław 	mutex_lock(&regulator_list_mutex);
2567778b28b4SRussell King 
2568f19b00daSKim, Milo 	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
2569778b28b4SRussell King 		if (pin->gpiod == gpiod) {
2570541d052dSLinus Walleij 			rdev_dbg(rdev, "GPIO is already used\n");
2571f19b00daSKim, Milo 			goto update_ena_gpio_to_rdev;
2572f19b00daSKim, Milo 		}
2573f19b00daSKim, Milo 	}
2574f19b00daSKim, Milo 
2575467bf301SMichał Mirosław 	if (new_pin == NULL) {
2576467bf301SMichał Mirosław 		mutex_unlock(&regulator_list_mutex);
2577f19b00daSKim, Milo 		return -ENOMEM;
2578467bf301SMichał Mirosław 	}
2579467bf301SMichał Mirosław 
2580467bf301SMichał Mirosław 	pin = new_pin;
2581467bf301SMichał Mirosław 	new_pin = NULL;
2582f19b00daSKim, Milo 
2583778b28b4SRussell King 	pin->gpiod = gpiod;
2584f19b00daSKim, Milo 	list_add(&pin->list, &regulator_ena_gpio_list);
2585f19b00daSKim, Milo 
2586f19b00daSKim, Milo update_ena_gpio_to_rdev:
2587f19b00daSKim, Milo 	pin->request_count++;
2588f19b00daSKim, Milo 	rdev->ena_pin = pin;
2589467bf301SMichał Mirosław 
2590467bf301SMichał Mirosław 	mutex_unlock(&regulator_list_mutex);
2591467bf301SMichał Mirosław 	kfree(new_pin);
2592467bf301SMichał Mirosław 
2593f19b00daSKim, Milo 	return 0;
2594f19b00daSKim, Milo }
2595f19b00daSKim, Milo 
regulator_ena_gpio_free(struct regulator_dev * rdev)2596f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev)
2597f19b00daSKim, Milo {
2598f19b00daSKim, Milo 	struct regulator_enable_gpio *pin, *n;
2599f19b00daSKim, Milo 
2600f19b00daSKim, Milo 	if (!rdev->ena_pin)
2601f19b00daSKim, Milo 		return;
2602f19b00daSKim, Milo 
2603f19b00daSKim, Milo 	/* Free the GPIO only in case of no use */
2604f19b00daSKim, Milo 	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
26052dbf0855SMichał Mirosław 		if (pin != rdev->ena_pin)
26062dbf0855SMichał Mirosław 			continue;
26072dbf0855SMichał Mirosław 
26082dbf0855SMichał Mirosław 		if (--pin->request_count)
26092dbf0855SMichał Mirosław 			break;
26102dbf0855SMichał Mirosław 
261178927aa4SLinus Walleij 		gpiod_put(pin->gpiod);
2612f19b00daSKim, Milo 		list_del(&pin->list);
2613f19b00daSKim, Milo 		kfree(pin);
26142dbf0855SMichał Mirosław 		break;
26152dbf0855SMichał Mirosław 	}
26162dbf0855SMichał Mirosław 
261760a2362fSSeung-Woo Kim 	rdev->ena_pin = NULL;
2618f19b00daSKim, Milo }
2619f19b00daSKim, Milo 
2620967cfb18SKim, Milo /**
262131d6eebfSRobert P. J. Day  * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control
262231d6eebfSRobert P. J. Day  * @rdev: regulator_dev structure
262331d6eebfSRobert P. J. Day  * @enable: enable GPIO at initial use?
262431d6eebfSRobert P. J. Day  *
2625967cfb18SKim, Milo  * GPIO is enabled in case of initial use. (enable_count is 0)
2626967cfb18SKim, Milo  * GPIO is disabled when it is not shared any more. (enable_count <= 1)
2627967cfb18SKim, Milo  */
regulator_ena_gpio_ctrl(struct regulator_dev * rdev,bool enable)2628967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
2629967cfb18SKim, Milo {
2630967cfb18SKim, Milo 	struct regulator_enable_gpio *pin = rdev->ena_pin;
2631967cfb18SKim, Milo 
2632967cfb18SKim, Milo 	if (!pin)
2633967cfb18SKim, Milo 		return -EINVAL;
2634967cfb18SKim, Milo 
2635967cfb18SKim, Milo 	if (enable) {
2636967cfb18SKim, Milo 		/* Enable GPIO at initial use */
2637967cfb18SKim, Milo 		if (pin->enable_count == 0)
263801dc79cdSLinus Walleij 			gpiod_set_value_cansleep(pin->gpiod, 1);
2639967cfb18SKim, Milo 
2640967cfb18SKim, Milo 		pin->enable_count++;
2641967cfb18SKim, Milo 	} else {
2642967cfb18SKim, Milo 		if (pin->enable_count > 1) {
2643967cfb18SKim, Milo 			pin->enable_count--;
2644967cfb18SKim, Milo 			return 0;
2645967cfb18SKim, Milo 		}
2646967cfb18SKim, Milo 
2647967cfb18SKim, Milo 		/* Disable GPIO if not used */
2648967cfb18SKim, Milo 		if (pin->enable_count <= 1) {
264901dc79cdSLinus Walleij 			gpiod_set_value_cansleep(pin->gpiod, 0);
2650967cfb18SKim, Milo 			pin->enable_count = 0;
2651967cfb18SKim, Milo 		}
2652967cfb18SKim, Milo 	}
2653967cfb18SKim, Milo 
2654967cfb18SKim, Milo 	return 0;
2655967cfb18SKim, Milo }
2656967cfb18SKim, Milo 
265779fd1141SGuodong Xu /**
2658a38dce4cSBrian Norris  * _regulator_delay_helper - a delay helper function
265979fd1141SGuodong Xu  * @delay: time to delay in microseconds
266079fd1141SGuodong Xu  *
26615df529d4SThierry Reding  * Delay for the requested amount of time as per the guidelines in:
26625df529d4SThierry Reding  *
2663458f69efSMauro Carvalho Chehab  *     Documentation/timers/timers-howto.rst
26645df529d4SThierry Reding  *
2665a38dce4cSBrian Norris  * The assumption here is that these regulator operations will never used in
26665df529d4SThierry Reding  * atomic context and therefore sleeping functions can be used.
26675df529d4SThierry Reding  */
_regulator_delay_helper(unsigned int delay)2668a38dce4cSBrian Norris static void _regulator_delay_helper(unsigned int delay)
266979fd1141SGuodong Xu {
26705df529d4SThierry Reding 	unsigned int ms = delay / 1000;
26715df529d4SThierry Reding 	unsigned int us = delay % 1000;
26725df529d4SThierry Reding 
26735df529d4SThierry Reding 	if (ms > 0) {
26745df529d4SThierry Reding 		/*
26755df529d4SThierry Reding 		 * For small enough values, handle super-millisecond
26765df529d4SThierry Reding 		 * delays in the usleep_range() call below.
26775df529d4SThierry Reding 		 */
26785df529d4SThierry Reding 		if (ms < 20)
26795df529d4SThierry Reding 			us += ms * 1000;
26805df529d4SThierry Reding 		else
26815df529d4SThierry Reding 			msleep(ms);
26825df529d4SThierry Reding 	}
26835df529d4SThierry Reding 
26845df529d4SThierry Reding 	/*
26855df529d4SThierry Reding 	 * Give the scheduler some room to coalesce with any other
26865df529d4SThierry Reding 	 * wakeup sources. For delays shorter than 10 us, don't even
26875df529d4SThierry Reding 	 * bother setting up high-resolution timers and just busy-
26885df529d4SThierry Reding 	 * loop.
26895df529d4SThierry Reding 	 */
26905df529d4SThierry Reding 	if (us >= 10)
26915df529d4SThierry Reding 		usleep_range(us, us + 100);
26925df529d4SThierry Reding 	else
26935df529d4SThierry Reding 		udelay(us);
26945c5659d0SMark Brown }
26955c5659d0SMark Brown 
2696f7d7ad42SSumit Semwal /**
2697f7d7ad42SSumit Semwal  * _regulator_check_status_enabled
2698f7d7ad42SSumit Semwal  *
2699f7d7ad42SSumit Semwal  * A helper function to check if the regulator status can be interpreted
2700f7d7ad42SSumit Semwal  * as 'regulator is enabled'.
2701f7d7ad42SSumit Semwal  * @rdev: the regulator device to check
2702f7d7ad42SSumit Semwal  *
2703f7d7ad42SSumit Semwal  * Return:
2704f7d7ad42SSumit Semwal  * * 1			- if status shows regulator is in enabled state
2705f7d7ad42SSumit Semwal  * * 0			- if not enabled state
2706f7d7ad42SSumit Semwal  * * Error Value	- as received from ops->get_status()
2707f7d7ad42SSumit Semwal  */
_regulator_check_status_enabled(struct regulator_dev * rdev)2708f7d7ad42SSumit Semwal static inline int _regulator_check_status_enabled(struct regulator_dev *rdev)
2709f7d7ad42SSumit Semwal {
2710f7d7ad42SSumit Semwal 	int ret = rdev->desc->ops->get_status(rdev);
2711f7d7ad42SSumit Semwal 
2712f7d7ad42SSumit Semwal 	if (ret < 0) {
2713f7d7ad42SSumit Semwal 		rdev_info(rdev, "get_status returned error: %d\n", ret);
2714f7d7ad42SSumit Semwal 		return ret;
2715f7d7ad42SSumit Semwal 	}
2716f7d7ad42SSumit Semwal 
2717f7d7ad42SSumit Semwal 	switch (ret) {
2718f7d7ad42SSumit Semwal 	case REGULATOR_STATUS_OFF:
2719f7d7ad42SSumit Semwal 	case REGULATOR_STATUS_ERROR:
2720f7d7ad42SSumit Semwal 	case REGULATOR_STATUS_UNDEFINED:
2721f7d7ad42SSumit Semwal 		return 0;
2722f7d7ad42SSumit Semwal 	default:
2723f7d7ad42SSumit Semwal 		return 1;
2724f7d7ad42SSumit Semwal 	}
2725f7d7ad42SSumit Semwal }
2726f7d7ad42SSumit Semwal 
_regulator_do_enable(struct regulator_dev * rdev)27275c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev)
27285c5659d0SMark Brown {
27295c5659d0SMark Brown 	int ret, delay;
27305c5659d0SMark Brown 
27315c5659d0SMark Brown 	/* Query before enabling in case configuration dependent.  */
27325c5659d0SMark Brown 	ret = _regulator_get_enable_time(rdev);
27335c5659d0SMark Brown 	if (ret >= 0) {
27345c5659d0SMark Brown 		delay = ret;
27355c5659d0SMark Brown 	} else {
273661aab5adSMichał Mirosław 		rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret));
2737414c70cbSLiam Girdwood 		delay = 0;
2738414c70cbSLiam Girdwood 	}
27395c5659d0SMark Brown 
2740414c70cbSLiam Girdwood 	trace_regulator_enable(rdev_get_name(rdev));
2741414c70cbSLiam Girdwood 
2742691c1fcdSDouglas Anderson 	if (rdev->desc->off_on_delay) {
2743871f5650SGuodong Xu 		/* if needed, keep a distance of off_on_delay from last time
2744871f5650SGuodong Xu 		 * this regulator was disabled.
2745871f5650SGuodong Xu 		 */
2746a8ce7bd8SVincent Whitchurch 		ktime_t end = ktime_add_us(rdev->last_off, rdev->desc->off_on_delay);
274780d2c29eSMatthias Kaehlcke 		s64 remaining = ktime_us_delta(end, ktime_get_boottime());
2748871f5650SGuodong Xu 
2749a8ce7bd8SVincent Whitchurch 		if (remaining > 0)
2750a38dce4cSBrian Norris 			_regulator_delay_helper(remaining);
2751871f5650SGuodong Xu 	}
2752871f5650SGuodong Xu 
2753414c70cbSLiam Girdwood 	if (rdev->ena_pin) {
275429d62ec5SDoug Anderson 		if (!rdev->ena_gpio_state) {
27559a2372faSMark Brown 			ret = regulator_ena_gpio_ctrl(rdev, true);
2756414c70cbSLiam Girdwood 			if (ret < 0)
2757414c70cbSLiam Girdwood 				return ret;
27589a2372faSMark Brown 			rdev->ena_gpio_state = 1;
275929d62ec5SDoug Anderson 		}
27609a2372faSMark Brown 	} else if (rdev->desc->ops->enable) {
27619a2372faSMark Brown 		ret = rdev->desc->ops->enable(rdev);
27629a2372faSMark Brown 		if (ret < 0)
27639a2372faSMark Brown 			return ret;
27649a2372faSMark Brown 	} else {
27659a2372faSMark Brown 		return -EINVAL;
27665c5659d0SMark Brown 	}
27679a2372faSMark Brown 
27689a2372faSMark Brown 	/* Allow the regulator to ramp; it would be useful to extend
276931aae2beSMark Brown 	 * this for bulk operations so that the regulators can ramp
277069b8821eSShubhankar Kuranagatti 	 * together.
277169b8821eSShubhankar Kuranagatti 	 */
27725da84fd9SJoe Perches 	trace_regulator_enable_delay(rdev_get_name(rdev));
2773414c70cbSLiam Girdwood 
2774f7d7ad42SSumit Semwal 	/* If poll_enabled_time is set, poll upto the delay calculated
2775f7d7ad42SSumit Semwal 	 * above, delaying poll_enabled_time uS to check if the regulator
2776f7d7ad42SSumit Semwal 	 * actually got enabled.
2777a38dce4cSBrian Norris 	 * If the regulator isn't enabled after our delay helper has expired,
2778a38dce4cSBrian Norris 	 * return -ETIMEDOUT.
2779f7d7ad42SSumit Semwal 	 */
2780f7d7ad42SSumit Semwal 	if (rdev->desc->poll_enabled_time) {
27818d8e1659SPatrick Rudolph 		int time_remaining = delay;
2782f7d7ad42SSumit Semwal 
2783f7d7ad42SSumit Semwal 		while (time_remaining > 0) {
2784a38dce4cSBrian Norris 			_regulator_delay_helper(rdev->desc->poll_enabled_time);
2785f7d7ad42SSumit Semwal 
2786f7d7ad42SSumit Semwal 			if (rdev->desc->ops->get_status) {
2787f7d7ad42SSumit Semwal 				ret = _regulator_check_status_enabled(rdev);
2788f7d7ad42SSumit Semwal 				if (ret < 0)
2789f7d7ad42SSumit Semwal 					return ret;
2790f7d7ad42SSumit Semwal 				else if (ret)
2791f7d7ad42SSumit Semwal 					break;
2792f7d7ad42SSumit Semwal 			} else if (rdev->desc->ops->is_enabled(rdev))
2793f7d7ad42SSumit Semwal 				break;
2794f7d7ad42SSumit Semwal 
2795f7d7ad42SSumit Semwal 			time_remaining -= rdev->desc->poll_enabled_time;
2796f7d7ad42SSumit Semwal 		}
2797f7d7ad42SSumit Semwal 
2798f7d7ad42SSumit Semwal 		if (time_remaining <= 0) {
2799f7d7ad42SSumit Semwal 			rdev_err(rdev, "Enabled check timed out\n");
2800f7d7ad42SSumit Semwal 			return -ETIMEDOUT;
2801f7d7ad42SSumit Semwal 		}
2802f7d7ad42SSumit Semwal 	} else {
2803a38dce4cSBrian Norris 		_regulator_delay_helper(delay);
2804f7d7ad42SSumit Semwal 	}
2805a7433cffSLinus Walleij 
2806414c70cbSLiam Girdwood 	trace_regulator_enable_complete(rdev_get_name(rdev));
2807414c70cbSLiam Girdwood 
28089a2372faSMark Brown 	return 0;
28099a2372faSMark Brown }
28109a2372faSMark Brown 
28115451781dSDouglas Anderson /**
28125451781dSDouglas Anderson  * _regulator_handle_consumer_enable - handle that a consumer enabled
28135451781dSDouglas Anderson  * @regulator: regulator source
28145451781dSDouglas Anderson  *
28155451781dSDouglas Anderson  * Some things on a regulator consumer (like the contribution towards total
28165451781dSDouglas Anderson  * load on the regulator) only have an effect when the consumer wants the
28175451781dSDouglas Anderson  * regulator enabled.  Explained in example with two consumers of the same
28185451781dSDouglas Anderson  * regulator:
28195451781dSDouglas Anderson  *   consumer A: set_load(100);       => total load = 0
28205451781dSDouglas Anderson  *   consumer A: regulator_enable();  => total load = 100
28215451781dSDouglas Anderson  *   consumer B: set_load(1000);      => total load = 100
28225451781dSDouglas Anderson  *   consumer B: regulator_enable();  => total load = 1100
28235451781dSDouglas Anderson  *   consumer A: regulator_disable(); => total_load = 1000
28245451781dSDouglas Anderson  *
28255451781dSDouglas Anderson  * This function (together with _regulator_handle_consumer_disable) is
28265451781dSDouglas Anderson  * responsible for keeping track of the refcount for a given regulator consumer
28275451781dSDouglas Anderson  * and applying / unapplying these things.
28285451781dSDouglas Anderson  *
28295451781dSDouglas Anderson  * Returns 0 upon no error; -error upon error.
28305451781dSDouglas Anderson  */
_regulator_handle_consumer_enable(struct regulator * regulator)28315451781dSDouglas Anderson static int _regulator_handle_consumer_enable(struct regulator *regulator)
2832414c70cbSLiam Girdwood {
2833c32f1ebfSAndrew Halaney 	int ret;
28345451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
28355451781dSDouglas Anderson 
28365451781dSDouglas Anderson 	lockdep_assert_held_once(&rdev->mutex.base);
28375451781dSDouglas Anderson 
28385451781dSDouglas Anderson 	regulator->enable_count++;
2839c32f1ebfSAndrew Halaney 	if (regulator->uA_load && regulator->enable_count == 1) {
2840c32f1ebfSAndrew Halaney 		ret = drms_uA_update(rdev);
2841c32f1ebfSAndrew Halaney 		if (ret)
2842c32f1ebfSAndrew Halaney 			regulator->enable_count--;
2843c32f1ebfSAndrew Halaney 		return ret;
2844c32f1ebfSAndrew Halaney 	}
28455451781dSDouglas Anderson 
28465451781dSDouglas Anderson 	return 0;
28475451781dSDouglas Anderson }
28485451781dSDouglas Anderson 
28495451781dSDouglas Anderson /**
28505451781dSDouglas Anderson  * _regulator_handle_consumer_disable - handle that a consumer disabled
28515451781dSDouglas Anderson  * @regulator: regulator source
28525451781dSDouglas Anderson  *
28535451781dSDouglas Anderson  * The opposite of _regulator_handle_consumer_enable().
28545451781dSDouglas Anderson  *
28555451781dSDouglas Anderson  * Returns 0 upon no error; -error upon error.
28565451781dSDouglas Anderson  */
_regulator_handle_consumer_disable(struct regulator * regulator)28575451781dSDouglas Anderson static int _regulator_handle_consumer_disable(struct regulator *regulator)
28585451781dSDouglas Anderson {
28595451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
28605451781dSDouglas Anderson 
28615451781dSDouglas Anderson 	lockdep_assert_held_once(&rdev->mutex.base);
28625451781dSDouglas Anderson 
28635451781dSDouglas Anderson 	if (!regulator->enable_count) {
28645451781dSDouglas Anderson 		rdev_err(rdev, "Underflow of regulator enable count\n");
28655451781dSDouglas Anderson 		return -EINVAL;
28665451781dSDouglas Anderson 	}
28675451781dSDouglas Anderson 
28685451781dSDouglas Anderson 	regulator->enable_count--;
28695451781dSDouglas Anderson 	if (regulator->uA_load && regulator->enable_count == 0)
28705451781dSDouglas Anderson 		return drms_uA_update(rdev);
28715451781dSDouglas Anderson 
28725451781dSDouglas Anderson 	return 0;
28735451781dSDouglas Anderson }
28745451781dSDouglas Anderson 
28755451781dSDouglas Anderson /* locks held by regulator_enable() */
_regulator_enable(struct regulator * regulator)28765451781dSDouglas Anderson static int _regulator_enable(struct regulator *regulator)
28775451781dSDouglas Anderson {
28785451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
2879414c70cbSLiam Girdwood 	int ret;
2880414c70cbSLiam Girdwood 
2881f8702f9eSDmitry Osipenko 	lockdep_assert_held_once(&rdev->mutex.base);
2882f8702f9eSDmitry Osipenko 
28831fc12b05SDouglas Anderson 	if (rdev->use_count == 0 && rdev->supply) {
28845451781dSDouglas Anderson 		ret = _regulator_enable(rdev->supply);
2885f8702f9eSDmitry Osipenko 		if (ret < 0)
2886f8702f9eSDmitry Osipenko 			return ret;
2887f8702f9eSDmitry Osipenko 	}
2888f8702f9eSDmitry Osipenko 
2889f8702f9eSDmitry Osipenko 	/* balance only if there are regulators coupled */
2890f8702f9eSDmitry Osipenko 	if (rdev->coupling_desc.n_coupled > 1) {
2891f8702f9eSDmitry Osipenko 		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
2892f8702f9eSDmitry Osipenko 		if (ret < 0)
2893f8702f9eSDmitry Osipenko 			goto err_disable_supply;
2894f8702f9eSDmitry Osipenko 	}
289570cfef26SKrzysztof Kozlowski 
28965451781dSDouglas Anderson 	ret = _regulator_handle_consumer_enable(regulator);
28975451781dSDouglas Anderson 	if (ret < 0)
28985451781dSDouglas Anderson 		goto err_disable_supply;
2899cf7bbcdfSMark Brown 
2900414c70cbSLiam Girdwood 	if (rdev->use_count == 0) {
290172241e31SSebastian Fricke 		/*
290272241e31SSebastian Fricke 		 * The regulator may already be enabled if it's not switchable
290372241e31SSebastian Fricke 		 * or was left on
290472241e31SSebastian Fricke 		 */
2905414c70cbSLiam Girdwood 		ret = _regulator_is_enabled(rdev);
2906414c70cbSLiam Girdwood 		if (ret == -EINVAL || ret == 0) {
29078a34e979SWEN Pingbo 			if (!regulator_ops_is_valid(rdev,
2908f8702f9eSDmitry Osipenko 					REGULATOR_CHANGE_STATUS)) {
2909f8702f9eSDmitry Osipenko 				ret = -EPERM;
29105451781dSDouglas Anderson 				goto err_consumer_disable;
2911f8702f9eSDmitry Osipenko 			}
2912412aec61SDavid Brownell 
2913414c70cbSLiam Girdwood 			ret = _regulator_do_enable(rdev);
2914412aec61SDavid Brownell 			if (ret < 0)
29155451781dSDouglas Anderson 				goto err_consumer_disable;
2916414c70cbSLiam Girdwood 
2917264b88c9SHarald Geyer 			_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,
2918264b88c9SHarald Geyer 					     NULL);
2919414c70cbSLiam Girdwood 		} else if (ret < 0) {
292061aab5adSMichał Mirosław 			rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret));
29215451781dSDouglas Anderson 			goto err_consumer_disable;
2922414c70cbSLiam Girdwood 		}
2923414c70cbSLiam Girdwood 		/* Fallthrough on positive return values - already enabled */
2924414c70cbSLiam Girdwood 	}
2925414c70cbSLiam Girdwood 
29263023b44aSRui Zhang 	if (regulator->enable_count == 1)
2927414c70cbSLiam Girdwood 		rdev->use_count++;
2928414c70cbSLiam Girdwood 
2929414c70cbSLiam Girdwood 	return 0;
2930f8702f9eSDmitry Osipenko 
29315451781dSDouglas Anderson err_consumer_disable:
29325451781dSDouglas Anderson 	_regulator_handle_consumer_disable(regulator);
29335451781dSDouglas Anderson 
2934f8702f9eSDmitry Osipenko err_disable_supply:
29351fc12b05SDouglas Anderson 	if (rdev->use_count == 0 && rdev->supply)
29365451781dSDouglas Anderson 		_regulator_disable(rdev->supply);
2937f8702f9eSDmitry Osipenko 
2938f8702f9eSDmitry Osipenko 	return ret;
2939414c70cbSLiam Girdwood }
2940414c70cbSLiam Girdwood 
2941414c70cbSLiam Girdwood /**
2942414c70cbSLiam Girdwood  * regulator_enable - enable regulator output
2943414c70cbSLiam Girdwood  * @regulator: regulator source
2944414c70cbSLiam Girdwood  *
2945414c70cbSLiam Girdwood  * Request that the regulator be enabled with the regulator output at
2946414c70cbSLiam Girdwood  * the predefined voltage or current value.  Calls to regulator_enable()
2947414c70cbSLiam Girdwood  * must be balanced with calls to regulator_disable().
2948414c70cbSLiam Girdwood  *
2949414c70cbSLiam Girdwood  * NOTE: the output value can be set by other drivers, boot loader or may be
2950414c70cbSLiam Girdwood  * hardwired in the regulator.
2951414c70cbSLiam Girdwood  */
regulator_enable(struct regulator * regulator)2952414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator)
2953414c70cbSLiam Girdwood {
2954414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2955f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
29565451781dSDouglas Anderson 	int ret;
29576492bc1bSMark Brown 
2958f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
29595451781dSDouglas Anderson 	ret = _regulator_enable(regulator);
2960f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(rdev, &ww_ctx);
29613801b86aSMark Brown 
2962414c70cbSLiam Girdwood 	return ret;
2963414c70cbSLiam Girdwood }
2964414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable);
2965414c70cbSLiam Girdwood 
_regulator_do_disable(struct regulator_dev * rdev)29665c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev)
29675c5659d0SMark Brown {
29685c5659d0SMark Brown 	int ret;
29695c5659d0SMark Brown 
29705c5659d0SMark Brown 	trace_regulator_disable(rdev_get_name(rdev));
29715c5659d0SMark Brown 
2972967cfb18SKim, Milo 	if (rdev->ena_pin) {
297329d62ec5SDoug Anderson 		if (rdev->ena_gpio_state) {
2974967cfb18SKim, Milo 			ret = regulator_ena_gpio_ctrl(rdev, false);
2975967cfb18SKim, Milo 			if (ret < 0)
2976967cfb18SKim, Milo 				return ret;
29775c5659d0SMark Brown 			rdev->ena_gpio_state = 0;
297829d62ec5SDoug Anderson 		}
29795c5659d0SMark Brown 
29805c5659d0SMark Brown 	} else if (rdev->desc->ops->disable) {
29815c5659d0SMark Brown 		ret = rdev->desc->ops->disable(rdev);
29825c5659d0SMark Brown 		if (ret != 0)
29835c5659d0SMark Brown 			return ret;
29845c5659d0SMark Brown 	}
29855c5659d0SMark Brown 
2986871f5650SGuodong Xu 	if (rdev->desc->off_on_delay)
298780d2c29eSMatthias Kaehlcke 		rdev->last_off = ktime_get_boottime();
2988871f5650SGuodong Xu 
29895c5659d0SMark Brown 	trace_regulator_disable_complete(rdev_get_name(rdev));
29905c5659d0SMark Brown 
29915c5659d0SMark Brown 	return 0;
29925c5659d0SMark Brown }
29935c5659d0SMark Brown 
2994414c70cbSLiam Girdwood /* locks held by regulator_disable() */
_regulator_disable(struct regulator * regulator)29955451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator)
2996414c70cbSLiam Girdwood {
29975451781dSDouglas Anderson 	struct regulator_dev *rdev = regulator->rdev;
2998414c70cbSLiam Girdwood 	int ret = 0;
2999414c70cbSLiam Girdwood 
3000f8702f9eSDmitry Osipenko 	lockdep_assert_held_once(&rdev->mutex.base);
300170cfef26SKrzysztof Kozlowski 
30023023b44aSRui Zhang 	if (WARN(regulator->enable_count == 0,
300343e7ee33SJoe Perches 		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
3004cd94b505SDavid Brownell 		return -EIO;
3005cd94b505SDavid Brownell 
30063023b44aSRui Zhang 	if (regulator->enable_count == 1) {
30073023b44aSRui Zhang 	/* disabling last enable_count from this regulator */
3008414c70cbSLiam Girdwood 		/* are we the last user and permitted to disable ? */
300960ef66fcSMark Brown 		if (rdev->use_count == 1 &&
301060ef66fcSMark Brown 		    (rdev->constraints && !rdev->constraints->always_on)) {
3011414c70cbSLiam Girdwood 
3012414c70cbSLiam Girdwood 			/* we are last user */
30138a34e979SWEN Pingbo 			if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
3014a1c8a551SRichard Fitzgerald 				ret = _notifier_call_chain(rdev,
3015a1c8a551SRichard Fitzgerald 							   REGULATOR_EVENT_PRE_DISABLE,
3016a1c8a551SRichard Fitzgerald 							   NULL);
3017a1c8a551SRichard Fitzgerald 				if (ret & NOTIFY_STOP_MASK)
3018a1c8a551SRichard Fitzgerald 					return -EINVAL;
3019a1c8a551SRichard Fitzgerald 
30205c5659d0SMark Brown 				ret = _regulator_do_disable(rdev);
3021414c70cbSLiam Girdwood 				if (ret < 0) {
302261aab5adSMichał Mirosław 					rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret));
3023a1c8a551SRichard Fitzgerald 					_notifier_call_chain(rdev,
3024a1c8a551SRichard Fitzgerald 							REGULATOR_EVENT_ABORT_DISABLE,
3025a1c8a551SRichard Fitzgerald 							NULL);
3026414c70cbSLiam Girdwood 					return ret;
3027414c70cbSLiam Girdwood 				}
302866fda75fSMarkus Pargmann 				_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
302966fda75fSMarkus Pargmann 						NULL);
3030414c70cbSLiam Girdwood 			}
3031414c70cbSLiam Girdwood 
3032414c70cbSLiam Girdwood 			rdev->use_count = 0;
3033414c70cbSLiam Girdwood 		} else if (rdev->use_count > 1) {
3034414c70cbSLiam Girdwood 			rdev->use_count--;
3035414c70cbSLiam Girdwood 		}
30363023b44aSRui Zhang 	}
30373801b86aSMark Brown 
30385451781dSDouglas Anderson 	if (ret == 0)
30395451781dSDouglas Anderson 		ret = _regulator_handle_consumer_disable(regulator);
30405451781dSDouglas Anderson 
3041f8702f9eSDmitry Osipenko 	if (ret == 0 && rdev->coupling_desc.n_coupled > 1)
3042f8702f9eSDmitry Osipenko 		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
3043f8702f9eSDmitry Osipenko 
30441fc12b05SDouglas Anderson 	if (ret == 0 && rdev->use_count == 0 && rdev->supply)
30455451781dSDouglas Anderson 		ret = _regulator_disable(rdev->supply);
3046f8702f9eSDmitry Osipenko 
3047414c70cbSLiam Girdwood 	return ret;
3048414c70cbSLiam Girdwood }
3049414c70cbSLiam Girdwood 
3050414c70cbSLiam Girdwood /**
3051414c70cbSLiam Girdwood  * regulator_disable - disable regulator output
3052414c70cbSLiam Girdwood  * @regulator: regulator source
3053414c70cbSLiam Girdwood  *
3054cf7bbcdfSMark Brown  * Disable the regulator output voltage or current.  Calls to
3055cf7bbcdfSMark Brown  * regulator_enable() must be balanced with calls to
3056cf7bbcdfSMark Brown  * regulator_disable().
305769279fb9SMark Brown  *
3058414c70cbSLiam Girdwood  * NOTE: this will only disable the regulator output if no other consumer
3059cf7bbcdfSMark Brown  * devices have it enabled, the regulator device supports disabling and
3060cf7bbcdfSMark Brown  * machine constraints permit this operation.
3061414c70cbSLiam Girdwood  */
regulator_disable(struct regulator * regulator)3062414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator)
3063414c70cbSLiam Girdwood {
3064412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
3065f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
30665451781dSDouglas Anderson 	int ret;
30676492bc1bSMark Brown 
3068f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
30695451781dSDouglas Anderson 	ret = _regulator_disable(regulator);
3070f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(rdev, &ww_ctx);
30718cbf811dSJeffrey Carlyle 
3072414c70cbSLiam Girdwood 	return ret;
3073414c70cbSLiam Girdwood }
3074414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable);
3075414c70cbSLiam Girdwood 
3076414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */
_regulator_force_disable(struct regulator_dev * rdev)30773801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev)
3078414c70cbSLiam Girdwood {
3079414c70cbSLiam Girdwood 	int ret = 0;
3080414c70cbSLiam Girdwood 
3081f8702f9eSDmitry Osipenko 	lockdep_assert_held_once(&rdev->mutex.base);
308270cfef26SKrzysztof Kozlowski 
3083a1c8a551SRichard Fitzgerald 	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
3084a1c8a551SRichard Fitzgerald 			REGULATOR_EVENT_PRE_DISABLE, NULL);
3085a1c8a551SRichard Fitzgerald 	if (ret & NOTIFY_STOP_MASK)
3086a1c8a551SRichard Fitzgerald 		return -EINVAL;
3087a1c8a551SRichard Fitzgerald 
308866fda75fSMarkus Pargmann 	ret = _regulator_do_disable(rdev);
3089414c70cbSLiam Girdwood 	if (ret < 0) {
309061aab5adSMichał Mirosław 		rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret));
3091a1c8a551SRichard Fitzgerald 		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
3092a1c8a551SRichard Fitzgerald 				REGULATOR_EVENT_ABORT_DISABLE, NULL);
3093414c70cbSLiam Girdwood 		return ret;
3094414c70cbSLiam Girdwood 	}
309566fda75fSMarkus Pargmann 
309684b68263SMark Brown 	_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
309784b68263SMark Brown 			REGULATOR_EVENT_DISABLE, NULL);
3098414c70cbSLiam Girdwood 
309966fda75fSMarkus Pargmann 	return 0;
3100414c70cbSLiam Girdwood }
3101414c70cbSLiam Girdwood 
3102414c70cbSLiam Girdwood /**
3103414c70cbSLiam Girdwood  * regulator_force_disable - force disable regulator output
3104414c70cbSLiam Girdwood  * @regulator: regulator source
3105414c70cbSLiam Girdwood  *
3106414c70cbSLiam Girdwood  * Forcibly disable the regulator output voltage or current.
3107414c70cbSLiam Girdwood  * NOTE: this *will* disable the regulator output even if other consumer
3108414c70cbSLiam Girdwood  * devices have it enabled. This should be used for situations when device
3109414c70cbSLiam Girdwood  * damage will likely occur if the regulator is not disabled (e.g. over temp).
3110414c70cbSLiam Girdwood  */
regulator_force_disable(struct regulator * regulator)3111414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator)
3112414c70cbSLiam Girdwood {
311382d15839SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
3114f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
3115414c70cbSLiam Girdwood 	int ret;
3116414c70cbSLiam Girdwood 
3117f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
31185451781dSDouglas Anderson 
31193801b86aSMark Brown 	ret = _regulator_force_disable(regulator->rdev);
31205451781dSDouglas Anderson 
31219243a195SMaciej Purski 	if (rdev->coupling_desc.n_coupled > 1)
31229243a195SMaciej Purski 		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
31235451781dSDouglas Anderson 
31245451781dSDouglas Anderson 	if (regulator->uA_load) {
31255451781dSDouglas Anderson 		regulator->uA_load = 0;
31265451781dSDouglas Anderson 		ret = drms_uA_update(rdev);
31275451781dSDouglas Anderson 	}
31285451781dSDouglas Anderson 
31291fc12b05SDouglas Anderson 	if (rdev->use_count != 0 && rdev->supply)
31301fc12b05SDouglas Anderson 		_regulator_disable(rdev->supply);
31318cbf811dSJeffrey Carlyle 
31321fc12b05SDouglas Anderson 	regulator_unlock_dependent(rdev, &ww_ctx);
31338cbf811dSJeffrey Carlyle 
3134414c70cbSLiam Girdwood 	return ret;
3135414c70cbSLiam Girdwood }
3136414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable);
3137414c70cbSLiam Girdwood 
regulator_disable_work(struct work_struct * work)3138da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work)
3139da07ecd9SMark Brown {
3140da07ecd9SMark Brown 	struct regulator_dev *rdev = container_of(work, struct regulator_dev,
3141da07ecd9SMark Brown 						  disable_work.work);
3142f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
3143da07ecd9SMark Brown 	int count, i, ret;
31445451781dSDouglas Anderson 	struct regulator *regulator;
31455451781dSDouglas Anderson 	int total_count = 0;
3146da07ecd9SMark Brown 
3147f8702f9eSDmitry Osipenko 	regulator_lock_dependent(rdev, &ww_ctx);
3148da07ecd9SMark Brown 
3149c9ccaa0cSTirupathi Reddy 	/*
3150c9ccaa0cSTirupathi Reddy 	 * Workqueue functions queue the new work instance while the previous
3151c9ccaa0cSTirupathi Reddy 	 * work instance is being processed. Cancel the queued work instance
3152c9ccaa0cSTirupathi Reddy 	 * as the work instance under processing does the job of the queued
3153c9ccaa0cSTirupathi Reddy 	 * work instance.
3154c9ccaa0cSTirupathi Reddy 	 */
3155c9ccaa0cSTirupathi Reddy 	cancel_delayed_work(&rdev->disable_work);
3156c9ccaa0cSTirupathi Reddy 
31575451781dSDouglas Anderson 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
31585451781dSDouglas Anderson 		count = regulator->deferred_disables;
31595451781dSDouglas Anderson 
31605451781dSDouglas Anderson 		if (!count)
31615451781dSDouglas Anderson 			continue;
31625451781dSDouglas Anderson 
31635451781dSDouglas Anderson 		total_count += count;
31645451781dSDouglas Anderson 		regulator->deferred_disables = 0;
31655451781dSDouglas Anderson 
3166da07ecd9SMark Brown 		for (i = 0; i < count; i++) {
31675451781dSDouglas Anderson 			ret = _regulator_disable(regulator);
3168da07ecd9SMark Brown 			if (ret != 0)
316961aab5adSMichał Mirosław 				rdev_err(rdev, "Deferred disable failed: %pe\n",
317061aab5adSMichał Mirosław 					 ERR_PTR(ret));
3171da07ecd9SMark Brown 		}
31725451781dSDouglas Anderson 	}
31735451781dSDouglas Anderson 	WARN_ON(!total_count);
3174da07ecd9SMark Brown 
3175f8702f9eSDmitry Osipenko 	if (rdev->coupling_desc.n_coupled > 1)
3176f8702f9eSDmitry Osipenko 		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
3177f8702f9eSDmitry Osipenko 
3178f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(rdev, &ww_ctx);
3179da07ecd9SMark Brown }
3180da07ecd9SMark Brown 
3181da07ecd9SMark Brown /**
3182da07ecd9SMark Brown  * regulator_disable_deferred - disable regulator output with delay
3183da07ecd9SMark Brown  * @regulator: regulator source
318448f1b4efSKrzysztof Kozlowski  * @ms: milliseconds until the regulator is disabled
3185da07ecd9SMark Brown  *
3186da07ecd9SMark Brown  * Execute regulator_disable() on the regulator after a delay.  This
3187da07ecd9SMark Brown  * is intended for use with devices that require some time to quiesce.
3188da07ecd9SMark Brown  *
3189da07ecd9SMark Brown  * NOTE: this will only disable the regulator output if no other consumer
3190da07ecd9SMark Brown  * devices have it enabled, the regulator device supports disabling and
3191da07ecd9SMark Brown  * machine constraints permit this operation.
3192da07ecd9SMark Brown  */
regulator_disable_deferred(struct regulator * regulator,int ms)3193da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms)
3194da07ecd9SMark Brown {
3195da07ecd9SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
3196da07ecd9SMark Brown 
31972b5a24a0SMark Brown 	if (!ms)
31982b5a24a0SMark Brown 		return regulator_disable(regulator);
31992b5a24a0SMark Brown 
320066cf9a7eSMaciej Purski 	regulator_lock(rdev);
32015451781dSDouglas Anderson 	regulator->deferred_disables++;
3202c9ccaa0cSTirupathi Reddy 	mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
3203c9ccaa0cSTirupathi Reddy 			 msecs_to_jiffies(ms));
320466cf9a7eSMaciej Purski 	regulator_unlock(rdev);
3205da07ecd9SMark Brown 
3206aa59802dSMark Brown 	return 0;
3207da07ecd9SMark Brown }
3208da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred);
3209da07ecd9SMark Brown 
_regulator_is_enabled(struct regulator_dev * rdev)3210414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev)
3211414c70cbSLiam Girdwood {
321265f73508SMark Brown 	/* A GPIO control always takes precedence */
32137b74d149SKim, Milo 	if (rdev->ena_pin)
321465f73508SMark Brown 		return rdev->ena_gpio_state;
321565f73508SMark Brown 
32169a7f6a4cSMark Brown 	/* If we don't know then assume that the regulator is always on */
32179332546fSMark Brown 	if (!rdev->desc->ops->is_enabled)
32189a7f6a4cSMark Brown 		return 1;
3219414c70cbSLiam Girdwood 
32209332546fSMark Brown 	return rdev->desc->ops->is_enabled(rdev);
3221414c70cbSLiam Girdwood }
3222414c70cbSLiam Girdwood 
_regulator_list_voltage(struct regulator_dev * rdev,unsigned selector,int lock)32233d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev,
32243a40cfc3SSascha Hauer 				   unsigned selector, int lock)
32253a40cfc3SSascha Hauer {
32263a40cfc3SSascha Hauer 	const struct regulator_ops *ops = rdev->desc->ops;
32273a40cfc3SSascha Hauer 	int ret;
32283a40cfc3SSascha Hauer 
32293a40cfc3SSascha Hauer 	if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
32303a40cfc3SSascha Hauer 		return rdev->desc->fixed_uV;
32313a40cfc3SSascha Hauer 
32323a40cfc3SSascha Hauer 	if (ops->list_voltage) {
32333a40cfc3SSascha Hauer 		if (selector >= rdev->desc->n_voltages)
32343a40cfc3SSascha Hauer 			return -EINVAL;
323555cca739SClaudiu Beznea 		if (selector < rdev->desc->linear_min_sel)
323655cca739SClaudiu Beznea 			return 0;
32373a40cfc3SSascha Hauer 		if (lock)
323866cf9a7eSMaciej Purski 			regulator_lock(rdev);
32393a40cfc3SSascha Hauer 		ret = ops->list_voltage(rdev, selector);
32403a40cfc3SSascha Hauer 		if (lock)
324166cf9a7eSMaciej Purski 			regulator_unlock(rdev);
3242fd086045SMatthias Kaehlcke 	} else if (rdev->is_switch && rdev->supply) {
32433d67fe95SMaciej Purski 		ret = _regulator_list_voltage(rdev->supply->rdev,
32443d67fe95SMaciej Purski 					      selector, lock);
32453a40cfc3SSascha Hauer 	} else {
32463a40cfc3SSascha Hauer 		return -EINVAL;
32473a40cfc3SSascha Hauer 	}
32483a40cfc3SSascha Hauer 
32493a40cfc3SSascha Hauer 	if (ret > 0) {
32503a40cfc3SSascha Hauer 		if (ret < rdev->constraints->min_uV)
32513a40cfc3SSascha Hauer 			ret = 0;
32523a40cfc3SSascha Hauer 		else if (ret > rdev->constraints->max_uV)
32533a40cfc3SSascha Hauer 			ret = 0;
32543a40cfc3SSascha Hauer 	}
32553a40cfc3SSascha Hauer 
32563a40cfc3SSascha Hauer 	return ret;
32573a40cfc3SSascha Hauer }
32583a40cfc3SSascha Hauer 
3259414c70cbSLiam Girdwood /**
3260414c70cbSLiam Girdwood  * regulator_is_enabled - is the regulator output enabled
3261414c70cbSLiam Girdwood  * @regulator: regulator source
3262414c70cbSLiam Girdwood  *
3263412aec61SDavid Brownell  * Returns positive if the regulator driver backing the source/client
3264412aec61SDavid Brownell  * has requested that the device be enabled, zero if it hasn't, else a
3265412aec61SDavid Brownell  * negative errno code.
3266412aec61SDavid Brownell  *
3267412aec61SDavid Brownell  * Note that the device backing this regulator handle can have multiple
3268412aec61SDavid Brownell  * users, so it might be enabled even if regulator_enable() was never
3269412aec61SDavid Brownell  * called for this particular source.
3270414c70cbSLiam Girdwood  */
regulator_is_enabled(struct regulator * regulator)3271414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator)
3272414c70cbSLiam Girdwood {
32739332546fSMark Brown 	int ret;
32749332546fSMark Brown 
32756492bc1bSMark Brown 	if (regulator->always_on)
32766492bc1bSMark Brown 		return 1;
32776492bc1bSMark Brown 
3278f8702f9eSDmitry Osipenko 	regulator_lock(regulator->rdev);
32799332546fSMark Brown 	ret = _regulator_is_enabled(regulator->rdev);
3280f8702f9eSDmitry Osipenko 	regulator_unlock(regulator->rdev);
32819332546fSMark Brown 
32829332546fSMark Brown 	return ret;
3283414c70cbSLiam Girdwood }
3284414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled);
3285414c70cbSLiam Girdwood 
3286414c70cbSLiam Girdwood /**
32874367cfdcSDavid Brownell  * regulator_count_voltages - count regulator_list_voltage() selectors
32884367cfdcSDavid Brownell  * @regulator: regulator source
32894367cfdcSDavid Brownell  *
32904367cfdcSDavid Brownell  * Returns number of selectors, or negative errno.  Selectors are
32914367cfdcSDavid Brownell  * numbered starting at zero, and typically correspond to bitfields
32924367cfdcSDavid Brownell  * in hardware registers.
32934367cfdcSDavid Brownell  */
regulator_count_voltages(struct regulator * regulator)32944367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator)
32954367cfdcSDavid Brownell {
32964367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
32974367cfdcSDavid Brownell 
329826988efeSJavier Martinez Canillas 	if (rdev->desc->n_voltages)
329926988efeSJavier Martinez Canillas 		return rdev->desc->n_voltages;
330026988efeSJavier Martinez Canillas 
3301fd086045SMatthias Kaehlcke 	if (!rdev->is_switch || !rdev->supply)
330226988efeSJavier Martinez Canillas 		return -EINVAL;
330326988efeSJavier Martinez Canillas 
330426988efeSJavier Martinez Canillas 	return regulator_count_voltages(rdev->supply);
33054367cfdcSDavid Brownell }
33064367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages);
33074367cfdcSDavid Brownell 
33084367cfdcSDavid Brownell /**
33094367cfdcSDavid Brownell  * regulator_list_voltage - enumerate supported voltages
33104367cfdcSDavid Brownell  * @regulator: regulator source
33114367cfdcSDavid Brownell  * @selector: identify voltage to list
33124367cfdcSDavid Brownell  * Context: can sleep
33134367cfdcSDavid Brownell  *
33144367cfdcSDavid Brownell  * Returns a voltage that can be passed to @regulator_set_voltage(),
331588393161SThomas Weber  * zero if this selector code can't be used on this system, or a
33164367cfdcSDavid Brownell  * negative errno.
33174367cfdcSDavid Brownell  */
regulator_list_voltage(struct regulator * regulator,unsigned selector)33184367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector)
33194367cfdcSDavid Brownell {
33203d67fe95SMaciej Purski 	return _regulator_list_voltage(regulator->rdev, selector, 1);
33214367cfdcSDavid Brownell }
33224367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage);
33234367cfdcSDavid Brownell 
33244367cfdcSDavid Brownell /**
332504eca28cSTuomas Tynkkynen  * regulator_get_regmap - get the regulator's register map
332604eca28cSTuomas Tynkkynen  * @regulator: regulator source
332704eca28cSTuomas Tynkkynen  *
332804eca28cSTuomas Tynkkynen  * Returns the register map for the given regulator, or an ERR_PTR value
332904eca28cSTuomas Tynkkynen  * if the regulator doesn't use regmap.
333004eca28cSTuomas Tynkkynen  */
regulator_get_regmap(struct regulator * regulator)333104eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator)
333204eca28cSTuomas Tynkkynen {
333304eca28cSTuomas Tynkkynen 	struct regmap *map = regulator->rdev->regmap;
333404eca28cSTuomas Tynkkynen 
333504eca28cSTuomas Tynkkynen 	return map ? map : ERR_PTR(-EOPNOTSUPP);
333604eca28cSTuomas Tynkkynen }
3337*186d7785SBiju Das EXPORT_SYMBOL_GPL(regulator_get_regmap);
333804eca28cSTuomas Tynkkynen 
333904eca28cSTuomas Tynkkynen /**
334004eca28cSTuomas Tynkkynen  * regulator_get_hardware_vsel_register - get the HW voltage selector register
334104eca28cSTuomas Tynkkynen  * @regulator: regulator source
334204eca28cSTuomas Tynkkynen  * @vsel_reg: voltage selector register, output parameter
334304eca28cSTuomas Tynkkynen  * @vsel_mask: mask for voltage selector bitfield, output parameter
334404eca28cSTuomas Tynkkynen  *
334504eca28cSTuomas Tynkkynen  * Returns the hardware register offset and bitmask used for setting the
334604eca28cSTuomas Tynkkynen  * regulator voltage. This might be useful when configuring voltage-scaling
334704eca28cSTuomas Tynkkynen  * hardware or firmware that can make I2C requests behind the kernel's back,
334804eca28cSTuomas Tynkkynen  * for example.
334904eca28cSTuomas Tynkkynen  *
335004eca28cSTuomas Tynkkynen  * On success, the output parameters @vsel_reg and @vsel_mask are filled in
335104eca28cSTuomas Tynkkynen  * and 0 is returned, otherwise a negative errno is returned.
335204eca28cSTuomas Tynkkynen  */
regulator_get_hardware_vsel_register(struct regulator * regulator,unsigned * vsel_reg,unsigned * vsel_mask)335304eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator,
335404eca28cSTuomas Tynkkynen 					 unsigned *vsel_reg,
335504eca28cSTuomas Tynkkynen 					 unsigned *vsel_mask)
335604eca28cSTuomas Tynkkynen {
335704eca28cSTuomas Tynkkynen 	struct regulator_dev *rdev = regulator->rdev;
335839f5460dSGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
335904eca28cSTuomas Tynkkynen 
336004eca28cSTuomas Tynkkynen 	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
336104eca28cSTuomas Tynkkynen 		return -EOPNOTSUPP;
336204eca28cSTuomas Tynkkynen 
336304eca28cSTuomas Tynkkynen 	*vsel_reg = rdev->desc->vsel_reg;
336404eca28cSTuomas Tynkkynen 	*vsel_mask = rdev->desc->vsel_mask;
336504eca28cSTuomas Tynkkynen 
336604eca28cSTuomas Tynkkynen 	return 0;
336704eca28cSTuomas Tynkkynen }
336804eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
336904eca28cSTuomas Tynkkynen 
337004eca28cSTuomas Tynkkynen /**
337104eca28cSTuomas Tynkkynen  * regulator_list_hardware_vsel - get the HW-specific register value for a selector
337204eca28cSTuomas Tynkkynen  * @regulator: regulator source
337304eca28cSTuomas Tynkkynen  * @selector: identify voltage to list
337404eca28cSTuomas Tynkkynen  *
337504eca28cSTuomas Tynkkynen  * Converts the selector to a hardware-specific voltage selector that can be
337604eca28cSTuomas Tynkkynen  * directly written to the regulator registers. The address of the voltage
337704eca28cSTuomas Tynkkynen  * register can be determined by calling @regulator_get_hardware_vsel_register.
337804eca28cSTuomas Tynkkynen  *
337904eca28cSTuomas Tynkkynen  * On error a negative errno is returned.
338004eca28cSTuomas Tynkkynen  */
regulator_list_hardware_vsel(struct regulator * regulator,unsigned selector)338104eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator,
338204eca28cSTuomas Tynkkynen 				 unsigned selector)
338304eca28cSTuomas Tynkkynen {
338404eca28cSTuomas Tynkkynen 	struct regulator_dev *rdev = regulator->rdev;
338539f5460dSGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
338604eca28cSTuomas Tynkkynen 
338704eca28cSTuomas Tynkkynen 	if (selector >= rdev->desc->n_voltages)
338804eca28cSTuomas Tynkkynen 		return -EINVAL;
338955cca739SClaudiu Beznea 	if (selector < rdev->desc->linear_min_sel)
339055cca739SClaudiu Beznea 		return 0;
339104eca28cSTuomas Tynkkynen 	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
339204eca28cSTuomas Tynkkynen 		return -EOPNOTSUPP;
339304eca28cSTuomas Tynkkynen 
339404eca28cSTuomas Tynkkynen 	return selector;
339504eca28cSTuomas Tynkkynen }
339604eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
339704eca28cSTuomas Tynkkynen 
339804eca28cSTuomas Tynkkynen /**
33992a668a8bSPaul Walmsley  * regulator_get_linear_step - return the voltage step size between VSEL values
34002a668a8bSPaul Walmsley  * @regulator: regulator source
34012a668a8bSPaul Walmsley  *
34022a668a8bSPaul Walmsley  * Returns the voltage step size between VSEL values for linear
34032a668a8bSPaul Walmsley  * regulators, or return 0 if the regulator isn't a linear regulator.
34042a668a8bSPaul Walmsley  */
regulator_get_linear_step(struct regulator * regulator)34052a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator)
34062a668a8bSPaul Walmsley {
34072a668a8bSPaul Walmsley 	struct regulator_dev *rdev = regulator->rdev;
34082a668a8bSPaul Walmsley 
34092a668a8bSPaul Walmsley 	return rdev->desc->uV_step;
34102a668a8bSPaul Walmsley }
34112a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step);
34122a668a8bSPaul Walmsley 
34132a668a8bSPaul Walmsley /**
3414a7a1ad90SMark Brown  * regulator_is_supported_voltage - check if a voltage range can be supported
3415a7a1ad90SMark Brown  *
3416a7a1ad90SMark Brown  * @regulator: Regulator to check.
3417a7a1ad90SMark Brown  * @min_uV: Minimum required voltage in uV.
3418a7a1ad90SMark Brown  * @max_uV: Maximum required voltage in uV.
3419a7a1ad90SMark Brown  *
342049820944SJorge Ramirez-Ortiz  * Returns a boolean.
3421a7a1ad90SMark Brown  */
regulator_is_supported_voltage(struct regulator * regulator,int min_uV,int max_uV)3422a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator,
3423a7a1ad90SMark Brown 				   int min_uV, int max_uV)
3424a7a1ad90SMark Brown {
3425c5f3939bSMark Brown 	struct regulator_dev *rdev = regulator->rdev;
3426a7a1ad90SMark Brown 	int i, voltages, ret;
3427a7a1ad90SMark Brown 
3428c5f3939bSMark Brown 	/* If we can't change voltage check the current voltage */
34298a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
3430c5f3939bSMark Brown 		ret = regulator_get_voltage(regulator);
3431c5f3939bSMark Brown 		if (ret >= 0)
34320d25d09dSJingoo Han 			return min_uV <= ret && ret <= max_uV;
3433c5f3939bSMark Brown 		else
3434c5f3939bSMark Brown 			return ret;
3435c5f3939bSMark Brown 	}
3436c5f3939bSMark Brown 
3437bd7a2b60SPawel Moll 	/* Any voltage within constrains range is fine? */
3438bd7a2b60SPawel Moll 	if (rdev->desc->continuous_voltage_range)
3439bd7a2b60SPawel Moll 		return min_uV >= rdev->constraints->min_uV &&
3440bd7a2b60SPawel Moll 				max_uV <= rdev->constraints->max_uV;
3441bd7a2b60SPawel Moll 
3442a7a1ad90SMark Brown 	ret = regulator_count_voltages(regulator);
3443a7a1ad90SMark Brown 	if (ret < 0)
344449820944SJorge Ramirez-Ortiz 		return 0;
3445a7a1ad90SMark Brown 	voltages = ret;
3446a7a1ad90SMark Brown 
3447a7a1ad90SMark Brown 	for (i = 0; i < voltages; i++) {
3448a7a1ad90SMark Brown 		ret = regulator_list_voltage(regulator, i);
3449a7a1ad90SMark Brown 
3450a7a1ad90SMark Brown 		if (ret >= min_uV && ret <= max_uV)
3451a7a1ad90SMark Brown 			return 1;
3452a7a1ad90SMark Brown 	}
3453a7a1ad90SMark Brown 
3454a7a1ad90SMark Brown 	return 0;
3455a7a1ad90SMark Brown }
3456a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
3457a7a1ad90SMark Brown 
regulator_map_voltage(struct regulator_dev * rdev,int min_uV,int max_uV)3458a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV,
3459a204f41eSSascha Hauer 				 int max_uV)
3460a204f41eSSascha Hauer {
3461a204f41eSSascha Hauer 	const struct regulator_desc *desc = rdev->desc;
3462a204f41eSSascha Hauer 
3463a204f41eSSascha Hauer 	if (desc->ops->map_voltage)
3464a204f41eSSascha Hauer 		return desc->ops->map_voltage(rdev, min_uV, max_uV);
3465a204f41eSSascha Hauer 
3466a204f41eSSascha Hauer 	if (desc->ops->list_voltage == regulator_list_voltage_linear)
3467a204f41eSSascha Hauer 		return regulator_map_voltage_linear(rdev, min_uV, max_uV);
3468a204f41eSSascha Hauer 
3469a204f41eSSascha Hauer 	if (desc->ops->list_voltage == regulator_list_voltage_linear_range)
3470a204f41eSSascha Hauer 		return regulator_map_voltage_linear_range(rdev, min_uV, max_uV);
3471a204f41eSSascha Hauer 
347218e4b55fSMatti Vaittinen 	if (desc->ops->list_voltage ==
347318e4b55fSMatti Vaittinen 		regulator_list_voltage_pickable_linear_range)
347418e4b55fSMatti Vaittinen 		return regulator_map_voltage_pickable_linear_range(rdev,
347518e4b55fSMatti Vaittinen 							min_uV, max_uV);
347618e4b55fSMatti Vaittinen 
3477a204f41eSSascha Hauer 	return regulator_map_voltage_iterate(rdev, min_uV, max_uV);
3478a204f41eSSascha Hauer }
3479a204f41eSSascha Hauer 
_regulator_call_set_voltage(struct regulator_dev * rdev,int min_uV,int max_uV,unsigned * selector)34807179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev,
34817179569aSHeiko Stübner 				       int min_uV, int max_uV,
34827179569aSHeiko Stübner 				       unsigned *selector)
34837179569aSHeiko Stübner {
34847179569aSHeiko Stübner 	struct pre_voltage_change_data data;
34857179569aSHeiko Stübner 	int ret;
34867179569aSHeiko Stübner 
3487d22b85a1SDmitry Osipenko 	data.old_uV = regulator_get_voltage_rdev(rdev);
34887179569aSHeiko Stübner 	data.min_uV = min_uV;
34897179569aSHeiko Stübner 	data.max_uV = max_uV;
34907179569aSHeiko Stübner 	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
34917179569aSHeiko Stübner 				   &data);
34927179569aSHeiko Stübner 	if (ret & NOTIFY_STOP_MASK)
34937179569aSHeiko Stübner 		return -EINVAL;
34947179569aSHeiko Stübner 
34957179569aSHeiko Stübner 	ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector);
34967179569aSHeiko Stübner 	if (ret >= 0)
34977179569aSHeiko Stübner 		return ret;
34987179569aSHeiko Stübner 
34997179569aSHeiko Stübner 	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
35007179569aSHeiko Stübner 			     (void *)data.old_uV);
35017179569aSHeiko Stübner 
35027179569aSHeiko Stübner 	return ret;
35037179569aSHeiko Stübner }
35047179569aSHeiko Stübner 
_regulator_call_set_voltage_sel(struct regulator_dev * rdev,int uV,unsigned selector)35057179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
35067179569aSHeiko Stübner 					   int uV, unsigned selector)
35077179569aSHeiko Stübner {
35087179569aSHeiko Stübner 	struct pre_voltage_change_data data;
35097179569aSHeiko Stübner 	int ret;
35107179569aSHeiko Stübner 
3511d22b85a1SDmitry Osipenko 	data.old_uV = regulator_get_voltage_rdev(rdev);
35127179569aSHeiko Stübner 	data.min_uV = uV;
35137179569aSHeiko Stübner 	data.max_uV = uV;
35147179569aSHeiko Stübner 	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
35157179569aSHeiko Stübner 				   &data);
35167179569aSHeiko Stübner 	if (ret & NOTIFY_STOP_MASK)
35177179569aSHeiko Stübner 		return -EINVAL;
35187179569aSHeiko Stübner 
35197179569aSHeiko Stübner 	ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
35207179569aSHeiko Stübner 	if (ret >= 0)
35217179569aSHeiko Stübner 		return ret;
35227179569aSHeiko Stübner 
35237179569aSHeiko Stübner 	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
35247179569aSHeiko Stübner 			     (void *)data.old_uV);
35257179569aSHeiko Stübner 
35267179569aSHeiko Stübner 	return ret;
35277179569aSHeiko Stübner }
35287179569aSHeiko Stübner 
_regulator_set_voltage_sel_step(struct regulator_dev * rdev,int uV,int new_selector)35292da8d947SBartosz Golaszewski static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev,
35302da8d947SBartosz Golaszewski 					   int uV, int new_selector)
35312da8d947SBartosz Golaszewski {
35322da8d947SBartosz Golaszewski 	const struct regulator_ops *ops = rdev->desc->ops;
35332da8d947SBartosz Golaszewski 	int diff, old_sel, curr_sel, ret;
35342da8d947SBartosz Golaszewski 
35352da8d947SBartosz Golaszewski 	/* Stepping is only needed if the regulator is enabled. */
35362da8d947SBartosz Golaszewski 	if (!_regulator_is_enabled(rdev))
35372da8d947SBartosz Golaszewski 		goto final_set;
35382da8d947SBartosz Golaszewski 
35392da8d947SBartosz Golaszewski 	if (!ops->get_voltage_sel)
35402da8d947SBartosz Golaszewski 		return -EINVAL;
35412da8d947SBartosz Golaszewski 
35422da8d947SBartosz Golaszewski 	old_sel = ops->get_voltage_sel(rdev);
35432da8d947SBartosz Golaszewski 	if (old_sel < 0)
35442da8d947SBartosz Golaszewski 		return old_sel;
35452da8d947SBartosz Golaszewski 
35462da8d947SBartosz Golaszewski 	diff = new_selector - old_sel;
35472da8d947SBartosz Golaszewski 	if (diff == 0)
35482da8d947SBartosz Golaszewski 		return 0; /* No change needed. */
35492da8d947SBartosz Golaszewski 
35502da8d947SBartosz Golaszewski 	if (diff > 0) {
35512da8d947SBartosz Golaszewski 		/* Stepping up. */
35522da8d947SBartosz Golaszewski 		for (curr_sel = old_sel + rdev->desc->vsel_step;
35532da8d947SBartosz Golaszewski 		     curr_sel < new_selector;
35542da8d947SBartosz Golaszewski 		     curr_sel += rdev->desc->vsel_step) {
35552da8d947SBartosz Golaszewski 			/*
35562da8d947SBartosz Golaszewski 			 * Call the callback directly instead of using
35572da8d947SBartosz Golaszewski 			 * _regulator_call_set_voltage_sel() as we don't
35582da8d947SBartosz Golaszewski 			 * want to notify anyone yet. Same in the branch
35592da8d947SBartosz Golaszewski 			 * below.
35602da8d947SBartosz Golaszewski 			 */
35612da8d947SBartosz Golaszewski 			ret = ops->set_voltage_sel(rdev, curr_sel);
35622da8d947SBartosz Golaszewski 			if (ret)
35632da8d947SBartosz Golaszewski 				goto try_revert;
35642da8d947SBartosz Golaszewski 		}
35652da8d947SBartosz Golaszewski 	} else {
35662da8d947SBartosz Golaszewski 		/* Stepping down. */
35672da8d947SBartosz Golaszewski 		for (curr_sel = old_sel - rdev->desc->vsel_step;
35682da8d947SBartosz Golaszewski 		     curr_sel > new_selector;
35692da8d947SBartosz Golaszewski 		     curr_sel -= rdev->desc->vsel_step) {
35702da8d947SBartosz Golaszewski 			ret = ops->set_voltage_sel(rdev, curr_sel);
35712da8d947SBartosz Golaszewski 			if (ret)
35722da8d947SBartosz Golaszewski 				goto try_revert;
35732da8d947SBartosz Golaszewski 		}
35742da8d947SBartosz Golaszewski 	}
35752da8d947SBartosz Golaszewski 
35762da8d947SBartosz Golaszewski final_set:
35772da8d947SBartosz Golaszewski 	/* The final selector will trigger the notifiers. */
35782da8d947SBartosz Golaszewski 	return _regulator_call_set_voltage_sel(rdev, uV, new_selector);
35792da8d947SBartosz Golaszewski 
35802da8d947SBartosz Golaszewski try_revert:
35812da8d947SBartosz Golaszewski 	/*
35822da8d947SBartosz Golaszewski 	 * At least try to return to the previous voltage if setting a new
35832da8d947SBartosz Golaszewski 	 * one failed.
35842da8d947SBartosz Golaszewski 	 */
35852da8d947SBartosz Golaszewski 	(void)ops->set_voltage_sel(rdev, old_sel);
35862da8d947SBartosz Golaszewski 	return ret;
35872da8d947SBartosz Golaszewski }
35882da8d947SBartosz Golaszewski 
_regulator_set_voltage_time(struct regulator_dev * rdev,int old_uV,int new_uV)358973e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev,
359073e705bfSMatthias Kaehlcke 				       int old_uV, int new_uV)
359173e705bfSMatthias Kaehlcke {
359273e705bfSMatthias Kaehlcke 	unsigned int ramp_delay = 0;
359373e705bfSMatthias Kaehlcke 
359473e705bfSMatthias Kaehlcke 	if (rdev->constraints->ramp_delay)
359573e705bfSMatthias Kaehlcke 		ramp_delay = rdev->constraints->ramp_delay;
359673e705bfSMatthias Kaehlcke 	else if (rdev->desc->ramp_delay)
359773e705bfSMatthias Kaehlcke 		ramp_delay = rdev->desc->ramp_delay;
3598d6c1dc3fSLaxman Dewangan 	else if (rdev->constraints->settling_time)
3599d6c1dc3fSLaxman Dewangan 		return rdev->constraints->settling_time;
36003ffad468SMatthias Kaehlcke 	else if (rdev->constraints->settling_time_up &&
36013ffad468SMatthias Kaehlcke 		 (new_uV > old_uV))
36023ffad468SMatthias Kaehlcke 		return rdev->constraints->settling_time_up;
36033ffad468SMatthias Kaehlcke 	else if (rdev->constraints->settling_time_down &&
36043ffad468SMatthias Kaehlcke 		 (new_uV < old_uV))
36053ffad468SMatthias Kaehlcke 		return rdev->constraints->settling_time_down;
360673e705bfSMatthias Kaehlcke 
36070739ce4cSChristian Kohlschütter 	if (ramp_delay == 0)
360873e705bfSMatthias Kaehlcke 		return 0;
360973e705bfSMatthias Kaehlcke 
361073e705bfSMatthias Kaehlcke 	return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
361173e705bfSMatthias Kaehlcke }
361273e705bfSMatthias Kaehlcke 
_regulator_do_set_voltage(struct regulator_dev * rdev,int min_uV,int max_uV)361375790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
361475790251SMark Brown 				     int min_uV, int max_uV)
361575790251SMark Brown {
361675790251SMark Brown 	int ret;
361777af1b26SLinus Walleij 	int delay = 0;
3618e113d792SMark Brown 	int best_val = 0;
361975790251SMark Brown 	unsigned int selector;
3620eba41a5eSAxel Lin 	int old_selector = -1;
362157995a48SMatthias Kaehlcke 	const struct regulator_ops *ops = rdev->desc->ops;
3622d22b85a1SDmitry Osipenko 	int old_uV = regulator_get_voltage_rdev(rdev);
362375790251SMark Brown 
362475790251SMark Brown 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
362575790251SMark Brown 
3626bf5892a8SMark Brown 	min_uV += rdev->constraints->uV_offset;
3627bf5892a8SMark Brown 	max_uV += rdev->constraints->uV_offset;
3628bf5892a8SMark Brown 
362977af1b26SLinus Walleij 	/*
363077af1b26SLinus Walleij 	 * If we can't obtain the old selector there is not enough
363177af1b26SLinus Walleij 	 * info to call set_voltage_time_sel().
363277af1b26SLinus Walleij 	 */
36338b7485efSAxel Lin 	if (_regulator_is_enabled(rdev) &&
363457995a48SMatthias Kaehlcke 	    ops->set_voltage_time_sel && ops->get_voltage_sel) {
363557995a48SMatthias Kaehlcke 		old_selector = ops->get_voltage_sel(rdev);
3636eba41a5eSAxel Lin 		if (old_selector < 0)
3637eba41a5eSAxel Lin 			return old_selector;
3638eba41a5eSAxel Lin 	}
363977af1b26SLinus Walleij 
364057995a48SMatthias Kaehlcke 	if (ops->set_voltage) {
36417179569aSHeiko Stübner 		ret = _regulator_call_set_voltage(rdev, min_uV, max_uV,
364275790251SMark Brown 						  &selector);
3643e113d792SMark Brown 
3644e113d792SMark Brown 		if (ret >= 0) {
364557995a48SMatthias Kaehlcke 			if (ops->list_voltage)
364657995a48SMatthias Kaehlcke 				best_val = ops->list_voltage(rdev,
3647e113d792SMark Brown 							     selector);
3648e113d792SMark Brown 			else
3649d22b85a1SDmitry Osipenko 				best_val = regulator_get_voltage_rdev(rdev);
3650e113d792SMark Brown 		}
3651e113d792SMark Brown 
365257995a48SMatthias Kaehlcke 	} else if (ops->set_voltage_sel) {
3653a204f41eSSascha Hauer 		ret = regulator_map_voltage(rdev, min_uV, max_uV);
3654e843fc46SMark Brown 		if (ret >= 0) {
365557995a48SMatthias Kaehlcke 			best_val = ops->list_voltage(rdev, ret);
3656e113d792SMark Brown 			if (min_uV <= best_val && max_uV >= best_val) {
3657e843fc46SMark Brown 				selector = ret;
3658c66a566aSAxel Lin 				if (old_selector == selector)
3659c66a566aSAxel Lin 					ret = 0;
36602da8d947SBartosz Golaszewski 				else if (rdev->desc->vsel_step)
36612da8d947SBartosz Golaszewski 					ret = _regulator_set_voltage_sel_step(
36622da8d947SBartosz Golaszewski 						rdev, best_val, selector);
3663c66a566aSAxel Lin 				else
36647179569aSHeiko Stübner 					ret = _regulator_call_set_voltage_sel(
36657179569aSHeiko Stübner 						rdev, best_val, selector);
3666e113d792SMark Brown 			} else {
3667e113d792SMark Brown 				ret = -EINVAL;
3668e113d792SMark Brown 			}
3669e843fc46SMark Brown 		}
3670e8eef82bSMark Brown 	} else {
3671e8eef82bSMark Brown 		ret = -EINVAL;
3672e8eef82bSMark Brown 	}
3673e8eef82bSMark Brown 
367431dfe686SMatthias Kaehlcke 	if (ret)
367531dfe686SMatthias Kaehlcke 		goto out;
3676eba41a5eSAxel Lin 
367773e705bfSMatthias Kaehlcke 	if (ops->set_voltage_time_sel) {
367873e705bfSMatthias Kaehlcke 		/*
367973e705bfSMatthias Kaehlcke 		 * Call set_voltage_time_sel if successfully obtained
368073e705bfSMatthias Kaehlcke 		 * old_selector
368173e705bfSMatthias Kaehlcke 		 */
368273e705bfSMatthias Kaehlcke 		if (old_selector >= 0 && old_selector != selector)
368373e705bfSMatthias Kaehlcke 			delay = ops->set_voltage_time_sel(rdev, old_selector,
368473e705bfSMatthias Kaehlcke 							  selector);
368573e705bfSMatthias Kaehlcke 	} else {
368673e705bfSMatthias Kaehlcke 		if (old_uV != best_val) {
368773e705bfSMatthias Kaehlcke 			if (ops->set_voltage_time)
368873e705bfSMatthias Kaehlcke 				delay = ops->set_voltage_time(rdev, old_uV,
368973e705bfSMatthias Kaehlcke 							      best_val);
369073e705bfSMatthias Kaehlcke 			else
369173e705bfSMatthias Kaehlcke 				delay = _regulator_set_voltage_time(rdev,
369273e705bfSMatthias Kaehlcke 								    old_uV,
369373e705bfSMatthias Kaehlcke 								    best_val);
369473e705bfSMatthias Kaehlcke 		}
369573e705bfSMatthias Kaehlcke 	}
369673e705bfSMatthias Kaehlcke 
3697eba41a5eSAxel Lin 	if (delay < 0) {
369861aab5adSMichał Mirosław 		rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay));
3699eba41a5eSAxel Lin 		delay = 0;
3700e8eef82bSMark Brown 	}
370175790251SMark Brown 
370277af1b26SLinus Walleij 	/* Insert any necessary delays */
3703062920d2SBrian Norris 	_regulator_delay_helper(delay);
370477af1b26SLinus Walleij 
370531dfe686SMatthias Kaehlcke 	if (best_val >= 0) {
37062f6c797fSAxel Lin 		unsigned long data = best_val;
37072f6c797fSAxel Lin 
3708ded06a52SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
37092f6c797fSAxel Lin 				     (void *)data);
37102f6c797fSAxel Lin 	}
3711ded06a52SMark Brown 
371231dfe686SMatthias Kaehlcke out:
3713eba41a5eSAxel Lin 	trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
371475790251SMark Brown 
371575790251SMark Brown 	return ret;
371675790251SMark Brown }
371775790251SMark Brown 
_regulator_do_set_suspend_voltage(struct regulator_dev * rdev,int min_uV,int max_uV,suspend_state_t state)3718f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev,
3719f7efad10SChunyan Zhang 				  int min_uV, int max_uV, suspend_state_t state)
3720f7efad10SChunyan Zhang {
3721f7efad10SChunyan Zhang 	struct regulator_state *rstate;
3722f7efad10SChunyan Zhang 	int uV, sel;
3723f7efad10SChunyan Zhang 
3724f7efad10SChunyan Zhang 	rstate = regulator_get_suspend_state(rdev, state);
3725f7efad10SChunyan Zhang 	if (rstate == NULL)
3726f7efad10SChunyan Zhang 		return -EINVAL;
3727f7efad10SChunyan Zhang 
3728f7efad10SChunyan Zhang 	if (min_uV < rstate->min_uV)
3729f7efad10SChunyan Zhang 		min_uV = rstate->min_uV;
3730f7efad10SChunyan Zhang 	if (max_uV > rstate->max_uV)
3731f7efad10SChunyan Zhang 		max_uV = rstate->max_uV;
3732f7efad10SChunyan Zhang 
3733f7efad10SChunyan Zhang 	sel = regulator_map_voltage(rdev, min_uV, max_uV);
3734f7efad10SChunyan Zhang 	if (sel < 0)
3735f7efad10SChunyan Zhang 		return sel;
3736f7efad10SChunyan Zhang 
3737f7efad10SChunyan Zhang 	uV = rdev->desc->ops->list_voltage(rdev, sel);
3738f7efad10SChunyan Zhang 	if (uV >= min_uV && uV <= max_uV)
3739f7efad10SChunyan Zhang 		rstate->uV = uV;
3740f7efad10SChunyan Zhang 
3741f7efad10SChunyan Zhang 	return 0;
3742f7efad10SChunyan Zhang }
3743f7efad10SChunyan Zhang 
regulator_set_voltage_unlocked(struct regulator * regulator,int min_uV,int max_uV,suspend_state_t state)3744a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator,
3745c360a6dfSChunyan Zhang 					  int min_uV, int max_uV,
3746c360a6dfSChunyan Zhang 					  suspend_state_t state)
3747414c70cbSLiam Girdwood {
3748414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
3749c360a6dfSChunyan Zhang 	struct regulator_voltage *voltage = &regulator->voltage[state];
375095a3c23aSMark Brown 	int ret = 0;
375192d7a558SPaolo Pisati 	int old_min_uV, old_max_uV;
3752c00dc359SBjorn Andersson 	int current_uV;
3753414c70cbSLiam Girdwood 
375495a3c23aSMark Brown 	/* If we're setting the same range as last time the change
375595a3c23aSMark Brown 	 * should be a noop (some cpufreq implementations use the same
375695a3c23aSMark Brown 	 * voltage for multiple frequencies, for example).
375795a3c23aSMark Brown 	 */
3758c360a6dfSChunyan Zhang 	if (voltage->min_uV == min_uV && voltage->max_uV == max_uV)
375995a3c23aSMark Brown 		goto out;
376095a3c23aSMark Brown 
3761c00dc359SBjorn Andersson 	/* If we're trying to set a range that overlaps the current voltage,
3762d3fb9800SViresh Kumar 	 * return successfully even though the regulator does not support
3763c00dc359SBjorn Andersson 	 * changing the voltage.
3764c00dc359SBjorn Andersson 	 */
37658a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
3766d22b85a1SDmitry Osipenko 		current_uV = regulator_get_voltage_rdev(rdev);
3767c00dc359SBjorn Andersson 		if (min_uV <= current_uV && current_uV <= max_uV) {
3768c360a6dfSChunyan Zhang 			voltage->min_uV = min_uV;
3769c360a6dfSChunyan Zhang 			voltage->max_uV = max_uV;
3770c00dc359SBjorn Andersson 			goto out;
3771c00dc359SBjorn Andersson 		}
3772c00dc359SBjorn Andersson 	}
3773c00dc359SBjorn Andersson 
3774414c70cbSLiam Girdwood 	/* sanity check */
3775e8eef82bSMark Brown 	if (!rdev->desc->ops->set_voltage &&
3776e8eef82bSMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
3777414c70cbSLiam Girdwood 		ret = -EINVAL;
3778414c70cbSLiam Girdwood 		goto out;
3779414c70cbSLiam Girdwood 	}
3780414c70cbSLiam Girdwood 
3781414c70cbSLiam Girdwood 	/* constraints check */
3782414c70cbSLiam Girdwood 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
3783414c70cbSLiam Girdwood 	if (ret < 0)
3784414c70cbSLiam Girdwood 		goto out;
378592d7a558SPaolo Pisati 
378692d7a558SPaolo Pisati 	/* restore original values in case of error */
3787c360a6dfSChunyan Zhang 	old_min_uV = voltage->min_uV;
3788c360a6dfSChunyan Zhang 	old_max_uV = voltage->max_uV;
3789c360a6dfSChunyan Zhang 	voltage->min_uV = min_uV;
3790c360a6dfSChunyan Zhang 	voltage->max_uV = max_uV;
37913a93f2a9SMark Brown 
37929243a195SMaciej Purski 	/* for not coupled regulators this will just set the voltage */
37939243a195SMaciej Purski 	ret = regulator_balance_voltage(rdev, state);
379470b46491SSteve Twiss 	if (ret < 0) {
37959243a195SMaciej Purski 		voltage->min_uV = old_min_uV;
37969243a195SMaciej Purski 		voltage->max_uV = old_max_uV;
379770b46491SSteve Twiss 	}
37989243a195SMaciej Purski 
379970b46491SSteve Twiss out:
38009243a195SMaciej Purski 	return ret;
38019243a195SMaciej Purski }
38029243a195SMaciej Purski 
regulator_set_voltage_rdev(struct regulator_dev * rdev,int min_uV,int max_uV,suspend_state_t state)3803d22b85a1SDmitry Osipenko int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
38049243a195SMaciej Purski 			       int max_uV, suspend_state_t state)
38059243a195SMaciej Purski {
38069243a195SMaciej Purski 	int best_supply_uV = 0;
38079243a195SMaciej Purski 	int supply_change_uV = 0;
38089243a195SMaciej Purski 	int ret;
38099243a195SMaciej Purski 
381043fc99f2SMark Brown 	if (rdev->supply &&
381143fc99f2SMark Brown 	    regulator_ops_is_valid(rdev->supply->rdev,
381243fc99f2SMark Brown 				   REGULATOR_CHANGE_VOLTAGE) &&
38132c2874b1STirupathi Reddy 	    (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage ||
38142c2874b1STirupathi Reddy 					   rdev->desc->ops->get_voltage_sel))) {
3815fc42112cSSascha Hauer 		int current_supply_uV;
3816fc42112cSSascha Hauer 		int selector;
3817fc42112cSSascha Hauer 
3818fc42112cSSascha Hauer 		selector = regulator_map_voltage(rdev, min_uV, max_uV);
3819fc42112cSSascha Hauer 		if (selector < 0) {
3820fc42112cSSascha Hauer 			ret = selector;
38219243a195SMaciej Purski 			goto out;
3822fc42112cSSascha Hauer 		}
3823fc42112cSSascha Hauer 
382400cb9f4fSMark Brown 		best_supply_uV = _regulator_list_voltage(rdev, selector, 0);
3825fc42112cSSascha Hauer 		if (best_supply_uV < 0) {
3826fc42112cSSascha Hauer 			ret = best_supply_uV;
38279243a195SMaciej Purski 			goto out;
3828fc42112cSSascha Hauer 		}
3829fc42112cSSascha Hauer 
3830fc42112cSSascha Hauer 		best_supply_uV += rdev->desc->min_dropout_uV;
3831fc42112cSSascha Hauer 
3832d22b85a1SDmitry Osipenko 		current_supply_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
3833fc42112cSSascha Hauer 		if (current_supply_uV < 0) {
3834fc42112cSSascha Hauer 			ret = current_supply_uV;
38359243a195SMaciej Purski 			goto out;
3836fc42112cSSascha Hauer 		}
3837fc42112cSSascha Hauer 
3838fc42112cSSascha Hauer 		supply_change_uV = best_supply_uV - current_supply_uV;
3839fc42112cSSascha Hauer 	}
3840fc42112cSSascha Hauer 
3841fc42112cSSascha Hauer 	if (supply_change_uV > 0) {
3842fc42112cSSascha Hauer 		ret = regulator_set_voltage_unlocked(rdev->supply,
3843c360a6dfSChunyan Zhang 				best_supply_uV, INT_MAX, state);
3844fc42112cSSascha Hauer 		if (ret) {
384561aab5adSMichał Mirosław 			dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n",
384661aab5adSMichał Mirosław 				ERR_PTR(ret));
38479243a195SMaciej Purski 			goto out;
3848fc42112cSSascha Hauer 		}
3849fc42112cSSascha Hauer 	}
3850fc42112cSSascha Hauer 
3851f7efad10SChunyan Zhang 	if (state == PM_SUSPEND_ON)
385275790251SMark Brown 		ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
3853f7efad10SChunyan Zhang 	else
3854f7efad10SChunyan Zhang 		ret = _regulator_do_set_suspend_voltage(rdev, min_uV,
3855f7efad10SChunyan Zhang 							max_uV, state);
385692d7a558SPaolo Pisati 	if (ret < 0)
38579243a195SMaciej Purski 		goto out;
385802fa3ec0SMark Brown 
3859fc42112cSSascha Hauer 	if (supply_change_uV < 0) {
3860fc42112cSSascha Hauer 		ret = regulator_set_voltage_unlocked(rdev->supply,
3861c360a6dfSChunyan Zhang 				best_supply_uV, INT_MAX, state);
3862fc42112cSSascha Hauer 		if (ret)
386361aab5adSMichał Mirosław 			dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n",
386461aab5adSMichał Mirosław 				 ERR_PTR(ret));
3865fc42112cSSascha Hauer 		/* No need to fail here */
3866fc42112cSSascha Hauer 		ret = 0;
3867fc42112cSSascha Hauer 	}
3868fc42112cSSascha Hauer 
3869414c70cbSLiam Girdwood out:
3870414c70cbSLiam Girdwood 	return ret;
387169686176SMaciej Purski }
38723d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_set_voltage_rdev);
387369686176SMaciej Purski 
regulator_limit_voltage_step(struct regulator_dev * rdev,int * current_uV,int * min_uV)387485254bcfSDmitry Osipenko static int regulator_limit_voltage_step(struct regulator_dev *rdev,
387585254bcfSDmitry Osipenko 					int *current_uV, int *min_uV)
387685254bcfSDmitry Osipenko {
387785254bcfSDmitry Osipenko 	struct regulation_constraints *constraints = rdev->constraints;
387885254bcfSDmitry Osipenko 
387985254bcfSDmitry Osipenko 	/* Limit voltage change only if necessary */
388085254bcfSDmitry Osipenko 	if (!constraints->max_uV_step || !_regulator_is_enabled(rdev))
388185254bcfSDmitry Osipenko 		return 1;
388285254bcfSDmitry Osipenko 
388385254bcfSDmitry Osipenko 	if (*current_uV < 0) {
3884d22b85a1SDmitry Osipenko 		*current_uV = regulator_get_voltage_rdev(rdev);
388585254bcfSDmitry Osipenko 
388685254bcfSDmitry Osipenko 		if (*current_uV < 0)
388785254bcfSDmitry Osipenko 			return *current_uV;
388885254bcfSDmitry Osipenko 	}
388985254bcfSDmitry Osipenko 
389085254bcfSDmitry Osipenko 	if (abs(*current_uV - *min_uV) <= constraints->max_uV_step)
389185254bcfSDmitry Osipenko 		return 1;
389285254bcfSDmitry Osipenko 
389385254bcfSDmitry Osipenko 	/* Clamp target voltage within the given step */
389485254bcfSDmitry Osipenko 	if (*current_uV < *min_uV)
389585254bcfSDmitry Osipenko 		*min_uV = min(*current_uV + constraints->max_uV_step,
389685254bcfSDmitry Osipenko 			      *min_uV);
389785254bcfSDmitry Osipenko 	else
389885254bcfSDmitry Osipenko 		*min_uV = max(*current_uV - constraints->max_uV_step,
389985254bcfSDmitry Osipenko 			      *min_uV);
390085254bcfSDmitry Osipenko 
390185254bcfSDmitry Osipenko 	return 0;
390285254bcfSDmitry Osipenko }
390385254bcfSDmitry Osipenko 
regulator_get_optimal_voltage(struct regulator_dev * rdev,int * current_uV,int * min_uV,int * max_uV,suspend_state_t state,int n_coupled)3904c054c6c7SMaciej Purski static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
3905c054c6c7SMaciej Purski 					 int *current_uV,
3906c054c6c7SMaciej Purski 					 int *min_uV, int *max_uV,
3907c054c6c7SMaciej Purski 					 suspend_state_t state,
3908c054c6c7SMaciej Purski 					 int n_coupled)
3909c054c6c7SMaciej Purski {
3910c054c6c7SMaciej Purski 	struct coupling_desc *c_desc = &rdev->coupling_desc;
3911c054c6c7SMaciej Purski 	struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
3912c054c6c7SMaciej Purski 	struct regulation_constraints *constraints = rdev->constraints;
3913c054c6c7SMaciej Purski 	int desired_min_uV = 0, desired_max_uV = INT_MAX;
3914c054c6c7SMaciej Purski 	int max_current_uV = 0, min_current_uV = INT_MAX;
3915c054c6c7SMaciej Purski 	int highest_min_uV = 0, target_uV, possible_uV;
3916d8ca7d18SDmitry Osipenko 	int i, ret, max_spread;
3917c054c6c7SMaciej Purski 	bool done;
3918c054c6c7SMaciej Purski 
3919c054c6c7SMaciej Purski 	*current_uV = -1;
3920c054c6c7SMaciej Purski 
3921c054c6c7SMaciej Purski 	/*
3922c054c6c7SMaciej Purski 	 * If there are no coupled regulators, simply set the voltage
3923c054c6c7SMaciej Purski 	 * demanded by consumers.
3924c054c6c7SMaciej Purski 	 */
3925c054c6c7SMaciej Purski 	if (n_coupled == 1) {
3926c054c6c7SMaciej Purski 		/*
3927c054c6c7SMaciej Purski 		 * If consumers don't provide any demands, set voltage
3928c054c6c7SMaciej Purski 		 * to min_uV
3929c054c6c7SMaciej Purski 		 */
3930c054c6c7SMaciej Purski 		desired_min_uV = constraints->min_uV;
3931c054c6c7SMaciej Purski 		desired_max_uV = constraints->max_uV;
3932c054c6c7SMaciej Purski 
3933c054c6c7SMaciej Purski 		ret = regulator_check_consumers(rdev,
3934c054c6c7SMaciej Purski 						&desired_min_uV,
3935c054c6c7SMaciej Purski 						&desired_max_uV, state);
3936c054c6c7SMaciej Purski 		if (ret < 0)
3937c054c6c7SMaciej Purski 			return ret;
3938c054c6c7SMaciej Purski 
3939c054c6c7SMaciej Purski 		possible_uV = desired_min_uV;
3940c054c6c7SMaciej Purski 		done = true;
3941c054c6c7SMaciej Purski 
3942c054c6c7SMaciej Purski 		goto finish;
3943c054c6c7SMaciej Purski 	}
3944c054c6c7SMaciej Purski 
3945c054c6c7SMaciej Purski 	/* Find highest min desired voltage */
3946c054c6c7SMaciej Purski 	for (i = 0; i < n_coupled; i++) {
3947c054c6c7SMaciej Purski 		int tmp_min = 0;
3948c054c6c7SMaciej Purski 		int tmp_max = INT_MAX;
3949c054c6c7SMaciej Purski 
3950f8702f9eSDmitry Osipenko 		lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
3951c054c6c7SMaciej Purski 
3952c054c6c7SMaciej Purski 		ret = regulator_check_consumers(c_rdevs[i],
3953c054c6c7SMaciej Purski 						&tmp_min,
3954c054c6c7SMaciej Purski 						&tmp_max, state);
3955c054c6c7SMaciej Purski 		if (ret < 0)
3956c054c6c7SMaciej Purski 			return ret;
3957c054c6c7SMaciej Purski 
3958c054c6c7SMaciej Purski 		ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max);
3959c054c6c7SMaciej Purski 		if (ret < 0)
3960c054c6c7SMaciej Purski 			return ret;
3961c054c6c7SMaciej Purski 
3962c054c6c7SMaciej Purski 		highest_min_uV = max(highest_min_uV, tmp_min);
3963c054c6c7SMaciej Purski 
3964c054c6c7SMaciej Purski 		if (i == 0) {
3965c054c6c7SMaciej Purski 			desired_min_uV = tmp_min;
3966c054c6c7SMaciej Purski 			desired_max_uV = tmp_max;
3967c054c6c7SMaciej Purski 		}
3968c054c6c7SMaciej Purski 	}
3969c054c6c7SMaciej Purski 
3970d8ca7d18SDmitry Osipenko 	max_spread = constraints->max_spread[0];
3971d8ca7d18SDmitry Osipenko 
3972c054c6c7SMaciej Purski 	/*
3973c054c6c7SMaciej Purski 	 * Let target_uV be equal to the desired one if possible.
3974c054c6c7SMaciej Purski 	 * If not, set it to minimum voltage, allowed by other coupled
3975c054c6c7SMaciej Purski 	 * regulators.
3976c054c6c7SMaciej Purski 	 */
3977c054c6c7SMaciej Purski 	target_uV = max(desired_min_uV, highest_min_uV - max_spread);
3978c054c6c7SMaciej Purski 
3979c054c6c7SMaciej Purski 	/*
3980c054c6c7SMaciej Purski 	 * Find min and max voltages, which currently aren't violating
3981c054c6c7SMaciej Purski 	 * max_spread.
3982c054c6c7SMaciej Purski 	 */
3983c054c6c7SMaciej Purski 	for (i = 1; i < n_coupled; i++) {
3984c054c6c7SMaciej Purski 		int tmp_act;
3985c054c6c7SMaciej Purski 
3986c054c6c7SMaciej Purski 		if (!_regulator_is_enabled(c_rdevs[i]))
3987c054c6c7SMaciej Purski 			continue;
3988c054c6c7SMaciej Purski 
3989d22b85a1SDmitry Osipenko 		tmp_act = regulator_get_voltage_rdev(c_rdevs[i]);
3990c054c6c7SMaciej Purski 		if (tmp_act < 0)
3991c054c6c7SMaciej Purski 			return tmp_act;
3992c054c6c7SMaciej Purski 
3993c054c6c7SMaciej Purski 		min_current_uV = min(tmp_act, min_current_uV);
3994c054c6c7SMaciej Purski 		max_current_uV = max(tmp_act, max_current_uV);
3995c054c6c7SMaciej Purski 	}
3996c054c6c7SMaciej Purski 
3997c054c6c7SMaciej Purski 	/* There aren't any other regulators enabled */
3998c054c6c7SMaciej Purski 	if (max_current_uV == 0) {
3999c054c6c7SMaciej Purski 		possible_uV = target_uV;
4000c054c6c7SMaciej Purski 	} else {
4001c054c6c7SMaciej Purski 		/*
4002c054c6c7SMaciej Purski 		 * Correct target voltage, so as it currently isn't
4003c054c6c7SMaciej Purski 		 * violating max_spread
4004c054c6c7SMaciej Purski 		 */
4005c054c6c7SMaciej Purski 		possible_uV = max(target_uV, max_current_uV - max_spread);
4006c054c6c7SMaciej Purski 		possible_uV = min(possible_uV, min_current_uV + max_spread);
4007c054c6c7SMaciej Purski 	}
4008c054c6c7SMaciej Purski 
4009c054c6c7SMaciej Purski 	if (possible_uV > desired_max_uV)
4010c054c6c7SMaciej Purski 		return -EINVAL;
4011c054c6c7SMaciej Purski 
4012c054c6c7SMaciej Purski 	done = (possible_uV == target_uV);
4013c054c6c7SMaciej Purski 	desired_min_uV = possible_uV;
4014c054c6c7SMaciej Purski 
4015c054c6c7SMaciej Purski finish:
401685254bcfSDmitry Osipenko 	/* Apply max_uV_step constraint if necessary */
401785254bcfSDmitry Osipenko 	if (state == PM_SUSPEND_ON) {
401885254bcfSDmitry Osipenko 		ret = regulator_limit_voltage_step(rdev, current_uV,
401985254bcfSDmitry Osipenko 						   &desired_min_uV);
402085254bcfSDmitry Osipenko 		if (ret < 0)
402185254bcfSDmitry Osipenko 			return ret;
402285254bcfSDmitry Osipenko 
402385254bcfSDmitry Osipenko 		if (ret == 0)
402485254bcfSDmitry Osipenko 			done = false;
402585254bcfSDmitry Osipenko 	}
402685254bcfSDmitry Osipenko 
4027c054c6c7SMaciej Purski 	/* Set current_uV if wasn't done earlier in the code and if necessary */
4028c054c6c7SMaciej Purski 	if (n_coupled > 1 && *current_uV == -1) {
4029c054c6c7SMaciej Purski 
4030c054c6c7SMaciej Purski 		if (_regulator_is_enabled(rdev)) {
4031d22b85a1SDmitry Osipenko 			ret = regulator_get_voltage_rdev(rdev);
4032c054c6c7SMaciej Purski 			if (ret < 0)
4033c054c6c7SMaciej Purski 				return ret;
4034c054c6c7SMaciej Purski 
4035c054c6c7SMaciej Purski 			*current_uV = ret;
4036c054c6c7SMaciej Purski 		} else {
4037c054c6c7SMaciej Purski 			*current_uV = desired_min_uV;
4038c054c6c7SMaciej Purski 		}
4039c054c6c7SMaciej Purski 	}
4040c054c6c7SMaciej Purski 
4041c054c6c7SMaciej Purski 	*min_uV = desired_min_uV;
4042c054c6c7SMaciej Purski 	*max_uV = desired_max_uV;
4043c054c6c7SMaciej Purski 
4044c054c6c7SMaciej Purski 	return done;
4045c054c6c7SMaciej Purski }
4046c054c6c7SMaciej Purski 
regulator_do_balance_voltage(struct regulator_dev * rdev,suspend_state_t state,bool skip_coupled)4047752db83aSMarek Szyprowski int regulator_do_balance_voltage(struct regulator_dev *rdev,
4048752db83aSMarek Szyprowski 				 suspend_state_t state, bool skip_coupled)
4049c054c6c7SMaciej Purski {
4050c054c6c7SMaciej Purski 	struct regulator_dev **c_rdevs;
4051c054c6c7SMaciej Purski 	struct regulator_dev *best_rdev;
4052c054c6c7SMaciej Purski 	struct coupling_desc *c_desc = &rdev->coupling_desc;
4053c054c6c7SMaciej Purski 	int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
4054c054c6c7SMaciej Purski 	unsigned int delta, best_delta;
4055d8ca7d18SDmitry Osipenko 	unsigned long c_rdev_done = 0;
4056d8ca7d18SDmitry Osipenko 	bool best_c_rdev_done;
4057c054c6c7SMaciej Purski 
4058c054c6c7SMaciej Purski 	c_rdevs = c_desc->coupled_rdevs;
4059752db83aSMarek Szyprowski 	n_coupled = skip_coupled ? 1 : c_desc->n_coupled;
4060c054c6c7SMaciej Purski 
4061c054c6c7SMaciej Purski 	/*
4062c054c6c7SMaciej Purski 	 * Find the best possible voltage change on each loop. Leave the loop
4063c054c6c7SMaciej Purski 	 * if there isn't any possible change.
4064c054c6c7SMaciej Purski 	 */
4065c054c6c7SMaciej Purski 	do {
4066c054c6c7SMaciej Purski 		best_c_rdev_done = false;
4067c054c6c7SMaciej Purski 		best_delta = 0;
4068c054c6c7SMaciej Purski 		best_min_uV = 0;
4069c054c6c7SMaciej Purski 		best_max_uV = 0;
4070c054c6c7SMaciej Purski 		best_c_rdev = 0;
4071c054c6c7SMaciej Purski 		best_rdev = NULL;
4072c054c6c7SMaciej Purski 
4073c054c6c7SMaciej Purski 		/*
4074c054c6c7SMaciej Purski 		 * Find highest difference between optimal voltage
4075c054c6c7SMaciej Purski 		 * and current voltage.
4076c054c6c7SMaciej Purski 		 */
4077c054c6c7SMaciej Purski 		for (i = 0; i < n_coupled; i++) {
4078c054c6c7SMaciej Purski 			/*
4079c054c6c7SMaciej Purski 			 * optimal_uV is the best voltage that can be set for
4080c054c6c7SMaciej Purski 			 * i-th regulator at the moment without violating
4081c054c6c7SMaciej Purski 			 * max_spread constraint in order to balance
4082c054c6c7SMaciej Purski 			 * the coupled voltages.
4083c054c6c7SMaciej Purski 			 */
4084c054c6c7SMaciej Purski 			int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
4085c054c6c7SMaciej Purski 
4086d8ca7d18SDmitry Osipenko 			if (test_bit(i, &c_rdev_done))
4087c054c6c7SMaciej Purski 				continue;
4088c054c6c7SMaciej Purski 
4089c054c6c7SMaciej Purski 			ret = regulator_get_optimal_voltage(c_rdevs[i],
4090c054c6c7SMaciej Purski 							    &current_uV,
4091c054c6c7SMaciej Purski 							    &optimal_uV,
4092c054c6c7SMaciej Purski 							    &optimal_max_uV,
4093c054c6c7SMaciej Purski 							    state, n_coupled);
4094c054c6c7SMaciej Purski 			if (ret < 0)
4095c054c6c7SMaciej Purski 				goto out;
4096c054c6c7SMaciej Purski 
4097c054c6c7SMaciej Purski 			delta = abs(optimal_uV - current_uV);
4098c054c6c7SMaciej Purski 
4099c054c6c7SMaciej Purski 			if (delta && best_delta <= delta) {
4100c054c6c7SMaciej Purski 				best_c_rdev_done = ret;
4101c054c6c7SMaciej Purski 				best_delta = delta;
4102c054c6c7SMaciej Purski 				best_rdev = c_rdevs[i];
4103c054c6c7SMaciej Purski 				best_min_uV = optimal_uV;
4104c054c6c7SMaciej Purski 				best_max_uV = optimal_max_uV;
4105c054c6c7SMaciej Purski 				best_c_rdev = i;
4106c054c6c7SMaciej Purski 			}
4107c054c6c7SMaciej Purski 		}
4108c054c6c7SMaciej Purski 
4109c054c6c7SMaciej Purski 		/* Nothing to change, return successfully */
4110c054c6c7SMaciej Purski 		if (!best_rdev) {
4111c054c6c7SMaciej Purski 			ret = 0;
4112c054c6c7SMaciej Purski 			goto out;
4113c054c6c7SMaciej Purski 		}
41149243a195SMaciej Purski 
4115c054c6c7SMaciej Purski 		ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
4116c054c6c7SMaciej Purski 						 best_max_uV, state);
41179243a195SMaciej Purski 
4118c054c6c7SMaciej Purski 		if (ret < 0)
4119c054c6c7SMaciej Purski 			goto out;
4120c054c6c7SMaciej Purski 
4121d8ca7d18SDmitry Osipenko 		if (best_c_rdev_done)
4122d8ca7d18SDmitry Osipenko 			set_bit(best_c_rdev, &c_rdev_done);
4123c054c6c7SMaciej Purski 
4124c054c6c7SMaciej Purski 	} while (n_coupled > 1);
4125c054c6c7SMaciej Purski 
4126c054c6c7SMaciej Purski out:
412769686176SMaciej Purski 	return ret;
412869686176SMaciej Purski }
412969686176SMaciej Purski 
regulator_balance_voltage(struct regulator_dev * rdev,suspend_state_t state)4130752db83aSMarek Szyprowski static int regulator_balance_voltage(struct regulator_dev *rdev,
4131752db83aSMarek Szyprowski 				     suspend_state_t state)
4132752db83aSMarek Szyprowski {
4133752db83aSMarek Szyprowski 	struct coupling_desc *c_desc = &rdev->coupling_desc;
4134752db83aSMarek Szyprowski 	struct regulator_coupler *coupler = c_desc->coupler;
4135752db83aSMarek Szyprowski 	bool skip_coupled = false;
4136752db83aSMarek Szyprowski 
4137752db83aSMarek Szyprowski 	/*
4138752db83aSMarek Szyprowski 	 * If system is in a state other than PM_SUSPEND_ON, don't check
4139752db83aSMarek Szyprowski 	 * other coupled regulators.
4140752db83aSMarek Szyprowski 	 */
4141752db83aSMarek Szyprowski 	if (state != PM_SUSPEND_ON)
4142752db83aSMarek Szyprowski 		skip_coupled = true;
4143752db83aSMarek Szyprowski 
4144752db83aSMarek Szyprowski 	if (c_desc->n_resolved < c_desc->n_coupled) {
4145752db83aSMarek Szyprowski 		rdev_err(rdev, "Not all coupled regulators registered\n");
4146752db83aSMarek Szyprowski 		return -EPERM;
4147752db83aSMarek Szyprowski 	}
4148752db83aSMarek Szyprowski 
4149752db83aSMarek Szyprowski 	/* Invoke custom balancer for customized couplers */
4150752db83aSMarek Szyprowski 	if (coupler && coupler->balance_voltage)
4151752db83aSMarek Szyprowski 		return coupler->balance_voltage(coupler, rdev, state);
4152752db83aSMarek Szyprowski 
4153752db83aSMarek Szyprowski 	return regulator_do_balance_voltage(rdev, state, skip_coupled);
4154752db83aSMarek Szyprowski }
4155752db83aSMarek Szyprowski 
4156a9f226bcSSascha Hauer /**
4157a9f226bcSSascha Hauer  * regulator_set_voltage - set regulator output voltage
4158a9f226bcSSascha Hauer  * @regulator: regulator source
4159a9f226bcSSascha Hauer  * @min_uV: Minimum required voltage in uV
4160a9f226bcSSascha Hauer  * @max_uV: Maximum acceptable voltage in uV
4161a9f226bcSSascha Hauer  *
4162a9f226bcSSascha Hauer  * Sets a voltage regulator to the desired output voltage. This can be set
4163a9f226bcSSascha Hauer  * during any regulator state. IOW, regulator can be disabled or enabled.
4164a9f226bcSSascha Hauer  *
4165a9f226bcSSascha Hauer  * If the regulator is enabled then the voltage will change to the new value
4166a9f226bcSSascha Hauer  * immediately otherwise if the regulator is disabled the regulator will
4167a9f226bcSSascha Hauer  * output at the new voltage when enabled.
4168a9f226bcSSascha Hauer  *
4169a9f226bcSSascha Hauer  * NOTE: If the regulator is shared between several devices then the lowest
4170a9f226bcSSascha Hauer  * request voltage that meets the system constraints will be used.
4171a9f226bcSSascha Hauer  * Regulator system constraints must be set for this regulator before
4172a9f226bcSSascha Hauer  * calling this function otherwise this call will fail.
4173a9f226bcSSascha Hauer  */
regulator_set_voltage(struct regulator * regulator,int min_uV,int max_uV)4174a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
4175a9f226bcSSascha Hauer {
4176f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
4177f8702f9eSDmitry Osipenko 	int ret;
4178a9f226bcSSascha Hauer 
4179f8702f9eSDmitry Osipenko 	regulator_lock_dependent(regulator->rdev, &ww_ctx);
4180a9f226bcSSascha Hauer 
4181c360a6dfSChunyan Zhang 	ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
4182c360a6dfSChunyan Zhang 					     PM_SUSPEND_ON);
4183a9f226bcSSascha Hauer 
4184f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
4185a9f226bcSSascha Hauer 
418692d7a558SPaolo Pisati 	return ret;
4187414c70cbSLiam Girdwood }
4188414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage);
4189414c70cbSLiam Girdwood 
regulator_suspend_toggle(struct regulator_dev * rdev,suspend_state_t state,bool en)4190f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev,
4191f7efad10SChunyan Zhang 					   suspend_state_t state, bool en)
4192f7efad10SChunyan Zhang {
4193f7efad10SChunyan Zhang 	struct regulator_state *rstate;
4194f7efad10SChunyan Zhang 
4195f7efad10SChunyan Zhang 	rstate = regulator_get_suspend_state(rdev, state);
4196f7efad10SChunyan Zhang 	if (rstate == NULL)
4197f7efad10SChunyan Zhang 		return -EINVAL;
4198f7efad10SChunyan Zhang 
4199f7efad10SChunyan Zhang 	if (!rstate->changeable)
4200f7efad10SChunyan Zhang 		return -EPERM;
4201f7efad10SChunyan Zhang 
42023edd79cfSMarek Szyprowski 	rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND;
4203f7efad10SChunyan Zhang 
4204f7efad10SChunyan Zhang 	return 0;
4205f7efad10SChunyan Zhang }
4206f7efad10SChunyan Zhang 
regulator_suspend_enable(struct regulator_dev * rdev,suspend_state_t state)4207f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev,
4208f7efad10SChunyan Zhang 				    suspend_state_t state)
4209f7efad10SChunyan Zhang {
4210f7efad10SChunyan Zhang 	return regulator_suspend_toggle(rdev, state, true);
4211f7efad10SChunyan Zhang }
4212f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable);
4213f7efad10SChunyan Zhang 
regulator_suspend_disable(struct regulator_dev * rdev,suspend_state_t state)4214f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev,
4215f7efad10SChunyan Zhang 				     suspend_state_t state)
4216f7efad10SChunyan Zhang {
4217f7efad10SChunyan Zhang 	struct regulator *regulator;
4218f7efad10SChunyan Zhang 	struct regulator_voltage *voltage;
4219f7efad10SChunyan Zhang 
4220f7efad10SChunyan Zhang 	/*
4221f7efad10SChunyan Zhang 	 * if any consumer wants this regulator device keeping on in
4222f7efad10SChunyan Zhang 	 * suspend states, don't set it as disabled.
4223f7efad10SChunyan Zhang 	 */
4224f7efad10SChunyan Zhang 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
4225f7efad10SChunyan Zhang 		voltage = &regulator->voltage[state];
4226f7efad10SChunyan Zhang 		if (voltage->min_uV || voltage->max_uV)
4227f7efad10SChunyan Zhang 			return 0;
4228f7efad10SChunyan Zhang 	}
4229f7efad10SChunyan Zhang 
4230f7efad10SChunyan Zhang 	return regulator_suspend_toggle(rdev, state, false);
4231f7efad10SChunyan Zhang }
4232f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable);
4233f7efad10SChunyan Zhang 
_regulator_set_suspend_voltage(struct regulator * regulator,int min_uV,int max_uV,suspend_state_t state)4234f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator,
4235f7efad10SChunyan Zhang 					  int min_uV, int max_uV,
4236f7efad10SChunyan Zhang 					  suspend_state_t state)
4237f7efad10SChunyan Zhang {
4238f7efad10SChunyan Zhang 	struct regulator_dev *rdev = regulator->rdev;
4239f7efad10SChunyan Zhang 	struct regulator_state *rstate;
4240f7efad10SChunyan Zhang 
4241f7efad10SChunyan Zhang 	rstate = regulator_get_suspend_state(rdev, state);
4242f7efad10SChunyan Zhang 	if (rstate == NULL)
4243f7efad10SChunyan Zhang 		return -EINVAL;
4244f7efad10SChunyan Zhang 
4245f7efad10SChunyan Zhang 	if (rstate->min_uV == rstate->max_uV) {
4246f7efad10SChunyan Zhang 		rdev_err(rdev, "The suspend voltage can't be changed!\n");
4247f7efad10SChunyan Zhang 		return -EPERM;
4248f7efad10SChunyan Zhang 	}
4249f7efad10SChunyan Zhang 
4250f7efad10SChunyan Zhang 	return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state);
4251f7efad10SChunyan Zhang }
4252f7efad10SChunyan Zhang 
regulator_set_suspend_voltage(struct regulator * regulator,int min_uV,int max_uV,suspend_state_t state)4253f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
4254f7efad10SChunyan Zhang 				  int max_uV, suspend_state_t state)
4255f7efad10SChunyan Zhang {
4256f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
4257f8702f9eSDmitry Osipenko 	int ret;
4258f7efad10SChunyan Zhang 
4259f7efad10SChunyan Zhang 	/* PM_SUSPEND_ON is handled by regulator_set_voltage() */
4260f7efad10SChunyan Zhang 	if (regulator_check_states(state) || state == PM_SUSPEND_ON)
4261f7efad10SChunyan Zhang 		return -EINVAL;
4262f7efad10SChunyan Zhang 
4263f8702f9eSDmitry Osipenko 	regulator_lock_dependent(regulator->rdev, &ww_ctx);
4264f7efad10SChunyan Zhang 
4265f7efad10SChunyan Zhang 	ret = _regulator_set_suspend_voltage(regulator, min_uV,
4266f7efad10SChunyan Zhang 					     max_uV, state);
4267f7efad10SChunyan Zhang 
4268f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
4269f7efad10SChunyan Zhang 
4270f7efad10SChunyan Zhang 	return ret;
4271f7efad10SChunyan Zhang }
4272f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage);
4273f7efad10SChunyan Zhang 
4274606a2562SMark Brown /**
427588cd222bSLinus Walleij  * regulator_set_voltage_time - get raise/fall time
427688cd222bSLinus Walleij  * @regulator: regulator source
427788cd222bSLinus Walleij  * @old_uV: starting voltage in microvolts
427888cd222bSLinus Walleij  * @new_uV: target voltage in microvolts
427988cd222bSLinus Walleij  *
428088cd222bSLinus Walleij  * Provided with the starting and ending voltage, this function attempts to
428188cd222bSLinus Walleij  * calculate the time in microseconds required to rise or fall to this new
428288cd222bSLinus Walleij  * voltage.
428388cd222bSLinus Walleij  */
regulator_set_voltage_time(struct regulator * regulator,int old_uV,int new_uV)428488cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator,
428588cd222bSLinus Walleij 			       int old_uV, int new_uV)
428688cd222bSLinus Walleij {
428788cd222bSLinus Walleij 	struct regulator_dev *rdev = regulator->rdev;
4288272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
428988cd222bSLinus Walleij 	int old_sel = -1;
429088cd222bSLinus Walleij 	int new_sel = -1;
429188cd222bSLinus Walleij 	int voltage;
429288cd222bSLinus Walleij 	int i;
429388cd222bSLinus Walleij 
429473e705bfSMatthias Kaehlcke 	if (ops->set_voltage_time)
429573e705bfSMatthias Kaehlcke 		return ops->set_voltage_time(rdev, old_uV, new_uV);
429673e705bfSMatthias Kaehlcke 	else if (!ops->set_voltage_time_sel)
429773e705bfSMatthias Kaehlcke 		return _regulator_set_voltage_time(rdev, old_uV, new_uV);
429873e705bfSMatthias Kaehlcke 
429988cd222bSLinus Walleij 	/* Currently requires operations to do this */
430073e705bfSMatthias Kaehlcke 	if (!ops->list_voltage || !rdev->desc->n_voltages)
430188cd222bSLinus Walleij 		return -EINVAL;
430288cd222bSLinus Walleij 
430388cd222bSLinus Walleij 	for (i = 0; i < rdev->desc->n_voltages; i++) {
430488cd222bSLinus Walleij 		/* We only look for exact voltage matches here */
4305bdcd1177SClaudiu Beznea 		if (i < rdev->desc->linear_min_sel)
4306bdcd1177SClaudiu Beznea 			continue;
4307bdcd1177SClaudiu Beznea 
4308ab97800eSClaudiu Beznea 		if (old_sel >= 0 && new_sel >= 0)
4309ab97800eSClaudiu Beznea 			break;
4310ab97800eSClaudiu Beznea 
431188cd222bSLinus Walleij 		voltage = regulator_list_voltage(regulator, i);
431288cd222bSLinus Walleij 		if (voltage < 0)
431388cd222bSLinus Walleij 			return -EINVAL;
431488cd222bSLinus Walleij 		if (voltage == 0)
431588cd222bSLinus Walleij 			continue;
431688cd222bSLinus Walleij 		if (voltage == old_uV)
431788cd222bSLinus Walleij 			old_sel = i;
431888cd222bSLinus Walleij 		if (voltage == new_uV)
431988cd222bSLinus Walleij 			new_sel = i;
432088cd222bSLinus Walleij 	}
432188cd222bSLinus Walleij 
432288cd222bSLinus Walleij 	if (old_sel < 0 || new_sel < 0)
432388cd222bSLinus Walleij 		return -EINVAL;
432488cd222bSLinus Walleij 
432588cd222bSLinus Walleij 	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
432688cd222bSLinus Walleij }
432788cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
432888cd222bSLinus Walleij 
432988cd222bSLinus Walleij /**
433098a175b6SYadwinder Singh Brar  * regulator_set_voltage_time_sel - get raise/fall time
4331296c6566SRandy Dunlap  * @rdev: regulator source device
433298a175b6SYadwinder Singh Brar  * @old_selector: selector for starting voltage
433398a175b6SYadwinder Singh Brar  * @new_selector: selector for target voltage
433498a175b6SYadwinder Singh Brar  *
433598a175b6SYadwinder Singh Brar  * Provided with the starting and target voltage selectors, this function
433698a175b6SYadwinder Singh Brar  * returns time in microseconds required to rise or fall to this new voltage
433798a175b6SYadwinder Singh Brar  *
4338f11d08c3SAxel Lin  * Drivers providing ramp_delay in regulation_constraints can use this as their
4339398715abSAxel Lin  * set_voltage_time_sel() operation.
434098a175b6SYadwinder Singh Brar  */
regulator_set_voltage_time_sel(struct regulator_dev * rdev,unsigned int old_selector,unsigned int new_selector)434198a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
434298a175b6SYadwinder Singh Brar 				   unsigned int old_selector,
434398a175b6SYadwinder Singh Brar 				   unsigned int new_selector)
434498a175b6SYadwinder Singh Brar {
4345f11d08c3SAxel Lin 	int old_volt, new_volt;
4346398715abSAxel Lin 
4347f11d08c3SAxel Lin 	/* sanity check */
4348f11d08c3SAxel Lin 	if (!rdev->desc->ops->list_voltage)
4349f11d08c3SAxel Lin 		return -EINVAL;
4350398715abSAxel Lin 
4351f11d08c3SAxel Lin 	old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
4352f11d08c3SAxel Lin 	new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
4353f11d08c3SAxel Lin 
435473e705bfSMatthias Kaehlcke 	if (rdev->desc->ops->set_voltage_time)
435573e705bfSMatthias Kaehlcke 		return rdev->desc->ops->set_voltage_time(rdev, old_volt,
435673e705bfSMatthias Kaehlcke 							 new_volt);
435773e705bfSMatthias Kaehlcke 	else
435873e705bfSMatthias Kaehlcke 		return _regulator_set_voltage_time(rdev, old_volt, new_volt);
435998a175b6SYadwinder Singh Brar }
4360b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
436198a175b6SYadwinder Singh Brar 
regulator_sync_voltage_rdev(struct regulator_dev * rdev)4362380d2b2dSDmitry Osipenko int regulator_sync_voltage_rdev(struct regulator_dev *rdev)
4363380d2b2dSDmitry Osipenko {
4364380d2b2dSDmitry Osipenko 	int ret;
4365380d2b2dSDmitry Osipenko 
4366380d2b2dSDmitry Osipenko 	regulator_lock(rdev);
4367380d2b2dSDmitry Osipenko 
4368380d2b2dSDmitry Osipenko 	if (!rdev->desc->ops->set_voltage &&
4369380d2b2dSDmitry Osipenko 	    !rdev->desc->ops->set_voltage_sel) {
4370380d2b2dSDmitry Osipenko 		ret = -EINVAL;
4371380d2b2dSDmitry Osipenko 		goto out;
4372380d2b2dSDmitry Osipenko 	}
4373380d2b2dSDmitry Osipenko 
4374380d2b2dSDmitry Osipenko 	/* balance only, if regulator is coupled */
4375380d2b2dSDmitry Osipenko 	if (rdev->coupling_desc.n_coupled > 1)
4376380d2b2dSDmitry Osipenko 		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
4377380d2b2dSDmitry Osipenko 	else
4378380d2b2dSDmitry Osipenko 		ret = -EOPNOTSUPP;
4379380d2b2dSDmitry Osipenko 
4380380d2b2dSDmitry Osipenko out:
4381380d2b2dSDmitry Osipenko 	regulator_unlock(rdev);
4382380d2b2dSDmitry Osipenko 	return ret;
4383380d2b2dSDmitry Osipenko }
4384380d2b2dSDmitry Osipenko 
438598a175b6SYadwinder Singh Brar /**
4386606a2562SMark Brown  * regulator_sync_voltage - re-apply last regulator output voltage
4387606a2562SMark Brown  * @regulator: regulator source
4388606a2562SMark Brown  *
4389606a2562SMark Brown  * Re-apply the last configured voltage.  This is intended to be used
4390606a2562SMark Brown  * where some external control source the consumer is cooperating with
4391606a2562SMark Brown  * has caused the configured voltage to change.
4392606a2562SMark Brown  */
regulator_sync_voltage(struct regulator * regulator)4393606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator)
4394606a2562SMark Brown {
4395606a2562SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
4396c360a6dfSChunyan Zhang 	struct regulator_voltage *voltage = &regulator->voltage[PM_SUSPEND_ON];
4397606a2562SMark Brown 	int ret, min_uV, max_uV;
4398606a2562SMark Brown 
4399400d5a5dSDmitry Osipenko 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
4400400d5a5dSDmitry Osipenko 		return 0;
4401400d5a5dSDmitry Osipenko 
440266cf9a7eSMaciej Purski 	regulator_lock(rdev);
4403606a2562SMark Brown 
4404606a2562SMark Brown 	if (!rdev->desc->ops->set_voltage &&
4405606a2562SMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
4406606a2562SMark Brown 		ret = -EINVAL;
4407606a2562SMark Brown 		goto out;
4408606a2562SMark Brown 	}
4409606a2562SMark Brown 
4410606a2562SMark Brown 	/* This is only going to work if we've had a voltage configured. */
4411c360a6dfSChunyan Zhang 	if (!voltage->min_uV && !voltage->max_uV) {
4412606a2562SMark Brown 		ret = -EINVAL;
4413606a2562SMark Brown 		goto out;
4414606a2562SMark Brown 	}
4415606a2562SMark Brown 
4416c360a6dfSChunyan Zhang 	min_uV = voltage->min_uV;
4417c360a6dfSChunyan Zhang 	max_uV = voltage->max_uV;
4418606a2562SMark Brown 
4419606a2562SMark Brown 	/* This should be a paranoia check... */
4420606a2562SMark Brown 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
4421606a2562SMark Brown 	if (ret < 0)
4422606a2562SMark Brown 		goto out;
4423606a2562SMark Brown 
4424c360a6dfSChunyan Zhang 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0);
4425606a2562SMark Brown 	if (ret < 0)
4426606a2562SMark Brown 		goto out;
4427606a2562SMark Brown 
442824be0c71SDmitry Osipenko 	/* balance only, if regulator is coupled */
442924be0c71SDmitry Osipenko 	if (rdev->coupling_desc.n_coupled > 1)
443024be0c71SDmitry Osipenko 		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
443124be0c71SDmitry Osipenko 	else
4432606a2562SMark Brown 		ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
4433606a2562SMark Brown 
4434606a2562SMark Brown out:
443566cf9a7eSMaciej Purski 	regulator_unlock(rdev);
4436606a2562SMark Brown 	return ret;
4437606a2562SMark Brown }
4438606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage);
4439606a2562SMark Brown 
regulator_get_voltage_rdev(struct regulator_dev * rdev)4440d22b85a1SDmitry Osipenko int regulator_get_voltage_rdev(struct regulator_dev *rdev)
4441414c70cbSLiam Girdwood {
4442bf5892a8SMark Brown 	int sel, ret;
4443fef95019SMark Brown 	bool bypassed;
4444fef95019SMark Brown 
4445fef95019SMark Brown 	if (rdev->desc->ops->get_bypass) {
4446fef95019SMark Brown 		ret = rdev->desc->ops->get_bypass(rdev, &bypassed);
4447fef95019SMark Brown 		if (ret < 0)
4448fef95019SMark Brown 			return ret;
4449fef95019SMark Brown 		if (bypassed) {
4450fef95019SMark Brown 			/* if bypassed the regulator must have a supply */
445145389c47SJon Hunter 			if (!rdev->supply) {
445245389c47SJon Hunter 				rdev_err(rdev,
445345389c47SJon Hunter 					 "bypassed regulator has no supply!\n");
445445389c47SJon Hunter 				return -EPROBE_DEFER;
445545389c47SJon Hunter 			}
4456fef95019SMark Brown 
4457d22b85a1SDmitry Osipenko 			return regulator_get_voltage_rdev(rdev->supply->rdev);
4458fef95019SMark Brown 		}
4459fef95019SMark Brown 	}
4460476c2d83SMark Brown 
4461476c2d83SMark Brown 	if (rdev->desc->ops->get_voltage_sel) {
4462476c2d83SMark Brown 		sel = rdev->desc->ops->get_voltage_sel(rdev);
4463476c2d83SMark Brown 		if (sel < 0)
4464476c2d83SMark Brown 			return sel;
4465bf5892a8SMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, sel);
4466cb220d16SAxel Lin 	} else if (rdev->desc->ops->get_voltage) {
4467bf5892a8SMark Brown 		ret = rdev->desc->ops->get_voltage(rdev);
4468f7df20ecSMark Brown 	} else if (rdev->desc->ops->list_voltage) {
4469f7df20ecSMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, 0);
44705a523605SLaxman Dewangan 	} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
44715a523605SLaxman Dewangan 		ret = rdev->desc->fixed_uV;
4472e303996eSJavier Martinez Canillas 	} else if (rdev->supply) {
4473d22b85a1SDmitry Osipenko 		ret = regulator_get_voltage_rdev(rdev->supply->rdev);
4474cf1ad559SMichał Mirosław 	} else if (rdev->supply_name) {
4475cf1ad559SMichał Mirosław 		return -EPROBE_DEFER;
4476cb220d16SAxel Lin 	} else {
4477414c70cbSLiam Girdwood 		return -EINVAL;
4478cb220d16SAxel Lin 	}
4479bf5892a8SMark Brown 
4480cb220d16SAxel Lin 	if (ret < 0)
4481cb220d16SAxel Lin 		return ret;
4482bf5892a8SMark Brown 	return ret - rdev->constraints->uV_offset;
4483414c70cbSLiam Girdwood }
44843d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_get_voltage_rdev);
4485414c70cbSLiam Girdwood 
4486414c70cbSLiam Girdwood /**
4487414c70cbSLiam Girdwood  * regulator_get_voltage - get regulator output voltage
4488414c70cbSLiam Girdwood  * @regulator: regulator source
4489414c70cbSLiam Girdwood  *
4490414c70cbSLiam Girdwood  * This returns the current regulator voltage in uV.
4491414c70cbSLiam Girdwood  *
4492414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the voltage value. This
4493414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
4494414c70cbSLiam Girdwood  */
regulator_get_voltage(struct regulator * regulator)4495414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator)
4496414c70cbSLiam Girdwood {
4497f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
4498414c70cbSLiam Girdwood 	int ret;
4499414c70cbSLiam Girdwood 
4500f8702f9eSDmitry Osipenko 	regulator_lock_dependent(regulator->rdev, &ww_ctx);
4501d22b85a1SDmitry Osipenko 	ret = regulator_get_voltage_rdev(regulator->rdev);
4502f8702f9eSDmitry Osipenko 	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
4503414c70cbSLiam Girdwood 
4504414c70cbSLiam Girdwood 	return ret;
4505414c70cbSLiam Girdwood }
4506414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage);
4507414c70cbSLiam Girdwood 
4508414c70cbSLiam Girdwood /**
4509414c70cbSLiam Girdwood  * regulator_set_current_limit - set regulator output current limit
4510414c70cbSLiam Girdwood  * @regulator: regulator source
4511ce0d10f8SCharles Keepax  * @min_uA: Minimum supported current in uA
4512414c70cbSLiam Girdwood  * @max_uA: Maximum supported current in uA
4513414c70cbSLiam Girdwood  *
4514414c70cbSLiam Girdwood  * Sets current sink to the desired output current. This can be set during
4515414c70cbSLiam Girdwood  * any regulator state. IOW, regulator can be disabled or enabled.
4516414c70cbSLiam Girdwood  *
4517414c70cbSLiam Girdwood  * If the regulator is enabled then the current will change to the new value
4518414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
4519414c70cbSLiam Girdwood  * output at the new current when enabled.
4520414c70cbSLiam Girdwood  *
4521414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
4522414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
4523414c70cbSLiam Girdwood  */
regulator_set_current_limit(struct regulator * regulator,int min_uA,int max_uA)4524414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator,
4525414c70cbSLiam Girdwood 			       int min_uA, int max_uA)
4526414c70cbSLiam Girdwood {
4527414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
4528414c70cbSLiam Girdwood 	int ret;
4529414c70cbSLiam Girdwood 
453066cf9a7eSMaciej Purski 	regulator_lock(rdev);
4531414c70cbSLiam Girdwood 
4532414c70cbSLiam Girdwood 	/* sanity check */
4533414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_current_limit) {
4534414c70cbSLiam Girdwood 		ret = -EINVAL;
4535414c70cbSLiam Girdwood 		goto out;
4536414c70cbSLiam Girdwood 	}
4537414c70cbSLiam Girdwood 
4538414c70cbSLiam Girdwood 	/* constraints check */
4539414c70cbSLiam Girdwood 	ret = regulator_check_current_limit(rdev, &min_uA, &max_uA);
4540414c70cbSLiam Girdwood 	if (ret < 0)
4541414c70cbSLiam Girdwood 		goto out;
4542414c70cbSLiam Girdwood 
4543414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
4544414c70cbSLiam Girdwood out:
454566cf9a7eSMaciej Purski 	regulator_unlock(rdev);
4546414c70cbSLiam Girdwood 	return ret;
4547414c70cbSLiam Girdwood }
4548414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit);
4549414c70cbSLiam Girdwood 
_regulator_get_current_limit_unlocked(struct regulator_dev * rdev)45507e4d9683SDouglas Anderson static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev)
45517e4d9683SDouglas Anderson {
45527e4d9683SDouglas Anderson 	/* sanity check */
45537e4d9683SDouglas Anderson 	if (!rdev->desc->ops->get_current_limit)
45547e4d9683SDouglas Anderson 		return -EINVAL;
45557e4d9683SDouglas Anderson 
45567e4d9683SDouglas Anderson 	return rdev->desc->ops->get_current_limit(rdev);
45577e4d9683SDouglas Anderson }
45587e4d9683SDouglas Anderson 
_regulator_get_current_limit(struct regulator_dev * rdev)4559414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev)
4560414c70cbSLiam Girdwood {
4561414c70cbSLiam Girdwood 	int ret;
4562414c70cbSLiam Girdwood 
456366cf9a7eSMaciej Purski 	regulator_lock(rdev);
45647e4d9683SDouglas Anderson 	ret = _regulator_get_current_limit_unlocked(rdev);
456566cf9a7eSMaciej Purski 	regulator_unlock(rdev);
45667e4d9683SDouglas Anderson 
4567414c70cbSLiam Girdwood 	return ret;
4568414c70cbSLiam Girdwood }
4569414c70cbSLiam Girdwood 
4570414c70cbSLiam Girdwood /**
4571414c70cbSLiam Girdwood  * regulator_get_current_limit - get regulator output current
4572414c70cbSLiam Girdwood  * @regulator: regulator source
4573414c70cbSLiam Girdwood  *
4574414c70cbSLiam Girdwood  * This returns the current supplied by the specified current sink in uA.
4575414c70cbSLiam Girdwood  *
4576414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the current value. This
4577414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
4578414c70cbSLiam Girdwood  */
regulator_get_current_limit(struct regulator * regulator)4579414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator)
4580414c70cbSLiam Girdwood {
4581414c70cbSLiam Girdwood 	return _regulator_get_current_limit(regulator->rdev);
4582414c70cbSLiam Girdwood }
4583414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit);
4584414c70cbSLiam Girdwood 
4585414c70cbSLiam Girdwood /**
4586414c70cbSLiam Girdwood  * regulator_set_mode - set regulator operating mode
4587414c70cbSLiam Girdwood  * @regulator: regulator source
4588414c70cbSLiam Girdwood  * @mode: operating mode - one of the REGULATOR_MODE constants
4589414c70cbSLiam Girdwood  *
4590414c70cbSLiam Girdwood  * Set regulator operating mode to increase regulator efficiency or improve
4591414c70cbSLiam Girdwood  * regulation performance.
4592414c70cbSLiam Girdwood  *
4593414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
4594414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
4595414c70cbSLiam Girdwood  */
regulator_set_mode(struct regulator * regulator,unsigned int mode)4596414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode)
4597414c70cbSLiam Girdwood {
4598414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
4599414c70cbSLiam Girdwood 	int ret;
4600500b4ac9SSundar R Iyer 	int regulator_curr_mode;
4601414c70cbSLiam Girdwood 
460266cf9a7eSMaciej Purski 	regulator_lock(rdev);
4603414c70cbSLiam Girdwood 
4604414c70cbSLiam Girdwood 	/* sanity check */
4605414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_mode) {
4606414c70cbSLiam Girdwood 		ret = -EINVAL;
4607414c70cbSLiam Girdwood 		goto out;
4608414c70cbSLiam Girdwood 	}
4609414c70cbSLiam Girdwood 
4610500b4ac9SSundar R Iyer 	/* return if the same mode is requested */
4611500b4ac9SSundar R Iyer 	if (rdev->desc->ops->get_mode) {
4612500b4ac9SSundar R Iyer 		regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
4613500b4ac9SSundar R Iyer 		if (regulator_curr_mode == mode) {
4614500b4ac9SSundar R Iyer 			ret = 0;
4615500b4ac9SSundar R Iyer 			goto out;
4616500b4ac9SSundar R Iyer 		}
4617500b4ac9SSundar R Iyer 	}
4618500b4ac9SSundar R Iyer 
4619414c70cbSLiam Girdwood 	/* constraints check */
462022c51b47SAxel Lin 	ret = regulator_mode_constrain(rdev, &mode);
4621414c70cbSLiam Girdwood 	if (ret < 0)
4622414c70cbSLiam Girdwood 		goto out;
4623414c70cbSLiam Girdwood 
4624414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
4625414c70cbSLiam Girdwood out:
462666cf9a7eSMaciej Purski 	regulator_unlock(rdev);
4627414c70cbSLiam Girdwood 	return ret;
4628414c70cbSLiam Girdwood }
4629414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode);
4630414c70cbSLiam Girdwood 
_regulator_get_mode_unlocked(struct regulator_dev * rdev)46317e4d9683SDouglas Anderson static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev)
46327e4d9683SDouglas Anderson {
46337e4d9683SDouglas Anderson 	/* sanity check */
46347e4d9683SDouglas Anderson 	if (!rdev->desc->ops->get_mode)
46357e4d9683SDouglas Anderson 		return -EINVAL;
46367e4d9683SDouglas Anderson 
46377e4d9683SDouglas Anderson 	return rdev->desc->ops->get_mode(rdev);
46387e4d9683SDouglas Anderson }
46397e4d9683SDouglas Anderson 
_regulator_get_mode(struct regulator_dev * rdev)4640414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
4641414c70cbSLiam Girdwood {
4642414c70cbSLiam Girdwood 	int ret;
4643414c70cbSLiam Girdwood 
464466cf9a7eSMaciej Purski 	regulator_lock(rdev);
46457e4d9683SDouglas Anderson 	ret = _regulator_get_mode_unlocked(rdev);
464666cf9a7eSMaciej Purski 	regulator_unlock(rdev);
46477e4d9683SDouglas Anderson 
4648414c70cbSLiam Girdwood 	return ret;
4649414c70cbSLiam Girdwood }
4650414c70cbSLiam Girdwood 
4651414c70cbSLiam Girdwood /**
4652414c70cbSLiam Girdwood  * regulator_get_mode - get regulator operating mode
4653414c70cbSLiam Girdwood  * @regulator: regulator source
4654414c70cbSLiam Girdwood  *
4655414c70cbSLiam Girdwood  * Get the current regulator operating mode.
4656414c70cbSLiam Girdwood  */
regulator_get_mode(struct regulator * regulator)4657414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator)
4658414c70cbSLiam Girdwood {
4659414c70cbSLiam Girdwood 	return _regulator_get_mode(regulator->rdev);
4660414c70cbSLiam Girdwood }
4661414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode);
4662414c70cbSLiam Girdwood 
rdev_get_cached_err_flags(struct regulator_dev * rdev)46637111c6d1SMatti Vaittinen static int rdev_get_cached_err_flags(struct regulator_dev *rdev)
46647111c6d1SMatti Vaittinen {
46657111c6d1SMatti Vaittinen 	int ret = 0;
46667111c6d1SMatti Vaittinen 
46677111c6d1SMatti Vaittinen 	if (rdev->use_cached_err) {
46687111c6d1SMatti Vaittinen 		spin_lock(&rdev->err_lock);
46697111c6d1SMatti Vaittinen 		ret = rdev->cached_err;
46707111c6d1SMatti Vaittinen 		spin_unlock(&rdev->err_lock);
46717111c6d1SMatti Vaittinen 	}
46727111c6d1SMatti Vaittinen 	return ret;
46737111c6d1SMatti Vaittinen }
46747111c6d1SMatti Vaittinen 
_regulator_get_error_flags(struct regulator_dev * rdev,unsigned int * flags)46751b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev,
46761b5b4221SAxel Haslam 					unsigned int *flags)
46771b5b4221SAxel Haslam {
46787111c6d1SMatti Vaittinen 	int cached_flags, ret = 0;
46791b5b4221SAxel Haslam 
468066cf9a7eSMaciej Purski 	regulator_lock(rdev);
46811b5b4221SAxel Haslam 
46827111c6d1SMatti Vaittinen 	cached_flags = rdev_get_cached_err_flags(rdev);
46831b5b4221SAxel Haslam 
46847111c6d1SMatti Vaittinen 	if (rdev->desc->ops->get_error_flags)
46851b5b4221SAxel Haslam 		ret = rdev->desc->ops->get_error_flags(rdev, flags);
46867111c6d1SMatti Vaittinen 	else if (!rdev->use_cached_err)
46877111c6d1SMatti Vaittinen 		ret = -EINVAL;
46887111c6d1SMatti Vaittinen 
46897111c6d1SMatti Vaittinen 	*flags |= cached_flags;
46907111c6d1SMatti Vaittinen 
469166cf9a7eSMaciej Purski 	regulator_unlock(rdev);
46927111c6d1SMatti Vaittinen 
46931b5b4221SAxel Haslam 	return ret;
46941b5b4221SAxel Haslam }
46951b5b4221SAxel Haslam 
46961b5b4221SAxel Haslam /**
46971b5b4221SAxel Haslam  * regulator_get_error_flags - get regulator error information
46981b5b4221SAxel Haslam  * @regulator: regulator source
46991b5b4221SAxel Haslam  * @flags: pointer to store error flags
47001b5b4221SAxel Haslam  *
47011b5b4221SAxel Haslam  * Get the current regulator error information.
47021b5b4221SAxel Haslam  */
regulator_get_error_flags(struct regulator * regulator,unsigned int * flags)47031b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator,
47041b5b4221SAxel Haslam 				unsigned int *flags)
47051b5b4221SAxel Haslam {
47061b5b4221SAxel Haslam 	return _regulator_get_error_flags(regulator->rdev, flags);
47071b5b4221SAxel Haslam }
47081b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags);
47091b5b4221SAxel Haslam 
4710414c70cbSLiam Girdwood /**
4711e39ce48fSBjorn Andersson  * regulator_set_load - set regulator load
4712414c70cbSLiam Girdwood  * @regulator: regulator source
4713414c70cbSLiam Girdwood  * @uA_load: load current
4714414c70cbSLiam Girdwood  *
4715414c70cbSLiam Girdwood  * Notifies the regulator core of a new device load. This is then used by
4716414c70cbSLiam Girdwood  * DRMS (if enabled by constraints) to set the most efficient regulator
4717414c70cbSLiam Girdwood  * operating mode for the new regulator loading.
4718414c70cbSLiam Girdwood  *
4719414c70cbSLiam Girdwood  * Consumer devices notify their supply regulator of the maximum power
4720414c70cbSLiam Girdwood  * they will require (can be taken from device datasheet in the power
4721414c70cbSLiam Girdwood  * consumption tables) when they change operational status and hence power
4722414c70cbSLiam Girdwood  * state. Examples of operational state changes that can affect power
4723414c70cbSLiam Girdwood  * consumption are :-
4724414c70cbSLiam Girdwood  *
4725414c70cbSLiam Girdwood  *    o Device is opened / closed.
4726414c70cbSLiam Girdwood  *    o Device I/O is about to begin or has just finished.
4727414c70cbSLiam Girdwood  *    o Device is idling in between work.
4728414c70cbSLiam Girdwood  *
4729414c70cbSLiam Girdwood  * This information is also exported via sysfs to userspace.
4730414c70cbSLiam Girdwood  *
4731414c70cbSLiam Girdwood  * DRMS will sum the total requested load on the regulator and change
4732414c70cbSLiam Girdwood  * to the most efficient operating mode if platform constraints allow.
4733414c70cbSLiam Girdwood  *
47345451781dSDouglas Anderson  * NOTE: when a regulator consumer requests to have a regulator
47355451781dSDouglas Anderson  * disabled then any load that consumer requested no longer counts
47365451781dSDouglas Anderson  * toward the total requested load.  If the regulator is re-enabled
47375451781dSDouglas Anderson  * then the previously requested load will start counting again.
47385451781dSDouglas Anderson  *
47395451781dSDouglas Anderson  * If a regulator is an always-on regulator then an individual consumer's
47405451781dSDouglas Anderson  * load will still be removed if that consumer is fully disabled.
47415451781dSDouglas Anderson  *
4742e39ce48fSBjorn Andersson  * On error a negative errno is returned.
4743414c70cbSLiam Girdwood  */
regulator_set_load(struct regulator * regulator,int uA_load)4744e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load)
4745414c70cbSLiam Girdwood {
4746414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
47475451781dSDouglas Anderson 	int old_uA_load;
47485451781dSDouglas Anderson 	int ret = 0;
4749d92d95b6SStephen Boyd 
475066cf9a7eSMaciej Purski 	regulator_lock(rdev);
47515451781dSDouglas Anderson 	old_uA_load = regulator->uA_load;
4752414c70cbSLiam Girdwood 	regulator->uA_load = uA_load;
47535451781dSDouglas Anderson 	if (regulator->enable_count && old_uA_load != uA_load) {
47548460ef38SBjorn Andersson 		ret = drms_uA_update(rdev);
47555451781dSDouglas Anderson 		if (ret < 0)
47565451781dSDouglas Anderson 			regulator->uA_load = old_uA_load;
47575451781dSDouglas Anderson 	}
475866cf9a7eSMaciej Purski 	regulator_unlock(rdev);
47598460ef38SBjorn Andersson 
4760414c70cbSLiam Girdwood 	return ret;
4761414c70cbSLiam Girdwood }
4762e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load);
4763414c70cbSLiam Girdwood 
4764414c70cbSLiam Girdwood /**
4765f59c8f9fSMark Brown  * regulator_allow_bypass - allow the regulator to go into bypass mode
4766f59c8f9fSMark Brown  *
4767f59c8f9fSMark Brown  * @regulator: Regulator to configure
47689345dfb8SNishanth Menon  * @enable: enable or disable bypass mode
4769f59c8f9fSMark Brown  *
4770f59c8f9fSMark Brown  * Allow the regulator to go into bypass mode if all other consumers
4771f59c8f9fSMark Brown  * for the regulator also enable bypass mode and the machine
4772f59c8f9fSMark Brown  * constraints allow this.  Bypass mode means that the regulator is
4773f59c8f9fSMark Brown  * simply passing the input directly to the output with no regulation.
4774f59c8f9fSMark Brown  */
regulator_allow_bypass(struct regulator * regulator,bool enable)4775f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable)
4776f59c8f9fSMark Brown {
4777f59c8f9fSMark Brown 	struct regulator_dev *rdev = regulator->rdev;
477848325655SCharles Keepax 	const char *name = rdev_get_name(rdev);
4779f59c8f9fSMark Brown 	int ret = 0;
4780f59c8f9fSMark Brown 
4781f59c8f9fSMark Brown 	if (!rdev->desc->ops->set_bypass)
4782f59c8f9fSMark Brown 		return 0;
4783f59c8f9fSMark Brown 
47848a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS))
4785f59c8f9fSMark Brown 		return 0;
4786f59c8f9fSMark Brown 
478766cf9a7eSMaciej Purski 	regulator_lock(rdev);
4788f59c8f9fSMark Brown 
4789f59c8f9fSMark Brown 	if (enable && !regulator->bypass) {
4790f59c8f9fSMark Brown 		rdev->bypass_count++;
4791f59c8f9fSMark Brown 
4792f59c8f9fSMark Brown 		if (rdev->bypass_count == rdev->open_count) {
479348325655SCharles Keepax 			trace_regulator_bypass_enable(name);
479448325655SCharles Keepax 
4795f59c8f9fSMark Brown 			ret = rdev->desc->ops->set_bypass(rdev, enable);
4796f59c8f9fSMark Brown 			if (ret != 0)
4797f59c8f9fSMark Brown 				rdev->bypass_count--;
479848325655SCharles Keepax 			else
479948325655SCharles Keepax 				trace_regulator_bypass_enable_complete(name);
4800f59c8f9fSMark Brown 		}
4801f59c8f9fSMark Brown 
4802f59c8f9fSMark Brown 	} else if (!enable && regulator->bypass) {
4803f59c8f9fSMark Brown 		rdev->bypass_count--;
4804f59c8f9fSMark Brown 
4805f59c8f9fSMark Brown 		if (rdev->bypass_count != rdev->open_count) {
480648325655SCharles Keepax 			trace_regulator_bypass_disable(name);
480748325655SCharles Keepax 
4808f59c8f9fSMark Brown 			ret = rdev->desc->ops->set_bypass(rdev, enable);
4809f59c8f9fSMark Brown 			if (ret != 0)
4810f59c8f9fSMark Brown 				rdev->bypass_count++;
481148325655SCharles Keepax 			else
481248325655SCharles Keepax 				trace_regulator_bypass_disable_complete(name);
4813f59c8f9fSMark Brown 		}
4814f59c8f9fSMark Brown 	}
4815f59c8f9fSMark Brown 
4816f59c8f9fSMark Brown 	if (ret == 0)
4817f59c8f9fSMark Brown 		regulator->bypass = enable;
4818f59c8f9fSMark Brown 
481966cf9a7eSMaciej Purski 	regulator_unlock(rdev);
4820f59c8f9fSMark Brown 
4821f59c8f9fSMark Brown 	return ret;
4822f59c8f9fSMark Brown }
4823f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass);
4824f59c8f9fSMark Brown 
4825f59c8f9fSMark Brown /**
4826414c70cbSLiam Girdwood  * regulator_register_notifier - register regulator event notifier
4827414c70cbSLiam Girdwood  * @regulator: regulator source
482869279fb9SMark Brown  * @nb: notifier block
4829414c70cbSLiam Girdwood  *
4830414c70cbSLiam Girdwood  * Register notifier block to receive regulator events.
4831414c70cbSLiam Girdwood  */
regulator_register_notifier(struct regulator * regulator,struct notifier_block * nb)4832414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator,
4833414c70cbSLiam Girdwood 			      struct notifier_block *nb)
4834414c70cbSLiam Girdwood {
4835414c70cbSLiam Girdwood 	return blocking_notifier_chain_register(&regulator->rdev->notifier,
4836414c70cbSLiam Girdwood 						nb);
4837414c70cbSLiam Girdwood }
4838414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier);
4839414c70cbSLiam Girdwood 
4840414c70cbSLiam Girdwood /**
4841414c70cbSLiam Girdwood  * regulator_unregister_notifier - unregister regulator event notifier
4842414c70cbSLiam Girdwood  * @regulator: regulator source
484369279fb9SMark Brown  * @nb: notifier block
4844414c70cbSLiam Girdwood  *
4845414c70cbSLiam Girdwood  * Unregister regulator event notifier block.
4846414c70cbSLiam Girdwood  */
regulator_unregister_notifier(struct regulator * regulator,struct notifier_block * nb)4847414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator,
4848414c70cbSLiam Girdwood 				struct notifier_block *nb)
4849414c70cbSLiam Girdwood {
4850414c70cbSLiam Girdwood 	return blocking_notifier_chain_unregister(&regulator->rdev->notifier,
4851414c70cbSLiam Girdwood 						  nb);
4852414c70cbSLiam Girdwood }
4853414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
4854414c70cbSLiam Girdwood 
4855b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers.
4856b136fb44SJonathan Cameron  * Note mutex must be held by caller.
4857b136fb44SJonathan Cameron  */
_notifier_call_chain(struct regulator_dev * rdev,unsigned long event,void * data)48587179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev,
4859414c70cbSLiam Girdwood 				  unsigned long event, void *data)
4860414c70cbSLiam Girdwood {
4861414c70cbSLiam Girdwood 	/* call rdev chain first */
48627179569aSHeiko Stübner 	return blocking_notifier_call_chain(&rdev->notifier, event, data);
4863414c70cbSLiam Girdwood }
4864414c70cbSLiam Girdwood 
_regulator_bulk_get(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers,enum regulator_get_type get_type)4865fd184506SZev Weiss int _regulator_bulk_get(struct device *dev, int num_consumers,
4866fd184506SZev Weiss 			struct regulator_bulk_data *consumers, enum regulator_get_type get_type)
4867414c70cbSLiam Girdwood {
4868414c70cbSLiam Girdwood 	int i;
4869414c70cbSLiam Girdwood 	int ret;
4870414c70cbSLiam Girdwood 
4871414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++)
4872414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
4873414c70cbSLiam Girdwood 
4874414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
4875fd184506SZev Weiss 		consumers[i].consumer = _regulator_get(dev,
4876fd184506SZev Weiss 						       consumers[i].supply, get_type);
4877414c70cbSLiam Girdwood 		if (IS_ERR(consumers[i].consumer)) {
48786eabfc01SDouglas Anderson 			ret = dev_err_probe(dev, PTR_ERR(consumers[i].consumer),
48796eabfc01SDouglas Anderson 					    "Failed to get supply '%s'",
48806eabfc01SDouglas Anderson 					    consumers[i].supply);
4881d511e8a7SDouglas Anderson 			consumers[i].consumer = NULL;
4882414c70cbSLiam Girdwood 			goto err;
4883414c70cbSLiam Girdwood 		}
48846eabfc01SDouglas Anderson 
48856eabfc01SDouglas Anderson 		if (consumers[i].init_load_uA > 0) {
48866eabfc01SDouglas Anderson 			ret = regulator_set_load(consumers[i].consumer,
48876eabfc01SDouglas Anderson 						 consumers[i].init_load_uA);
48886eabfc01SDouglas Anderson 			if (ret) {
48896eabfc01SDouglas Anderson 				i++;
48906eabfc01SDouglas Anderson 				goto err;
48916eabfc01SDouglas Anderson 			}
48926eabfc01SDouglas Anderson 		}
4893414c70cbSLiam Girdwood 	}
4894414c70cbSLiam Girdwood 
4895414c70cbSLiam Girdwood 	return 0;
4896414c70cbSLiam Girdwood 
4897414c70cbSLiam Girdwood err:
4898b29c7690SAxel Lin 	while (--i >= 0)
4899414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
4900414c70cbSLiam Girdwood 
4901414c70cbSLiam Girdwood 	return ret;
4902414c70cbSLiam Girdwood }
4903fd184506SZev Weiss 
4904fd184506SZev Weiss /**
4905fd184506SZev Weiss  * regulator_bulk_get - get multiple regulator consumers
4906fd184506SZev Weiss  *
4907fd184506SZev Weiss  * @dev:           Device to supply
4908fd184506SZev Weiss  * @num_consumers: Number of consumers to register
4909fd184506SZev Weiss  * @consumers:     Configuration of consumers; clients are stored here.
4910fd184506SZev Weiss  *
4911fd184506SZev Weiss  * @return 0 on success, an errno on failure.
4912fd184506SZev Weiss  *
4913fd184506SZev Weiss  * This helper function allows drivers to get several regulator
4914fd184506SZev Weiss  * consumers in one operation.  If any of the regulators cannot be
4915fd184506SZev Weiss  * acquired then any regulators that were allocated will be freed
4916fd184506SZev Weiss  * before returning to the caller.
4917fd184506SZev Weiss  */
regulator_bulk_get(struct device * dev,int num_consumers,struct regulator_bulk_data * consumers)4918fd184506SZev Weiss int regulator_bulk_get(struct device *dev, int num_consumers,
4919fd184506SZev Weiss 		       struct regulator_bulk_data *consumers)
4920fd184506SZev Weiss {
4921fd184506SZev Weiss 	return _regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET);
4922fd184506SZev Weiss }
4923414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get);
4924414c70cbSLiam Girdwood 
regulator_bulk_enable_async(void * data,async_cookie_t cookie)4925f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
4926f21e0e81SMark Brown {
4927f21e0e81SMark Brown 	struct regulator_bulk_data *bulk = data;
4928f21e0e81SMark Brown 
4929f21e0e81SMark Brown 	bulk->ret = regulator_enable(bulk->consumer);
4930f21e0e81SMark Brown }
4931f21e0e81SMark Brown 
4932414c70cbSLiam Girdwood /**
4933414c70cbSLiam Girdwood  * regulator_bulk_enable - enable multiple regulator consumers
4934414c70cbSLiam Girdwood  *
4935414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
4936414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
4937414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
4938414c70cbSLiam Girdwood  *
4939414c70cbSLiam Girdwood  * This convenience API allows consumers to enable multiple regulator
4940414c70cbSLiam Girdwood  * clients in a single API call.  If any consumers cannot be enabled
4941414c70cbSLiam Girdwood  * then any others that were enabled will be disabled again prior to
4942414c70cbSLiam Girdwood  * return.
4943414c70cbSLiam Girdwood  */
regulator_bulk_enable(int num_consumers,struct regulator_bulk_data * consumers)4944414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers,
4945414c70cbSLiam Girdwood 			  struct regulator_bulk_data *consumers)
4946414c70cbSLiam Girdwood {
49472955b47dSDan Williams 	ASYNC_DOMAIN_EXCLUSIVE(async_domain);
4948414c70cbSLiam Girdwood 	int i;
4949f21e0e81SMark Brown 	int ret = 0;
4950414c70cbSLiam Girdwood 
49516492bc1bSMark Brown 	for (i = 0; i < num_consumers; i++) {
4952f21e0e81SMark Brown 		async_schedule_domain(regulator_bulk_enable_async,
4953f21e0e81SMark Brown 				      &consumers[i], &async_domain);
49546492bc1bSMark Brown 	}
4955f21e0e81SMark Brown 
4956f21e0e81SMark Brown 	async_synchronize_full_domain(&async_domain);
4957f21e0e81SMark Brown 
4958f21e0e81SMark Brown 	/* If any consumer failed we need to unwind any that succeeded */
4959414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
4960f21e0e81SMark Brown 		if (consumers[i].ret != 0) {
4961f21e0e81SMark Brown 			ret = consumers[i].ret;
4962414c70cbSLiam Girdwood 			goto err;
4963414c70cbSLiam Girdwood 		}
4964f21e0e81SMark Brown 	}
4965414c70cbSLiam Girdwood 
4966414c70cbSLiam Girdwood 	return 0;
4967414c70cbSLiam Girdwood 
4968414c70cbSLiam Girdwood err:
4969fbe31057SAndrzej Hajda 	for (i = 0; i < num_consumers; i++) {
4970fbe31057SAndrzej Hajda 		if (consumers[i].ret < 0)
497161aab5adSMichał Mirosław 			pr_err("Failed to enable %s: %pe\n", consumers[i].supply,
497261aab5adSMichał Mirosław 			       ERR_PTR(consumers[i].ret));
4973fbe31057SAndrzej Hajda 		else
4974414c70cbSLiam Girdwood 			regulator_disable(consumers[i].consumer);
4975fbe31057SAndrzej Hajda 	}
4976414c70cbSLiam Girdwood 
4977414c70cbSLiam Girdwood 	return ret;
4978414c70cbSLiam Girdwood }
4979414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable);
4980414c70cbSLiam Girdwood 
4981414c70cbSLiam Girdwood /**
4982414c70cbSLiam Girdwood  * regulator_bulk_disable - disable multiple regulator consumers
4983414c70cbSLiam Girdwood  *
4984414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
4985414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
4986414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
4987414c70cbSLiam Girdwood  *
4988414c70cbSLiam Girdwood  * This convenience API allows consumers to disable multiple regulator
498949e22632SSylwester Nawrocki  * clients in a single API call.  If any consumers cannot be disabled
499049e22632SSylwester Nawrocki  * then any others that were disabled will be enabled again prior to
4991414c70cbSLiam Girdwood  * return.
4992414c70cbSLiam Girdwood  */
regulator_bulk_disable(int num_consumers,struct regulator_bulk_data * consumers)4993414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers,
4994414c70cbSLiam Girdwood 			   struct regulator_bulk_data *consumers)
4995414c70cbSLiam Girdwood {
4996414c70cbSLiam Girdwood 	int i;
499701e86f49SMark Brown 	int ret, r;
4998414c70cbSLiam Girdwood 
499949e22632SSylwester Nawrocki 	for (i = num_consumers - 1; i >= 0; --i) {
5000414c70cbSLiam Girdwood 		ret = regulator_disable(consumers[i].consumer);
5001414c70cbSLiam Girdwood 		if (ret != 0)
5002414c70cbSLiam Girdwood 			goto err;
5003414c70cbSLiam Girdwood 	}
5004414c70cbSLiam Girdwood 
5005414c70cbSLiam Girdwood 	return 0;
5006414c70cbSLiam Girdwood 
5007414c70cbSLiam Girdwood err:
500861aab5adSMichał Mirosław 	pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret));
500901e86f49SMark Brown 	for (++i; i < num_consumers; ++i) {
501001e86f49SMark Brown 		r = regulator_enable(consumers[i].consumer);
501101e86f49SMark Brown 		if (r != 0)
501261aab5adSMichał Mirosław 			pr_err("Failed to re-enable %s: %pe\n",
501361aab5adSMichał Mirosław 			       consumers[i].supply, ERR_PTR(r));
501401e86f49SMark Brown 	}
5015414c70cbSLiam Girdwood 
5016414c70cbSLiam Girdwood 	return ret;
5017414c70cbSLiam Girdwood }
5018414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable);
5019414c70cbSLiam Girdwood 
5020414c70cbSLiam Girdwood /**
5021e1de2f42SDonggeun Kim  * regulator_bulk_force_disable - force disable multiple regulator consumers
5022e1de2f42SDonggeun Kim  *
5023e1de2f42SDonggeun Kim  * @num_consumers: Number of consumers
5024e1de2f42SDonggeun Kim  * @consumers:     Consumer data; clients are stored here.
5025e1de2f42SDonggeun Kim  * @return         0 on success, an errno on failure
5026e1de2f42SDonggeun Kim  *
5027e1de2f42SDonggeun Kim  * This convenience API allows consumers to forcibly disable multiple regulator
5028e1de2f42SDonggeun Kim  * clients in a single API call.
5029e1de2f42SDonggeun Kim  * NOTE: This should be used for situations when device damage will
5030e1de2f42SDonggeun Kim  * likely occur if the regulators are not disabled (e.g. over temp).
5031e1de2f42SDonggeun Kim  * Although regulator_force_disable function call for some consumers can
5032e1de2f42SDonggeun Kim  * return error numbers, the function is called for all consumers.
5033e1de2f42SDonggeun Kim  */
regulator_bulk_force_disable(int num_consumers,struct regulator_bulk_data * consumers)5034e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers,
5035e1de2f42SDonggeun Kim 			   struct regulator_bulk_data *consumers)
5036e1de2f42SDonggeun Kim {
5037e1de2f42SDonggeun Kim 	int i;
5038b8c77ff6SDmitry Torokhov 	int ret = 0;
5039e1de2f42SDonggeun Kim 
5040b8c77ff6SDmitry Torokhov 	for (i = 0; i < num_consumers; i++) {
5041e1de2f42SDonggeun Kim 		consumers[i].ret =
5042e1de2f42SDonggeun Kim 			    regulator_force_disable(consumers[i].consumer);
5043e1de2f42SDonggeun Kim 
5044b8c77ff6SDmitry Torokhov 		/* Store first error for reporting */
5045b8c77ff6SDmitry Torokhov 		if (consumers[i].ret && !ret)
5046e1de2f42SDonggeun Kim 			ret = consumers[i].ret;
5047e1de2f42SDonggeun Kim 	}
5048e1de2f42SDonggeun Kim 
5049e1de2f42SDonggeun Kim 	return ret;
5050e1de2f42SDonggeun Kim }
5051e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
5052e1de2f42SDonggeun Kim 
5053e1de2f42SDonggeun Kim /**
5054414c70cbSLiam Girdwood  * regulator_bulk_free - free multiple regulator consumers
5055414c70cbSLiam Girdwood  *
5056414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
5057414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
5058414c70cbSLiam Girdwood  *
5059414c70cbSLiam Girdwood  * This convenience API allows consumers to free multiple regulator
5060414c70cbSLiam Girdwood  * clients in a single API call.
5061414c70cbSLiam Girdwood  */
regulator_bulk_free(int num_consumers,struct regulator_bulk_data * consumers)5062414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers,
5063414c70cbSLiam Girdwood 			 struct regulator_bulk_data *consumers)
5064414c70cbSLiam Girdwood {
5065414c70cbSLiam Girdwood 	int i;
5066414c70cbSLiam Girdwood 
5067414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
5068414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
5069414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
5070414c70cbSLiam Girdwood 	}
5071414c70cbSLiam Girdwood }
5072414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free);
5073414c70cbSLiam Girdwood 
5074414c70cbSLiam Girdwood /**
5075414c70cbSLiam Girdwood  * regulator_notifier_call_chain - call regulator event notifier
507669279fb9SMark Brown  * @rdev: regulator source
5077414c70cbSLiam Girdwood  * @event: notifier block
507869279fb9SMark Brown  * @data: callback-specific data.
5079414c70cbSLiam Girdwood  *
5080414c70cbSLiam Girdwood  * Called by regulator drivers to notify clients a regulator event has
50813bca239dSMichał Mirosław  * occurred.
5082414c70cbSLiam Girdwood  */
regulator_notifier_call_chain(struct regulator_dev * rdev,unsigned long event,void * data)5083414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev,
5084414c70cbSLiam Girdwood 				  unsigned long event, void *data)
5085414c70cbSLiam Girdwood {
5086414c70cbSLiam Girdwood 	_notifier_call_chain(rdev, event, data);
5087414c70cbSLiam Girdwood 	return NOTIFY_DONE;
5088414c70cbSLiam Girdwood 
5089414c70cbSLiam Girdwood }
5090414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
5091414c70cbSLiam Girdwood 
5092be721979SMark Brown /**
5093be721979SMark Brown  * regulator_mode_to_status - convert a regulator mode into a status
5094be721979SMark Brown  *
5095be721979SMark Brown  * @mode: Mode to convert
5096be721979SMark Brown  *
5097be721979SMark Brown  * Convert a regulator mode into a status.
5098be721979SMark Brown  */
regulator_mode_to_status(unsigned int mode)5099be721979SMark Brown int regulator_mode_to_status(unsigned int mode)
5100be721979SMark Brown {
5101be721979SMark Brown 	switch (mode) {
5102be721979SMark Brown 	case REGULATOR_MODE_FAST:
5103be721979SMark Brown 		return REGULATOR_STATUS_FAST;
5104be721979SMark Brown 	case REGULATOR_MODE_NORMAL:
5105be721979SMark Brown 		return REGULATOR_STATUS_NORMAL;
5106be721979SMark Brown 	case REGULATOR_MODE_IDLE:
5107be721979SMark Brown 		return REGULATOR_STATUS_IDLE;
510803ffcf3dSKrystian Garbaciak 	case REGULATOR_MODE_STANDBY:
5109be721979SMark Brown 		return REGULATOR_STATUS_STANDBY;
5110be721979SMark Brown 	default:
51111beaf762SKrystian Garbaciak 		return REGULATOR_STATUS_UNDEFINED;
5112be721979SMark Brown 	}
5113be721979SMark Brown }
5114be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status);
5115be721979SMark Brown 
511639f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = {
511739f802d6STakashi Iwai 	&dev_attr_name.attr,
511839f802d6STakashi Iwai 	&dev_attr_num_users.attr,
511939f802d6STakashi Iwai 	&dev_attr_type.attr,
512039f802d6STakashi Iwai 	&dev_attr_microvolts.attr,
512139f802d6STakashi Iwai 	&dev_attr_microamps.attr,
512239f802d6STakashi Iwai 	&dev_attr_opmode.attr,
512339f802d6STakashi Iwai 	&dev_attr_state.attr,
512439f802d6STakashi Iwai 	&dev_attr_status.attr,
512539f802d6STakashi Iwai 	&dev_attr_bypass.attr,
512639f802d6STakashi Iwai 	&dev_attr_requested_microamps.attr,
512739f802d6STakashi Iwai 	&dev_attr_min_microvolts.attr,
512839f802d6STakashi Iwai 	&dev_attr_max_microvolts.attr,
512939f802d6STakashi Iwai 	&dev_attr_min_microamps.attr,
513039f802d6STakashi Iwai 	&dev_attr_max_microamps.attr,
51310f2d636eSZev Weiss 	&dev_attr_under_voltage.attr,
51320f2d636eSZev Weiss 	&dev_attr_over_current.attr,
51330f2d636eSZev Weiss 	&dev_attr_regulation_out.attr,
51340f2d636eSZev Weiss 	&dev_attr_fail.attr,
51350f2d636eSZev Weiss 	&dev_attr_over_temp.attr,
51360f2d636eSZev Weiss 	&dev_attr_under_voltage_warn.attr,
51370f2d636eSZev Weiss 	&dev_attr_over_current_warn.attr,
51380f2d636eSZev Weiss 	&dev_attr_over_voltage_warn.attr,
51390f2d636eSZev Weiss 	&dev_attr_over_temp_warn.attr,
514039f802d6STakashi Iwai 	&dev_attr_suspend_standby_state.attr,
514139f802d6STakashi Iwai 	&dev_attr_suspend_mem_state.attr,
514239f802d6STakashi Iwai 	&dev_attr_suspend_disk_state.attr,
514339f802d6STakashi Iwai 	&dev_attr_suspend_standby_microvolts.attr,
514439f802d6STakashi Iwai 	&dev_attr_suspend_mem_microvolts.attr,
514539f802d6STakashi Iwai 	&dev_attr_suspend_disk_microvolts.attr,
514639f802d6STakashi Iwai 	&dev_attr_suspend_standby_mode.attr,
514739f802d6STakashi Iwai 	&dev_attr_suspend_mem_mode.attr,
514839f802d6STakashi Iwai 	&dev_attr_suspend_disk_mode.attr,
514939f802d6STakashi Iwai 	NULL
515039f802d6STakashi Iwai };
515139f802d6STakashi Iwai 
51527ad68e2fSDavid Brownell /*
51537ad68e2fSDavid Brownell  * To avoid cluttering sysfs (and memory) with useless state, only
51547ad68e2fSDavid Brownell  * create attributes that can be meaningfully displayed.
51557ad68e2fSDavid Brownell  */
regulator_attr_is_visible(struct kobject * kobj,struct attribute * attr,int idx)515639f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj,
515739f802d6STakashi Iwai 					 struct attribute *attr, int idx)
51587ad68e2fSDavid Brownell {
515939f802d6STakashi Iwai 	struct device *dev = kobj_to_dev(kobj);
516083080a14SGeliang Tang 	struct regulator_dev *rdev = dev_to_rdev(dev);
5161272e2315SGuodong Xu 	const struct regulator_ops *ops = rdev->desc->ops;
516239f802d6STakashi Iwai 	umode_t mode = attr->mode;
516339f802d6STakashi Iwai 
516439f802d6STakashi Iwai 	/* these three are always present */
516539f802d6STakashi Iwai 	if (attr == &dev_attr_name.attr ||
516639f802d6STakashi Iwai 	    attr == &dev_attr_num_users.attr ||
516739f802d6STakashi Iwai 	    attr == &dev_attr_type.attr)
516839f802d6STakashi Iwai 		return mode;
51697ad68e2fSDavid Brownell 
51707ad68e2fSDavid Brownell 	/* some attributes need specific methods to be displayed */
517139f802d6STakashi Iwai 	if (attr == &dev_attr_microvolts.attr) {
51724c78899bSMark Brown 		if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
5173f2889e65SMark Brown 		    (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
51745a523605SLaxman Dewangan 		    (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
517539f802d6STakashi Iwai 		    (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1))
517639f802d6STakashi Iwai 			return mode;
517739f802d6STakashi Iwai 		return 0;
5178f59c8f9fSMark Brown 	}
51797ad68e2fSDavid Brownell 
518039f802d6STakashi Iwai 	if (attr == &dev_attr_microamps.attr)
518139f802d6STakashi Iwai 		return ops->get_current_limit ? mode : 0;
518239f802d6STakashi Iwai 
518339f802d6STakashi Iwai 	if (attr == &dev_attr_opmode.attr)
518439f802d6STakashi Iwai 		return ops->get_mode ? mode : 0;
518539f802d6STakashi Iwai 
518639f802d6STakashi Iwai 	if (attr == &dev_attr_state.attr)
518739f802d6STakashi Iwai 		return (rdev->ena_pin || ops->is_enabled) ? mode : 0;
518839f802d6STakashi Iwai 
518939f802d6STakashi Iwai 	if (attr == &dev_attr_status.attr)
519039f802d6STakashi Iwai 		return ops->get_status ? mode : 0;
519139f802d6STakashi Iwai 
519239f802d6STakashi Iwai 	if (attr == &dev_attr_bypass.attr)
519339f802d6STakashi Iwai 		return ops->get_bypass ? mode : 0;
519439f802d6STakashi Iwai 
51950f2d636eSZev Weiss 	if (attr == &dev_attr_under_voltage.attr ||
51960f2d636eSZev Weiss 	    attr == &dev_attr_over_current.attr ||
51970f2d636eSZev Weiss 	    attr == &dev_attr_regulation_out.attr ||
51980f2d636eSZev Weiss 	    attr == &dev_attr_fail.attr ||
51990f2d636eSZev Weiss 	    attr == &dev_attr_over_temp.attr ||
52000f2d636eSZev Weiss 	    attr == &dev_attr_under_voltage_warn.attr ||
52010f2d636eSZev Weiss 	    attr == &dev_attr_over_current_warn.attr ||
52020f2d636eSZev Weiss 	    attr == &dev_attr_over_voltage_warn.attr ||
52030f2d636eSZev Weiss 	    attr == &dev_attr_over_temp_warn.attr)
52040f2d636eSZev Weiss 		return ops->get_error_flags ? mode : 0;
52050f2d636eSZev Weiss 
52067ad68e2fSDavid Brownell 	/* constraints need specific supporting methods */
520739f802d6STakashi Iwai 	if (attr == &dev_attr_min_microvolts.attr ||
520839f802d6STakashi Iwai 	    attr == &dev_attr_max_microvolts.attr)
520939f802d6STakashi Iwai 		return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0;
521039f802d6STakashi Iwai 
521139f802d6STakashi Iwai 	if (attr == &dev_attr_min_microamps.attr ||
521239f802d6STakashi Iwai 	    attr == &dev_attr_max_microamps.attr)
521339f802d6STakashi Iwai 		return ops->set_current_limit ? mode : 0;
521439f802d6STakashi Iwai 
521539f802d6STakashi Iwai 	if (attr == &dev_attr_suspend_standby_state.attr ||
521639f802d6STakashi Iwai 	    attr == &dev_attr_suspend_mem_state.attr ||
521739f802d6STakashi Iwai 	    attr == &dev_attr_suspend_disk_state.attr)
521839f802d6STakashi Iwai 		return mode;
521939f802d6STakashi Iwai 
522039f802d6STakashi Iwai 	if (attr == &dev_attr_suspend_standby_microvolts.attr ||
522139f802d6STakashi Iwai 	    attr == &dev_attr_suspend_mem_microvolts.attr ||
522239f802d6STakashi Iwai 	    attr == &dev_attr_suspend_disk_microvolts.attr)
522339f802d6STakashi Iwai 		return ops->set_suspend_voltage ? mode : 0;
522439f802d6STakashi Iwai 
522539f802d6STakashi Iwai 	if (attr == &dev_attr_suspend_standby_mode.attr ||
522639f802d6STakashi Iwai 	    attr == &dev_attr_suspend_mem_mode.attr ||
522739f802d6STakashi Iwai 	    attr == &dev_attr_suspend_disk_mode.attr)
522839f802d6STakashi Iwai 		return ops->set_suspend_mode ? mode : 0;
522939f802d6STakashi Iwai 
523039f802d6STakashi Iwai 	return mode;
52317ad68e2fSDavid Brownell }
52327ad68e2fSDavid Brownell 
523339f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = {
523439f802d6STakashi Iwai 	.attrs = regulator_dev_attrs,
523539f802d6STakashi Iwai 	.is_visible = regulator_attr_is_visible,
523639f802d6STakashi Iwai };
52377ad68e2fSDavid Brownell 
523839f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = {
523939f802d6STakashi Iwai 	&regulator_dev_group,
524039f802d6STakashi Iwai 	NULL
524139f802d6STakashi Iwai };
524239f802d6STakashi Iwai 
regulator_dev_release(struct device * dev)524339f802d6STakashi Iwai static void regulator_dev_release(struct device *dev)
524439f802d6STakashi Iwai {
524539f802d6STakashi Iwai 	struct regulator_dev *rdev = dev_get_drvdata(dev);
524629f5f486SMark Brown 
52471f386d68SYang Yingliang 	debugfs_remove_recursive(rdev->debugfs);
524829f5f486SMark Brown 	kfree(rdev->constraints);
524929f5f486SMark Brown 	of_node_put(rdev->dev.of_node);
525039f802d6STakashi Iwai 	kfree(rdev);
52517ad68e2fSDavid Brownell }
52527ad68e2fSDavid Brownell 
rdev_init_debugfs(struct regulator_dev * rdev)52531130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev)
52541130e5b3SMark Brown {
5255a9eaa813SGuenter Roeck 	struct device *parent = rdev->dev.parent;
5256a9eaa813SGuenter Roeck 	const char *rname = rdev_get_name(rdev);
5257a9eaa813SGuenter Roeck 	char name[NAME_MAX];
5258a9eaa813SGuenter Roeck 
5259a9eaa813SGuenter Roeck 	/* Avoid duplicate debugfs directory names */
5260a9eaa813SGuenter Roeck 	if (parent && rname == rdev->desc->name) {
5261a9eaa813SGuenter Roeck 		snprintf(name, sizeof(name), "%s-%s", dev_name(parent),
5262a9eaa813SGuenter Roeck 			 rname);
5263a9eaa813SGuenter Roeck 		rname = name;
5264a9eaa813SGuenter Roeck 	}
5265a9eaa813SGuenter Roeck 
5266a9eaa813SGuenter Roeck 	rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
526708880713SGeert Uytterhoeven 	if (IS_ERR(rdev->debugfs))
526808880713SGeert Uytterhoeven 		rdev_dbg(rdev, "Failed to create debugfs directory\n");
52691130e5b3SMark Brown 
52701130e5b3SMark Brown 	debugfs_create_u32("use_count", 0444, rdev->debugfs,
52711130e5b3SMark Brown 			   &rdev->use_count);
52721130e5b3SMark Brown 	debugfs_create_u32("open_count", 0444, rdev->debugfs,
52731130e5b3SMark Brown 			   &rdev->open_count);
5274f59c8f9fSMark Brown 	debugfs_create_u32("bypass_count", 0444, rdev->debugfs,
5275f59c8f9fSMark Brown 			   &rdev->bypass_count);
52761130e5b3SMark Brown }
52771130e5b3SMark Brown 
regulator_register_resolve_supply(struct device * dev,void * data)52785e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data)
52795e3ca2b3SJavier Martinez Canillas {
52807ddede6aSJon Hunter 	struct regulator_dev *rdev = dev_to_rdev(dev);
52817ddede6aSJon Hunter 
52827ddede6aSJon Hunter 	if (regulator_resolve_supply(rdev))
52837ddede6aSJon Hunter 		rdev_dbg(rdev, "unable to resolve supply\n");
52847ddede6aSJon Hunter 
52857ddede6aSJon Hunter 	return 0;
52865e3ca2b3SJavier Martinez Canillas }
52875e3ca2b3SJavier Martinez Canillas 
regulator_coupler_register(struct regulator_coupler * coupler)5288d8ca7d18SDmitry Osipenko int regulator_coupler_register(struct regulator_coupler *coupler)
5289d8ca7d18SDmitry Osipenko {
5290d8ca7d18SDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
5291d8ca7d18SDmitry Osipenko 	list_add_tail(&coupler->list, &regulator_coupler_list);
5292d8ca7d18SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
5293d8ca7d18SDmitry Osipenko 
5294d8ca7d18SDmitry Osipenko 	return 0;
5295d8ca7d18SDmitry Osipenko }
5296d8ca7d18SDmitry Osipenko 
5297d8ca7d18SDmitry Osipenko static struct regulator_coupler *
regulator_find_coupler(struct regulator_dev * rdev)5298d8ca7d18SDmitry Osipenko regulator_find_coupler(struct regulator_dev *rdev)
5299d8ca7d18SDmitry Osipenko {
5300d8ca7d18SDmitry Osipenko 	struct regulator_coupler *coupler;
5301d8ca7d18SDmitry Osipenko 	int err;
5302d8ca7d18SDmitry Osipenko 
5303d8ca7d18SDmitry Osipenko 	/*
5304d8ca7d18SDmitry Osipenko 	 * Note that regulators are appended to the list and the generic
5305d8ca7d18SDmitry Osipenko 	 * coupler is registered first, hence it will be attached at last
5306d8ca7d18SDmitry Osipenko 	 * if nobody cared.
5307d8ca7d18SDmitry Osipenko 	 */
5308d8ca7d18SDmitry Osipenko 	list_for_each_entry_reverse(coupler, &regulator_coupler_list, list) {
5309d8ca7d18SDmitry Osipenko 		err = coupler->attach_regulator(coupler, rdev);
5310d8ca7d18SDmitry Osipenko 		if (!err) {
5311d8ca7d18SDmitry Osipenko 			if (!coupler->balance_voltage &&
5312d8ca7d18SDmitry Osipenko 			    rdev->coupling_desc.n_coupled > 2)
5313d8ca7d18SDmitry Osipenko 				goto err_unsupported;
5314d8ca7d18SDmitry Osipenko 
5315d8ca7d18SDmitry Osipenko 			return coupler;
5316d8ca7d18SDmitry Osipenko 		}
5317d8ca7d18SDmitry Osipenko 
5318d8ca7d18SDmitry Osipenko 		if (err < 0)
5319d8ca7d18SDmitry Osipenko 			return ERR_PTR(err);
5320d8ca7d18SDmitry Osipenko 
5321d8ca7d18SDmitry Osipenko 		if (err == 1)
5322d8ca7d18SDmitry Osipenko 			continue;
5323d8ca7d18SDmitry Osipenko 
5324d8ca7d18SDmitry Osipenko 		break;
5325d8ca7d18SDmitry Osipenko 	}
5326d8ca7d18SDmitry Osipenko 
5327d8ca7d18SDmitry Osipenko 	return ERR_PTR(-EINVAL);
5328d8ca7d18SDmitry Osipenko 
5329d8ca7d18SDmitry Osipenko err_unsupported:
5330d8ca7d18SDmitry Osipenko 	if (coupler->detach_regulator)
5331d8ca7d18SDmitry Osipenko 		coupler->detach_regulator(coupler, rdev);
5332d8ca7d18SDmitry Osipenko 
5333d8ca7d18SDmitry Osipenko 	rdev_err(rdev,
5334d8ca7d18SDmitry Osipenko 		"Voltage balancing for multiple regulator couples is unimplemented\n");
5335d8ca7d18SDmitry Osipenko 
5336d8ca7d18SDmitry Osipenko 	return ERR_PTR(-EPERM);
5337d8ca7d18SDmitry Osipenko }
5338d8ca7d18SDmitry Osipenko 
regulator_resolve_coupling(struct regulator_dev * rdev)5339f9503385SDmitry Osipenko static void regulator_resolve_coupling(struct regulator_dev *rdev)
5340d3d64537SMaciej Purski {
5341d8ca7d18SDmitry Osipenko 	struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
5342d3d64537SMaciej Purski 	struct coupling_desc *c_desc = &rdev->coupling_desc;
5343d3d64537SMaciej Purski 	int n_coupled = c_desc->n_coupled;
5344d3d64537SMaciej Purski 	struct regulator_dev *c_rdev;
5345d3d64537SMaciej Purski 	int i;
5346d3d64537SMaciej Purski 
5347d3d64537SMaciej Purski 	for (i = 1; i < n_coupled; i++) {
5348d3d64537SMaciej Purski 		/* already resolved */
5349d3d64537SMaciej Purski 		if (c_desc->coupled_rdevs[i])
5350d3d64537SMaciej Purski 			continue;
5351d3d64537SMaciej Purski 
5352d3d64537SMaciej Purski 		c_rdev = of_parse_coupled_regulator(rdev, i - 1);
5353d3d64537SMaciej Purski 
5354f9503385SDmitry Osipenko 		if (!c_rdev)
5355f9503385SDmitry Osipenko 			continue;
5356f9503385SDmitry Osipenko 
5357d8ca7d18SDmitry Osipenko 		if (c_rdev->coupling_desc.coupler != coupler) {
5358d8ca7d18SDmitry Osipenko 			rdev_err(rdev, "coupler mismatch with %s\n",
5359d8ca7d18SDmitry Osipenko 				 rdev_get_name(c_rdev));
5360d8ca7d18SDmitry Osipenko 			return;
5361d8ca7d18SDmitry Osipenko 		}
5362d8ca7d18SDmitry Osipenko 
5363d3d64537SMaciej Purski 		c_desc->coupled_rdevs[i] = c_rdev;
5364d3d64537SMaciej Purski 		c_desc->n_resolved++;
5365f9503385SDmitry Osipenko 
5366f9503385SDmitry Osipenko 		regulator_resolve_coupling(c_rdev);
5367d3d64537SMaciej Purski 	}
5368d3d64537SMaciej Purski }
5369d3d64537SMaciej Purski 
regulator_remove_coupling(struct regulator_dev * rdev)53706303f3e7SDmitry Osipenko static void regulator_remove_coupling(struct regulator_dev *rdev)
5371d3d64537SMaciej Purski {
5372d8ca7d18SDmitry Osipenko 	struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
53736303f3e7SDmitry Osipenko 	struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc;
53746303f3e7SDmitry Osipenko 	struct regulator_dev *__c_rdev, *c_rdev;
53756303f3e7SDmitry Osipenko 	unsigned int __n_coupled, n_coupled;
53766303f3e7SDmitry Osipenko 	int i, k;
5377d8ca7d18SDmitry Osipenko 	int err;
5378d3d64537SMaciej Purski 
53796303f3e7SDmitry Osipenko 	n_coupled = c_desc->n_coupled;
5380d3d64537SMaciej Purski 
53816303f3e7SDmitry Osipenko 	for (i = 1; i < n_coupled; i++) {
53826303f3e7SDmitry Osipenko 		c_rdev = c_desc->coupled_rdevs[i];
5383d3d64537SMaciej Purski 
53846303f3e7SDmitry Osipenko 		if (!c_rdev)
53856303f3e7SDmitry Osipenko 			continue;
53866303f3e7SDmitry Osipenko 
53876303f3e7SDmitry Osipenko 		regulator_lock(c_rdev);
53886303f3e7SDmitry Osipenko 
53896303f3e7SDmitry Osipenko 		__c_desc = &c_rdev->coupling_desc;
53906303f3e7SDmitry Osipenko 		__n_coupled = __c_desc->n_coupled;
53916303f3e7SDmitry Osipenko 
53926303f3e7SDmitry Osipenko 		for (k = 1; k < __n_coupled; k++) {
53936303f3e7SDmitry Osipenko 			__c_rdev = __c_desc->coupled_rdevs[k];
53946303f3e7SDmitry Osipenko 
53956303f3e7SDmitry Osipenko 			if (__c_rdev == rdev) {
53966303f3e7SDmitry Osipenko 				__c_desc->coupled_rdevs[k] = NULL;
53976303f3e7SDmitry Osipenko 				__c_desc->n_resolved--;
53986303f3e7SDmitry Osipenko 				break;
53996303f3e7SDmitry Osipenko 			}
5400d3d64537SMaciej Purski 		}
5401d3d64537SMaciej Purski 
54026303f3e7SDmitry Osipenko 		regulator_unlock(c_rdev);
54036303f3e7SDmitry Osipenko 
54046303f3e7SDmitry Osipenko 		c_desc->coupled_rdevs[i] = NULL;
54056303f3e7SDmitry Osipenko 		c_desc->n_resolved--;
54066303f3e7SDmitry Osipenko 	}
5407d8ca7d18SDmitry Osipenko 
5408d8ca7d18SDmitry Osipenko 	if (coupler && coupler->detach_regulator) {
5409d8ca7d18SDmitry Osipenko 		err = coupler->detach_regulator(coupler, rdev);
5410d8ca7d18SDmitry Osipenko 		if (err)
541161aab5adSMichał Mirosław 			rdev_err(rdev, "failed to detach from coupler: %pe\n",
541261aab5adSMichał Mirosław 				 ERR_PTR(err));
5413d8ca7d18SDmitry Osipenko 	}
5414d8ca7d18SDmitry Osipenko 
5415d8ca7d18SDmitry Osipenko 	kfree(rdev->coupling_desc.coupled_rdevs);
5416d8ca7d18SDmitry Osipenko 	rdev->coupling_desc.coupled_rdevs = NULL;
54176303f3e7SDmitry Osipenko }
54186303f3e7SDmitry Osipenko 
regulator_init_coupling(struct regulator_dev * rdev)5419f9503385SDmitry Osipenko static int regulator_init_coupling(struct regulator_dev *rdev)
5420d3d64537SMaciej Purski {
54217d819664SMichał Mirosław 	struct regulator_dev **coupled;
5422d8ca7d18SDmitry Osipenko 	int err, n_phandles;
5423d3d64537SMaciej Purski 
5424d3d64537SMaciej Purski 	if (!IS_ENABLED(CONFIG_OF))
5425d3d64537SMaciej Purski 		n_phandles = 0;
5426d3d64537SMaciej Purski 	else
5427d3d64537SMaciej Purski 		n_phandles = of_get_n_coupled(rdev);
5428d3d64537SMaciej Purski 
54297d819664SMichał Mirosław 	coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL);
54307d819664SMichał Mirosław 	if (!coupled)
5431d8ca7d18SDmitry Osipenko 		return -ENOMEM;
5432d3d64537SMaciej Purski 
54337d819664SMichał Mirosław 	rdev->coupling_desc.coupled_rdevs = coupled;
54347d819664SMichał Mirosław 
5435d3d64537SMaciej Purski 	/*
5436d3d64537SMaciej Purski 	 * Every regulator should always have coupling descriptor filled with
5437d3d64537SMaciej Purski 	 * at least pointer to itself.
5438d3d64537SMaciej Purski 	 */
5439d3d64537SMaciej Purski 	rdev->coupling_desc.coupled_rdevs[0] = rdev;
5440d3d64537SMaciej Purski 	rdev->coupling_desc.n_coupled = n_phandles + 1;
5441d3d64537SMaciej Purski 	rdev->coupling_desc.n_resolved++;
5442d3d64537SMaciej Purski 
5443d3d64537SMaciej Purski 	/* regulator isn't coupled */
5444d3d64537SMaciej Purski 	if (n_phandles == 0)
5445d3d64537SMaciej Purski 		return 0;
5446d3d64537SMaciej Purski 
5447d3d64537SMaciej Purski 	if (!of_check_coupling_data(rdev))
5448d3d64537SMaciej Purski 		return -EPERM;
5449d3d64537SMaciej Purski 
545073a32129SMichał Mirosław 	mutex_lock(&regulator_list_mutex);
5451d8ca7d18SDmitry Osipenko 	rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
545273a32129SMichał Mirosław 	mutex_unlock(&regulator_list_mutex);
545373a32129SMichał Mirosław 
5454d8ca7d18SDmitry Osipenko 	if (IS_ERR(rdev->coupling_desc.coupler)) {
5455d8ca7d18SDmitry Osipenko 		err = PTR_ERR(rdev->coupling_desc.coupler);
545661aab5adSMichał Mirosław 		rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err));
5457d8ca7d18SDmitry Osipenko 		return err;
5458d8ca7d18SDmitry Osipenko 	}
5459d8ca7d18SDmitry Osipenko 
5460d3d64537SMaciej Purski 	return 0;
5461d3d64537SMaciej Purski }
5462d3d64537SMaciej Purski 
generic_coupler_attach(struct regulator_coupler * coupler,struct regulator_dev * rdev)5463d8ca7d18SDmitry Osipenko static int generic_coupler_attach(struct regulator_coupler *coupler,
5464d8ca7d18SDmitry Osipenko 				  struct regulator_dev *rdev)
5465d8ca7d18SDmitry Osipenko {
5466d8ca7d18SDmitry Osipenko 	if (rdev->coupling_desc.n_coupled > 2) {
5467d8ca7d18SDmitry Osipenko 		rdev_err(rdev,
5468d8ca7d18SDmitry Osipenko 			 "Voltage balancing for multiple regulator couples is unimplemented\n");
5469d8ca7d18SDmitry Osipenko 		return -EPERM;
5470d8ca7d18SDmitry Osipenko 	}
5471d8ca7d18SDmitry Osipenko 
5472e381bfe4SDmitry Osipenko 	if (!rdev->constraints->always_on) {
5473e381bfe4SDmitry Osipenko 		rdev_err(rdev,
5474e381bfe4SDmitry Osipenko 			 "Coupling of a non always-on regulator is unimplemented\n");
5475e381bfe4SDmitry Osipenko 		return -ENOTSUPP;
5476e381bfe4SDmitry Osipenko 	}
5477e381bfe4SDmitry Osipenko 
5478d8ca7d18SDmitry Osipenko 	return 0;
5479d8ca7d18SDmitry Osipenko }
5480d8ca7d18SDmitry Osipenko 
5481d8ca7d18SDmitry Osipenko static struct regulator_coupler generic_regulator_coupler = {
5482d8ca7d18SDmitry Osipenko 	.attach_regulator = generic_coupler_attach,
5483d8ca7d18SDmitry Osipenko };
5484d8ca7d18SDmitry Osipenko 
5485414c70cbSLiam Girdwood /**
5486414c70cbSLiam Girdwood  * regulator_register - register regulator
54878f3cbcd6SChiYuan Huang  * @dev: the device that drive the regulator
548869279fb9SMark Brown  * @regulator_desc: regulator to register
5489f47531b1SKrzysztof Kozlowski  * @cfg: runtime configuration for regulator
5490414c70cbSLiam Girdwood  *
5491414c70cbSLiam Girdwood  * Called by regulator drivers to register a regulator.
54920384618aSAxel Lin  * Returns a valid pointer to struct regulator_dev on success
54930384618aSAxel Lin  * or an ERR_PTR() on error.
5494414c70cbSLiam Girdwood  */
549565f26846SMark Brown struct regulator_dev *
regulator_register(struct device * dev,const struct regulator_desc * regulator_desc,const struct regulator_config * cfg)54968f3cbcd6SChiYuan Huang regulator_register(struct device *dev,
54978f3cbcd6SChiYuan Huang 		   const struct regulator_desc *regulator_desc,
54981b3de223SKrzysztof Kozlowski 		   const struct regulator_config *cfg)
5499414c70cbSLiam Girdwood {
5500c172708dSMark Brown 	const struct regulator_init_data *init_data;
55011b3de223SKrzysztof Kozlowski 	struct regulator_config *config = NULL;
550272dca06fSAniroop Mathur 	static atomic_t regulator_no = ATOMIC_INIT(-1);
5503414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
55040edb040dSLinus Walleij 	bool dangling_cfg_gpiod = false;
55050edb040dSLinus Walleij 	bool dangling_of_gpiod = false;
5506a5766f11SLiam Girdwood 	int ret, i;
5507520fb178SChristian Kohlschütter 	bool resolved_early = false;
5508414c70cbSLiam Girdwood 
55090edb040dSLinus Walleij 	if (cfg == NULL)
5510414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
55110edb040dSLinus Walleij 	if (cfg->ena_gpiod)
55120edb040dSLinus Walleij 		dangling_cfg_gpiod = true;
55130edb040dSLinus Walleij 	if (regulator_desc == NULL) {
55140edb040dSLinus Walleij 		ret = -EINVAL;
55150edb040dSLinus Walleij 		goto rinse;
55160edb040dSLinus Walleij 	}
5517414c70cbSLiam Girdwood 
55188f3cbcd6SChiYuan Huang 	WARN_ON(!dev || !cfg->dev);
551932c8fad4SMark Brown 
55200edb040dSLinus Walleij 	if (regulator_desc->name == NULL || regulator_desc->ops == NULL) {
55210edb040dSLinus Walleij 		ret = -EINVAL;
55220edb040dSLinus Walleij 		goto rinse;
55230edb040dSLinus Walleij 	}
5524414c70cbSLiam Girdwood 
5525cd78dfc6SDiego Liziero 	if (regulator_desc->type != REGULATOR_VOLTAGE &&
55260edb040dSLinus Walleij 	    regulator_desc->type != REGULATOR_CURRENT) {
55270edb040dSLinus Walleij 		ret = -EINVAL;
55280edb040dSLinus Walleij 		goto rinse;
55290edb040dSLinus Walleij 	}
5530414c70cbSLiam Girdwood 
5531476c2d83SMark Brown 	/* Only one of each should be implemented */
5532476c2d83SMark Brown 	WARN_ON(regulator_desc->ops->get_voltage &&
5533476c2d83SMark Brown 		regulator_desc->ops->get_voltage_sel);
5534e8eef82bSMark Brown 	WARN_ON(regulator_desc->ops->set_voltage &&
5535e8eef82bSMark Brown 		regulator_desc->ops->set_voltage_sel);
5536476c2d83SMark Brown 
5537476c2d83SMark Brown 	/* If we're using selectors we must implement list_voltage. */
5538476c2d83SMark Brown 	if (regulator_desc->ops->get_voltage_sel &&
5539476c2d83SMark Brown 	    !regulator_desc->ops->list_voltage) {
55400edb040dSLinus Walleij 		ret = -EINVAL;
55410edb040dSLinus Walleij 		goto rinse;
5542476c2d83SMark Brown 	}
5543e8eef82bSMark Brown 	if (regulator_desc->ops->set_voltage_sel &&
5544e8eef82bSMark Brown 	    !regulator_desc->ops->list_voltage) {
55450edb040dSLinus Walleij 		ret = -EINVAL;
55460edb040dSLinus Walleij 		goto rinse;
5547e8eef82bSMark Brown 	}
5548476c2d83SMark Brown 
5549414c70cbSLiam Girdwood 	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
55500edb040dSLinus Walleij 	if (rdev == NULL) {
55510edb040dSLinus Walleij 		ret = -ENOMEM;
55520edb040dSLinus Walleij 		goto rinse;
55530edb040dSLinus Walleij 	}
5554d3c73156SMichał Mirosław 	device_initialize(&rdev->dev);
55558adb4e64SMichał Mirosław 	dev_set_drvdata(&rdev->dev, rdev);
55568adb4e64SMichał Mirosław 	rdev->dev.class = &regulator_class;
55577111c6d1SMatti Vaittinen 	spin_lock_init(&rdev->err_lock);
5558414c70cbSLiam Girdwood 
55591b3de223SKrzysztof Kozlowski 	/*
55601b3de223SKrzysztof Kozlowski 	 * Duplicate the config so the driver could override it after
55611b3de223SKrzysztof Kozlowski 	 * parsing init data.
55621b3de223SKrzysztof Kozlowski 	 */
55631b3de223SKrzysztof Kozlowski 	config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
55641b3de223SKrzysztof Kozlowski 	if (config == NULL) {
55650edb040dSLinus Walleij 		ret = -ENOMEM;
5566d3c73156SMichał Mirosław 		goto clean;
55671b3de223SKrzysztof Kozlowski 	}
55681b3de223SKrzysztof Kozlowski 
5569bfa21a0dSKrzysztof Kozlowski 	init_data = regulator_of_get_init_data(dev, regulator_desc, config,
5570a0c7b164SMark Brown 					       &rdev->dev.of_node);
5571f8970d34SMarco Felsch 
5572f8970d34SMarco Felsch 	/*
5573f8970d34SMarco Felsch 	 * Sometimes not all resources are probed already so we need to take
5574f8970d34SMarco Felsch 	 * that into account. This happens most the time if the ena_gpiod comes
5575f8970d34SMarco Felsch 	 * from a gpio extender or something else.
5576f8970d34SMarco Felsch 	 */
5577f8970d34SMarco Felsch 	if (PTR_ERR(init_data) == -EPROBE_DEFER) {
5578f8970d34SMarco Felsch 		ret = -EPROBE_DEFER;
5579d3c73156SMichał Mirosław 		goto clean;
5580f8970d34SMarco Felsch 	}
5581f8970d34SMarco Felsch 
55820edb040dSLinus Walleij 	/*
55830edb040dSLinus Walleij 	 * We need to keep track of any GPIO descriptor coming from the
55840edb040dSLinus Walleij 	 * device tree until we have handled it over to the core. If the
55850edb040dSLinus Walleij 	 * config that was passed in to this function DOES NOT contain
55860edb040dSLinus Walleij 	 * a descriptor, and the config after this call DOES contain
558748f1b4efSKrzysztof Kozlowski 	 * a descriptor, we definitely got one from parsing the device
55880edb040dSLinus Walleij 	 * tree.
55890edb040dSLinus Walleij 	 */
55900edb040dSLinus Walleij 	if (!cfg->ena_gpiod && config->ena_gpiod)
55910edb040dSLinus Walleij 		dangling_of_gpiod = true;
5592a0c7b164SMark Brown 	if (!init_data) {
5593a0c7b164SMark Brown 		init_data = config->init_data;
5594a0c7b164SMark Brown 		rdev->dev.of_node = of_node_get(config->of_node);
5595a0c7b164SMark Brown 	}
5596a0c7b164SMark Brown 
5597f8702f9eSDmitry Osipenko 	ww_mutex_init(&rdev->mutex, &regulator_ww_class);
5598c172708dSMark Brown 	rdev->reg_data = config->driver_data;
5599414c70cbSLiam Girdwood 	rdev->owner = regulator_desc->owner;
5600414c70cbSLiam Girdwood 	rdev->desc = regulator_desc;
56013a4b0a07SMark Brown 	if (config->regmap)
560265b19ce6SMark Brown 		rdev->regmap = config->regmap;
560352b84dacSAnilKumar Ch 	else if (dev_get_regmap(dev, NULL))
56043a4b0a07SMark Brown 		rdev->regmap = dev_get_regmap(dev, NULL);
560552b84dacSAnilKumar Ch 	else if (dev->parent)
560652b84dacSAnilKumar Ch 		rdev->regmap = dev_get_regmap(dev->parent, NULL);
5607414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->consumer_list);
5608414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->list);
5609414c70cbSLiam Girdwood 	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
5610da07ecd9SMark Brown 	INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
5611414c70cbSLiam Girdwood 
5612520fb178SChristian Kohlschütter 	if (init_data && init_data->supply_regulator)
5613520fb178SChristian Kohlschütter 		rdev->supply_name = init_data->supply_regulator;
5614520fb178SChristian Kohlschütter 	else if (regulator_desc->supply_name)
5615520fb178SChristian Kohlschütter 		rdev->supply_name = regulator_desc->supply_name;
5616daad134dSKrzysztof Adamski 
5617a5766f11SLiam Girdwood 	/* register with sysfs */
56180debed5bSChiYuan Huang 	rdev->dev.parent = config->dev;
561972dca06fSAniroop Mathur 	dev_set_name(&rdev->dev, "regulator.%lu",
562039138818SAniroop Mathur 		    (unsigned long) atomic_inc_return(&regulator_no));
5621a5766f11SLiam Girdwood 
562274f544c1SMike Rapoport 	/* set regulator constraints */
56239a8f5e07SMark Brown 	if (init_data)
562457a6ad48SMichał Mirosław 		rdev->constraints = kmemdup(&init_data->constraints,
562557a6ad48SMichał Mirosław 					    sizeof(*rdev->constraints),
562657a6ad48SMichał Mirosław 					    GFP_KERNEL);
562757a6ad48SMichał Mirosław 	else
562857a6ad48SMichał Mirosław 		rdev->constraints = kzalloc(sizeof(*rdev->constraints),
562957a6ad48SMichał Mirosław 					    GFP_KERNEL);
563057a6ad48SMichał Mirosław 	if (!rdev->constraints) {
563157a6ad48SMichał Mirosław 		ret = -ENOMEM;
563257a6ad48SMichał Mirosław 		goto wash;
563357a6ad48SMichał Mirosław 	}
56349a8f5e07SMark Brown 
56358a866d52SChristian Kohlschütter 	if ((rdev->supply_name && !rdev->supply) &&
56368a866d52SChristian Kohlschütter 		(rdev->constraints->always_on ||
56378a866d52SChristian Kohlschütter 		 rdev->constraints->boot_on)) {
56388a866d52SChristian Kohlschütter 		ret = regulator_resolve_supply(rdev);
56398a866d52SChristian Kohlschütter 		if (ret)
56408a866d52SChristian Kohlschütter 			rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
56418a866d52SChristian Kohlschütter 					 ERR_PTR(ret));
5642520fb178SChristian Kohlschütter 
5643520fb178SChristian Kohlschütter 		resolved_early = true;
56448a866d52SChristian Kohlschütter 	}
56458a866d52SChristian Kohlschütter 
56468a866d52SChristian Kohlschütter 	/* perform any regulator specific init */
5647414c70cbSLiam Girdwood 	if (init_data && init_data->regulator_init) {
5648414c70cbSLiam Girdwood 		ret = init_data->regulator_init(rdev->reg_data);
5649414c70cbSLiam Girdwood 		if (ret < 0)
5650520fb178SChristian Kohlschütter 			goto wash;
5651414c70cbSLiam Girdwood 	}
5652414c70cbSLiam Girdwood 
5653414c70cbSLiam Girdwood 	if (config->ena_gpiod) {
5654414c70cbSLiam Girdwood 		ret = regulator_ena_gpio_request(rdev, config);
5655a5766f11SLiam Girdwood 		if (ret != 0) {
5656a5766f11SLiam Girdwood 			rdev_err(rdev, "Failed to request enable GPIO: %pe\n",
5657a5766f11SLiam Girdwood 				 ERR_PTR(ret));
5658520fb178SChristian Kohlschütter 			goto wash;
5659a5766f11SLiam Girdwood 		}
5660a5766f11SLiam Girdwood 		/* The regulator core took over the GPIO descriptor */
5661a5766f11SLiam Girdwood 		dangling_cfg_gpiod = false;
5662a5766f11SLiam Girdwood 		dangling_of_gpiod = false;
5663a5766f11SLiam Girdwood 	}
566469511a45SRajendra Nayak 
566557a6ad48SMichał Mirosław 	ret = set_machine_constraints(rdev);
5666520fb178SChristian Kohlschütter 	if (ret == -EPROBE_DEFER && !resolved_early) {
5667aea6cb99SMichał Mirosław 		/* Regulator might be in bypass mode and so needs its supply
566869b8821eSShubhankar Kuranagatti 		 * to set the constraints
566969b8821eSShubhankar Kuranagatti 		 */
5670aea6cb99SMichał Mirosław 		/* FIXME: this currently triggers a chicken-and-egg problem
5671aea6cb99SMichał Mirosław 		 * when creating -SUPPLY symlink in sysfs to a regulator
567269b8821eSShubhankar Kuranagatti 		 * that is just being created
567369b8821eSShubhankar Kuranagatti 		 */
56740917c9dbSMichał Mirosław 		rdev_dbg(rdev, "will resolve supply early: %s\n",
56750917c9dbSMichał Mirosław 			 rdev->supply_name);
5676aea6cb99SMichał Mirosław 		ret = regulator_resolve_supply(rdev);
5677aea6cb99SMichał Mirosław 		if (!ret)
567857a6ad48SMichał Mirosław 			ret = set_machine_constraints(rdev);
5679aea6cb99SMichał Mirosław 		else
5680aea6cb99SMichał Mirosław 			rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
5681aea6cb99SMichał Mirosław 				 ERR_PTR(ret));
5682aea6cb99SMichał Mirosław 	}
568345389c47SJon Hunter 	if (ret < 0)
568445389c47SJon Hunter 		goto wash;
568545389c47SJon Hunter 
5686f9503385SDmitry Osipenko 	ret = regulator_init_coupling(rdev);
5687f9503385SDmitry Osipenko 	if (ret < 0)
5688d3d64537SMaciej Purski 		goto wash;
5689d3d64537SMaciej Purski 
5690a5766f11SLiam Girdwood 	/* add consumers devices */
56919a8f5e07SMark Brown 	if (init_data) {
5692a5766f11SLiam Girdwood 		for (i = 0; i < init_data->num_consumer_supplies; i++) {
5693a5766f11SLiam Girdwood 			ret = set_consumer_device_supply(rdev,
569440f9244fSMark Brown 				init_data->consumer_supplies[i].dev_name,
5695a5766f11SLiam Girdwood 				init_data->consumer_supplies[i].supply);
569623c2f041SMark Brown 			if (ret < 0) {
569723c2f041SMark Brown 				dev_err(dev, "Failed to set supply %s\n",
569823c2f041SMark Brown 					init_data->consumer_supplies[i].supply);
5699d4033b54SJani Nikula 				goto unset_supplies;
5700a5766f11SLiam Girdwood 			}
570123c2f041SMark Brown 		}
57029a8f5e07SMark Brown 	}
5703a5766f11SLiam Girdwood 
5704fd086045SMatthias Kaehlcke 	if (!rdev->desc->ops->get_voltage &&
5705fd086045SMatthias Kaehlcke 	    !rdev->desc->ops->list_voltage &&
5706fd086045SMatthias Kaehlcke 	    !rdev->desc->fixed_uV)
5707fd086045SMatthias Kaehlcke 		rdev->is_switch = true;
5708fd086045SMatthias Kaehlcke 
57099177514cSVladimir Zapolskiy 	ret = device_add(&rdev->dev);
57109177514cSVladimir Zapolskiy 	if (ret != 0)
5711c438b9d0SJon Hunter 		goto unset_supplies;
5712c438b9d0SJon Hunter 
57131130e5b3SMark Brown 	rdev_init_debugfs(rdev);
57145e3ca2b3SJavier Martinez Canillas 
5715f9503385SDmitry Osipenko 	/* try to resolve regulators coupling since a new one was registered */
5716f9503385SDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
5717f9503385SDmitry Osipenko 	regulator_resolve_coupling(rdev);
5718f9503385SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
5719f9503385SDmitry Osipenko 
57205e3ca2b3SJavier Martinez Canillas 	/* try to resolve regulators supply since a new one was registered */
57215e3ca2b3SJavier Martinez Canillas 	class_for_each_device(&regulator_class, NULL, NULL,
57225e3ca2b3SJavier Martinez Canillas 			      regulator_register_resolve_supply);
57231b3de223SKrzysztof Kozlowski 	kfree(config);
5724414c70cbSLiam Girdwood 	return rdev;
57254fca9545SDavid Brownell 
5726d4033b54SJani Nikula unset_supplies:
572745389c47SJon Hunter 	mutex_lock(&regulator_list_mutex);
5728d4033b54SJani Nikula 	unset_regulator_supplies(rdev);
5729d8ca7d18SDmitry Osipenko 	regulator_remove_coupling(rdev);
573045389c47SJon Hunter 	mutex_unlock(&regulator_list_mutex);
573132165230SKrzysztof Adamski wash:
5732ba62319aSYang Yingliang 	regulator_put(rdev->supply);
573326c2c997SDmitry Osipenko 	kfree(rdev->coupling_desc.coupled_rdevs);
573445389c47SJon Hunter 	mutex_lock(&regulator_list_mutex);
573532165230SKrzysztof Adamski 	regulator_ena_gpio_free(rdev);
573645389c47SJon Hunter 	mutex_unlock(&regulator_list_mutex);
57374fca9545SDavid Brownell clean:
57380edb040dSLinus Walleij 	if (dangling_of_gpiod)
57390edb040dSLinus Walleij 		gpiod_put(config->ena_gpiod);
5740a2151374SJon Hunter 	kfree(config);
57416e800968SMichał Mirosław 	put_device(&rdev->dev);
57420edb040dSLinus Walleij rinse:
57430edb040dSLinus Walleij 	if (dangling_cfg_gpiod)
57440edb040dSLinus Walleij 		gpiod_put(cfg->ena_gpiod);
5745a2151374SJon Hunter 	return ERR_PTR(ret);
5746414c70cbSLiam Girdwood }
5747414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register);
5748414c70cbSLiam Girdwood 
5749414c70cbSLiam Girdwood /**
5750414c70cbSLiam Girdwood  * regulator_unregister - unregister regulator
575169279fb9SMark Brown  * @rdev: regulator to unregister
5752414c70cbSLiam Girdwood  *
5753414c70cbSLiam Girdwood  * Called by regulator drivers to unregister a regulator.
5754414c70cbSLiam Girdwood  */
regulator_unregister(struct regulator_dev * rdev)5755414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev)
5756414c70cbSLiam Girdwood {
5757414c70cbSLiam Girdwood 	if (rdev == NULL)
5758414c70cbSLiam Girdwood 		return;
5759414c70cbSLiam Girdwood 
5760891636eaSMark Brown 	if (rdev->supply) {
5761891636eaSMark Brown 		while (rdev->use_count--)
5762891636eaSMark Brown 			regulator_disable(rdev->supply);
5763e032b376SMark Brown 		regulator_put(rdev->supply);
5764891636eaSMark Brown 	}
5765ff9b34b6SDmitry Osipenko 
576606377301SCharles Keepax 	flush_work(&rdev->disable_work.work);
576706377301SCharles Keepax 
5768414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
5769ff9b34b6SDmitry Osipenko 
57706bf87d17SMark Brown 	WARN_ON(rdev->open_count);
57716303f3e7SDmitry Osipenko 	regulator_remove_coupling(rdev);
57720f1d747bSMike Rapoport 	unset_regulator_supplies(rdev);
5773414c70cbSLiam Girdwood 	list_del(&rdev->list);
5774f19b00daSKim, Milo 	regulator_ena_gpio_free(rdev);
577558fb5cf5SLothar Waßmann 	device_unregister(&rdev->dev);
5776ff9b34b6SDmitry Osipenko 
5777ff9b34b6SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
5778414c70cbSLiam Girdwood }
5779414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister);
5780414c70cbSLiam Girdwood 
5781f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND
5782414c70cbSLiam Girdwood /**
57830380cf7dSpascal paillet  * regulator_suspend - prepare regulators for system wide suspend
57841efef7ccSRandy Dunlap  * @dev: ``&struct device`` pointer that is passed to _regulator_suspend()
5785414c70cbSLiam Girdwood  *
5786414c70cbSLiam Girdwood  * Configure each regulator with it's suspend operating parameters for state.
5787414c70cbSLiam Girdwood  */
regulator_suspend(struct device * dev)57880380cf7dSpascal paillet static int regulator_suspend(struct device *dev)
5789414c70cbSLiam Girdwood {
5790cd7e36abSMarek Szyprowski 	struct regulator_dev *rdev = dev_to_rdev(dev);
5791f7efad10SChunyan Zhang 	suspend_state_t state = pm_suspend_target_state;
5792cd7e36abSMarek Szyprowski 	int ret;
57930955f5beSStephen Boyd 	const struct regulator_state *rstate;
57940955f5beSStephen Boyd 
57950955f5beSStephen Boyd 	rstate = regulator_get_suspend_state_check(rdev, state);
57960955f5beSStephen Boyd 	if (!rstate)
57970955f5beSStephen Boyd 		return 0;
5798414c70cbSLiam Girdwood 
5799cd7e36abSMarek Szyprowski 	regulator_lock(rdev);
58000955f5beSStephen Boyd 	ret = __suspend_set_state(rdev, rstate);
5801cd7e36abSMarek Szyprowski 	regulator_unlock(rdev);
5802cd7e36abSMarek Szyprowski 
5803cd7e36abSMarek Szyprowski 	return ret;
5804414c70cbSLiam Girdwood }
5805d3e4eccbSMark Brown 
regulator_resume(struct device * dev)5806cd7e36abSMarek Szyprowski static int regulator_resume(struct device *dev)
580785f3b431STomeu Vizoso {
5808cd7e36abSMarek Szyprowski 	suspend_state_t state = pm_suspend_target_state;
580985f3b431STomeu Vizoso 	struct regulator_dev *rdev = dev_to_rdev(dev);
5810f7efad10SChunyan Zhang 	struct regulator_state *rstate;
5811cd7e36abSMarek Szyprowski 	int ret = 0;
5812f7efad10SChunyan Zhang 
5813cd7e36abSMarek Szyprowski 	rstate = regulator_get_suspend_state(rdev, state);
5814f7efad10SChunyan Zhang 	if (rstate == NULL)
581535b5f14eSGeert Uytterhoeven 		return 0;
581685f3b431STomeu Vizoso 
58170955f5beSStephen Boyd 	/* Avoid grabbing the lock if we don't need to */
58180955f5beSStephen Boyd 	if (!rdev->desc->ops->resume)
58190955f5beSStephen Boyd 		return 0;
58200955f5beSStephen Boyd 
582166cf9a7eSMaciej Purski 	regulator_lock(rdev);
582285f3b431STomeu Vizoso 
58230955f5beSStephen Boyd 	if (rstate->enabled == ENABLE_IN_SUSPEND ||
58240955f5beSStephen Boyd 	    rstate->enabled == DISABLE_IN_SUSPEND)
58250380cf7dSpascal paillet 		ret = rdev->desc->ops->resume(rdev);
5826f7efad10SChunyan Zhang 
582766cf9a7eSMaciej Purski 	regulator_unlock(rdev);
582885f3b431STomeu Vizoso 
5829f7efad10SChunyan Zhang 	return ret;
583085f3b431STomeu Vizoso }
5831f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */
5832f7efad10SChunyan Zhang 
58330380cf7dSpascal paillet #define regulator_suspend	NULL
58340380cf7dSpascal paillet #define regulator_resume	NULL
5835f7efad10SChunyan Zhang 
5836f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */
5837f7efad10SChunyan Zhang 
5838f7efad10SChunyan Zhang #ifdef CONFIG_PM
5839f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = {
58400380cf7dSpascal paillet 	.suspend	= regulator_suspend,
58410380cf7dSpascal paillet 	.resume		= regulator_resume,
5842f7efad10SChunyan Zhang };
5843f7efad10SChunyan Zhang #endif
5844f7efad10SChunyan Zhang 
5845285c22deSMark Brown struct class regulator_class = {
5846f7efad10SChunyan Zhang 	.name = "regulator",
5847f7efad10SChunyan Zhang 	.dev_release = regulator_dev_release,
5848f7efad10SChunyan Zhang 	.dev_groups = regulator_dev_groups,
5849f7efad10SChunyan Zhang #ifdef CONFIG_PM
5850f7efad10SChunyan Zhang 	.pm = &regulator_pm_ops,
5851f7efad10SChunyan Zhang #endif
5852f7efad10SChunyan Zhang };
58537a32b589SMyungJoo Ham /**
5854ca725561SMark Brown  * regulator_has_full_constraints - the system has fully specified constraints
5855ca725561SMark Brown  *
5856ca725561SMark Brown  * Calling this function will cause the regulator API to disable all
5857ca725561SMark Brown  * regulators which have a zero use count and don't have an always_on
5858ca725561SMark Brown  * constraint in a late_initcall.
5859ca725561SMark Brown  *
5860ca725561SMark Brown  * The intention is that this will become the default behaviour in a
5861ca725561SMark Brown  * future kernel release so users are encouraged to use this facility
5862ca725561SMark Brown  * now.
5863ca725561SMark Brown  */
regulator_has_full_constraints(void)5864ca725561SMark Brown void regulator_has_full_constraints(void)
5865ca725561SMark Brown {
5866ca725561SMark Brown 	has_full_constraints = 1;
5867ca725561SMark Brown }
5868ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
5869ca725561SMark Brown 
5870ca725561SMark Brown /**
5871414c70cbSLiam Girdwood  * rdev_get_drvdata - get rdev regulator driver data
587269279fb9SMark Brown  * @rdev: regulator
5873414c70cbSLiam Girdwood  *
5874414c70cbSLiam Girdwood  * Get rdev regulator driver private data. This call can be used in the
5875414c70cbSLiam Girdwood  * regulator driver context.
5876414c70cbSLiam Girdwood  */
rdev_get_drvdata(struct regulator_dev * rdev)5877414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev)
5878414c70cbSLiam Girdwood {
5879414c70cbSLiam Girdwood 	return rdev->reg_data;
5880414c70cbSLiam Girdwood }
5881414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata);
5882414c70cbSLiam Girdwood 
5883414c70cbSLiam Girdwood /**
5884414c70cbSLiam Girdwood  * regulator_get_drvdata - get regulator driver data
5885414c70cbSLiam Girdwood  * @regulator: regulator
5886414c70cbSLiam Girdwood  *
5887414c70cbSLiam Girdwood  * Get regulator driver private data. This call can be used in the consumer
5888414c70cbSLiam Girdwood  * driver context when non API regulator specific functions need to be called.
5889414c70cbSLiam Girdwood  */
regulator_get_drvdata(struct regulator * regulator)5890414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator)
5891414c70cbSLiam Girdwood {
5892414c70cbSLiam Girdwood 	return regulator->rdev->reg_data;
5893414c70cbSLiam Girdwood }
5894414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata);
5895414c70cbSLiam Girdwood 
5896414c70cbSLiam Girdwood /**
5897414c70cbSLiam Girdwood  * regulator_set_drvdata - set regulator driver data
5898414c70cbSLiam Girdwood  * @regulator: regulator
5899414c70cbSLiam Girdwood  * @data: data
5900414c70cbSLiam Girdwood  */
regulator_set_drvdata(struct regulator * regulator,void * data)5901414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data)
5902414c70cbSLiam Girdwood {
5903414c70cbSLiam Girdwood 	regulator->rdev->reg_data = data;
5904414c70cbSLiam Girdwood }
5905414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata);
5906414c70cbSLiam Girdwood 
5907414c70cbSLiam Girdwood /**
5908d73e873bSMauro Carvalho Chehab  * rdev_get_id - get regulator ID
590969279fb9SMark Brown  * @rdev: regulator
5910414c70cbSLiam Girdwood  */
rdev_get_id(struct regulator_dev * rdev)5911414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev)
5912414c70cbSLiam Girdwood {
5913414c70cbSLiam Girdwood 	return rdev->desc->id;
5914414c70cbSLiam Girdwood }
5915414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id);
5916414c70cbSLiam Girdwood 
rdev_get_dev(struct regulator_dev * rdev)5917a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev)
5918a5766f11SLiam Girdwood {
5919a5766f11SLiam Girdwood 	return &rdev->dev;
5920a5766f11SLiam Girdwood }
5921a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev);
5922a5766f11SLiam Girdwood 
rdev_get_regmap(struct regulator_dev * rdev)592303c87b95SBartosz Golaszewski struct regmap *rdev_get_regmap(struct regulator_dev *rdev)
592403c87b95SBartosz Golaszewski {
592503c87b95SBartosz Golaszewski 	return rdev->regmap;
592603c87b95SBartosz Golaszewski }
592703c87b95SBartosz Golaszewski EXPORT_SYMBOL_GPL(rdev_get_regmap);
592803c87b95SBartosz Golaszewski 
regulator_get_init_drvdata(struct regulator_init_data * reg_init_data)5929a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
5930a5766f11SLiam Girdwood {
5931a5766f11SLiam Girdwood 	return reg_init_data->driver_data;
5932a5766f11SLiam Girdwood }
5933a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
5934a5766f11SLiam Girdwood 
5935ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS
supply_map_show(struct seq_file * sf,void * data)5936dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data)
5937ba55a974SMark Brown {
5938ba55a974SMark Brown 	struct regulator_map *map;
5939ba55a974SMark Brown 
5940ba55a974SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
5941dbc55955SHaishan Zhou 		seq_printf(sf, "%s -> %s.%s\n",
5942ba55a974SMark Brown 				rdev_get_name(map->regulator), map->dev_name,
5943ba55a974SMark Brown 				map->supply);
5944ba55a974SMark Brown 	}
5945ba55a974SMark Brown 
5946dbc55955SHaishan Zhou 	return 0;
5947dbc55955SHaishan Zhou }
59483e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(supply_map);
5949ba55a974SMark Brown 
595085f3b431STomeu Vizoso struct summary_data {
595185f3b431STomeu Vizoso 	struct seq_file *s;
595285f3b431STomeu Vizoso 	struct regulator_dev *parent;
595385f3b431STomeu Vizoso 	int level;
595485f3b431STomeu Vizoso };
595585f3b431STomeu Vizoso 
595685f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s,
595785f3b431STomeu Vizoso 					   struct regulator_dev *rdev,
595885f3b431STomeu Vizoso 					   int level);
595985f3b431STomeu Vizoso 
regulator_summary_show_children(struct device * dev,void * data)596085f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data)
596185f3b431STomeu Vizoso {
596285f3b431STomeu Vizoso 	struct regulator_dev *rdev = dev_to_rdev(dev);
596385f3b431STomeu Vizoso 	struct summary_data *summary_data = data;
596485f3b431STomeu Vizoso 
596585f3b431STomeu Vizoso 	if (rdev->supply && rdev->supply->rdev == summary_data->parent)
596685f3b431STomeu Vizoso 		regulator_summary_show_subtree(summary_data->s, rdev,
596785f3b431STomeu Vizoso 					       summary_data->level + 1);
596885f3b431STomeu Vizoso 
596985f3b431STomeu Vizoso 	return 0;
597085f3b431STomeu Vizoso }
597185f3b431STomeu Vizoso 
regulator_summary_show_subtree(struct seq_file * s,struct regulator_dev * rdev,int level)59727c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s,
59737c225ec9SHeiko Stübner 					   struct regulator_dev *rdev,
59747c225ec9SHeiko Stübner 					   int level)
59757c225ec9SHeiko Stübner {
59767c225ec9SHeiko Stübner 	struct regulation_constraints *c;
59777c225ec9SHeiko Stübner 	struct regulator *consumer;
597885f3b431STomeu Vizoso 	struct summary_data summary_data;
59797e4d9683SDouglas Anderson 	unsigned int opmode;
59807c225ec9SHeiko Stübner 
59817c225ec9SHeiko Stübner 	if (!rdev)
59827c225ec9SHeiko Stübner 		return;
59837c225ec9SHeiko Stübner 
59847e4d9683SDouglas Anderson 	opmode = _regulator_get_mode_unlocked(rdev);
598501de19d0SDouglas Anderson 	seq_printf(s, "%*s%-*s %3d %4d %6d %7s ",
59867c225ec9SHeiko Stübner 		   level * 3 + 1, "",
59877c225ec9SHeiko Stübner 		   30 - level * 3, rdev_get_name(rdev),
598801de19d0SDouglas Anderson 		   rdev->use_count, rdev->open_count, rdev->bypass_count,
59897e4d9683SDouglas Anderson 		   regulator_opmode_to_str(opmode));
59907c225ec9SHeiko Stübner 
5991d22b85a1SDmitry Osipenko 	seq_printf(s, "%5dmV ", regulator_get_voltage_rdev(rdev) / 1000);
59927e4d9683SDouglas Anderson 	seq_printf(s, "%5dmA ",
59937e4d9683SDouglas Anderson 		   _regulator_get_current_limit_unlocked(rdev) / 1000);
59947c225ec9SHeiko Stübner 
59957c225ec9SHeiko Stübner 	c = rdev->constraints;
59967c225ec9SHeiko Stübner 	if (c) {
59977c225ec9SHeiko Stübner 		switch (rdev->desc->type) {
59987c225ec9SHeiko Stübner 		case REGULATOR_VOLTAGE:
59997c225ec9SHeiko Stübner 			seq_printf(s, "%5dmV %5dmV ",
60007c225ec9SHeiko Stübner 				   c->min_uV / 1000, c->max_uV / 1000);
60017c225ec9SHeiko Stübner 			break;
60027c225ec9SHeiko Stübner 		case REGULATOR_CURRENT:
60037c225ec9SHeiko Stübner 			seq_printf(s, "%5dmA %5dmA ",
60047c225ec9SHeiko Stübner 				   c->min_uA / 1000, c->max_uA / 1000);
60057c225ec9SHeiko Stübner 			break;
60067c225ec9SHeiko Stübner 		}
60077c225ec9SHeiko Stübner 	}
60087c225ec9SHeiko Stübner 
60097c225ec9SHeiko Stübner 	seq_puts(s, "\n");
60107c225ec9SHeiko Stübner 
60117c225ec9SHeiko Stübner 	list_for_each_entry(consumer, &rdev->consumer_list, list) {
6012e42a46b6SLeonard Crestez 		if (consumer->dev && consumer->dev->class == &regulator_class)
60137c225ec9SHeiko Stübner 			continue;
60147c225ec9SHeiko Stübner 
60157c225ec9SHeiko Stübner 		seq_printf(s, "%*s%-*s ",
60167c225ec9SHeiko Stübner 			   (level + 1) * 3 + 1, "",
6017e42a46b6SLeonard Crestez 			   30 - (level + 1) * 3,
60186b576eb0SMichał Mirosław 			   consumer->supply_name ? consumer->supply_name :
6019e42a46b6SLeonard Crestez 			   consumer->dev ? dev_name(consumer->dev) : "deviceless");
60207c225ec9SHeiko Stübner 
60217c225ec9SHeiko Stübner 		switch (rdev->desc->type) {
60227c225ec9SHeiko Stübner 		case REGULATOR_VOLTAGE:
60235451781dSDouglas Anderson 			seq_printf(s, "%3d %33dmA%c%5dmV %5dmV",
60245451781dSDouglas Anderson 				   consumer->enable_count,
60257d3827b5SDouglas Anderson 				   consumer->uA_load / 1000,
60265451781dSDouglas Anderson 				   consumer->uA_load && !consumer->enable_count ?
60275451781dSDouglas Anderson 				   '*' : ' ',
6028c360a6dfSChunyan Zhang 				   consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
6029c360a6dfSChunyan Zhang 				   consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
60307c225ec9SHeiko Stübner 			break;
60317c225ec9SHeiko Stübner 		case REGULATOR_CURRENT:
60327c225ec9SHeiko Stübner 			break;
60337c225ec9SHeiko Stübner 		}
60347c225ec9SHeiko Stübner 
60357c225ec9SHeiko Stübner 		seq_puts(s, "\n");
60367c225ec9SHeiko Stübner 	}
60377c225ec9SHeiko Stübner 
603885f3b431STomeu Vizoso 	summary_data.s = s;
603985f3b431STomeu Vizoso 	summary_data.level = level;
604085f3b431STomeu Vizoso 	summary_data.parent = rdev;
60417c225ec9SHeiko Stübner 
604285f3b431STomeu Vizoso 	class_for_each_device(&regulator_class, NULL, &summary_data,
604385f3b431STomeu Vizoso 			      regulator_summary_show_children);
6044f8702f9eSDmitry Osipenko }
6045f8702f9eSDmitry Osipenko 
6046f8702f9eSDmitry Osipenko struct summary_lock_data {
6047f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx *ww_ctx;
6048f8702f9eSDmitry Osipenko 	struct regulator_dev **new_contended_rdev;
6049f8702f9eSDmitry Osipenko 	struct regulator_dev **old_contended_rdev;
6050f8702f9eSDmitry Osipenko };
6051f8702f9eSDmitry Osipenko 
regulator_summary_lock_one(struct device * dev,void * data)6052f8702f9eSDmitry Osipenko static int regulator_summary_lock_one(struct device *dev, void *data)
6053f8702f9eSDmitry Osipenko {
6054f8702f9eSDmitry Osipenko 	struct regulator_dev *rdev = dev_to_rdev(dev);
6055f8702f9eSDmitry Osipenko 	struct summary_lock_data *lock_data = data;
6056f8702f9eSDmitry Osipenko 	int ret = 0;
6057f8702f9eSDmitry Osipenko 
6058f8702f9eSDmitry Osipenko 	if (rdev != *lock_data->old_contended_rdev) {
6059f8702f9eSDmitry Osipenko 		ret = regulator_lock_nested(rdev, lock_data->ww_ctx);
6060f8702f9eSDmitry Osipenko 
6061f8702f9eSDmitry Osipenko 		if (ret == -EDEADLK)
6062f8702f9eSDmitry Osipenko 			*lock_data->new_contended_rdev = rdev;
6063f8702f9eSDmitry Osipenko 		else
6064f8702f9eSDmitry Osipenko 			WARN_ON_ONCE(ret);
6065f8702f9eSDmitry Osipenko 	} else {
6066f8702f9eSDmitry Osipenko 		*lock_data->old_contended_rdev = NULL;
6067f8702f9eSDmitry Osipenko 	}
6068f8702f9eSDmitry Osipenko 
6069f8702f9eSDmitry Osipenko 	return ret;
6070f8702f9eSDmitry Osipenko }
6071f8702f9eSDmitry Osipenko 
regulator_summary_unlock_one(struct device * dev,void * data)6072f8702f9eSDmitry Osipenko static int regulator_summary_unlock_one(struct device *dev, void *data)
6073f8702f9eSDmitry Osipenko {
6074f8702f9eSDmitry Osipenko 	struct regulator_dev *rdev = dev_to_rdev(dev);
6075f8702f9eSDmitry Osipenko 	struct summary_lock_data *lock_data = data;
6076f8702f9eSDmitry Osipenko 
6077f8702f9eSDmitry Osipenko 	if (lock_data) {
6078f8702f9eSDmitry Osipenko 		if (rdev == *lock_data->new_contended_rdev)
6079f8702f9eSDmitry Osipenko 			return -EDEADLK;
6080f8702f9eSDmitry Osipenko 	}
60817e4d9683SDouglas Anderson 
60827e4d9683SDouglas Anderson 	regulator_unlock(rdev);
6083f8702f9eSDmitry Osipenko 
6084f8702f9eSDmitry Osipenko 	return 0;
6085f8702f9eSDmitry Osipenko }
6086f8702f9eSDmitry Osipenko 
regulator_summary_lock_all(struct ww_acquire_ctx * ww_ctx,struct regulator_dev ** new_contended_rdev,struct regulator_dev ** old_contended_rdev)6087f8702f9eSDmitry Osipenko static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx,
6088f8702f9eSDmitry Osipenko 				      struct regulator_dev **new_contended_rdev,
6089f8702f9eSDmitry Osipenko 				      struct regulator_dev **old_contended_rdev)
6090f8702f9eSDmitry Osipenko {
6091f8702f9eSDmitry Osipenko 	struct summary_lock_data lock_data;
6092f8702f9eSDmitry Osipenko 	int ret;
6093f8702f9eSDmitry Osipenko 
6094f8702f9eSDmitry Osipenko 	lock_data.ww_ctx = ww_ctx;
6095f8702f9eSDmitry Osipenko 	lock_data.new_contended_rdev = new_contended_rdev;
6096f8702f9eSDmitry Osipenko 	lock_data.old_contended_rdev = old_contended_rdev;
6097f8702f9eSDmitry Osipenko 
6098f8702f9eSDmitry Osipenko 	ret = class_for_each_device(&regulator_class, NULL, &lock_data,
6099f8702f9eSDmitry Osipenko 				    regulator_summary_lock_one);
6100f8702f9eSDmitry Osipenko 	if (ret)
6101f8702f9eSDmitry Osipenko 		class_for_each_device(&regulator_class, NULL, &lock_data,
6102f8702f9eSDmitry Osipenko 				      regulator_summary_unlock_one);
6103f8702f9eSDmitry Osipenko 
6104f8702f9eSDmitry Osipenko 	return ret;
6105f8702f9eSDmitry Osipenko }
6106f8702f9eSDmitry Osipenko 
regulator_summary_lock(struct ww_acquire_ctx * ww_ctx)6107f8702f9eSDmitry Osipenko static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx)
6108f8702f9eSDmitry Osipenko {
6109f8702f9eSDmitry Osipenko 	struct regulator_dev *new_contended_rdev = NULL;
6110f8702f9eSDmitry Osipenko 	struct regulator_dev *old_contended_rdev = NULL;
6111f8702f9eSDmitry Osipenko 	int err;
6112f8702f9eSDmitry Osipenko 
6113ff9b34b6SDmitry Osipenko 	mutex_lock(&regulator_list_mutex);
6114ff9b34b6SDmitry Osipenko 
6115f8702f9eSDmitry Osipenko 	ww_acquire_init(ww_ctx, &regulator_ww_class);
6116f8702f9eSDmitry Osipenko 
6117f8702f9eSDmitry Osipenko 	do {
6118f8702f9eSDmitry Osipenko 		if (new_contended_rdev) {
6119f8702f9eSDmitry Osipenko 			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
6120f8702f9eSDmitry Osipenko 			old_contended_rdev = new_contended_rdev;
6121f8702f9eSDmitry Osipenko 			old_contended_rdev->ref_cnt++;
6122b83a1772SDouglas Anderson 			old_contended_rdev->mutex_owner = current;
6123f8702f9eSDmitry Osipenko 		}
6124f8702f9eSDmitry Osipenko 
6125f8702f9eSDmitry Osipenko 		err = regulator_summary_lock_all(ww_ctx,
6126f8702f9eSDmitry Osipenko 						 &new_contended_rdev,
6127f8702f9eSDmitry Osipenko 						 &old_contended_rdev);
6128f8702f9eSDmitry Osipenko 
6129f8702f9eSDmitry Osipenko 		if (old_contended_rdev)
6130f8702f9eSDmitry Osipenko 			regulator_unlock(old_contended_rdev);
6131f8702f9eSDmitry Osipenko 
6132f8702f9eSDmitry Osipenko 	} while (err == -EDEADLK);
6133f8702f9eSDmitry Osipenko 
6134f8702f9eSDmitry Osipenko 	ww_acquire_done(ww_ctx);
6135f8702f9eSDmitry Osipenko }
6136f8702f9eSDmitry Osipenko 
regulator_summary_unlock(struct ww_acquire_ctx * ww_ctx)6137f8702f9eSDmitry Osipenko static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx)
6138f8702f9eSDmitry Osipenko {
6139f8702f9eSDmitry Osipenko 	class_for_each_device(&regulator_class, NULL, NULL,
6140f8702f9eSDmitry Osipenko 			      regulator_summary_unlock_one);
6141f8702f9eSDmitry Osipenko 	ww_acquire_fini(ww_ctx);
6142ff9b34b6SDmitry Osipenko 
6143ff9b34b6SDmitry Osipenko 	mutex_unlock(&regulator_list_mutex);
61447c225ec9SHeiko Stübner }
614585f3b431STomeu Vizoso 
regulator_summary_show_roots(struct device * dev,void * data)614685f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data)
614785f3b431STomeu Vizoso {
614885f3b431STomeu Vizoso 	struct regulator_dev *rdev = dev_to_rdev(dev);
614985f3b431STomeu Vizoso 	struct seq_file *s = data;
615085f3b431STomeu Vizoso 
615185f3b431STomeu Vizoso 	if (!rdev->supply)
615285f3b431STomeu Vizoso 		regulator_summary_show_subtree(s, rdev, 0);
615385f3b431STomeu Vizoso 
615485f3b431STomeu Vizoso 	return 0;
61557c225ec9SHeiko Stübner }
61567c225ec9SHeiko Stübner 
regulator_summary_show(struct seq_file * s,void * data)61577c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data)
61587c225ec9SHeiko Stübner {
6159f8702f9eSDmitry Osipenko 	struct ww_acquire_ctx ww_ctx;
6160f8702f9eSDmitry Osipenko 
616101de19d0SDouglas Anderson 	seq_puts(s, " regulator                      use open bypass  opmode voltage current     min     max\n");
616201de19d0SDouglas Anderson 	seq_puts(s, "---------------------------------------------------------------------------------------\n");
61637c225ec9SHeiko Stübner 
6164f8702f9eSDmitry Osipenko 	regulator_summary_lock(&ww_ctx);
6165f8702f9eSDmitry Osipenko 
616685f3b431STomeu Vizoso 	class_for_each_device(&regulator_class, NULL, s,
616785f3b431STomeu Vizoso 			      regulator_summary_show_roots);
61687c225ec9SHeiko Stübner 
6169f8702f9eSDmitry Osipenko 	regulator_summary_unlock(&ww_ctx);
6170f8702f9eSDmitry Osipenko 
61717c225ec9SHeiko Stübner 	return 0;
61727c225ec9SHeiko Stübner }
61733e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(regulator_summary);
61743e60b4fcSYangtao Li #endif /* CONFIG_DEBUG_FS */
61757c225ec9SHeiko Stübner 
regulator_init(void)6176414c70cbSLiam Girdwood static int __init regulator_init(void)
6177414c70cbSLiam Girdwood {
617834abbd68SMark Brown 	int ret;
617934abbd68SMark Brown 
618034abbd68SMark Brown 	ret = class_register(&regulator_class);
618134abbd68SMark Brown 
61821130e5b3SMark Brown 	debugfs_root = debugfs_create_dir("regulator", NULL);
61832bf1c45bSOsama Muhammad 	if (IS_ERR(debugfs_root))
618408880713SGeert Uytterhoeven 		pr_debug("regulator: Failed to create debugfs directory\n");
6185ba55a974SMark Brown 
61863e60b4fcSYangtao Li #ifdef CONFIG_DEBUG_FS
6187f4d562c6SMark Brown 	debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
6188f4d562c6SMark Brown 			    &supply_map_fops);
61891130e5b3SMark Brown 
61907c225ec9SHeiko Stübner 	debugfs_create_file("regulator_summary", 0444, debugfs_root,
619185f3b431STomeu Vizoso 			    NULL, &regulator_summary_fops);
61923e60b4fcSYangtao Li #endif
619334abbd68SMark Brown 	regulator_dummy_init();
619434abbd68SMark Brown 
6195d8ca7d18SDmitry Osipenko 	regulator_coupler_register(&generic_regulator_coupler);
6196d8ca7d18SDmitry Osipenko 
619734abbd68SMark Brown 	return ret;
6198414c70cbSLiam Girdwood }
6199414c70cbSLiam Girdwood 
6200414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */
6201414c70cbSLiam Girdwood core_initcall(regulator_init);
6202ca725561SMark Brown 
regulator_late_cleanup(struct device * dev,void * data)620355576cf1SMark Brown static int regulator_late_cleanup(struct device *dev, void *data)
6204ca725561SMark Brown {
6205609ca5f3SMark Brown 	struct regulator_dev *rdev = dev_to_rdev(dev);
6206609ca5f3SMark Brown 	struct regulation_constraints *c = rdev->constraints;
62074e2a354eSOliver Barta 	int ret;
6208ca725561SMark Brown 
620966fda75fSMarkus Pargmann 	if (c && c->always_on)
6210609ca5f3SMark Brown 		return 0;
6211ca725561SMark Brown 
62128a34e979SWEN Pingbo 	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS))
6213609ca5f3SMark Brown 		return 0;
6214e9535834SMark Brown 
621566cf9a7eSMaciej Purski 	regulator_lock(rdev);
6216ca725561SMark Brown 
6217ca725561SMark Brown 	if (rdev->use_count)
6218ca725561SMark Brown 		goto unlock;
6219ca725561SMark Brown 
62204e2a354eSOliver Barta 	/* If reading the status failed, assume that it's off. */
62214e2a354eSOliver Barta 	if (_regulator_is_enabled(rdev) <= 0)
6222ca725561SMark Brown 		goto unlock;
6223ca725561SMark Brown 
622487b28417SMark Brown 	if (have_full_constraints()) {
6225609ca5f3SMark Brown 		/* We log since this may kill the system if it goes
622669b8821eSShubhankar Kuranagatti 		 * wrong.
622769b8821eSShubhankar Kuranagatti 		 */
62285da84fd9SJoe Perches 		rdev_info(rdev, "disabling\n");
622966fda75fSMarkus Pargmann 		ret = _regulator_do_disable(rdev);
62300d25d09dSJingoo Han 		if (ret != 0)
623161aab5adSMichał Mirosław 			rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret));
6232ca725561SMark Brown 	} else {
6233ca725561SMark Brown 		/* The intention is that in future we will
6234ca725561SMark Brown 		 * assume that full constraints are provided
6235ca725561SMark Brown 		 * so warn even if we aren't going to do
6236ca725561SMark Brown 		 * anything here.
6237ca725561SMark Brown 		 */
62385da84fd9SJoe Perches 		rdev_warn(rdev, "incomplete constraints, leaving on\n");
6239ca725561SMark Brown 	}
6240ca725561SMark Brown 
6241ca725561SMark Brown unlock:
624266cf9a7eSMaciej Purski 	regulator_unlock(rdev);
6243609ca5f3SMark Brown 
6244609ca5f3SMark Brown 	return 0;
6245ca725561SMark Brown }
6246ca725561SMark Brown 
regulator_init_complete_work_function(struct work_struct * work)624755576cf1SMark Brown static void regulator_init_complete_work_function(struct work_struct *work)
6248609ca5f3SMark Brown {
6249609ca5f3SMark Brown 	/*
62503827b64dSJavier Martinez Canillas 	 * Regulators may had failed to resolve their input supplies
62513827b64dSJavier Martinez Canillas 	 * when were registered, either because the input supply was
62523827b64dSJavier Martinez Canillas 	 * not registered yet or because its parent device was not
62533827b64dSJavier Martinez Canillas 	 * bound yet. So attempt to resolve the input supplies for
62543827b64dSJavier Martinez Canillas 	 * pending regulators before trying to disable unused ones.
62553827b64dSJavier Martinez Canillas 	 */
62563827b64dSJavier Martinez Canillas 	class_for_each_device(&regulator_class, NULL, NULL,
62573827b64dSJavier Martinez Canillas 			      regulator_register_resolve_supply);
62583827b64dSJavier Martinez Canillas 
6259609ca5f3SMark Brown 	/* If we have a full configuration then disable any regulators
6260609ca5f3SMark Brown 	 * we have permission to change the status for and which are
6261609ca5f3SMark Brown 	 * not in use or always_on.  This is effectively the default
6262609ca5f3SMark Brown 	 * for DT and ACPI as they have full constraints.
6263609ca5f3SMark Brown 	 */
6264609ca5f3SMark Brown 	class_for_each_device(&regulator_class, NULL, NULL,
6265609ca5f3SMark Brown 			      regulator_late_cleanup);
626655576cf1SMark Brown }
626755576cf1SMark Brown 
626855576cf1SMark Brown static DECLARE_DELAYED_WORK(regulator_init_complete_work,
626955576cf1SMark Brown 			    regulator_init_complete_work_function);
627055576cf1SMark Brown 
regulator_init_complete(void)627155576cf1SMark Brown static int __init regulator_init_complete(void)
627255576cf1SMark Brown {
627355576cf1SMark Brown 	/*
627455576cf1SMark Brown 	 * Since DT doesn't provide an idiomatic mechanism for
627555576cf1SMark Brown 	 * enabling full constraints and since it's much more natural
627655576cf1SMark Brown 	 * with DT to provide them just assume that a DT enabled
627755576cf1SMark Brown 	 * system has full constraints.
627855576cf1SMark Brown 	 */
627955576cf1SMark Brown 	if (of_have_populated_dt())
628055576cf1SMark Brown 		has_full_constraints = true;
628155576cf1SMark Brown 
628255576cf1SMark Brown 	/*
62832a15483bSJohn Stultz 	 * We punt completion for an arbitrary amount of time since
62842a15483bSJohn Stultz 	 * systems like distros will load many drivers from userspace
62852a15483bSJohn Stultz 	 * so consumers might not always be ready yet, this is
62862a15483bSJohn Stultz 	 * particularly an issue with laptops where this might bounce
62872a15483bSJohn Stultz 	 * the display off then on.  Ideally we'd get a notification
62882a15483bSJohn Stultz 	 * from userspace when this happens but we don't so just wait
62892a15483bSJohn Stultz 	 * a bit and hope we waited long enough.  It'd be better if
62902a15483bSJohn Stultz 	 * we'd only do this on systems that need it, and a kernel
62912a15483bSJohn Stultz 	 * command line option might be useful.
629255576cf1SMark Brown 	 */
62932a15483bSJohn Stultz 	schedule_delayed_work(&regulator_init_complete_work,
62942a15483bSJohn Stultz 			      msecs_to_jiffies(30000));
6295ca725561SMark Brown 
6296ca725561SMark Brown 	return 0;
6297ca725561SMark Brown }
6298fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete);
6299