xref: /openbmc/linux/drivers/regulator/core.c (revision 2c043bcb)
1414c70cbSLiam Girdwood /*
2414c70cbSLiam Girdwood  * core.c  --  Voltage/Current Regulator framework.
3414c70cbSLiam Girdwood  *
4414c70cbSLiam Girdwood  * Copyright 2007, 2008 Wolfson Microelectronics PLC.
5a5766f11SLiam Girdwood  * Copyright 2008 SlimLogic Ltd.
6414c70cbSLiam Girdwood  *
7a5766f11SLiam Girdwood  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
8414c70cbSLiam Girdwood  *
9414c70cbSLiam Girdwood  *  This program is free software; you can redistribute  it and/or modify it
10414c70cbSLiam Girdwood  *  under  the terms of  the GNU General  Public License as published by the
11414c70cbSLiam Girdwood  *  Free Software Foundation;  either version 2 of the  License, or (at your
12414c70cbSLiam Girdwood  *  option) any later version.
13414c70cbSLiam Girdwood  *
14414c70cbSLiam Girdwood  */
15414c70cbSLiam Girdwood 
16c5e28ed7SDaniel Walker #define pr_fmt(fmt) "%s: " fmt, __func__
17c5e28ed7SDaniel Walker 
18414c70cbSLiam Girdwood #include <linux/kernel.h>
19414c70cbSLiam Girdwood #include <linux/init.h>
201130e5b3SMark Brown #include <linux/debugfs.h>
21414c70cbSLiam Girdwood #include <linux/device.h>
225a0e3ad6STejun Heo #include <linux/slab.h>
23f21e0e81SMark Brown #include <linux/async.h>
24414c70cbSLiam Girdwood #include <linux/err.h>
25414c70cbSLiam Girdwood #include <linux/mutex.h>
26414c70cbSLiam Girdwood #include <linux/suspend.h>
2731aae2beSMark Brown #include <linux/delay.h>
28414c70cbSLiam Girdwood #include <linux/regulator/consumer.h>
29414c70cbSLiam Girdwood #include <linux/regulator/driver.h>
30414c70cbSLiam Girdwood #include <linux/regulator/machine.h>
3165602c32SPaul Gortmaker #include <linux/module.h>
32414c70cbSLiam Girdwood 
3302fa3ec0SMark Brown #define CREATE_TRACE_POINTS
3402fa3ec0SMark Brown #include <trace/events/regulator.h>
3502fa3ec0SMark Brown 
3634abbd68SMark Brown #include "dummy.h"
3734abbd68SMark Brown 
387d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...)					\
397d51a0dbSMark Brown 	pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
405da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...)					\
415da84fd9SJoe Perches 	pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
425da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...)					\
435da84fd9SJoe Perches 	pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
445da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...)					\
455da84fd9SJoe Perches 	pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
465da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...)					\
475da84fd9SJoe Perches 	pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
485da84fd9SJoe Perches 
49414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex);
50414c70cbSLiam Girdwood static LIST_HEAD(regulator_list);
51414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list);
5221cf891aSMark Brown static bool has_full_constraints;
53688fe99aSMark Brown static bool board_wants_dummy_regulator;
54414c70cbSLiam Girdwood 
551130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
561130e5b3SMark Brown static struct dentry *debugfs_root;
571130e5b3SMark Brown #endif
581130e5b3SMark Brown 
598dc5390dSMark Brown /*
60414c70cbSLiam Girdwood  * struct regulator_map
61414c70cbSLiam Girdwood  *
62414c70cbSLiam Girdwood  * Used to provide symbolic supply names to devices.
63414c70cbSLiam Girdwood  */
64414c70cbSLiam Girdwood struct regulator_map {
65414c70cbSLiam Girdwood 	struct list_head list;
6640f9244fSMark Brown 	const char *dev_name;   /* The dev_name() for the consumer */
67414c70cbSLiam Girdwood 	const char *supply;
68a5766f11SLiam Girdwood 	struct regulator_dev *regulator;
69414c70cbSLiam Girdwood };
70414c70cbSLiam Girdwood 
71414c70cbSLiam Girdwood /*
72414c70cbSLiam Girdwood  * struct regulator
73414c70cbSLiam Girdwood  *
74414c70cbSLiam Girdwood  * One for each consumer device.
75414c70cbSLiam Girdwood  */
76414c70cbSLiam Girdwood struct regulator {
77414c70cbSLiam Girdwood 	struct device *dev;
78414c70cbSLiam Girdwood 	struct list_head list;
79414c70cbSLiam Girdwood 	int uA_load;
80414c70cbSLiam Girdwood 	int min_uV;
81414c70cbSLiam Girdwood 	int max_uV;
82414c70cbSLiam Girdwood 	char *supply_name;
83414c70cbSLiam Girdwood 	struct device_attribute dev_attr;
84414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
855de70519SMark Brown #ifdef CONFIG_DEBUG_FS
865de70519SMark Brown 	struct dentry *debugfs;
875de70519SMark Brown #endif
88414c70cbSLiam Girdwood };
89414c70cbSLiam Girdwood 
90414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev);
913801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev);
92414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev);
93414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev);
94414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
95414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev,
96414c70cbSLiam Girdwood 				  unsigned long event, void *data);
9775790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
9875790251SMark Brown 				     int min_uV, int max_uV);
993801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev,
1003801b86aSMark Brown 					  struct device *dev,
1013801b86aSMark Brown 					  const char *supply_name);
102414c70cbSLiam Girdwood 
1031083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev)
1041083c393SMark Brown {
1051083c393SMark Brown 	if (rdev->constraints && rdev->constraints->name)
1061083c393SMark Brown 		return rdev->constraints->name;
1071083c393SMark Brown 	else if (rdev->desc->name)
1081083c393SMark Brown 		return rdev->desc->name;
1091083c393SMark Brown 	else
1101083c393SMark Brown 		return "";
1111083c393SMark Brown }
1121083c393SMark Brown 
113414c70cbSLiam Girdwood /* gets the regulator for a given consumer device */
114414c70cbSLiam Girdwood static struct regulator *get_device_regulator(struct device *dev)
115414c70cbSLiam Girdwood {
116414c70cbSLiam Girdwood 	struct regulator *regulator = NULL;
117414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
118414c70cbSLiam Girdwood 
119414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
120414c70cbSLiam Girdwood 	list_for_each_entry(rdev, &regulator_list, list) {
121414c70cbSLiam Girdwood 		mutex_lock(&rdev->mutex);
122414c70cbSLiam Girdwood 		list_for_each_entry(regulator, &rdev->consumer_list, list) {
123414c70cbSLiam Girdwood 			if (regulator->dev == dev) {
124414c70cbSLiam Girdwood 				mutex_unlock(&rdev->mutex);
125414c70cbSLiam Girdwood 				mutex_unlock(&regulator_list_mutex);
126414c70cbSLiam Girdwood 				return regulator;
127414c70cbSLiam Girdwood 			}
128414c70cbSLiam Girdwood 		}
129414c70cbSLiam Girdwood 		mutex_unlock(&rdev->mutex);
130414c70cbSLiam Girdwood 	}
131414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
132414c70cbSLiam Girdwood 	return NULL;
133414c70cbSLiam Girdwood }
134414c70cbSLiam Girdwood 
135414c70cbSLiam Girdwood /* Platform voltage constraint check */
136414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev,
137414c70cbSLiam Girdwood 				   int *min_uV, int *max_uV)
138414c70cbSLiam Girdwood {
139414c70cbSLiam Girdwood 	BUG_ON(*min_uV > *max_uV);
140414c70cbSLiam Girdwood 
141414c70cbSLiam Girdwood 	if (!rdev->constraints) {
1425da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
143414c70cbSLiam Girdwood 		return -ENODEV;
144414c70cbSLiam Girdwood 	}
145414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
1465da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
147414c70cbSLiam Girdwood 		return -EPERM;
148414c70cbSLiam Girdwood 	}
149414c70cbSLiam Girdwood 
150414c70cbSLiam Girdwood 	if (*max_uV > rdev->constraints->max_uV)
151414c70cbSLiam Girdwood 		*max_uV = rdev->constraints->max_uV;
152414c70cbSLiam Girdwood 	if (*min_uV < rdev->constraints->min_uV)
153414c70cbSLiam Girdwood 		*min_uV = rdev->constraints->min_uV;
154414c70cbSLiam Girdwood 
15589f425edSMark Brown 	if (*min_uV > *max_uV) {
15689f425edSMark Brown 		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
15754abd335SMark Brown 			 *min_uV, *max_uV);
158414c70cbSLiam Girdwood 		return -EINVAL;
15989f425edSMark Brown 	}
160414c70cbSLiam Girdwood 
161414c70cbSLiam Girdwood 	return 0;
162414c70cbSLiam Girdwood }
163414c70cbSLiam Girdwood 
16405fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all
16505fda3b1SThomas Petazzoni  * regulator consumers
16605fda3b1SThomas Petazzoni  */
16705fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev,
16805fda3b1SThomas Petazzoni 				     int *min_uV, int *max_uV)
16905fda3b1SThomas Petazzoni {
17005fda3b1SThomas Petazzoni 	struct regulator *regulator;
17105fda3b1SThomas Petazzoni 
17205fda3b1SThomas Petazzoni 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
1734aa922c0SMark Brown 		/*
1744aa922c0SMark Brown 		 * Assume consumers that didn't say anything are OK
1754aa922c0SMark Brown 		 * with anything in the constraint range.
1764aa922c0SMark Brown 		 */
1774aa922c0SMark Brown 		if (!regulator->min_uV && !regulator->max_uV)
1784aa922c0SMark Brown 			continue;
1794aa922c0SMark Brown 
18005fda3b1SThomas Petazzoni 		if (*max_uV > regulator->max_uV)
18105fda3b1SThomas Petazzoni 			*max_uV = regulator->max_uV;
18205fda3b1SThomas Petazzoni 		if (*min_uV < regulator->min_uV)
18305fda3b1SThomas Petazzoni 			*min_uV = regulator->min_uV;
18405fda3b1SThomas Petazzoni 	}
18505fda3b1SThomas Petazzoni 
18605fda3b1SThomas Petazzoni 	if (*min_uV > *max_uV)
18705fda3b1SThomas Petazzoni 		return -EINVAL;
18805fda3b1SThomas Petazzoni 
18905fda3b1SThomas Petazzoni 	return 0;
19005fda3b1SThomas Petazzoni }
19105fda3b1SThomas Petazzoni 
192414c70cbSLiam Girdwood /* current constraint check */
193414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev,
194414c70cbSLiam Girdwood 					int *min_uA, int *max_uA)
195414c70cbSLiam Girdwood {
196414c70cbSLiam Girdwood 	BUG_ON(*min_uA > *max_uA);
197414c70cbSLiam Girdwood 
198414c70cbSLiam Girdwood 	if (!rdev->constraints) {
1995da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
200414c70cbSLiam Girdwood 		return -ENODEV;
201414c70cbSLiam Girdwood 	}
202414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
2035da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
204414c70cbSLiam Girdwood 		return -EPERM;
205414c70cbSLiam Girdwood 	}
206414c70cbSLiam Girdwood 
207414c70cbSLiam Girdwood 	if (*max_uA > rdev->constraints->max_uA)
208414c70cbSLiam Girdwood 		*max_uA = rdev->constraints->max_uA;
209414c70cbSLiam Girdwood 	if (*min_uA < rdev->constraints->min_uA)
210414c70cbSLiam Girdwood 		*min_uA = rdev->constraints->min_uA;
211414c70cbSLiam Girdwood 
21289f425edSMark Brown 	if (*min_uA > *max_uA) {
21389f425edSMark Brown 		rdev_err(rdev, "unsupportable current range: %d-%duA\n",
21454abd335SMark Brown 			 *min_uA, *max_uA);
215414c70cbSLiam Girdwood 		return -EINVAL;
21689f425edSMark Brown 	}
217414c70cbSLiam Girdwood 
218414c70cbSLiam Girdwood 	return 0;
219414c70cbSLiam Girdwood }
220414c70cbSLiam Girdwood 
221414c70cbSLiam Girdwood /* operating mode constraint check */
2222c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
223414c70cbSLiam Girdwood {
2242c608234SMark Brown 	switch (*mode) {
225e573520bSDavid Brownell 	case REGULATOR_MODE_FAST:
226e573520bSDavid Brownell 	case REGULATOR_MODE_NORMAL:
227e573520bSDavid Brownell 	case REGULATOR_MODE_IDLE:
228e573520bSDavid Brownell 	case REGULATOR_MODE_STANDBY:
229e573520bSDavid Brownell 		break;
230e573520bSDavid Brownell 	default:
23189f425edSMark Brown 		rdev_err(rdev, "invalid mode %x specified\n", *mode);
232e573520bSDavid Brownell 		return -EINVAL;
233e573520bSDavid Brownell 	}
234e573520bSDavid Brownell 
235414c70cbSLiam Girdwood 	if (!rdev->constraints) {
2365da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
237414c70cbSLiam Girdwood 		return -ENODEV;
238414c70cbSLiam Girdwood 	}
239414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
2405da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
241414c70cbSLiam Girdwood 		return -EPERM;
242414c70cbSLiam Girdwood 	}
2432c608234SMark Brown 
2442c608234SMark Brown 	/* The modes are bitmasks, the most power hungry modes having
2452c608234SMark Brown 	 * the lowest values. If the requested mode isn't supported
2462c608234SMark Brown 	 * try higher modes. */
2472c608234SMark Brown 	while (*mode) {
2482c608234SMark Brown 		if (rdev->constraints->valid_modes_mask & *mode)
249414c70cbSLiam Girdwood 			return 0;
2502c608234SMark Brown 		*mode /= 2;
2512c608234SMark Brown 	}
2522c608234SMark Brown 
2532c608234SMark Brown 	return -EINVAL;
254414c70cbSLiam Girdwood }
255414c70cbSLiam Girdwood 
256414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */
257414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev)
258414c70cbSLiam Girdwood {
259414c70cbSLiam Girdwood 	if (!rdev->constraints) {
2605da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
261414c70cbSLiam Girdwood 		return -ENODEV;
262414c70cbSLiam Girdwood 	}
263414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
2645da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
265414c70cbSLiam Girdwood 		return -EPERM;
266414c70cbSLiam Girdwood 	}
267414c70cbSLiam Girdwood 	return 0;
268414c70cbSLiam Girdwood }
269414c70cbSLiam Girdwood 
270414c70cbSLiam Girdwood static ssize_t device_requested_uA_show(struct device *dev,
271414c70cbSLiam Girdwood 			     struct device_attribute *attr, char *buf)
272414c70cbSLiam Girdwood {
273414c70cbSLiam Girdwood 	struct regulator *regulator;
274414c70cbSLiam Girdwood 
275414c70cbSLiam Girdwood 	regulator = get_device_regulator(dev);
276414c70cbSLiam Girdwood 	if (regulator == NULL)
277414c70cbSLiam Girdwood 		return 0;
278414c70cbSLiam Girdwood 
279414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", regulator->uA_load);
280414c70cbSLiam Girdwood }
281414c70cbSLiam Girdwood 
282414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev,
283414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
284414c70cbSLiam Girdwood {
285a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
286414c70cbSLiam Girdwood 	ssize_t ret;
287414c70cbSLiam Girdwood 
288414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
289414c70cbSLiam Girdwood 	ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev));
290414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
291414c70cbSLiam Girdwood 
292414c70cbSLiam Girdwood 	return ret;
293414c70cbSLiam Girdwood }
2947ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);
295414c70cbSLiam Girdwood 
296414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev,
297414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
298414c70cbSLiam Girdwood {
299a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
300414c70cbSLiam Girdwood 
301414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
302414c70cbSLiam Girdwood }
3037ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);
304414c70cbSLiam Girdwood 
305bc558a60SMark Brown static ssize_t regulator_name_show(struct device *dev,
306bc558a60SMark Brown 			     struct device_attribute *attr, char *buf)
307bc558a60SMark Brown {
308bc558a60SMark Brown 	struct regulator_dev *rdev = dev_get_drvdata(dev);
309bc558a60SMark Brown 
3101083c393SMark Brown 	return sprintf(buf, "%s\n", rdev_get_name(rdev));
311bc558a60SMark Brown }
312bc558a60SMark Brown 
3134fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode)
314414c70cbSLiam Girdwood {
315414c70cbSLiam Girdwood 	switch (mode) {
316414c70cbSLiam Girdwood 	case REGULATOR_MODE_FAST:
317414c70cbSLiam Girdwood 		return sprintf(buf, "fast\n");
318414c70cbSLiam Girdwood 	case REGULATOR_MODE_NORMAL:
319414c70cbSLiam Girdwood 		return sprintf(buf, "normal\n");
320414c70cbSLiam Girdwood 	case REGULATOR_MODE_IDLE:
321414c70cbSLiam Girdwood 		return sprintf(buf, "idle\n");
322414c70cbSLiam Girdwood 	case REGULATOR_MODE_STANDBY:
323414c70cbSLiam Girdwood 		return sprintf(buf, "standby\n");
324414c70cbSLiam Girdwood 	}
325414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
326414c70cbSLiam Girdwood }
327414c70cbSLiam Girdwood 
3284fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev,
329414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
330414c70cbSLiam Girdwood {
331a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
332414c70cbSLiam Girdwood 
3334fca9545SDavid Brownell 	return regulator_print_opmode(buf, _regulator_get_mode(rdev));
3344fca9545SDavid Brownell }
3357ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL);
3364fca9545SDavid Brownell 
3374fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state)
3384fca9545SDavid Brownell {
339414c70cbSLiam Girdwood 	if (state > 0)
340414c70cbSLiam Girdwood 		return sprintf(buf, "enabled\n");
341414c70cbSLiam Girdwood 	else if (state == 0)
342414c70cbSLiam Girdwood 		return sprintf(buf, "disabled\n");
343414c70cbSLiam Girdwood 	else
344414c70cbSLiam Girdwood 		return sprintf(buf, "unknown\n");
345414c70cbSLiam Girdwood }
346414c70cbSLiam Girdwood 
3474fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev,
3484fca9545SDavid Brownell 				   struct device_attribute *attr, char *buf)
3494fca9545SDavid Brownell {
3504fca9545SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
3519332546fSMark Brown 	ssize_t ret;
3524fca9545SDavid Brownell 
3539332546fSMark Brown 	mutex_lock(&rdev->mutex);
3549332546fSMark Brown 	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
3559332546fSMark Brown 	mutex_unlock(&rdev->mutex);
3569332546fSMark Brown 
3579332546fSMark Brown 	return ret;
3584fca9545SDavid Brownell }
3597ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
3604fca9545SDavid Brownell 
361853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev,
362853116a1SDavid Brownell 				   struct device_attribute *attr, char *buf)
363853116a1SDavid Brownell {
364853116a1SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
365853116a1SDavid Brownell 	int status;
366853116a1SDavid Brownell 	char *label;
367853116a1SDavid Brownell 
368853116a1SDavid Brownell 	status = rdev->desc->ops->get_status(rdev);
369853116a1SDavid Brownell 	if (status < 0)
370853116a1SDavid Brownell 		return status;
371853116a1SDavid Brownell 
372853116a1SDavid Brownell 	switch (status) {
373853116a1SDavid Brownell 	case REGULATOR_STATUS_OFF:
374853116a1SDavid Brownell 		label = "off";
375853116a1SDavid Brownell 		break;
376853116a1SDavid Brownell 	case REGULATOR_STATUS_ON:
377853116a1SDavid Brownell 		label = "on";
378853116a1SDavid Brownell 		break;
379853116a1SDavid Brownell 	case REGULATOR_STATUS_ERROR:
380853116a1SDavid Brownell 		label = "error";
381853116a1SDavid Brownell 		break;
382853116a1SDavid Brownell 	case REGULATOR_STATUS_FAST:
383853116a1SDavid Brownell 		label = "fast";
384853116a1SDavid Brownell 		break;
385853116a1SDavid Brownell 	case REGULATOR_STATUS_NORMAL:
386853116a1SDavid Brownell 		label = "normal";
387853116a1SDavid Brownell 		break;
388853116a1SDavid Brownell 	case REGULATOR_STATUS_IDLE:
389853116a1SDavid Brownell 		label = "idle";
390853116a1SDavid Brownell 		break;
391853116a1SDavid Brownell 	case REGULATOR_STATUS_STANDBY:
392853116a1SDavid Brownell 		label = "standby";
393853116a1SDavid Brownell 		break;
394853116a1SDavid Brownell 	default:
395853116a1SDavid Brownell 		return -ERANGE;
396853116a1SDavid Brownell 	}
397853116a1SDavid Brownell 
398853116a1SDavid Brownell 	return sprintf(buf, "%s\n", label);
399853116a1SDavid Brownell }
400853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL);
401853116a1SDavid Brownell 
402414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev,
403414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
404414c70cbSLiam Girdwood {
405a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
406414c70cbSLiam Girdwood 
407414c70cbSLiam Girdwood 	if (!rdev->constraints)
408414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
409414c70cbSLiam Girdwood 
410414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uA);
411414c70cbSLiam Girdwood }
4127ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL);
413414c70cbSLiam Girdwood 
414414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev,
415414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
416414c70cbSLiam Girdwood {
417a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
418414c70cbSLiam Girdwood 
419414c70cbSLiam Girdwood 	if (!rdev->constraints)
420414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
421414c70cbSLiam Girdwood 
422414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uA);
423414c70cbSLiam Girdwood }
4247ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL);
425414c70cbSLiam Girdwood 
426414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev,
427414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
428414c70cbSLiam Girdwood {
429a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
430414c70cbSLiam Girdwood 
431414c70cbSLiam Girdwood 	if (!rdev->constraints)
432414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
433414c70cbSLiam Girdwood 
434414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uV);
435414c70cbSLiam Girdwood }
4367ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL);
437414c70cbSLiam Girdwood 
438414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev,
439414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
440414c70cbSLiam Girdwood {
441a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
442414c70cbSLiam Girdwood 
443414c70cbSLiam Girdwood 	if (!rdev->constraints)
444414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
445414c70cbSLiam Girdwood 
446414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uV);
447414c70cbSLiam Girdwood }
4487ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL);
449414c70cbSLiam Girdwood 
450414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev,
451414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
452414c70cbSLiam Girdwood {
453a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
454414c70cbSLiam Girdwood 	struct regulator *regulator;
455414c70cbSLiam Girdwood 	int uA = 0;
456414c70cbSLiam Girdwood 
457414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
458414c70cbSLiam Girdwood 	list_for_each_entry(regulator, &rdev->consumer_list, list)
459414c70cbSLiam Girdwood 		uA += regulator->uA_load;
460414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
461414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", uA);
462414c70cbSLiam Girdwood }
4637ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
464414c70cbSLiam Girdwood 
465414c70cbSLiam Girdwood static ssize_t regulator_num_users_show(struct device *dev,
466414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
467414c70cbSLiam Girdwood {
468a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
469414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->use_count);
470414c70cbSLiam Girdwood }
471414c70cbSLiam Girdwood 
472414c70cbSLiam Girdwood static ssize_t regulator_type_show(struct device *dev,
473414c70cbSLiam Girdwood 				  struct device_attribute *attr, char *buf)
474414c70cbSLiam Girdwood {
475a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
476414c70cbSLiam Girdwood 
477414c70cbSLiam Girdwood 	switch (rdev->desc->type) {
478414c70cbSLiam Girdwood 	case REGULATOR_VOLTAGE:
479414c70cbSLiam Girdwood 		return sprintf(buf, "voltage\n");
480414c70cbSLiam Girdwood 	case REGULATOR_CURRENT:
481414c70cbSLiam Girdwood 		return sprintf(buf, "current\n");
482414c70cbSLiam Girdwood 	}
483414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
484414c70cbSLiam Girdwood }
485414c70cbSLiam Girdwood 
486414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
487414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
488414c70cbSLiam Girdwood {
489a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
490414c70cbSLiam Girdwood 
491414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
492414c70cbSLiam Girdwood }
4937ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444,
4947ad68e2fSDavid Brownell 		regulator_suspend_mem_uV_show, NULL);
495414c70cbSLiam Girdwood 
496414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
497414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
498414c70cbSLiam Girdwood {
499a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
500414c70cbSLiam Girdwood 
501414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
502414c70cbSLiam Girdwood }
5037ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444,
5047ad68e2fSDavid Brownell 		regulator_suspend_disk_uV_show, NULL);
505414c70cbSLiam Girdwood 
506414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
507414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
508414c70cbSLiam Girdwood {
509a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
510414c70cbSLiam Girdwood 
511414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
512414c70cbSLiam Girdwood }
5137ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444,
5147ad68e2fSDavid Brownell 		regulator_suspend_standby_uV_show, NULL);
515414c70cbSLiam Girdwood 
516414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
517414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
518414c70cbSLiam Girdwood {
519a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
520414c70cbSLiam Girdwood 
5214fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5224fca9545SDavid Brownell 		rdev->constraints->state_mem.mode);
523414c70cbSLiam Girdwood }
5247ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444,
5257ad68e2fSDavid Brownell 		regulator_suspend_mem_mode_show, NULL);
526414c70cbSLiam Girdwood 
527414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
528414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
529414c70cbSLiam Girdwood {
530a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
531414c70cbSLiam Girdwood 
5324fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5334fca9545SDavid Brownell 		rdev->constraints->state_disk.mode);
534414c70cbSLiam Girdwood }
5357ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444,
5367ad68e2fSDavid Brownell 		regulator_suspend_disk_mode_show, NULL);
537414c70cbSLiam Girdwood 
538414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
539414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
540414c70cbSLiam Girdwood {
541a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
542414c70cbSLiam Girdwood 
5434fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5444fca9545SDavid Brownell 		rdev->constraints->state_standby.mode);
545414c70cbSLiam Girdwood }
5467ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444,
5477ad68e2fSDavid Brownell 		regulator_suspend_standby_mode_show, NULL);
548414c70cbSLiam Girdwood 
549414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev,
550414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
551414c70cbSLiam Girdwood {
552a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
553414c70cbSLiam Girdwood 
5544fca9545SDavid Brownell 	return regulator_print_state(buf,
5554fca9545SDavid Brownell 			rdev->constraints->state_mem.enabled);
556414c70cbSLiam Girdwood }
5577ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444,
5587ad68e2fSDavid Brownell 		regulator_suspend_mem_state_show, NULL);
559414c70cbSLiam Girdwood 
560414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev,
561414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
562414c70cbSLiam Girdwood {
563a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
564414c70cbSLiam Girdwood 
5654fca9545SDavid Brownell 	return regulator_print_state(buf,
5664fca9545SDavid Brownell 			rdev->constraints->state_disk.enabled);
567414c70cbSLiam Girdwood }
5687ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444,
5697ad68e2fSDavid Brownell 		regulator_suspend_disk_state_show, NULL);
570414c70cbSLiam Girdwood 
571414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev,
572414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
573414c70cbSLiam Girdwood {
574a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
575414c70cbSLiam Girdwood 
5764fca9545SDavid Brownell 	return regulator_print_state(buf,
5774fca9545SDavid Brownell 			rdev->constraints->state_standby.enabled);
578414c70cbSLiam Girdwood }
5797ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444,
5807ad68e2fSDavid Brownell 		regulator_suspend_standby_state_show, NULL);
581bc558a60SMark Brown 
5827ad68e2fSDavid Brownell 
5837ad68e2fSDavid Brownell /*
5847ad68e2fSDavid Brownell  * These are the only attributes are present for all regulators.
5857ad68e2fSDavid Brownell  * Other attributes are a function of regulator functionality.
5867ad68e2fSDavid Brownell  */
587414c70cbSLiam Girdwood static struct device_attribute regulator_dev_attrs[] = {
588bc558a60SMark Brown 	__ATTR(name, 0444, regulator_name_show, NULL),
589414c70cbSLiam Girdwood 	__ATTR(num_users, 0444, regulator_num_users_show, NULL),
590414c70cbSLiam Girdwood 	__ATTR(type, 0444, regulator_type_show, NULL),
591414c70cbSLiam Girdwood 	__ATTR_NULL,
592414c70cbSLiam Girdwood };
593414c70cbSLiam Girdwood 
594414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev)
595414c70cbSLiam Girdwood {
596a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
597414c70cbSLiam Girdwood 	kfree(rdev);
598414c70cbSLiam Girdwood }
599414c70cbSLiam Girdwood 
600414c70cbSLiam Girdwood static struct class regulator_class = {
601414c70cbSLiam Girdwood 	.name = "regulator",
602414c70cbSLiam Girdwood 	.dev_release = regulator_dev_release,
603414c70cbSLiam Girdwood 	.dev_attrs = regulator_dev_attrs,
604414c70cbSLiam Girdwood };
605414c70cbSLiam Girdwood 
606414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total
607414c70cbSLiam Girdwood  * consumer load. All locks held by caller */
608414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev)
609414c70cbSLiam Girdwood {
610414c70cbSLiam Girdwood 	struct regulator *sibling;
611414c70cbSLiam Girdwood 	int current_uA = 0, output_uV, input_uV, err;
612414c70cbSLiam Girdwood 	unsigned int mode;
613414c70cbSLiam Girdwood 
614414c70cbSLiam Girdwood 	err = regulator_check_drms(rdev);
615414c70cbSLiam Girdwood 	if (err < 0 || !rdev->desc->ops->get_optimum_mode ||
616476c2d83SMark Brown 	    (!rdev->desc->ops->get_voltage &&
617476c2d83SMark Brown 	     !rdev->desc->ops->get_voltage_sel) ||
618476c2d83SMark Brown 	    !rdev->desc->ops->set_mode)
619414c70cbSLiam Girdwood 		return;
620414c70cbSLiam Girdwood 
621414c70cbSLiam Girdwood 	/* get output voltage */
6221bf5a1f8SMark Brown 	output_uV = _regulator_get_voltage(rdev);
623414c70cbSLiam Girdwood 	if (output_uV <= 0)
624414c70cbSLiam Girdwood 		return;
625414c70cbSLiam Girdwood 
626414c70cbSLiam Girdwood 	/* get input voltage */
6271bf5a1f8SMark Brown 	input_uV = 0;
6281bf5a1f8SMark Brown 	if (rdev->supply)
6291bf5a1f8SMark Brown 		input_uV = _regulator_get_voltage(rdev);
6301bf5a1f8SMark Brown 	if (input_uV <= 0)
631414c70cbSLiam Girdwood 		input_uV = rdev->constraints->input_uV;
632414c70cbSLiam Girdwood 	if (input_uV <= 0)
633414c70cbSLiam Girdwood 		return;
634414c70cbSLiam Girdwood 
635414c70cbSLiam Girdwood 	/* calc total requested load */
636414c70cbSLiam Girdwood 	list_for_each_entry(sibling, &rdev->consumer_list, list)
637414c70cbSLiam Girdwood 		current_uA += sibling->uA_load;
638414c70cbSLiam Girdwood 
639414c70cbSLiam Girdwood 	/* now get the optimum mode for our new total regulator load */
640414c70cbSLiam Girdwood 	mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
641414c70cbSLiam Girdwood 						  output_uV, current_uA);
642414c70cbSLiam Girdwood 
643414c70cbSLiam Girdwood 	/* check the new mode is allowed */
6442c608234SMark Brown 	err = regulator_mode_constrain(rdev, &mode);
645414c70cbSLiam Girdwood 	if (err == 0)
646414c70cbSLiam Girdwood 		rdev->desc->ops->set_mode(rdev, mode);
647414c70cbSLiam Girdwood }
648414c70cbSLiam Girdwood 
649414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev,
650414c70cbSLiam Girdwood 	struct regulator_state *rstate)
651414c70cbSLiam Girdwood {
652414c70cbSLiam Girdwood 	int ret = 0;
653638f85c5SMark Brown 	bool can_set_state;
654414c70cbSLiam Girdwood 
655638f85c5SMark Brown 	can_set_state = rdev->desc->ops->set_suspend_enable &&
656638f85c5SMark Brown 		rdev->desc->ops->set_suspend_disable;
657638f85c5SMark Brown 
658638f85c5SMark Brown 	/* If we have no suspend mode configration don't set anything;
659638f85c5SMark Brown 	 * only warn if the driver actually makes the suspend mode
660638f85c5SMark Brown 	 * configurable.
661638f85c5SMark Brown 	 */
662638f85c5SMark Brown 	if (!rstate->enabled && !rstate->disabled) {
663638f85c5SMark Brown 		if (can_set_state)
6645da84fd9SJoe Perches 			rdev_warn(rdev, "No configuration\n");
665638f85c5SMark Brown 		return 0;
666638f85c5SMark Brown 	}
667638f85c5SMark Brown 
668638f85c5SMark Brown 	if (rstate->enabled && rstate->disabled) {
6695da84fd9SJoe Perches 		rdev_err(rdev, "invalid configuration\n");
670638f85c5SMark Brown 		return -EINVAL;
671638f85c5SMark Brown 	}
672638f85c5SMark Brown 
673638f85c5SMark Brown 	if (!can_set_state) {
6745da84fd9SJoe Perches 		rdev_err(rdev, "no way to set suspend state\n");
675414c70cbSLiam Girdwood 		return -EINVAL;
676a5766f11SLiam Girdwood 	}
677414c70cbSLiam Girdwood 
678414c70cbSLiam Girdwood 	if (rstate->enabled)
679414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_enable(rdev);
680414c70cbSLiam Girdwood 	else
681414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_disable(rdev);
682414c70cbSLiam Girdwood 	if (ret < 0) {
6835da84fd9SJoe Perches 		rdev_err(rdev, "failed to enabled/disable\n");
684414c70cbSLiam Girdwood 		return ret;
685414c70cbSLiam Girdwood 	}
686414c70cbSLiam Girdwood 
687414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
688414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
689414c70cbSLiam Girdwood 		if (ret < 0) {
6905da84fd9SJoe Perches 			rdev_err(rdev, "failed to set voltage\n");
691414c70cbSLiam Girdwood 			return ret;
692414c70cbSLiam Girdwood 		}
693414c70cbSLiam Girdwood 	}
694414c70cbSLiam Girdwood 
695414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
696414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
697414c70cbSLiam Girdwood 		if (ret < 0) {
6985da84fd9SJoe Perches 			rdev_err(rdev, "failed to set mode\n");
699414c70cbSLiam Girdwood 			return ret;
700414c70cbSLiam Girdwood 		}
701414c70cbSLiam Girdwood 	}
702414c70cbSLiam Girdwood 	return ret;
703414c70cbSLiam Girdwood }
704414c70cbSLiam Girdwood 
705414c70cbSLiam Girdwood /* locks held by caller */
706414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state)
707414c70cbSLiam Girdwood {
708414c70cbSLiam Girdwood 	if (!rdev->constraints)
709414c70cbSLiam Girdwood 		return -EINVAL;
710414c70cbSLiam Girdwood 
711414c70cbSLiam Girdwood 	switch (state) {
712414c70cbSLiam Girdwood 	case PM_SUSPEND_STANDBY:
713414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
714414c70cbSLiam Girdwood 			&rdev->constraints->state_standby);
715414c70cbSLiam Girdwood 	case PM_SUSPEND_MEM:
716414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
717414c70cbSLiam Girdwood 			&rdev->constraints->state_mem);
718414c70cbSLiam Girdwood 	case PM_SUSPEND_MAX:
719414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
720414c70cbSLiam Girdwood 			&rdev->constraints->state_disk);
721414c70cbSLiam Girdwood 	default:
722414c70cbSLiam Girdwood 		return -EINVAL;
723414c70cbSLiam Girdwood 	}
724414c70cbSLiam Girdwood }
725414c70cbSLiam Girdwood 
726414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev)
727414c70cbSLiam Girdwood {
728414c70cbSLiam Girdwood 	struct regulation_constraints *constraints = rdev->constraints;
729973e9a27SMark Brown 	char buf[80] = "";
7308f031b48SMark Brown 	int count = 0;
7318f031b48SMark Brown 	int ret;
732414c70cbSLiam Girdwood 
7338f031b48SMark Brown 	if (constraints->min_uV && constraints->max_uV) {
734414c70cbSLiam Girdwood 		if (constraints->min_uV == constraints->max_uV)
7358f031b48SMark Brown 			count += sprintf(buf + count, "%d mV ",
736414c70cbSLiam Girdwood 					 constraints->min_uV / 1000);
737414c70cbSLiam Girdwood 		else
7388f031b48SMark Brown 			count += sprintf(buf + count, "%d <--> %d mV ",
739414c70cbSLiam Girdwood 					 constraints->min_uV / 1000,
740414c70cbSLiam Girdwood 					 constraints->max_uV / 1000);
7418f031b48SMark Brown 	}
7428f031b48SMark Brown 
7438f031b48SMark Brown 	if (!constraints->min_uV ||
7448f031b48SMark Brown 	    constraints->min_uV != constraints->max_uV) {
7458f031b48SMark Brown 		ret = _regulator_get_voltage(rdev);
7468f031b48SMark Brown 		if (ret > 0)
7478f031b48SMark Brown 			count += sprintf(buf + count, "at %d mV ", ret / 1000);
7488f031b48SMark Brown 	}
7498f031b48SMark Brown 
750bf5892a8SMark Brown 	if (constraints->uV_offset)
751bf5892a8SMark Brown 		count += sprintf(buf, "%dmV offset ",
752bf5892a8SMark Brown 				 constraints->uV_offset / 1000);
753bf5892a8SMark Brown 
7548f031b48SMark Brown 	if (constraints->min_uA && constraints->max_uA) {
755414c70cbSLiam Girdwood 		if (constraints->min_uA == constraints->max_uA)
7568f031b48SMark Brown 			count += sprintf(buf + count, "%d mA ",
757414c70cbSLiam Girdwood 					 constraints->min_uA / 1000);
758414c70cbSLiam Girdwood 		else
7598f031b48SMark Brown 			count += sprintf(buf + count, "%d <--> %d mA ",
760414c70cbSLiam Girdwood 					 constraints->min_uA / 1000,
761414c70cbSLiam Girdwood 					 constraints->max_uA / 1000);
762414c70cbSLiam Girdwood 	}
7638f031b48SMark Brown 
7648f031b48SMark Brown 	if (!constraints->min_uA ||
7658f031b48SMark Brown 	    constraints->min_uA != constraints->max_uA) {
7668f031b48SMark Brown 		ret = _regulator_get_current_limit(rdev);
7678f031b48SMark Brown 		if (ret > 0)
768e4a6376bSCyril Chemparathy 			count += sprintf(buf + count, "at %d mA ", ret / 1000);
7698f031b48SMark Brown 	}
7708f031b48SMark Brown 
771414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
772414c70cbSLiam Girdwood 		count += sprintf(buf + count, "fast ");
773414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
774414c70cbSLiam Girdwood 		count += sprintf(buf + count, "normal ");
775414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
776414c70cbSLiam Girdwood 		count += sprintf(buf + count, "idle ");
777414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
778414c70cbSLiam Girdwood 		count += sprintf(buf + count, "standby");
779414c70cbSLiam Girdwood 
78013ce29f8SMark Brown 	rdev_info(rdev, "%s\n", buf);
781414c70cbSLiam Girdwood }
782414c70cbSLiam Girdwood 
783e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev,
7841083c393SMark Brown 	struct regulation_constraints *constraints)
785e79055d6SMark Brown {
786e79055d6SMark Brown 	struct regulator_ops *ops = rdev->desc->ops;
787af5866c9SMark Brown 	int ret;
788af5866c9SMark Brown 
789af5866c9SMark Brown 	/* do we need to apply the constraint voltage */
790af5866c9SMark Brown 	if (rdev->constraints->apply_uV &&
79175790251SMark Brown 	    rdev->constraints->min_uV == rdev->constraints->max_uV) {
79275790251SMark Brown 		ret = _regulator_do_set_voltage(rdev,
7933a93f2a9SMark Brown 						rdev->constraints->min_uV,
79475790251SMark Brown 						rdev->constraints->max_uV);
795af5866c9SMark Brown 		if (ret < 0) {
7965da84fd9SJoe Perches 			rdev_err(rdev, "failed to apply %duV constraint\n",
7975da84fd9SJoe Perches 				 rdev->constraints->min_uV);
798af5866c9SMark Brown 			return ret;
799af5866c9SMark Brown 		}
800af5866c9SMark Brown 	}
801e79055d6SMark Brown 
802e79055d6SMark Brown 	/* constrain machine-level voltage specs to fit
803e79055d6SMark Brown 	 * the actual range supported by this regulator.
804e79055d6SMark Brown 	 */
805e79055d6SMark Brown 	if (ops->list_voltage && rdev->desc->n_voltages) {
806e79055d6SMark Brown 		int	count = rdev->desc->n_voltages;
807e79055d6SMark Brown 		int	i;
808e79055d6SMark Brown 		int	min_uV = INT_MAX;
809e79055d6SMark Brown 		int	max_uV = INT_MIN;
810e79055d6SMark Brown 		int	cmin = constraints->min_uV;
811e79055d6SMark Brown 		int	cmax = constraints->max_uV;
812e79055d6SMark Brown 
813e79055d6SMark Brown 		/* it's safe to autoconfigure fixed-voltage supplies
814e79055d6SMark Brown 		   and the constraints are used by list_voltage. */
815e79055d6SMark Brown 		if (count == 1 && !cmin) {
816e79055d6SMark Brown 			cmin = 1;
817e79055d6SMark Brown 			cmax = INT_MAX;
818e79055d6SMark Brown 			constraints->min_uV = cmin;
819e79055d6SMark Brown 			constraints->max_uV = cmax;
820e79055d6SMark Brown 		}
821e79055d6SMark Brown 
822e79055d6SMark Brown 		/* voltage constraints are optional */
823e79055d6SMark Brown 		if ((cmin == 0) && (cmax == 0))
824e79055d6SMark Brown 			return 0;
825e79055d6SMark Brown 
826e79055d6SMark Brown 		/* else require explicit machine-level constraints */
827e79055d6SMark Brown 		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
8285da84fd9SJoe Perches 			rdev_err(rdev, "invalid voltage constraints\n");
829e79055d6SMark Brown 			return -EINVAL;
830e79055d6SMark Brown 		}
831e79055d6SMark Brown 
832e79055d6SMark Brown 		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
833e79055d6SMark Brown 		for (i = 0; i < count; i++) {
834e79055d6SMark Brown 			int	value;
835e79055d6SMark Brown 
836e79055d6SMark Brown 			value = ops->list_voltage(rdev, i);
837e79055d6SMark Brown 			if (value <= 0)
838e79055d6SMark Brown 				continue;
839e79055d6SMark Brown 
840e79055d6SMark Brown 			/* maybe adjust [min_uV..max_uV] */
841e79055d6SMark Brown 			if (value >= cmin && value < min_uV)
842e79055d6SMark Brown 				min_uV = value;
843e79055d6SMark Brown 			if (value <= cmax && value > max_uV)
844e79055d6SMark Brown 				max_uV = value;
845e79055d6SMark Brown 		}
846e79055d6SMark Brown 
847e79055d6SMark Brown 		/* final: [min_uV..max_uV] valid iff constraints valid */
848e79055d6SMark Brown 		if (max_uV < min_uV) {
8495da84fd9SJoe Perches 			rdev_err(rdev, "unsupportable voltage constraints\n");
850e79055d6SMark Brown 			return -EINVAL;
851e79055d6SMark Brown 		}
852e79055d6SMark Brown 
853e79055d6SMark Brown 		/* use regulator's subset of machine constraints */
854e79055d6SMark Brown 		if (constraints->min_uV < min_uV) {
8555da84fd9SJoe Perches 			rdev_dbg(rdev, "override min_uV, %d -> %d\n",
8565da84fd9SJoe Perches 				 constraints->min_uV, min_uV);
857e79055d6SMark Brown 			constraints->min_uV = min_uV;
858e79055d6SMark Brown 		}
859e79055d6SMark Brown 		if (constraints->max_uV > max_uV) {
8605da84fd9SJoe Perches 			rdev_dbg(rdev, "override max_uV, %d -> %d\n",
8615da84fd9SJoe Perches 				 constraints->max_uV, max_uV);
862e79055d6SMark Brown 			constraints->max_uV = max_uV;
863e79055d6SMark Brown 		}
864e79055d6SMark Brown 	}
865e79055d6SMark Brown 
866e79055d6SMark Brown 	return 0;
867e79055d6SMark Brown }
868e79055d6SMark Brown 
869a5766f11SLiam Girdwood /**
870a5766f11SLiam Girdwood  * set_machine_constraints - sets regulator constraints
87169279fb9SMark Brown  * @rdev: regulator source
872c8e7e464SMark Brown  * @constraints: constraints to apply
873a5766f11SLiam Girdwood  *
874a5766f11SLiam Girdwood  * Allows platform initialisation code to define and constrain
875a5766f11SLiam Girdwood  * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
876a5766f11SLiam Girdwood  * Constraints *must* be set by platform code in order for some
877a5766f11SLiam Girdwood  * regulator operations to proceed i.e. set_voltage, set_current_limit,
878a5766f11SLiam Girdwood  * set_mode.
879a5766f11SLiam Girdwood  */
880a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev,
881f8c12fe3SMark Brown 	const struct regulation_constraints *constraints)
882a5766f11SLiam Girdwood {
883a5766f11SLiam Girdwood 	int ret = 0;
884e5fda26cSMark Brown 	struct regulator_ops *ops = rdev->desc->ops;
885e06f5b4fSMark Brown 
886f8c12fe3SMark Brown 	rdev->constraints = kmemdup(constraints, sizeof(*constraints),
887f8c12fe3SMark Brown 				    GFP_KERNEL);
888f8c12fe3SMark Brown 	if (!rdev->constraints)
889f8c12fe3SMark Brown 		return -ENOMEM;
890af5866c9SMark Brown 
891f8c12fe3SMark Brown 	ret = machine_constraints_voltage(rdev, rdev->constraints);
892e79055d6SMark Brown 	if (ret != 0)
8933e2b9abdSMark Brown 		goto out;
8943e2b9abdSMark Brown 
895a5766f11SLiam Girdwood 	/* do we need to setup our suspend state */
896e06f5b4fSMark Brown 	if (constraints->initial_state) {
897f8c12fe3SMark Brown 		ret = suspend_prepare(rdev, rdev->constraints->initial_state);
898e06f5b4fSMark Brown 		if (ret < 0) {
8995da84fd9SJoe Perches 			rdev_err(rdev, "failed to set suspend state\n");
900e06f5b4fSMark Brown 			goto out;
901e06f5b4fSMark Brown 		}
902e06f5b4fSMark Brown 	}
903a5766f11SLiam Girdwood 
904a308466cSMark Brown 	if (constraints->initial_mode) {
905a308466cSMark Brown 		if (!ops->set_mode) {
9065da84fd9SJoe Perches 			rdev_err(rdev, "no set_mode operation\n");
907a308466cSMark Brown 			ret = -EINVAL;
908a308466cSMark Brown 			goto out;
909a308466cSMark Brown 		}
910a308466cSMark Brown 
911f8c12fe3SMark Brown 		ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
912a308466cSMark Brown 		if (ret < 0) {
9135da84fd9SJoe Perches 			rdev_err(rdev, "failed to set initial mode: %d\n", ret);
914a308466cSMark Brown 			goto out;
915a308466cSMark Brown 		}
916a308466cSMark Brown 	}
917a308466cSMark Brown 
918cacf90f2SMark Brown 	/* If the constraints say the regulator should be on at this point
919cacf90f2SMark Brown 	 * and we have control then make sure it is enabled.
920cacf90f2SMark Brown 	 */
921f8c12fe3SMark Brown 	if ((rdev->constraints->always_on || rdev->constraints->boot_on) &&
922f8c12fe3SMark Brown 	    ops->enable) {
923e5fda26cSMark Brown 		ret = ops->enable(rdev);
924e5fda26cSMark Brown 		if (ret < 0) {
9255da84fd9SJoe Perches 			rdev_err(rdev, "failed to enable\n");
926e5fda26cSMark Brown 			goto out;
927e5fda26cSMark Brown 		}
928e5fda26cSMark Brown 	}
929e5fda26cSMark Brown 
930a5766f11SLiam Girdwood 	print_constraints(rdev);
9311a6958e7SAxel Lin 	return 0;
932a5766f11SLiam Girdwood out:
9331a6958e7SAxel Lin 	kfree(rdev->constraints);
9341a6958e7SAxel Lin 	rdev->constraints = NULL;
935a5766f11SLiam Girdwood 	return ret;
936a5766f11SLiam Girdwood }
937a5766f11SLiam Girdwood 
938a5766f11SLiam Girdwood /**
939a5766f11SLiam Girdwood  * set_supply - set regulator supply regulator
94069279fb9SMark Brown  * @rdev: regulator name
94169279fb9SMark Brown  * @supply_rdev: supply regulator name
942a5766f11SLiam Girdwood  *
943a5766f11SLiam Girdwood  * Called by platform initialisation code to set the supply regulator for this
944a5766f11SLiam Girdwood  * regulator. This ensures that a regulators supply will also be enabled by the
945a5766f11SLiam Girdwood  * core if it's child is enabled.
946a5766f11SLiam Girdwood  */
947a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev,
948a5766f11SLiam Girdwood 		      struct regulator_dev *supply_rdev)
949a5766f11SLiam Girdwood {
950a5766f11SLiam Girdwood 	int err;
951a5766f11SLiam Girdwood 
9523801b86aSMark Brown 	rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
9533801b86aSMark Brown 
9543801b86aSMark Brown 	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
9553801b86aSMark Brown 	if (IS_ERR(rdev->supply)) {
9563801b86aSMark Brown 		err = PTR_ERR(rdev->supply);
9573801b86aSMark Brown 		rdev->supply = NULL;
958a5766f11SLiam Girdwood 		return err;
959a5766f11SLiam Girdwood 	}
960a5766f11SLiam Girdwood 
9613801b86aSMark Brown 	return 0;
9623801b86aSMark Brown }
9633801b86aSMark Brown 
964a5766f11SLiam Girdwood /**
96506c63f93SRandy Dunlap  * set_consumer_device_supply - Bind a regulator to a symbolic supply
96669279fb9SMark Brown  * @rdev:         regulator source
96769279fb9SMark Brown  * @consumer_dev: device the supply applies to
96840f9244fSMark Brown  * @consumer_dev_name: dev_name() string for device supply applies to
969a5766f11SLiam Girdwood  * @supply:       symbolic name for supply
970a5766f11SLiam Girdwood  *
971a5766f11SLiam Girdwood  * Allows platform initialisation code to map physical regulator
972a5766f11SLiam Girdwood  * sources to symbolic names for supplies for use by devices.  Devices
973a5766f11SLiam Girdwood  * should use these symbolic names to request regulators, avoiding the
974a5766f11SLiam Girdwood  * need to provide board-specific regulator names as platform data.
97540f9244fSMark Brown  *
97640f9244fSMark Brown  * Only one of consumer_dev and consumer_dev_name may be specified.
977a5766f11SLiam Girdwood  */
978a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev,
97940f9244fSMark Brown 	struct device *consumer_dev, const char *consumer_dev_name,
98040f9244fSMark Brown 	const char *supply)
981a5766f11SLiam Girdwood {
982a5766f11SLiam Girdwood 	struct regulator_map *node;
9839ed2099eSMark Brown 	int has_dev;
984a5766f11SLiam Girdwood 
98540f9244fSMark Brown 	if (consumer_dev && consumer_dev_name)
98640f9244fSMark Brown 		return -EINVAL;
98740f9244fSMark Brown 
98840f9244fSMark Brown 	if (!consumer_dev_name && consumer_dev)
98940f9244fSMark Brown 		consumer_dev_name = dev_name(consumer_dev);
99040f9244fSMark Brown 
991a5766f11SLiam Girdwood 	if (supply == NULL)
992a5766f11SLiam Girdwood 		return -EINVAL;
993a5766f11SLiam Girdwood 
9949ed2099eSMark Brown 	if (consumer_dev_name != NULL)
9959ed2099eSMark Brown 		has_dev = 1;
9969ed2099eSMark Brown 	else
9979ed2099eSMark Brown 		has_dev = 0;
9989ed2099eSMark Brown 
9996001e13cSDavid Brownell 	list_for_each_entry(node, &regulator_map_list, list) {
100023b5cc2aSJani Nikula 		if (node->dev_name && consumer_dev_name) {
100123b5cc2aSJani Nikula 			if (strcmp(node->dev_name, consumer_dev_name) != 0)
10026001e13cSDavid Brownell 				continue;
100323b5cc2aSJani Nikula 		} else if (node->dev_name || consumer_dev_name) {
100423b5cc2aSJani Nikula 			continue;
100523b5cc2aSJani Nikula 		}
100623b5cc2aSJani Nikula 
10076001e13cSDavid Brownell 		if (strcmp(node->supply, supply) != 0)
10086001e13cSDavid Brownell 			continue;
10096001e13cSDavid Brownell 
10106001e13cSDavid Brownell 		dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n",
10116001e13cSDavid Brownell 			dev_name(&node->regulator->dev),
10126001e13cSDavid Brownell 			node->regulator->desc->name,
10136001e13cSDavid Brownell 			supply,
10141083c393SMark Brown 			dev_name(&rdev->dev), rdev_get_name(rdev));
10156001e13cSDavid Brownell 		return -EBUSY;
10166001e13cSDavid Brownell 	}
10176001e13cSDavid Brownell 
10189ed2099eSMark Brown 	node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
1019a5766f11SLiam Girdwood 	if (node == NULL)
1020a5766f11SLiam Girdwood 		return -ENOMEM;
1021a5766f11SLiam Girdwood 
1022a5766f11SLiam Girdwood 	node->regulator = rdev;
1023a5766f11SLiam Girdwood 	node->supply = supply;
1024a5766f11SLiam Girdwood 
10259ed2099eSMark Brown 	if (has_dev) {
10269ed2099eSMark Brown 		node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
102740f9244fSMark Brown 		if (node->dev_name == NULL) {
102840f9244fSMark Brown 			kfree(node);
102940f9244fSMark Brown 			return -ENOMEM;
103040f9244fSMark Brown 		}
10319ed2099eSMark Brown 	}
103240f9244fSMark Brown 
1033a5766f11SLiam Girdwood 	list_add(&node->list, &regulator_map_list);
1034a5766f11SLiam Girdwood 	return 0;
1035a5766f11SLiam Girdwood }
1036a5766f11SLiam Girdwood 
10370f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev)
10380f1d747bSMike Rapoport {
10390f1d747bSMike Rapoport 	struct regulator_map *node, *n;
10400f1d747bSMike Rapoport 
10410f1d747bSMike Rapoport 	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
10420f1d747bSMike Rapoport 		if (rdev == node->regulator) {
10430f1d747bSMike Rapoport 			list_del(&node->list);
104440f9244fSMark Brown 			kfree(node->dev_name);
10450f1d747bSMike Rapoport 			kfree(node);
10460f1d747bSMike Rapoport 		}
10470f1d747bSMike Rapoport 	}
10480f1d747bSMike Rapoport }
10490f1d747bSMike Rapoport 
1050f5726ae3SMark Brown #define REG_STR_SIZE	64
1051414c70cbSLiam Girdwood 
1052414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev,
1053414c70cbSLiam Girdwood 					  struct device *dev,
1054414c70cbSLiam Girdwood 					  const char *supply_name)
1055414c70cbSLiam Girdwood {
1056414c70cbSLiam Girdwood 	struct regulator *regulator;
1057414c70cbSLiam Girdwood 	char buf[REG_STR_SIZE];
1058414c70cbSLiam Girdwood 	int err, size;
1059414c70cbSLiam Girdwood 
1060414c70cbSLiam Girdwood 	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
1061414c70cbSLiam Girdwood 	if (regulator == NULL)
1062414c70cbSLiam Girdwood 		return NULL;
1063414c70cbSLiam Girdwood 
1064414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
1065414c70cbSLiam Girdwood 	regulator->rdev = rdev;
1066414c70cbSLiam Girdwood 	list_add(&regulator->list, &rdev->consumer_list);
1067414c70cbSLiam Girdwood 
1068414c70cbSLiam Girdwood 	if (dev) {
1069414c70cbSLiam Girdwood 		/* create a 'requested_microamps_name' sysfs entry */
1070e0eaedefSMark Brown 		size = scnprintf(buf, REG_STR_SIZE,
1071e0eaedefSMark Brown 				 "microamps_requested_%s-%s",
1072e0eaedefSMark Brown 				 dev_name(dev), supply_name);
1073414c70cbSLiam Girdwood 		if (size >= REG_STR_SIZE)
1074414c70cbSLiam Girdwood 			goto overflow_err;
1075414c70cbSLiam Girdwood 
1076414c70cbSLiam Girdwood 		regulator->dev = dev;
10774f26a2abSAmeya Palande 		sysfs_attr_init(&regulator->dev_attr.attr);
1078414c70cbSLiam Girdwood 		regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
1079414c70cbSLiam Girdwood 		if (regulator->dev_attr.attr.name == NULL)
1080414c70cbSLiam Girdwood 			goto attr_name_err;
1081414c70cbSLiam Girdwood 
1082414c70cbSLiam Girdwood 		regulator->dev_attr.attr.mode = 0444;
1083414c70cbSLiam Girdwood 		regulator->dev_attr.show = device_requested_uA_show;
1084414c70cbSLiam Girdwood 		err = device_create_file(dev, &regulator->dev_attr);
1085414c70cbSLiam Girdwood 		if (err < 0) {
10865da84fd9SJoe Perches 			rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
1087414c70cbSLiam Girdwood 			goto attr_name_err;
1088414c70cbSLiam Girdwood 		}
1089414c70cbSLiam Girdwood 
1090414c70cbSLiam Girdwood 		/* also add a link to the device sysfs entry */
1091414c70cbSLiam Girdwood 		size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
1092414c70cbSLiam Girdwood 				 dev->kobj.name, supply_name);
1093414c70cbSLiam Girdwood 		if (size >= REG_STR_SIZE)
1094414c70cbSLiam Girdwood 			goto attr_err;
1095414c70cbSLiam Girdwood 
1096414c70cbSLiam Girdwood 		regulator->supply_name = kstrdup(buf, GFP_KERNEL);
1097414c70cbSLiam Girdwood 		if (regulator->supply_name == NULL)
1098414c70cbSLiam Girdwood 			goto attr_err;
1099414c70cbSLiam Girdwood 
1100414c70cbSLiam Girdwood 		err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
1101414c70cbSLiam Girdwood 					buf);
1102414c70cbSLiam Girdwood 		if (err) {
11035da84fd9SJoe Perches 			rdev_warn(rdev, "could not add device link %s err %d\n",
11041d7372e1SDaniel Walker 				  dev->kobj.name, err);
1105414c70cbSLiam Girdwood 			goto link_name_err;
1106414c70cbSLiam Girdwood 		}
11075de70519SMark Brown 	} else {
11085de70519SMark Brown 		regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
11095de70519SMark Brown 		if (regulator->supply_name == NULL)
11105de70519SMark Brown 			goto attr_err;
1111414c70cbSLiam Girdwood 	}
11125de70519SMark Brown 
11135de70519SMark Brown #ifdef CONFIG_DEBUG_FS
11145de70519SMark Brown 	regulator->debugfs = debugfs_create_dir(regulator->supply_name,
11155de70519SMark Brown 						rdev->debugfs);
11165de70519SMark Brown 	if (IS_ERR_OR_NULL(regulator->debugfs)) {
11175de70519SMark Brown 		rdev_warn(rdev, "Failed to create debugfs directory\n");
11185de70519SMark Brown 		regulator->debugfs = NULL;
11195de70519SMark Brown 	} else {
11205de70519SMark Brown 		debugfs_create_u32("uA_load", 0444, regulator->debugfs,
11215de70519SMark Brown 				   &regulator->uA_load);
11225de70519SMark Brown 		debugfs_create_u32("min_uV", 0444, regulator->debugfs,
11235de70519SMark Brown 				   &regulator->min_uV);
11245de70519SMark Brown 		debugfs_create_u32("max_uV", 0444, regulator->debugfs,
11255de70519SMark Brown 				   &regulator->max_uV);
11265de70519SMark Brown 	}
11275de70519SMark Brown #endif
11285de70519SMark Brown 
1129414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1130414c70cbSLiam Girdwood 	return regulator;
1131414c70cbSLiam Girdwood link_name_err:
1132414c70cbSLiam Girdwood 	kfree(regulator->supply_name);
1133414c70cbSLiam Girdwood attr_err:
1134414c70cbSLiam Girdwood 	device_remove_file(regulator->dev, &regulator->dev_attr);
1135414c70cbSLiam Girdwood attr_name_err:
1136414c70cbSLiam Girdwood 	kfree(regulator->dev_attr.attr.name);
1137414c70cbSLiam Girdwood overflow_err:
1138414c70cbSLiam Girdwood 	list_del(&regulator->list);
1139414c70cbSLiam Girdwood 	kfree(regulator);
1140414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1141414c70cbSLiam Girdwood 	return NULL;
1142414c70cbSLiam Girdwood }
1143414c70cbSLiam Girdwood 
114431aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev)
114531aae2beSMark Brown {
114631aae2beSMark Brown 	if (!rdev->desc->ops->enable_time)
114731aae2beSMark Brown 		return 0;
114831aae2beSMark Brown 	return rdev->desc->ops->enable_time(rdev);
114931aae2beSMark Brown }
115031aae2beSMark Brown 
11515ffbd136SMark Brown /* Internal regulator request function */
11525ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id,
11535ffbd136SMark Brown 					int exclusive)
1154414c70cbSLiam Girdwood {
1155414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
1156414c70cbSLiam Girdwood 	struct regulator_map *map;
1157414c70cbSLiam Girdwood 	struct regulator *regulator = ERR_PTR(-ENODEV);
115840f9244fSMark Brown 	const char *devname = NULL;
11595ffbd136SMark Brown 	int ret;
1160414c70cbSLiam Girdwood 
1161414c70cbSLiam Girdwood 	if (id == NULL) {
11625da84fd9SJoe Perches 		pr_err("get() with no identifier\n");
1163414c70cbSLiam Girdwood 		return regulator;
1164414c70cbSLiam Girdwood 	}
1165414c70cbSLiam Girdwood 
116640f9244fSMark Brown 	if (dev)
116740f9244fSMark Brown 		devname = dev_name(dev);
116840f9244fSMark Brown 
1169414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
1170414c70cbSLiam Girdwood 
1171414c70cbSLiam Girdwood 	list_for_each_entry(map, &regulator_map_list, list) {
117240f9244fSMark Brown 		/* If the mapping has a device set up it must match */
117340f9244fSMark Brown 		if (map->dev_name &&
117440f9244fSMark Brown 		    (!devname || strcmp(map->dev_name, devname)))
117540f9244fSMark Brown 			continue;
117640f9244fSMark Brown 
117740f9244fSMark Brown 		if (strcmp(map->supply, id) == 0) {
1178a5766f11SLiam Girdwood 			rdev = map->regulator;
1179414c70cbSLiam Girdwood 			goto found;
1180414c70cbSLiam Girdwood 		}
1181a5766f11SLiam Girdwood 	}
118234abbd68SMark Brown 
1183688fe99aSMark Brown 	if (board_wants_dummy_regulator) {
1184688fe99aSMark Brown 		rdev = dummy_regulator_rdev;
1185688fe99aSMark Brown 		goto found;
1186688fe99aSMark Brown 	}
1187688fe99aSMark Brown 
118834abbd68SMark Brown #ifdef CONFIG_REGULATOR_DUMMY
118934abbd68SMark Brown 	if (!devname)
119034abbd68SMark Brown 		devname = "deviceless";
119134abbd68SMark Brown 
119234abbd68SMark Brown 	/* If the board didn't flag that it was fully constrained then
119334abbd68SMark Brown 	 * substitute in a dummy regulator so consumers can continue.
119434abbd68SMark Brown 	 */
119534abbd68SMark Brown 	if (!has_full_constraints) {
11965da84fd9SJoe Perches 		pr_warn("%s supply %s not found, using dummy regulator\n",
119734abbd68SMark Brown 			devname, id);
119834abbd68SMark Brown 		rdev = dummy_regulator_rdev;
119934abbd68SMark Brown 		goto found;
120034abbd68SMark Brown 	}
120134abbd68SMark Brown #endif
120234abbd68SMark Brown 
1203414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
1204414c70cbSLiam Girdwood 	return regulator;
1205414c70cbSLiam Girdwood 
1206414c70cbSLiam Girdwood found:
12075ffbd136SMark Brown 	if (rdev->exclusive) {
12085ffbd136SMark Brown 		regulator = ERR_PTR(-EPERM);
12095ffbd136SMark Brown 		goto out;
12105ffbd136SMark Brown 	}
12115ffbd136SMark Brown 
12125ffbd136SMark Brown 	if (exclusive && rdev->open_count) {
12135ffbd136SMark Brown 		regulator = ERR_PTR(-EBUSY);
12145ffbd136SMark Brown 		goto out;
12155ffbd136SMark Brown 	}
12165ffbd136SMark Brown 
1217a5766f11SLiam Girdwood 	if (!try_module_get(rdev->owner))
1218a5766f11SLiam Girdwood 		goto out;
1219a5766f11SLiam Girdwood 
1220414c70cbSLiam Girdwood 	regulator = create_regulator(rdev, dev, id);
1221414c70cbSLiam Girdwood 	if (regulator == NULL) {
1222414c70cbSLiam Girdwood 		regulator = ERR_PTR(-ENOMEM);
1223414c70cbSLiam Girdwood 		module_put(rdev->owner);
1224414c70cbSLiam Girdwood 	}
1225414c70cbSLiam Girdwood 
12265ffbd136SMark Brown 	rdev->open_count++;
12275ffbd136SMark Brown 	if (exclusive) {
12285ffbd136SMark Brown 		rdev->exclusive = 1;
12295ffbd136SMark Brown 
12305ffbd136SMark Brown 		ret = _regulator_is_enabled(rdev);
12315ffbd136SMark Brown 		if (ret > 0)
12325ffbd136SMark Brown 			rdev->use_count = 1;
12335ffbd136SMark Brown 		else
12345ffbd136SMark Brown 			rdev->use_count = 0;
12355ffbd136SMark Brown 	}
12365ffbd136SMark Brown 
1237a5766f11SLiam Girdwood out:
1238414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
12395ffbd136SMark Brown 
1240414c70cbSLiam Girdwood 	return regulator;
1241414c70cbSLiam Girdwood }
12425ffbd136SMark Brown 
12435ffbd136SMark Brown /**
12445ffbd136SMark Brown  * regulator_get - lookup and obtain a reference to a regulator.
12455ffbd136SMark Brown  * @dev: device for regulator "consumer"
12465ffbd136SMark Brown  * @id: Supply name or regulator ID.
12475ffbd136SMark Brown  *
12485ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
12495ffbd136SMark Brown  * or IS_ERR() condition containing errno.
12505ffbd136SMark Brown  *
12515ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
12525ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
12535ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
12545ffbd136SMark Brown  * device pins in the datasheet.
12555ffbd136SMark Brown  */
12565ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id)
12575ffbd136SMark Brown {
12585ffbd136SMark Brown 	return _regulator_get(dev, id, 0);
12595ffbd136SMark Brown }
1260414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get);
1261414c70cbSLiam Girdwood 
1262414c70cbSLiam Girdwood /**
12635ffbd136SMark Brown  * regulator_get_exclusive - obtain exclusive access to a regulator.
12645ffbd136SMark Brown  * @dev: device for regulator "consumer"
12655ffbd136SMark Brown  * @id: Supply name or regulator ID.
12665ffbd136SMark Brown  *
12675ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
12685ffbd136SMark Brown  * or IS_ERR() condition containing errno.  Other consumers will be
12695ffbd136SMark Brown  * unable to obtain this reference is held and the use count for the
12705ffbd136SMark Brown  * regulator will be initialised to reflect the current state of the
12715ffbd136SMark Brown  * regulator.
12725ffbd136SMark Brown  *
12735ffbd136SMark Brown  * This is intended for use by consumers which cannot tolerate shared
12745ffbd136SMark Brown  * use of the regulator such as those which need to force the
12755ffbd136SMark Brown  * regulator off for correct operation of the hardware they are
12765ffbd136SMark Brown  * controlling.
12775ffbd136SMark Brown  *
12785ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
12795ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
12805ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
12815ffbd136SMark Brown  * device pins in the datasheet.
12825ffbd136SMark Brown  */
12835ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
12845ffbd136SMark Brown {
12855ffbd136SMark Brown 	return _regulator_get(dev, id, 1);
12865ffbd136SMark Brown }
12875ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive);
12885ffbd136SMark Brown 
12895ffbd136SMark Brown /**
1290414c70cbSLiam Girdwood  * regulator_put - "free" the regulator source
1291414c70cbSLiam Girdwood  * @regulator: regulator source
1292414c70cbSLiam Girdwood  *
1293414c70cbSLiam Girdwood  * Note: drivers must ensure that all regulator_enable calls made on this
1294414c70cbSLiam Girdwood  * regulator source are balanced by regulator_disable calls prior to calling
1295414c70cbSLiam Girdwood  * this function.
1296414c70cbSLiam Girdwood  */
1297414c70cbSLiam Girdwood void regulator_put(struct regulator *regulator)
1298414c70cbSLiam Girdwood {
1299414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
1300414c70cbSLiam Girdwood 
1301414c70cbSLiam Girdwood 	if (regulator == NULL || IS_ERR(regulator))
1302414c70cbSLiam Girdwood 		return;
1303414c70cbSLiam Girdwood 
1304414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
1305414c70cbSLiam Girdwood 	rdev = regulator->rdev;
1306414c70cbSLiam Girdwood 
13075de70519SMark Brown #ifdef CONFIG_DEBUG_FS
13085de70519SMark Brown 	debugfs_remove_recursive(regulator->debugfs);
13095de70519SMark Brown #endif
13105de70519SMark Brown 
1311414c70cbSLiam Girdwood 	/* remove any sysfs entries */
1312414c70cbSLiam Girdwood 	if (regulator->dev) {
1313414c70cbSLiam Girdwood 		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
1314414c70cbSLiam Girdwood 		device_remove_file(regulator->dev, &regulator->dev_attr);
1315414c70cbSLiam Girdwood 		kfree(regulator->dev_attr.attr.name);
1316414c70cbSLiam Girdwood 	}
13175de70519SMark Brown 	kfree(regulator->supply_name);
1318414c70cbSLiam Girdwood 	list_del(&regulator->list);
1319414c70cbSLiam Girdwood 	kfree(regulator);
1320414c70cbSLiam Girdwood 
13215ffbd136SMark Brown 	rdev->open_count--;
13225ffbd136SMark Brown 	rdev->exclusive = 0;
13235ffbd136SMark Brown 
1324414c70cbSLiam Girdwood 	module_put(rdev->owner);
1325414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
1326414c70cbSLiam Girdwood }
1327414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put);
1328414c70cbSLiam Girdwood 
13299a2372faSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev)
13309a2372faSMark Brown {
13319a2372faSMark Brown 	if (!rdev->constraints)
13329a2372faSMark Brown 		return 0;
13339a2372faSMark Brown 
13349a2372faSMark Brown 	if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
13359a2372faSMark Brown 		return 1;
13369a2372faSMark Brown 	else
13379a2372faSMark Brown 		return 0;
13389a2372faSMark Brown }
13399a2372faSMark Brown 
1340414c70cbSLiam Girdwood /* locks held by regulator_enable() */
1341414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev)
1342414c70cbSLiam Girdwood {
134331aae2beSMark Brown 	int ret, delay;
1344414c70cbSLiam Girdwood 
1345414c70cbSLiam Girdwood 	/* check voltage and requested load before enabling */
1346414c70cbSLiam Girdwood 	if (rdev->constraints &&
13479a2372faSMark Brown 	    (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
1348414c70cbSLiam Girdwood 		drms_uA_update(rdev);
1349414c70cbSLiam Girdwood 
13509a2372faSMark Brown 	if (rdev->use_count == 0) {
13519a2372faSMark Brown 		/* The regulator may on if it's not switchable or left on */
13529a2372faSMark Brown 		ret = _regulator_is_enabled(rdev);
13539a2372faSMark Brown 		if (ret == -EINVAL || ret == 0) {
13549a2372faSMark Brown 			if (!_regulator_can_change_status(rdev))
13559a2372faSMark Brown 				return -EPERM;
13569a2372faSMark Brown 
135731aae2beSMark Brown 			if (!rdev->desc->ops->enable)
135831aae2beSMark Brown 				return -EINVAL;
135931aae2beSMark Brown 
136031aae2beSMark Brown 			/* Query before enabling in case configuration
136125985edcSLucas De Marchi 			 * dependent.  */
136231aae2beSMark Brown 			ret = _regulator_get_enable_time(rdev);
136331aae2beSMark Brown 			if (ret >= 0) {
136431aae2beSMark Brown 				delay = ret;
136531aae2beSMark Brown 			} else {
13665da84fd9SJoe Perches 				rdev_warn(rdev, "enable_time() failed: %d\n",
136731aae2beSMark Brown 					   ret);
136831aae2beSMark Brown 				delay = 0;
136931aae2beSMark Brown 			}
137031aae2beSMark Brown 
137102fa3ec0SMark Brown 			trace_regulator_enable(rdev_get_name(rdev));
137202fa3ec0SMark Brown 
137331aae2beSMark Brown 			/* Allow the regulator to ramp; it would be useful
137431aae2beSMark Brown 			 * to extend this for bulk operations so that the
137531aae2beSMark Brown 			 * regulators can ramp together.  */
1376414c70cbSLiam Girdwood 			ret = rdev->desc->ops->enable(rdev);
13779a2372faSMark Brown 			if (ret < 0)
13789a2372faSMark Brown 				return ret;
137931aae2beSMark Brown 
138002fa3ec0SMark Brown 			trace_regulator_enable_delay(rdev_get_name(rdev));
138102fa3ec0SMark Brown 
1382e36c1df8SAxel Lin 			if (delay >= 1000) {
138331aae2beSMark Brown 				mdelay(delay / 1000);
1384e36c1df8SAxel Lin 				udelay(delay % 1000);
1385e36c1df8SAxel Lin 			} else if (delay) {
138631aae2beSMark Brown 				udelay(delay);
1387e36c1df8SAxel Lin 			}
138831aae2beSMark Brown 
138902fa3ec0SMark Brown 			trace_regulator_enable_complete(rdev_get_name(rdev));
139002fa3ec0SMark Brown 
1391a7433cffSLinus Walleij 		} else if (ret < 0) {
13925da84fd9SJoe Perches 			rdev_err(rdev, "is_enabled() failed: %d\n", ret);
1393414c70cbSLiam Girdwood 			return ret;
1394414c70cbSLiam Girdwood 		}
1395a7433cffSLinus Walleij 		/* Fallthrough on positive return values - already enabled */
1396414c70cbSLiam Girdwood 	}
1397414c70cbSLiam Girdwood 
13989a2372faSMark Brown 	rdev->use_count++;
13999a2372faSMark Brown 
14009a2372faSMark Brown 	return 0;
1401414c70cbSLiam Girdwood }
1402414c70cbSLiam Girdwood 
1403414c70cbSLiam Girdwood /**
1404414c70cbSLiam Girdwood  * regulator_enable - enable regulator output
1405414c70cbSLiam Girdwood  * @regulator: regulator source
1406414c70cbSLiam Girdwood  *
1407cf7bbcdfSMark Brown  * Request that the regulator be enabled with the regulator output at
1408cf7bbcdfSMark Brown  * the predefined voltage or current value.  Calls to regulator_enable()
1409cf7bbcdfSMark Brown  * must be balanced with calls to regulator_disable().
1410cf7bbcdfSMark Brown  *
1411414c70cbSLiam Girdwood  * NOTE: the output value can be set by other drivers, boot loader or may be
1412cf7bbcdfSMark Brown  * hardwired in the regulator.
1413414c70cbSLiam Girdwood  */
1414414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator)
1415414c70cbSLiam Girdwood {
1416412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
1417412aec61SDavid Brownell 	int ret = 0;
1418414c70cbSLiam Girdwood 
14193801b86aSMark Brown 	if (rdev->supply) {
14203801b86aSMark Brown 		ret = regulator_enable(rdev->supply);
14213801b86aSMark Brown 		if (ret != 0)
14223801b86aSMark Brown 			return ret;
14233801b86aSMark Brown 	}
14243801b86aSMark Brown 
1425412aec61SDavid Brownell 	mutex_lock(&rdev->mutex);
1426412aec61SDavid Brownell 	ret = _regulator_enable(rdev);
1427412aec61SDavid Brownell 	mutex_unlock(&rdev->mutex);
14283801b86aSMark Brown 
1429d1685e4eSHeiko Stübner 	if (ret != 0 && rdev->supply)
14303801b86aSMark Brown 		regulator_disable(rdev->supply);
14313801b86aSMark Brown 
1432414c70cbSLiam Girdwood 	return ret;
1433414c70cbSLiam Girdwood }
1434414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable);
1435414c70cbSLiam Girdwood 
1436414c70cbSLiam Girdwood /* locks held by regulator_disable() */
14373801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev)
1438414c70cbSLiam Girdwood {
1439414c70cbSLiam Girdwood 	int ret = 0;
1440414c70cbSLiam Girdwood 
1441cd94b505SDavid Brownell 	if (WARN(rdev->use_count <= 0,
144243e7ee33SJoe Perches 		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
1443cd94b505SDavid Brownell 		return -EIO;
1444cd94b505SDavid Brownell 
1445414c70cbSLiam Girdwood 	/* are we the last user and permitted to disable ? */
144660ef66fcSMark Brown 	if (rdev->use_count == 1 &&
144760ef66fcSMark Brown 	    (rdev->constraints && !rdev->constraints->always_on)) {
1448414c70cbSLiam Girdwood 
1449414c70cbSLiam Girdwood 		/* we are last user */
14509a2372faSMark Brown 		if (_regulator_can_change_status(rdev) &&
14519a2372faSMark Brown 		    rdev->desc->ops->disable) {
145202fa3ec0SMark Brown 			trace_regulator_disable(rdev_get_name(rdev));
145302fa3ec0SMark Brown 
1454414c70cbSLiam Girdwood 			ret = rdev->desc->ops->disable(rdev);
1455414c70cbSLiam Girdwood 			if (ret < 0) {
14565da84fd9SJoe Perches 				rdev_err(rdev, "failed to disable\n");
1457414c70cbSLiam Girdwood 				return ret;
1458414c70cbSLiam Girdwood 			}
145984b68263SMark Brown 
146002fa3ec0SMark Brown 			trace_regulator_disable_complete(rdev_get_name(rdev));
146102fa3ec0SMark Brown 
146284b68263SMark Brown 			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
146384b68263SMark Brown 					     NULL);
1464414c70cbSLiam Girdwood 		}
1465414c70cbSLiam Girdwood 
1466414c70cbSLiam Girdwood 		rdev->use_count = 0;
1467414c70cbSLiam Girdwood 	} else if (rdev->use_count > 1) {
1468414c70cbSLiam Girdwood 
1469414c70cbSLiam Girdwood 		if (rdev->constraints &&
1470414c70cbSLiam Girdwood 			(rdev->constraints->valid_ops_mask &
1471414c70cbSLiam Girdwood 			REGULATOR_CHANGE_DRMS))
1472414c70cbSLiam Girdwood 			drms_uA_update(rdev);
1473414c70cbSLiam Girdwood 
1474414c70cbSLiam Girdwood 		rdev->use_count--;
1475414c70cbSLiam Girdwood 	}
14763801b86aSMark Brown 
1477414c70cbSLiam Girdwood 	return ret;
1478414c70cbSLiam Girdwood }
1479414c70cbSLiam Girdwood 
1480414c70cbSLiam Girdwood /**
1481414c70cbSLiam Girdwood  * regulator_disable - disable regulator output
1482414c70cbSLiam Girdwood  * @regulator: regulator source
1483414c70cbSLiam Girdwood  *
1484cf7bbcdfSMark Brown  * Disable the regulator output voltage or current.  Calls to
1485cf7bbcdfSMark Brown  * regulator_enable() must be balanced with calls to
1486cf7bbcdfSMark Brown  * regulator_disable().
148769279fb9SMark Brown  *
1488414c70cbSLiam Girdwood  * NOTE: this will only disable the regulator output if no other consumer
1489cf7bbcdfSMark Brown  * devices have it enabled, the regulator device supports disabling and
1490cf7bbcdfSMark Brown  * machine constraints permit this operation.
1491414c70cbSLiam Girdwood  */
1492414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator)
1493414c70cbSLiam Girdwood {
1494412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
1495412aec61SDavid Brownell 	int ret = 0;
1496414c70cbSLiam Girdwood 
1497412aec61SDavid Brownell 	mutex_lock(&rdev->mutex);
14983801b86aSMark Brown 	ret = _regulator_disable(rdev);
1499412aec61SDavid Brownell 	mutex_unlock(&rdev->mutex);
15008cbf811dSJeffrey Carlyle 
15013801b86aSMark Brown 	if (ret == 0 && rdev->supply)
15023801b86aSMark Brown 		regulator_disable(rdev->supply);
15038cbf811dSJeffrey Carlyle 
1504414c70cbSLiam Girdwood 	return ret;
1505414c70cbSLiam Girdwood }
1506414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable);
1507414c70cbSLiam Girdwood 
1508414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */
15093801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev)
1510414c70cbSLiam Girdwood {
1511414c70cbSLiam Girdwood 	int ret = 0;
1512414c70cbSLiam Girdwood 
1513414c70cbSLiam Girdwood 	/* force disable */
1514414c70cbSLiam Girdwood 	if (rdev->desc->ops->disable) {
1515414c70cbSLiam Girdwood 		/* ah well, who wants to live forever... */
1516414c70cbSLiam Girdwood 		ret = rdev->desc->ops->disable(rdev);
1517414c70cbSLiam Girdwood 		if (ret < 0) {
15185da84fd9SJoe Perches 			rdev_err(rdev, "failed to force disable\n");
1519414c70cbSLiam Girdwood 			return ret;
1520414c70cbSLiam Girdwood 		}
1521414c70cbSLiam Girdwood 		/* notify other consumers that power has been forced off */
152284b68263SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
152384b68263SMark Brown 			REGULATOR_EVENT_DISABLE, NULL);
1524414c70cbSLiam Girdwood 	}
1525414c70cbSLiam Girdwood 
1526414c70cbSLiam Girdwood 	return ret;
1527414c70cbSLiam Girdwood }
1528414c70cbSLiam Girdwood 
1529414c70cbSLiam Girdwood /**
1530414c70cbSLiam Girdwood  * regulator_force_disable - force disable regulator output
1531414c70cbSLiam Girdwood  * @regulator: regulator source
1532414c70cbSLiam Girdwood  *
1533414c70cbSLiam Girdwood  * Forcibly disable the regulator output voltage or current.
1534414c70cbSLiam Girdwood  * NOTE: this *will* disable the regulator output even if other consumer
1535414c70cbSLiam Girdwood  * devices have it enabled. This should be used for situations when device
1536414c70cbSLiam Girdwood  * damage will likely occur if the regulator is not disabled (e.g. over temp).
1537414c70cbSLiam Girdwood  */
1538414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator)
1539414c70cbSLiam Girdwood {
154082d15839SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
1541414c70cbSLiam Girdwood 	int ret;
1542414c70cbSLiam Girdwood 
154382d15839SMark Brown 	mutex_lock(&rdev->mutex);
1544414c70cbSLiam Girdwood 	regulator->uA_load = 0;
15453801b86aSMark Brown 	ret = _regulator_force_disable(regulator->rdev);
154682d15839SMark Brown 	mutex_unlock(&rdev->mutex);
15478cbf811dSJeffrey Carlyle 
15483801b86aSMark Brown 	if (rdev->supply)
15493801b86aSMark Brown 		while (rdev->open_count--)
15503801b86aSMark Brown 			regulator_disable(rdev->supply);
15518cbf811dSJeffrey Carlyle 
1552414c70cbSLiam Girdwood 	return ret;
1553414c70cbSLiam Girdwood }
1554414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable);
1555414c70cbSLiam Girdwood 
1556da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work)
1557da07ecd9SMark Brown {
1558da07ecd9SMark Brown 	struct regulator_dev *rdev = container_of(work, struct regulator_dev,
1559da07ecd9SMark Brown 						  disable_work.work);
1560da07ecd9SMark Brown 	int count, i, ret;
1561da07ecd9SMark Brown 
1562da07ecd9SMark Brown 	mutex_lock(&rdev->mutex);
1563da07ecd9SMark Brown 
1564da07ecd9SMark Brown 	BUG_ON(!rdev->deferred_disables);
1565da07ecd9SMark Brown 
1566da07ecd9SMark Brown 	count = rdev->deferred_disables;
1567da07ecd9SMark Brown 	rdev->deferred_disables = 0;
1568da07ecd9SMark Brown 
1569da07ecd9SMark Brown 	for (i = 0; i < count; i++) {
1570da07ecd9SMark Brown 		ret = _regulator_disable(rdev);
1571da07ecd9SMark Brown 		if (ret != 0)
1572da07ecd9SMark Brown 			rdev_err(rdev, "Deferred disable failed: %d\n", ret);
1573da07ecd9SMark Brown 	}
1574da07ecd9SMark Brown 
1575da07ecd9SMark Brown 	mutex_unlock(&rdev->mutex);
1576da07ecd9SMark Brown 
1577da07ecd9SMark Brown 	if (rdev->supply) {
1578da07ecd9SMark Brown 		for (i = 0; i < count; i++) {
1579da07ecd9SMark Brown 			ret = regulator_disable(rdev->supply);
1580da07ecd9SMark Brown 			if (ret != 0) {
1581da07ecd9SMark Brown 				rdev_err(rdev,
1582da07ecd9SMark Brown 					 "Supply disable failed: %d\n", ret);
1583da07ecd9SMark Brown 			}
1584da07ecd9SMark Brown 		}
1585da07ecd9SMark Brown 	}
1586da07ecd9SMark Brown }
1587da07ecd9SMark Brown 
1588da07ecd9SMark Brown /**
1589da07ecd9SMark Brown  * regulator_disable_deferred - disable regulator output with delay
1590da07ecd9SMark Brown  * @regulator: regulator source
1591da07ecd9SMark Brown  * @ms: miliseconds until the regulator is disabled
1592da07ecd9SMark Brown  *
1593da07ecd9SMark Brown  * Execute regulator_disable() on the regulator after a delay.  This
1594da07ecd9SMark Brown  * is intended for use with devices that require some time to quiesce.
1595da07ecd9SMark Brown  *
1596da07ecd9SMark Brown  * NOTE: this will only disable the regulator output if no other consumer
1597da07ecd9SMark Brown  * devices have it enabled, the regulator device supports disabling and
1598da07ecd9SMark Brown  * machine constraints permit this operation.
1599da07ecd9SMark Brown  */
1600da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms)
1601da07ecd9SMark Brown {
1602da07ecd9SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
1603aa59802dSMark Brown 	int ret;
1604da07ecd9SMark Brown 
1605da07ecd9SMark Brown 	mutex_lock(&rdev->mutex);
1606da07ecd9SMark Brown 	rdev->deferred_disables++;
1607da07ecd9SMark Brown 	mutex_unlock(&rdev->mutex);
1608da07ecd9SMark Brown 
1609aa59802dSMark Brown 	ret = schedule_delayed_work(&rdev->disable_work,
1610da07ecd9SMark Brown 				    msecs_to_jiffies(ms));
1611aa59802dSMark Brown 	if (ret < 0)
1612aa59802dSMark Brown 		return ret;
1613aa59802dSMark Brown 	else
1614aa59802dSMark Brown 		return 0;
1615da07ecd9SMark Brown }
1616da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred);
1617da07ecd9SMark Brown 
1618414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev)
1619414c70cbSLiam Girdwood {
16209a7f6a4cSMark Brown 	/* If we don't know then assume that the regulator is always on */
16219332546fSMark Brown 	if (!rdev->desc->ops->is_enabled)
16229a7f6a4cSMark Brown 		return 1;
1623414c70cbSLiam Girdwood 
16249332546fSMark Brown 	return rdev->desc->ops->is_enabled(rdev);
1625414c70cbSLiam Girdwood }
1626414c70cbSLiam Girdwood 
1627414c70cbSLiam Girdwood /**
1628414c70cbSLiam Girdwood  * regulator_is_enabled - is the regulator output enabled
1629414c70cbSLiam Girdwood  * @regulator: regulator source
1630414c70cbSLiam Girdwood  *
1631412aec61SDavid Brownell  * Returns positive if the regulator driver backing the source/client
1632412aec61SDavid Brownell  * has requested that the device be enabled, zero if it hasn't, else a
1633412aec61SDavid Brownell  * negative errno code.
1634412aec61SDavid Brownell  *
1635412aec61SDavid Brownell  * Note that the device backing this regulator handle can have multiple
1636412aec61SDavid Brownell  * users, so it might be enabled even if regulator_enable() was never
1637412aec61SDavid Brownell  * called for this particular source.
1638414c70cbSLiam Girdwood  */
1639414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator)
1640414c70cbSLiam Girdwood {
16419332546fSMark Brown 	int ret;
16429332546fSMark Brown 
16439332546fSMark Brown 	mutex_lock(&regulator->rdev->mutex);
16449332546fSMark Brown 	ret = _regulator_is_enabled(regulator->rdev);
16459332546fSMark Brown 	mutex_unlock(&regulator->rdev->mutex);
16469332546fSMark Brown 
16479332546fSMark Brown 	return ret;
1648414c70cbSLiam Girdwood }
1649414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled);
1650414c70cbSLiam Girdwood 
1651414c70cbSLiam Girdwood /**
16524367cfdcSDavid Brownell  * regulator_count_voltages - count regulator_list_voltage() selectors
16534367cfdcSDavid Brownell  * @regulator: regulator source
16544367cfdcSDavid Brownell  *
16554367cfdcSDavid Brownell  * Returns number of selectors, or negative errno.  Selectors are
16564367cfdcSDavid Brownell  * numbered starting at zero, and typically correspond to bitfields
16574367cfdcSDavid Brownell  * in hardware registers.
16584367cfdcSDavid Brownell  */
16594367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator)
16604367cfdcSDavid Brownell {
16614367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
16624367cfdcSDavid Brownell 
16634367cfdcSDavid Brownell 	return rdev->desc->n_voltages ? : -EINVAL;
16644367cfdcSDavid Brownell }
16654367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages);
16664367cfdcSDavid Brownell 
16674367cfdcSDavid Brownell /**
16684367cfdcSDavid Brownell  * regulator_list_voltage - enumerate supported voltages
16694367cfdcSDavid Brownell  * @regulator: regulator source
16704367cfdcSDavid Brownell  * @selector: identify voltage to list
16714367cfdcSDavid Brownell  * Context: can sleep
16724367cfdcSDavid Brownell  *
16734367cfdcSDavid Brownell  * Returns a voltage that can be passed to @regulator_set_voltage(),
167488393161SThomas Weber  * zero if this selector code can't be used on this system, or a
16754367cfdcSDavid Brownell  * negative errno.
16764367cfdcSDavid Brownell  */
16774367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector)
16784367cfdcSDavid Brownell {
16794367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
16804367cfdcSDavid Brownell 	struct regulator_ops	*ops = rdev->desc->ops;
16814367cfdcSDavid Brownell 	int			ret;
16824367cfdcSDavid Brownell 
16834367cfdcSDavid Brownell 	if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
16844367cfdcSDavid Brownell 		return -EINVAL;
16854367cfdcSDavid Brownell 
16864367cfdcSDavid Brownell 	mutex_lock(&rdev->mutex);
16874367cfdcSDavid Brownell 	ret = ops->list_voltage(rdev, selector);
16884367cfdcSDavid Brownell 	mutex_unlock(&rdev->mutex);
16894367cfdcSDavid Brownell 
16904367cfdcSDavid Brownell 	if (ret > 0) {
16914367cfdcSDavid Brownell 		if (ret < rdev->constraints->min_uV)
16924367cfdcSDavid Brownell 			ret = 0;
16934367cfdcSDavid Brownell 		else if (ret > rdev->constraints->max_uV)
16944367cfdcSDavid Brownell 			ret = 0;
16954367cfdcSDavid Brownell 	}
16964367cfdcSDavid Brownell 
16974367cfdcSDavid Brownell 	return ret;
16984367cfdcSDavid Brownell }
16994367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage);
17004367cfdcSDavid Brownell 
17014367cfdcSDavid Brownell /**
1702a7a1ad90SMark Brown  * regulator_is_supported_voltage - check if a voltage range can be supported
1703a7a1ad90SMark Brown  *
1704a7a1ad90SMark Brown  * @regulator: Regulator to check.
1705a7a1ad90SMark Brown  * @min_uV: Minimum required voltage in uV.
1706a7a1ad90SMark Brown  * @max_uV: Maximum required voltage in uV.
1707a7a1ad90SMark Brown  *
1708a7a1ad90SMark Brown  * Returns a boolean or a negative error code.
1709a7a1ad90SMark Brown  */
1710a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator,
1711a7a1ad90SMark Brown 				   int min_uV, int max_uV)
1712a7a1ad90SMark Brown {
1713a7a1ad90SMark Brown 	int i, voltages, ret;
1714a7a1ad90SMark Brown 
1715a7a1ad90SMark Brown 	ret = regulator_count_voltages(regulator);
1716a7a1ad90SMark Brown 	if (ret < 0)
1717a7a1ad90SMark Brown 		return ret;
1718a7a1ad90SMark Brown 	voltages = ret;
1719a7a1ad90SMark Brown 
1720a7a1ad90SMark Brown 	for (i = 0; i < voltages; i++) {
1721a7a1ad90SMark Brown 		ret = regulator_list_voltage(regulator, i);
1722a7a1ad90SMark Brown 
1723a7a1ad90SMark Brown 		if (ret >= min_uV && ret <= max_uV)
1724a7a1ad90SMark Brown 			return 1;
1725a7a1ad90SMark Brown 	}
1726a7a1ad90SMark Brown 
1727a7a1ad90SMark Brown 	return 0;
1728a7a1ad90SMark Brown }
1729a7a1ad90SMark Brown 
173075790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
173175790251SMark Brown 				     int min_uV, int max_uV)
173275790251SMark Brown {
173375790251SMark Brown 	int ret;
173477af1b26SLinus Walleij 	int delay = 0;
173575790251SMark Brown 	unsigned int selector;
173675790251SMark Brown 
173775790251SMark Brown 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
173875790251SMark Brown 
1739bf5892a8SMark Brown 	min_uV += rdev->constraints->uV_offset;
1740bf5892a8SMark Brown 	max_uV += rdev->constraints->uV_offset;
1741bf5892a8SMark Brown 
174275790251SMark Brown 	if (rdev->desc->ops->set_voltage) {
174375790251SMark Brown 		ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
174475790251SMark Brown 						   &selector);
174575790251SMark Brown 
174675790251SMark Brown 		if (rdev->desc->ops->list_voltage)
174775790251SMark Brown 			selector = rdev->desc->ops->list_voltage(rdev,
174875790251SMark Brown 								 selector);
174975790251SMark Brown 		else
175075790251SMark Brown 			selector = -1;
1751e8eef82bSMark Brown 	} else if (rdev->desc->ops->set_voltage_sel) {
1752e8eef82bSMark Brown 		int best_val = INT_MAX;
1753e8eef82bSMark Brown 		int i;
1754e8eef82bSMark Brown 
1755e8eef82bSMark Brown 		selector = 0;
1756e8eef82bSMark Brown 
1757e8eef82bSMark Brown 		/* Find the smallest voltage that falls within the specified
1758e8eef82bSMark Brown 		 * range.
1759e8eef82bSMark Brown 		 */
1760e8eef82bSMark Brown 		for (i = 0; i < rdev->desc->n_voltages; i++) {
1761e8eef82bSMark Brown 			ret = rdev->desc->ops->list_voltage(rdev, i);
1762e8eef82bSMark Brown 			if (ret < 0)
1763e8eef82bSMark Brown 				continue;
1764e8eef82bSMark Brown 
1765e8eef82bSMark Brown 			if (ret < best_val && ret >= min_uV && ret <= max_uV) {
1766e8eef82bSMark Brown 				best_val = ret;
1767e8eef82bSMark Brown 				selector = i;
1768e8eef82bSMark Brown 			}
1769e8eef82bSMark Brown 		}
1770e8eef82bSMark Brown 
177177af1b26SLinus Walleij 		/*
177277af1b26SLinus Walleij 		 * If we can't obtain the old selector there is not enough
177377af1b26SLinus Walleij 		 * info to call set_voltage_time_sel().
177477af1b26SLinus Walleij 		 */
177577af1b26SLinus Walleij 		if (rdev->desc->ops->set_voltage_time_sel &&
177677af1b26SLinus Walleij 		    rdev->desc->ops->get_voltage_sel) {
177777af1b26SLinus Walleij 			unsigned int old_selector = 0;
177877af1b26SLinus Walleij 
177977af1b26SLinus Walleij 			ret = rdev->desc->ops->get_voltage_sel(rdev);
178077af1b26SLinus Walleij 			if (ret < 0)
178177af1b26SLinus Walleij 				return ret;
178277af1b26SLinus Walleij 			old_selector = ret;
178377af1b26SLinus Walleij 			delay = rdev->desc->ops->set_voltage_time_sel(rdev,
178477af1b26SLinus Walleij 						old_selector, selector);
178577af1b26SLinus Walleij 		}
178677af1b26SLinus Walleij 
1787e8eef82bSMark Brown 		if (best_val != INT_MAX) {
1788e8eef82bSMark Brown 			ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
1789e8eef82bSMark Brown 			selector = best_val;
1790e8eef82bSMark Brown 		} else {
1791e8eef82bSMark Brown 			ret = -EINVAL;
1792e8eef82bSMark Brown 		}
179375790251SMark Brown 	} else {
179475790251SMark Brown 		ret = -EINVAL;
179575790251SMark Brown 	}
179675790251SMark Brown 
179777af1b26SLinus Walleij 	/* Insert any necessary delays */
179877af1b26SLinus Walleij 	if (delay >= 1000) {
179977af1b26SLinus Walleij 		mdelay(delay / 1000);
180077af1b26SLinus Walleij 		udelay(delay % 1000);
180177af1b26SLinus Walleij 	} else if (delay) {
180277af1b26SLinus Walleij 		udelay(delay);
180377af1b26SLinus Walleij 	}
180477af1b26SLinus Walleij 
1805ded06a52SMark Brown 	if (ret == 0)
1806ded06a52SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
1807ded06a52SMark Brown 				     NULL);
1808ded06a52SMark Brown 
180975790251SMark Brown 	trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector);
181075790251SMark Brown 
181175790251SMark Brown 	return ret;
181275790251SMark Brown }
181375790251SMark Brown 
1814a7a1ad90SMark Brown /**
1815414c70cbSLiam Girdwood  * regulator_set_voltage - set regulator output voltage
1816414c70cbSLiam Girdwood  * @regulator: regulator source
1817414c70cbSLiam Girdwood  * @min_uV: Minimum required voltage in uV
1818414c70cbSLiam Girdwood  * @max_uV: Maximum acceptable voltage in uV
1819414c70cbSLiam Girdwood  *
1820414c70cbSLiam Girdwood  * Sets a voltage regulator to the desired output voltage. This can be set
1821414c70cbSLiam Girdwood  * during any regulator state. IOW, regulator can be disabled or enabled.
1822414c70cbSLiam Girdwood  *
1823414c70cbSLiam Girdwood  * If the regulator is enabled then the voltage will change to the new value
1824414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
1825414c70cbSLiam Girdwood  * output at the new voltage when enabled.
1826414c70cbSLiam Girdwood  *
1827414c70cbSLiam Girdwood  * NOTE: If the regulator is shared between several devices then the lowest
1828414c70cbSLiam Girdwood  * request voltage that meets the system constraints will be used.
182969279fb9SMark Brown  * Regulator system constraints must be set for this regulator before
1830414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
1831414c70cbSLiam Girdwood  */
1832414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
1833414c70cbSLiam Girdwood {
1834414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
183595a3c23aSMark Brown 	int ret = 0;
1836414c70cbSLiam Girdwood 
1837414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
1838414c70cbSLiam Girdwood 
183995a3c23aSMark Brown 	/* If we're setting the same range as last time the change
184095a3c23aSMark Brown 	 * should be a noop (some cpufreq implementations use the same
184195a3c23aSMark Brown 	 * voltage for multiple frequencies, for example).
184295a3c23aSMark Brown 	 */
184395a3c23aSMark Brown 	if (regulator->min_uV == min_uV && regulator->max_uV == max_uV)
184495a3c23aSMark Brown 		goto out;
184595a3c23aSMark Brown 
1846414c70cbSLiam Girdwood 	/* sanity check */
1847e8eef82bSMark Brown 	if (!rdev->desc->ops->set_voltage &&
1848e8eef82bSMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
1849414c70cbSLiam Girdwood 		ret = -EINVAL;
1850414c70cbSLiam Girdwood 		goto out;
1851414c70cbSLiam Girdwood 	}
1852414c70cbSLiam Girdwood 
1853414c70cbSLiam Girdwood 	/* constraints check */
1854414c70cbSLiam Girdwood 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
1855414c70cbSLiam Girdwood 	if (ret < 0)
1856414c70cbSLiam Girdwood 		goto out;
1857414c70cbSLiam Girdwood 	regulator->min_uV = min_uV;
1858414c70cbSLiam Girdwood 	regulator->max_uV = max_uV;
18593a93f2a9SMark Brown 
186005fda3b1SThomas Petazzoni 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
186105fda3b1SThomas Petazzoni 	if (ret < 0)
186205fda3b1SThomas Petazzoni 		goto out;
186305fda3b1SThomas Petazzoni 
186475790251SMark Brown 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
186502fa3ec0SMark Brown 
1866414c70cbSLiam Girdwood out:
1867414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1868414c70cbSLiam Girdwood 	return ret;
1869414c70cbSLiam Girdwood }
1870414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage);
1871414c70cbSLiam Girdwood 
1872606a2562SMark Brown /**
187388cd222bSLinus Walleij  * regulator_set_voltage_time - get raise/fall time
187488cd222bSLinus Walleij  * @regulator: regulator source
187588cd222bSLinus Walleij  * @old_uV: starting voltage in microvolts
187688cd222bSLinus Walleij  * @new_uV: target voltage in microvolts
187788cd222bSLinus Walleij  *
187888cd222bSLinus Walleij  * Provided with the starting and ending voltage, this function attempts to
187988cd222bSLinus Walleij  * calculate the time in microseconds required to rise or fall to this new
188088cd222bSLinus Walleij  * voltage.
188188cd222bSLinus Walleij  */
188288cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator,
188388cd222bSLinus Walleij 			       int old_uV, int new_uV)
188488cd222bSLinus Walleij {
188588cd222bSLinus Walleij 	struct regulator_dev	*rdev = regulator->rdev;
188688cd222bSLinus Walleij 	struct regulator_ops	*ops = rdev->desc->ops;
188788cd222bSLinus Walleij 	int old_sel = -1;
188888cd222bSLinus Walleij 	int new_sel = -1;
188988cd222bSLinus Walleij 	int voltage;
189088cd222bSLinus Walleij 	int i;
189188cd222bSLinus Walleij 
189288cd222bSLinus Walleij 	/* Currently requires operations to do this */
189388cd222bSLinus Walleij 	if (!ops->list_voltage || !ops->set_voltage_time_sel
189488cd222bSLinus Walleij 	    || !rdev->desc->n_voltages)
189588cd222bSLinus Walleij 		return -EINVAL;
189688cd222bSLinus Walleij 
189788cd222bSLinus Walleij 	for (i = 0; i < rdev->desc->n_voltages; i++) {
189888cd222bSLinus Walleij 		/* We only look for exact voltage matches here */
189988cd222bSLinus Walleij 		voltage = regulator_list_voltage(regulator, i);
190088cd222bSLinus Walleij 		if (voltage < 0)
190188cd222bSLinus Walleij 			return -EINVAL;
190288cd222bSLinus Walleij 		if (voltage == 0)
190388cd222bSLinus Walleij 			continue;
190488cd222bSLinus Walleij 		if (voltage == old_uV)
190588cd222bSLinus Walleij 			old_sel = i;
190688cd222bSLinus Walleij 		if (voltage == new_uV)
190788cd222bSLinus Walleij 			new_sel = i;
190888cd222bSLinus Walleij 	}
190988cd222bSLinus Walleij 
191088cd222bSLinus Walleij 	if (old_sel < 0 || new_sel < 0)
191188cd222bSLinus Walleij 		return -EINVAL;
191288cd222bSLinus Walleij 
191388cd222bSLinus Walleij 	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
191488cd222bSLinus Walleij }
191588cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
191688cd222bSLinus Walleij 
191788cd222bSLinus Walleij /**
1918606a2562SMark Brown  * regulator_sync_voltage - re-apply last regulator output voltage
1919606a2562SMark Brown  * @regulator: regulator source
1920606a2562SMark Brown  *
1921606a2562SMark Brown  * Re-apply the last configured voltage.  This is intended to be used
1922606a2562SMark Brown  * where some external control source the consumer is cooperating with
1923606a2562SMark Brown  * has caused the configured voltage to change.
1924606a2562SMark Brown  */
1925606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator)
1926606a2562SMark Brown {
1927606a2562SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
1928606a2562SMark Brown 	int ret, min_uV, max_uV;
1929606a2562SMark Brown 
1930606a2562SMark Brown 	mutex_lock(&rdev->mutex);
1931606a2562SMark Brown 
1932606a2562SMark Brown 	if (!rdev->desc->ops->set_voltage &&
1933606a2562SMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
1934606a2562SMark Brown 		ret = -EINVAL;
1935606a2562SMark Brown 		goto out;
1936606a2562SMark Brown 	}
1937606a2562SMark Brown 
1938606a2562SMark Brown 	/* This is only going to work if we've had a voltage configured. */
1939606a2562SMark Brown 	if (!regulator->min_uV && !regulator->max_uV) {
1940606a2562SMark Brown 		ret = -EINVAL;
1941606a2562SMark Brown 		goto out;
1942606a2562SMark Brown 	}
1943606a2562SMark Brown 
1944606a2562SMark Brown 	min_uV = regulator->min_uV;
1945606a2562SMark Brown 	max_uV = regulator->max_uV;
1946606a2562SMark Brown 
1947606a2562SMark Brown 	/* This should be a paranoia check... */
1948606a2562SMark Brown 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
1949606a2562SMark Brown 	if (ret < 0)
1950606a2562SMark Brown 		goto out;
1951606a2562SMark Brown 
1952606a2562SMark Brown 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
1953606a2562SMark Brown 	if (ret < 0)
1954606a2562SMark Brown 		goto out;
1955606a2562SMark Brown 
1956606a2562SMark Brown 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
1957606a2562SMark Brown 
1958606a2562SMark Brown out:
1959606a2562SMark Brown 	mutex_unlock(&rdev->mutex);
1960606a2562SMark Brown 	return ret;
1961606a2562SMark Brown }
1962606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage);
1963606a2562SMark Brown 
1964414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev)
1965414c70cbSLiam Girdwood {
1966bf5892a8SMark Brown 	int sel, ret;
1967476c2d83SMark Brown 
1968476c2d83SMark Brown 	if (rdev->desc->ops->get_voltage_sel) {
1969476c2d83SMark Brown 		sel = rdev->desc->ops->get_voltage_sel(rdev);
1970476c2d83SMark Brown 		if (sel < 0)
1971476c2d83SMark Brown 			return sel;
1972bf5892a8SMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, sel);
1973cb220d16SAxel Lin 	} else if (rdev->desc->ops->get_voltage) {
1974bf5892a8SMark Brown 		ret = rdev->desc->ops->get_voltage(rdev);
1975cb220d16SAxel Lin 	} else {
1976414c70cbSLiam Girdwood 		return -EINVAL;
1977cb220d16SAxel Lin 	}
1978bf5892a8SMark Brown 
1979cb220d16SAxel Lin 	if (ret < 0)
1980cb220d16SAxel Lin 		return ret;
1981bf5892a8SMark Brown 	return ret - rdev->constraints->uV_offset;
1982414c70cbSLiam Girdwood }
1983414c70cbSLiam Girdwood 
1984414c70cbSLiam Girdwood /**
1985414c70cbSLiam Girdwood  * regulator_get_voltage - get regulator output voltage
1986414c70cbSLiam Girdwood  * @regulator: regulator source
1987414c70cbSLiam Girdwood  *
1988414c70cbSLiam Girdwood  * This returns the current regulator voltage in uV.
1989414c70cbSLiam Girdwood  *
1990414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the voltage value. This
1991414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
1992414c70cbSLiam Girdwood  */
1993414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator)
1994414c70cbSLiam Girdwood {
1995414c70cbSLiam Girdwood 	int ret;
1996414c70cbSLiam Girdwood 
1997414c70cbSLiam Girdwood 	mutex_lock(&regulator->rdev->mutex);
1998414c70cbSLiam Girdwood 
1999414c70cbSLiam Girdwood 	ret = _regulator_get_voltage(regulator->rdev);
2000414c70cbSLiam Girdwood 
2001414c70cbSLiam Girdwood 	mutex_unlock(&regulator->rdev->mutex);
2002414c70cbSLiam Girdwood 
2003414c70cbSLiam Girdwood 	return ret;
2004414c70cbSLiam Girdwood }
2005414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage);
2006414c70cbSLiam Girdwood 
2007414c70cbSLiam Girdwood /**
2008414c70cbSLiam Girdwood  * regulator_set_current_limit - set regulator output current limit
2009414c70cbSLiam Girdwood  * @regulator: regulator source
2010414c70cbSLiam Girdwood  * @min_uA: Minimuum supported current in uA
2011414c70cbSLiam Girdwood  * @max_uA: Maximum supported current in uA
2012414c70cbSLiam Girdwood  *
2013414c70cbSLiam Girdwood  * Sets current sink to the desired output current. This can be set during
2014414c70cbSLiam Girdwood  * any regulator state. IOW, regulator can be disabled or enabled.
2015414c70cbSLiam Girdwood  *
2016414c70cbSLiam Girdwood  * If the regulator is enabled then the current will change to the new value
2017414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
2018414c70cbSLiam Girdwood  * output at the new current when enabled.
2019414c70cbSLiam Girdwood  *
2020414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
2021414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
2022414c70cbSLiam Girdwood  */
2023414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator,
2024414c70cbSLiam Girdwood 			       int min_uA, int max_uA)
2025414c70cbSLiam Girdwood {
2026414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2027414c70cbSLiam Girdwood 	int ret;
2028414c70cbSLiam Girdwood 
2029414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2030414c70cbSLiam Girdwood 
2031414c70cbSLiam Girdwood 	/* sanity check */
2032414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_current_limit) {
2033414c70cbSLiam Girdwood 		ret = -EINVAL;
2034414c70cbSLiam Girdwood 		goto out;
2035414c70cbSLiam Girdwood 	}
2036414c70cbSLiam Girdwood 
2037414c70cbSLiam Girdwood 	/* constraints check */
2038414c70cbSLiam Girdwood 	ret = regulator_check_current_limit(rdev, &min_uA, &max_uA);
2039414c70cbSLiam Girdwood 	if (ret < 0)
2040414c70cbSLiam Girdwood 		goto out;
2041414c70cbSLiam Girdwood 
2042414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
2043414c70cbSLiam Girdwood out:
2044414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2045414c70cbSLiam Girdwood 	return ret;
2046414c70cbSLiam Girdwood }
2047414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit);
2048414c70cbSLiam Girdwood 
2049414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev)
2050414c70cbSLiam Girdwood {
2051414c70cbSLiam Girdwood 	int ret;
2052414c70cbSLiam Girdwood 
2053414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2054414c70cbSLiam Girdwood 
2055414c70cbSLiam Girdwood 	/* sanity check */
2056414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_current_limit) {
2057414c70cbSLiam Girdwood 		ret = -EINVAL;
2058414c70cbSLiam Girdwood 		goto out;
2059414c70cbSLiam Girdwood 	}
2060414c70cbSLiam Girdwood 
2061414c70cbSLiam Girdwood 	ret = rdev->desc->ops->get_current_limit(rdev);
2062414c70cbSLiam Girdwood out:
2063414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2064414c70cbSLiam Girdwood 	return ret;
2065414c70cbSLiam Girdwood }
2066414c70cbSLiam Girdwood 
2067414c70cbSLiam Girdwood /**
2068414c70cbSLiam Girdwood  * regulator_get_current_limit - get regulator output current
2069414c70cbSLiam Girdwood  * @regulator: regulator source
2070414c70cbSLiam Girdwood  *
2071414c70cbSLiam Girdwood  * This returns the current supplied by the specified current sink in uA.
2072414c70cbSLiam Girdwood  *
2073414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the current value. This
2074414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
2075414c70cbSLiam Girdwood  */
2076414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator)
2077414c70cbSLiam Girdwood {
2078414c70cbSLiam Girdwood 	return _regulator_get_current_limit(regulator->rdev);
2079414c70cbSLiam Girdwood }
2080414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit);
2081414c70cbSLiam Girdwood 
2082414c70cbSLiam Girdwood /**
2083414c70cbSLiam Girdwood  * regulator_set_mode - set regulator operating mode
2084414c70cbSLiam Girdwood  * @regulator: regulator source
2085414c70cbSLiam Girdwood  * @mode: operating mode - one of the REGULATOR_MODE constants
2086414c70cbSLiam Girdwood  *
2087414c70cbSLiam Girdwood  * Set regulator operating mode to increase regulator efficiency or improve
2088414c70cbSLiam Girdwood  * regulation performance.
2089414c70cbSLiam Girdwood  *
2090414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
2091414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
2092414c70cbSLiam Girdwood  */
2093414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode)
2094414c70cbSLiam Girdwood {
2095414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2096414c70cbSLiam Girdwood 	int ret;
2097500b4ac9SSundar R Iyer 	int regulator_curr_mode;
2098414c70cbSLiam Girdwood 
2099414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2100414c70cbSLiam Girdwood 
2101414c70cbSLiam Girdwood 	/* sanity check */
2102414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_mode) {
2103414c70cbSLiam Girdwood 		ret = -EINVAL;
2104414c70cbSLiam Girdwood 		goto out;
2105414c70cbSLiam Girdwood 	}
2106414c70cbSLiam Girdwood 
2107500b4ac9SSundar R Iyer 	/* return if the same mode is requested */
2108500b4ac9SSundar R Iyer 	if (rdev->desc->ops->get_mode) {
2109500b4ac9SSundar R Iyer 		regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
2110500b4ac9SSundar R Iyer 		if (regulator_curr_mode == mode) {
2111500b4ac9SSundar R Iyer 			ret = 0;
2112500b4ac9SSundar R Iyer 			goto out;
2113500b4ac9SSundar R Iyer 		}
2114500b4ac9SSundar R Iyer 	}
2115500b4ac9SSundar R Iyer 
2116414c70cbSLiam Girdwood 	/* constraints check */
211722c51b47SAxel Lin 	ret = regulator_mode_constrain(rdev, &mode);
2118414c70cbSLiam Girdwood 	if (ret < 0)
2119414c70cbSLiam Girdwood 		goto out;
2120414c70cbSLiam Girdwood 
2121414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
2122414c70cbSLiam Girdwood out:
2123414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2124414c70cbSLiam Girdwood 	return ret;
2125414c70cbSLiam Girdwood }
2126414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode);
2127414c70cbSLiam Girdwood 
2128414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
2129414c70cbSLiam Girdwood {
2130414c70cbSLiam Girdwood 	int ret;
2131414c70cbSLiam Girdwood 
2132414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2133414c70cbSLiam Girdwood 
2134414c70cbSLiam Girdwood 	/* sanity check */
2135414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_mode) {
2136414c70cbSLiam Girdwood 		ret = -EINVAL;
2137414c70cbSLiam Girdwood 		goto out;
2138414c70cbSLiam Girdwood 	}
2139414c70cbSLiam Girdwood 
2140414c70cbSLiam Girdwood 	ret = rdev->desc->ops->get_mode(rdev);
2141414c70cbSLiam Girdwood out:
2142414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2143414c70cbSLiam Girdwood 	return ret;
2144414c70cbSLiam Girdwood }
2145414c70cbSLiam Girdwood 
2146414c70cbSLiam Girdwood /**
2147414c70cbSLiam Girdwood  * regulator_get_mode - get regulator operating mode
2148414c70cbSLiam Girdwood  * @regulator: regulator source
2149414c70cbSLiam Girdwood  *
2150414c70cbSLiam Girdwood  * Get the current regulator operating mode.
2151414c70cbSLiam Girdwood  */
2152414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator)
2153414c70cbSLiam Girdwood {
2154414c70cbSLiam Girdwood 	return _regulator_get_mode(regulator->rdev);
2155414c70cbSLiam Girdwood }
2156414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode);
2157414c70cbSLiam Girdwood 
2158414c70cbSLiam Girdwood /**
2159414c70cbSLiam Girdwood  * regulator_set_optimum_mode - set regulator optimum operating mode
2160414c70cbSLiam Girdwood  * @regulator: regulator source
2161414c70cbSLiam Girdwood  * @uA_load: load current
2162414c70cbSLiam Girdwood  *
2163414c70cbSLiam Girdwood  * Notifies the regulator core of a new device load. This is then used by
2164414c70cbSLiam Girdwood  * DRMS (if enabled by constraints) to set the most efficient regulator
2165414c70cbSLiam Girdwood  * operating mode for the new regulator loading.
2166414c70cbSLiam Girdwood  *
2167414c70cbSLiam Girdwood  * Consumer devices notify their supply regulator of the maximum power
2168414c70cbSLiam Girdwood  * they will require (can be taken from device datasheet in the power
2169414c70cbSLiam Girdwood  * consumption tables) when they change operational status and hence power
2170414c70cbSLiam Girdwood  * state. Examples of operational state changes that can affect power
2171414c70cbSLiam Girdwood  * consumption are :-
2172414c70cbSLiam Girdwood  *
2173414c70cbSLiam Girdwood  *    o Device is opened / closed.
2174414c70cbSLiam Girdwood  *    o Device I/O is about to begin or has just finished.
2175414c70cbSLiam Girdwood  *    o Device is idling in between work.
2176414c70cbSLiam Girdwood  *
2177414c70cbSLiam Girdwood  * This information is also exported via sysfs to userspace.
2178414c70cbSLiam Girdwood  *
2179414c70cbSLiam Girdwood  * DRMS will sum the total requested load on the regulator and change
2180414c70cbSLiam Girdwood  * to the most efficient operating mode if platform constraints allow.
2181414c70cbSLiam Girdwood  *
2182414c70cbSLiam Girdwood  * Returns the new regulator mode or error.
2183414c70cbSLiam Girdwood  */
2184414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
2185414c70cbSLiam Girdwood {
2186414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2187414c70cbSLiam Girdwood 	struct regulator *consumer;
2188414c70cbSLiam Girdwood 	int ret, output_uV, input_uV, total_uA_load = 0;
2189414c70cbSLiam Girdwood 	unsigned int mode;
2190414c70cbSLiam Girdwood 
2191414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2192414c70cbSLiam Girdwood 
2193a4b41483SMark Brown 	/*
2194a4b41483SMark Brown 	 * first check to see if we can set modes at all, otherwise just
2195a4b41483SMark Brown 	 * tell the consumer everything is OK.
2196a4b41483SMark Brown 	 */
2197414c70cbSLiam Girdwood 	regulator->uA_load = uA_load;
2198414c70cbSLiam Girdwood 	ret = regulator_check_drms(rdev);
2199a4b41483SMark Brown 	if (ret < 0) {
2200a4b41483SMark Brown 		ret = 0;
2201414c70cbSLiam Girdwood 		goto out;
2202a4b41483SMark Brown 	}
2203414c70cbSLiam Girdwood 
2204414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_optimum_mode)
2205414c70cbSLiam Girdwood 		goto out;
2206414c70cbSLiam Girdwood 
2207a4b41483SMark Brown 	/*
2208a4b41483SMark Brown 	 * we can actually do this so any errors are indicators of
2209a4b41483SMark Brown 	 * potential real failure.
2210a4b41483SMark Brown 	 */
2211a4b41483SMark Brown 	ret = -EINVAL;
2212a4b41483SMark Brown 
2213414c70cbSLiam Girdwood 	/* get output voltage */
22141bf5a1f8SMark Brown 	output_uV = _regulator_get_voltage(rdev);
2215414c70cbSLiam Girdwood 	if (output_uV <= 0) {
22165da84fd9SJoe Perches 		rdev_err(rdev, "invalid output voltage found\n");
2217414c70cbSLiam Girdwood 		goto out;
2218414c70cbSLiam Girdwood 	}
2219414c70cbSLiam Girdwood 
2220414c70cbSLiam Girdwood 	/* get input voltage */
22211bf5a1f8SMark Brown 	input_uV = 0;
22221bf5a1f8SMark Brown 	if (rdev->supply)
22233801b86aSMark Brown 		input_uV = regulator_get_voltage(rdev->supply);
22241bf5a1f8SMark Brown 	if (input_uV <= 0)
2225414c70cbSLiam Girdwood 		input_uV = rdev->constraints->input_uV;
2226414c70cbSLiam Girdwood 	if (input_uV <= 0) {
22275da84fd9SJoe Perches 		rdev_err(rdev, "invalid input voltage found\n");
2228414c70cbSLiam Girdwood 		goto out;
2229414c70cbSLiam Girdwood 	}
2230414c70cbSLiam Girdwood 
2231414c70cbSLiam Girdwood 	/* calc total requested load for this regulator */
2232414c70cbSLiam Girdwood 	list_for_each_entry(consumer, &rdev->consumer_list, list)
2233414c70cbSLiam Girdwood 		total_uA_load += consumer->uA_load;
2234414c70cbSLiam Girdwood 
2235414c70cbSLiam Girdwood 	mode = rdev->desc->ops->get_optimum_mode(rdev,
2236414c70cbSLiam Girdwood 						 input_uV, output_uV,
2237414c70cbSLiam Girdwood 						 total_uA_load);
22382c608234SMark Brown 	ret = regulator_mode_constrain(rdev, &mode);
2239e573520bSDavid Brownell 	if (ret < 0) {
22405da84fd9SJoe Perches 		rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
2241414c70cbSLiam Girdwood 			 total_uA_load, input_uV, output_uV);
2242414c70cbSLiam Girdwood 		goto out;
2243414c70cbSLiam Girdwood 	}
2244414c70cbSLiam Girdwood 
2245414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
2246e573520bSDavid Brownell 	if (ret < 0) {
22475da84fd9SJoe Perches 		rdev_err(rdev, "failed to set optimum mode %x\n", mode);
2248414c70cbSLiam Girdwood 		goto out;
2249414c70cbSLiam Girdwood 	}
2250414c70cbSLiam Girdwood 	ret = mode;
2251414c70cbSLiam Girdwood out:
2252414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2253414c70cbSLiam Girdwood 	return ret;
2254414c70cbSLiam Girdwood }
2255414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
2256414c70cbSLiam Girdwood 
2257414c70cbSLiam Girdwood /**
2258414c70cbSLiam Girdwood  * regulator_register_notifier - register regulator event notifier
2259414c70cbSLiam Girdwood  * @regulator: regulator source
226069279fb9SMark Brown  * @nb: notifier block
2261414c70cbSLiam Girdwood  *
2262414c70cbSLiam Girdwood  * Register notifier block to receive regulator events.
2263414c70cbSLiam Girdwood  */
2264414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator,
2265414c70cbSLiam Girdwood 			      struct notifier_block *nb)
2266414c70cbSLiam Girdwood {
2267414c70cbSLiam Girdwood 	return blocking_notifier_chain_register(&regulator->rdev->notifier,
2268414c70cbSLiam Girdwood 						nb);
2269414c70cbSLiam Girdwood }
2270414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier);
2271414c70cbSLiam Girdwood 
2272414c70cbSLiam Girdwood /**
2273414c70cbSLiam Girdwood  * regulator_unregister_notifier - unregister regulator event notifier
2274414c70cbSLiam Girdwood  * @regulator: regulator source
227569279fb9SMark Brown  * @nb: notifier block
2276414c70cbSLiam Girdwood  *
2277414c70cbSLiam Girdwood  * Unregister regulator event notifier block.
2278414c70cbSLiam Girdwood  */
2279414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator,
2280414c70cbSLiam Girdwood 				struct notifier_block *nb)
2281414c70cbSLiam Girdwood {
2282414c70cbSLiam Girdwood 	return blocking_notifier_chain_unregister(&regulator->rdev->notifier,
2283414c70cbSLiam Girdwood 						  nb);
2284414c70cbSLiam Girdwood }
2285414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
2286414c70cbSLiam Girdwood 
2287b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers.
2288b136fb44SJonathan Cameron  * Note mutex must be held by caller.
2289b136fb44SJonathan Cameron  */
2290414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev,
2291414c70cbSLiam Girdwood 				  unsigned long event, void *data)
2292414c70cbSLiam Girdwood {
2293414c70cbSLiam Girdwood 	/* call rdev chain first */
2294414c70cbSLiam Girdwood 	blocking_notifier_call_chain(&rdev->notifier, event, NULL);
2295414c70cbSLiam Girdwood }
2296414c70cbSLiam Girdwood 
2297414c70cbSLiam Girdwood /**
2298414c70cbSLiam Girdwood  * regulator_bulk_get - get multiple regulator consumers
2299414c70cbSLiam Girdwood  *
2300414c70cbSLiam Girdwood  * @dev:           Device to supply
2301414c70cbSLiam Girdwood  * @num_consumers: Number of consumers to register
2302414c70cbSLiam Girdwood  * @consumers:     Configuration of consumers; clients are stored here.
2303414c70cbSLiam Girdwood  *
2304414c70cbSLiam Girdwood  * @return 0 on success, an errno on failure.
2305414c70cbSLiam Girdwood  *
2306414c70cbSLiam Girdwood  * This helper function allows drivers to get several regulator
2307414c70cbSLiam Girdwood  * consumers in one operation.  If any of the regulators cannot be
2308414c70cbSLiam Girdwood  * acquired then any regulators that were allocated will be freed
2309414c70cbSLiam Girdwood  * before returning to the caller.
2310414c70cbSLiam Girdwood  */
2311414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers,
2312414c70cbSLiam Girdwood 		       struct regulator_bulk_data *consumers)
2313414c70cbSLiam Girdwood {
2314414c70cbSLiam Girdwood 	int i;
2315414c70cbSLiam Girdwood 	int ret;
2316414c70cbSLiam Girdwood 
2317414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++)
2318414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
2319414c70cbSLiam Girdwood 
2320414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2321414c70cbSLiam Girdwood 		consumers[i].consumer = regulator_get(dev,
2322414c70cbSLiam Girdwood 						      consumers[i].supply);
2323414c70cbSLiam Girdwood 		if (IS_ERR(consumers[i].consumer)) {
2324414c70cbSLiam Girdwood 			ret = PTR_ERR(consumers[i].consumer);
23255b307627SMark Brown 			dev_err(dev, "Failed to get supply '%s': %d\n",
23265b307627SMark Brown 				consumers[i].supply, ret);
2327414c70cbSLiam Girdwood 			consumers[i].consumer = NULL;
2328414c70cbSLiam Girdwood 			goto err;
2329414c70cbSLiam Girdwood 		}
2330414c70cbSLiam Girdwood 	}
2331414c70cbSLiam Girdwood 
2332414c70cbSLiam Girdwood 	return 0;
2333414c70cbSLiam Girdwood 
2334414c70cbSLiam Girdwood err:
2335414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
2336414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
2337414c70cbSLiam Girdwood 
2338414c70cbSLiam Girdwood 	return ret;
2339414c70cbSLiam Girdwood }
2340414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get);
2341414c70cbSLiam Girdwood 
2342f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
2343f21e0e81SMark Brown {
2344f21e0e81SMark Brown 	struct regulator_bulk_data *bulk = data;
2345f21e0e81SMark Brown 
2346f21e0e81SMark Brown 	bulk->ret = regulator_enable(bulk->consumer);
2347f21e0e81SMark Brown }
2348f21e0e81SMark Brown 
2349414c70cbSLiam Girdwood /**
2350414c70cbSLiam Girdwood  * regulator_bulk_enable - enable multiple regulator consumers
2351414c70cbSLiam Girdwood  *
2352414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2353414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2354414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
2355414c70cbSLiam Girdwood  *
2356414c70cbSLiam Girdwood  * This convenience API allows consumers to enable multiple regulator
2357414c70cbSLiam Girdwood  * clients in a single API call.  If any consumers cannot be enabled
2358414c70cbSLiam Girdwood  * then any others that were enabled will be disabled again prior to
2359414c70cbSLiam Girdwood  * return.
2360414c70cbSLiam Girdwood  */
2361414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers,
2362414c70cbSLiam Girdwood 			  struct regulator_bulk_data *consumers)
2363414c70cbSLiam Girdwood {
2364f21e0e81SMark Brown 	LIST_HEAD(async_domain);
2365414c70cbSLiam Girdwood 	int i;
2366f21e0e81SMark Brown 	int ret = 0;
2367414c70cbSLiam Girdwood 
2368f21e0e81SMark Brown 	for (i = 0; i < num_consumers; i++)
2369f21e0e81SMark Brown 		async_schedule_domain(regulator_bulk_enable_async,
2370f21e0e81SMark Brown 				      &consumers[i], &async_domain);
2371f21e0e81SMark Brown 
2372f21e0e81SMark Brown 	async_synchronize_full_domain(&async_domain);
2373f21e0e81SMark Brown 
2374f21e0e81SMark Brown 	/* If any consumer failed we need to unwind any that succeeded */
2375414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2376f21e0e81SMark Brown 		if (consumers[i].ret != 0) {
2377f21e0e81SMark Brown 			ret = consumers[i].ret;
2378414c70cbSLiam Girdwood 			goto err;
2379414c70cbSLiam Girdwood 		}
2380f21e0e81SMark Brown 	}
2381414c70cbSLiam Girdwood 
2382414c70cbSLiam Girdwood 	return 0;
2383414c70cbSLiam Girdwood 
2384414c70cbSLiam Girdwood err:
2385f21e0e81SMark Brown 	for (i = 0; i < num_consumers; i++)
2386f21e0e81SMark Brown 		if (consumers[i].ret == 0)
2387414c70cbSLiam Girdwood 			regulator_disable(consumers[i].consumer);
2388f21e0e81SMark Brown 		else
2389f21e0e81SMark Brown 			pr_err("Failed to enable %s: %d\n",
2390f21e0e81SMark Brown 			       consumers[i].supply, consumers[i].ret);
2391414c70cbSLiam Girdwood 
2392414c70cbSLiam Girdwood 	return ret;
2393414c70cbSLiam Girdwood }
2394414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable);
2395414c70cbSLiam Girdwood 
2396414c70cbSLiam Girdwood /**
2397414c70cbSLiam Girdwood  * regulator_bulk_disable - disable multiple regulator consumers
2398414c70cbSLiam Girdwood  *
2399414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2400414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2401414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
2402414c70cbSLiam Girdwood  *
2403414c70cbSLiam Girdwood  * This convenience API allows consumers to disable multiple regulator
2404414c70cbSLiam Girdwood  * clients in a single API call.  If any consumers cannot be enabled
2405414c70cbSLiam Girdwood  * then any others that were disabled will be disabled again prior to
2406414c70cbSLiam Girdwood  * return.
2407414c70cbSLiam Girdwood  */
2408414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers,
2409414c70cbSLiam Girdwood 			   struct regulator_bulk_data *consumers)
2410414c70cbSLiam Girdwood {
2411414c70cbSLiam Girdwood 	int i;
2412414c70cbSLiam Girdwood 	int ret;
2413414c70cbSLiam Girdwood 
2414414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2415414c70cbSLiam Girdwood 		ret = regulator_disable(consumers[i].consumer);
2416414c70cbSLiam Girdwood 		if (ret != 0)
2417414c70cbSLiam Girdwood 			goto err;
2418414c70cbSLiam Girdwood 	}
2419414c70cbSLiam Girdwood 
2420414c70cbSLiam Girdwood 	return 0;
2421414c70cbSLiam Girdwood 
2422414c70cbSLiam Girdwood err:
24235da84fd9SJoe Perches 	pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
2424eb143ac1SLars-Peter Clausen 	for (--i; i >= 0; --i)
2425414c70cbSLiam Girdwood 		regulator_enable(consumers[i].consumer);
2426414c70cbSLiam Girdwood 
2427414c70cbSLiam Girdwood 	return ret;
2428414c70cbSLiam Girdwood }
2429414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable);
2430414c70cbSLiam Girdwood 
2431414c70cbSLiam Girdwood /**
2432414c70cbSLiam Girdwood  * regulator_bulk_free - free multiple regulator consumers
2433414c70cbSLiam Girdwood  *
2434414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2435414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2436414c70cbSLiam Girdwood  *
2437414c70cbSLiam Girdwood  * This convenience API allows consumers to free multiple regulator
2438414c70cbSLiam Girdwood  * clients in a single API call.
2439414c70cbSLiam Girdwood  */
2440414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers,
2441414c70cbSLiam Girdwood 			 struct regulator_bulk_data *consumers)
2442414c70cbSLiam Girdwood {
2443414c70cbSLiam Girdwood 	int i;
2444414c70cbSLiam Girdwood 
2445414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2446414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
2447414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
2448414c70cbSLiam Girdwood 	}
2449414c70cbSLiam Girdwood }
2450414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free);
2451414c70cbSLiam Girdwood 
2452414c70cbSLiam Girdwood /**
2453414c70cbSLiam Girdwood  * regulator_notifier_call_chain - call regulator event notifier
245469279fb9SMark Brown  * @rdev: regulator source
2455414c70cbSLiam Girdwood  * @event: notifier block
245669279fb9SMark Brown  * @data: callback-specific data.
2457414c70cbSLiam Girdwood  *
2458414c70cbSLiam Girdwood  * Called by regulator drivers to notify clients a regulator event has
2459414c70cbSLiam Girdwood  * occurred. We also notify regulator clients downstream.
2460b136fb44SJonathan Cameron  * Note lock must be held by caller.
2461414c70cbSLiam Girdwood  */
2462414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev,
2463414c70cbSLiam Girdwood 				  unsigned long event, void *data)
2464414c70cbSLiam Girdwood {
2465414c70cbSLiam Girdwood 	_notifier_call_chain(rdev, event, data);
2466414c70cbSLiam Girdwood 	return NOTIFY_DONE;
2467414c70cbSLiam Girdwood 
2468414c70cbSLiam Girdwood }
2469414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
2470414c70cbSLiam Girdwood 
2471be721979SMark Brown /**
2472be721979SMark Brown  * regulator_mode_to_status - convert a regulator mode into a status
2473be721979SMark Brown  *
2474be721979SMark Brown  * @mode: Mode to convert
2475be721979SMark Brown  *
2476be721979SMark Brown  * Convert a regulator mode into a status.
2477be721979SMark Brown  */
2478be721979SMark Brown int regulator_mode_to_status(unsigned int mode)
2479be721979SMark Brown {
2480be721979SMark Brown 	switch (mode) {
2481be721979SMark Brown 	case REGULATOR_MODE_FAST:
2482be721979SMark Brown 		return REGULATOR_STATUS_FAST;
2483be721979SMark Brown 	case REGULATOR_MODE_NORMAL:
2484be721979SMark Brown 		return REGULATOR_STATUS_NORMAL;
2485be721979SMark Brown 	case REGULATOR_MODE_IDLE:
2486be721979SMark Brown 		return REGULATOR_STATUS_IDLE;
2487be721979SMark Brown 	case REGULATOR_STATUS_STANDBY:
2488be721979SMark Brown 		return REGULATOR_STATUS_STANDBY;
2489be721979SMark Brown 	default:
2490be721979SMark Brown 		return 0;
2491be721979SMark Brown 	}
2492be721979SMark Brown }
2493be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status);
2494be721979SMark Brown 
24957ad68e2fSDavid Brownell /*
24967ad68e2fSDavid Brownell  * To avoid cluttering sysfs (and memory) with useless state, only
24977ad68e2fSDavid Brownell  * create attributes that can be meaningfully displayed.
24987ad68e2fSDavid Brownell  */
24997ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev)
25007ad68e2fSDavid Brownell {
25017ad68e2fSDavid Brownell 	struct device		*dev = &rdev->dev;
25027ad68e2fSDavid Brownell 	struct regulator_ops	*ops = rdev->desc->ops;
25037ad68e2fSDavid Brownell 	int			status = 0;
25047ad68e2fSDavid Brownell 
25057ad68e2fSDavid Brownell 	/* some attributes need specific methods to be displayed */
2506476c2d83SMark Brown 	if (ops->get_voltage || ops->get_voltage_sel) {
25077ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_microvolts);
25087ad68e2fSDavid Brownell 		if (status < 0)
25097ad68e2fSDavid Brownell 			return status;
25107ad68e2fSDavid Brownell 	}
25117ad68e2fSDavid Brownell 	if (ops->get_current_limit) {
25127ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_microamps);
25137ad68e2fSDavid Brownell 		if (status < 0)
25147ad68e2fSDavid Brownell 			return status;
25157ad68e2fSDavid Brownell 	}
25167ad68e2fSDavid Brownell 	if (ops->get_mode) {
25177ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_opmode);
25187ad68e2fSDavid Brownell 		if (status < 0)
25197ad68e2fSDavid Brownell 			return status;
25207ad68e2fSDavid Brownell 	}
25217ad68e2fSDavid Brownell 	if (ops->is_enabled) {
25227ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_state);
25237ad68e2fSDavid Brownell 		if (status < 0)
25247ad68e2fSDavid Brownell 			return status;
25257ad68e2fSDavid Brownell 	}
2526853116a1SDavid Brownell 	if (ops->get_status) {
2527853116a1SDavid Brownell 		status = device_create_file(dev, &dev_attr_status);
2528853116a1SDavid Brownell 		if (status < 0)
2529853116a1SDavid Brownell 			return status;
2530853116a1SDavid Brownell 	}
25317ad68e2fSDavid Brownell 
25327ad68e2fSDavid Brownell 	/* some attributes are type-specific */
25337ad68e2fSDavid Brownell 	if (rdev->desc->type == REGULATOR_CURRENT) {
25347ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_requested_microamps);
25357ad68e2fSDavid Brownell 		if (status < 0)
25367ad68e2fSDavid Brownell 			return status;
25377ad68e2fSDavid Brownell 	}
25387ad68e2fSDavid Brownell 
25397ad68e2fSDavid Brownell 	/* all the other attributes exist to support constraints;
25407ad68e2fSDavid Brownell 	 * don't show them if there are no constraints, or if the
25417ad68e2fSDavid Brownell 	 * relevant supporting methods are missing.
25427ad68e2fSDavid Brownell 	 */
25437ad68e2fSDavid Brownell 	if (!rdev->constraints)
25447ad68e2fSDavid Brownell 		return status;
25457ad68e2fSDavid Brownell 
25467ad68e2fSDavid Brownell 	/* constraints need specific supporting methods */
2547e8eef82bSMark Brown 	if (ops->set_voltage || ops->set_voltage_sel) {
25487ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_min_microvolts);
25497ad68e2fSDavid Brownell 		if (status < 0)
25507ad68e2fSDavid Brownell 			return status;
25517ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_max_microvolts);
25527ad68e2fSDavid Brownell 		if (status < 0)
25537ad68e2fSDavid Brownell 			return status;
25547ad68e2fSDavid Brownell 	}
25557ad68e2fSDavid Brownell 	if (ops->set_current_limit) {
25567ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_min_microamps);
25577ad68e2fSDavid Brownell 		if (status < 0)
25587ad68e2fSDavid Brownell 			return status;
25597ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_max_microamps);
25607ad68e2fSDavid Brownell 		if (status < 0)
25617ad68e2fSDavid Brownell 			return status;
25627ad68e2fSDavid Brownell 	}
25637ad68e2fSDavid Brownell 
25647ad68e2fSDavid Brownell 	/* suspend mode constraints need multiple supporting methods */
25657ad68e2fSDavid Brownell 	if (!(ops->set_suspend_enable && ops->set_suspend_disable))
25667ad68e2fSDavid Brownell 		return status;
25677ad68e2fSDavid Brownell 
25687ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_standby_state);
25697ad68e2fSDavid Brownell 	if (status < 0)
25707ad68e2fSDavid Brownell 		return status;
25717ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_mem_state);
25727ad68e2fSDavid Brownell 	if (status < 0)
25737ad68e2fSDavid Brownell 		return status;
25747ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_disk_state);
25757ad68e2fSDavid Brownell 	if (status < 0)
25767ad68e2fSDavid Brownell 		return status;
25777ad68e2fSDavid Brownell 
25787ad68e2fSDavid Brownell 	if (ops->set_suspend_voltage) {
25797ad68e2fSDavid Brownell 		status = device_create_file(dev,
25807ad68e2fSDavid Brownell 				&dev_attr_suspend_standby_microvolts);
25817ad68e2fSDavid Brownell 		if (status < 0)
25827ad68e2fSDavid Brownell 			return status;
25837ad68e2fSDavid Brownell 		status = device_create_file(dev,
25847ad68e2fSDavid Brownell 				&dev_attr_suspend_mem_microvolts);
25857ad68e2fSDavid Brownell 		if (status < 0)
25867ad68e2fSDavid Brownell 			return status;
25877ad68e2fSDavid Brownell 		status = device_create_file(dev,
25887ad68e2fSDavid Brownell 				&dev_attr_suspend_disk_microvolts);
25897ad68e2fSDavid Brownell 		if (status < 0)
25907ad68e2fSDavid Brownell 			return status;
25917ad68e2fSDavid Brownell 	}
25927ad68e2fSDavid Brownell 
25937ad68e2fSDavid Brownell 	if (ops->set_suspend_mode) {
25947ad68e2fSDavid Brownell 		status = device_create_file(dev,
25957ad68e2fSDavid Brownell 				&dev_attr_suspend_standby_mode);
25967ad68e2fSDavid Brownell 		if (status < 0)
25977ad68e2fSDavid Brownell 			return status;
25987ad68e2fSDavid Brownell 		status = device_create_file(dev,
25997ad68e2fSDavid Brownell 				&dev_attr_suspend_mem_mode);
26007ad68e2fSDavid Brownell 		if (status < 0)
26017ad68e2fSDavid Brownell 			return status;
26027ad68e2fSDavid Brownell 		status = device_create_file(dev,
26037ad68e2fSDavid Brownell 				&dev_attr_suspend_disk_mode);
26047ad68e2fSDavid Brownell 		if (status < 0)
26057ad68e2fSDavid Brownell 			return status;
26067ad68e2fSDavid Brownell 	}
26077ad68e2fSDavid Brownell 
26087ad68e2fSDavid Brownell 	return status;
26097ad68e2fSDavid Brownell }
26107ad68e2fSDavid Brownell 
26111130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev)
26121130e5b3SMark Brown {
26131130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
26141130e5b3SMark Brown 	rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
26151130e5b3SMark Brown 	if (IS_ERR(rdev->debugfs) || !rdev->debugfs) {
26161130e5b3SMark Brown 		rdev_warn(rdev, "Failed to create debugfs directory\n");
26171130e5b3SMark Brown 		rdev->debugfs = NULL;
26181130e5b3SMark Brown 		return;
26191130e5b3SMark Brown 	}
26201130e5b3SMark Brown 
26211130e5b3SMark Brown 	debugfs_create_u32("use_count", 0444, rdev->debugfs,
26221130e5b3SMark Brown 			   &rdev->use_count);
26231130e5b3SMark Brown 	debugfs_create_u32("open_count", 0444, rdev->debugfs,
26241130e5b3SMark Brown 			   &rdev->open_count);
26251130e5b3SMark Brown #endif
26261130e5b3SMark Brown }
26271130e5b3SMark Brown 
2628414c70cbSLiam Girdwood /**
2629414c70cbSLiam Girdwood  * regulator_register - register regulator
263069279fb9SMark Brown  * @regulator_desc: regulator to register
263169279fb9SMark Brown  * @dev: struct device for the regulator
26320527100fSMark Brown  * @init_data: platform provided init data, passed through by driver
263369279fb9SMark Brown  * @driver_data: private regulator data
2634414c70cbSLiam Girdwood  *
2635414c70cbSLiam Girdwood  * Called by regulator drivers to register a regulator.
2636414c70cbSLiam Girdwood  * Returns 0 on success.
2637414c70cbSLiam Girdwood  */
2638414c70cbSLiam Girdwood struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2639f8c12fe3SMark Brown 	struct device *dev, const struct regulator_init_data *init_data,
26402c043bcbSRajendra Nayak 	void *driver_data, struct device_node *of_node)
2641414c70cbSLiam Girdwood {
2642414c70cbSLiam Girdwood 	static atomic_t regulator_no = ATOMIC_INIT(0);
2643414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
2644a5766f11SLiam Girdwood 	int ret, i;
2645414c70cbSLiam Girdwood 
2646414c70cbSLiam Girdwood 	if (regulator_desc == NULL)
2647414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
2648414c70cbSLiam Girdwood 
2649414c70cbSLiam Girdwood 	if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
2650414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
2651414c70cbSLiam Girdwood 
2652cd78dfc6SDiego Liziero 	if (regulator_desc->type != REGULATOR_VOLTAGE &&
2653cd78dfc6SDiego Liziero 	    regulator_desc->type != REGULATOR_CURRENT)
2654414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
2655414c70cbSLiam Girdwood 
265646fabe1eSMark Brown 	if (!init_data)
265746fabe1eSMark Brown 		return ERR_PTR(-EINVAL);
265846fabe1eSMark Brown 
2659476c2d83SMark Brown 	/* Only one of each should be implemented */
2660476c2d83SMark Brown 	WARN_ON(regulator_desc->ops->get_voltage &&
2661476c2d83SMark Brown 		regulator_desc->ops->get_voltage_sel);
2662e8eef82bSMark Brown 	WARN_ON(regulator_desc->ops->set_voltage &&
2663e8eef82bSMark Brown 		regulator_desc->ops->set_voltage_sel);
2664476c2d83SMark Brown 
2665476c2d83SMark Brown 	/* If we're using selectors we must implement list_voltage. */
2666476c2d83SMark Brown 	if (regulator_desc->ops->get_voltage_sel &&
2667476c2d83SMark Brown 	    !regulator_desc->ops->list_voltage) {
2668476c2d83SMark Brown 		return ERR_PTR(-EINVAL);
2669476c2d83SMark Brown 	}
2670e8eef82bSMark Brown 	if (regulator_desc->ops->set_voltage_sel &&
2671e8eef82bSMark Brown 	    !regulator_desc->ops->list_voltage) {
2672e8eef82bSMark Brown 		return ERR_PTR(-EINVAL);
2673e8eef82bSMark Brown 	}
2674476c2d83SMark Brown 
2675414c70cbSLiam Girdwood 	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
2676414c70cbSLiam Girdwood 	if (rdev == NULL)
2677414c70cbSLiam Girdwood 		return ERR_PTR(-ENOMEM);
2678414c70cbSLiam Girdwood 
2679414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
2680414c70cbSLiam Girdwood 
2681414c70cbSLiam Girdwood 	mutex_init(&rdev->mutex);
2682a5766f11SLiam Girdwood 	rdev->reg_data = driver_data;
2683414c70cbSLiam Girdwood 	rdev->owner = regulator_desc->owner;
2684414c70cbSLiam Girdwood 	rdev->desc = regulator_desc;
2685414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->consumer_list);
2686414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->list);
2687414c70cbSLiam Girdwood 	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
2688da07ecd9SMark Brown 	INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
2689414c70cbSLiam Girdwood 
2690a5766f11SLiam Girdwood 	/* preform any regulator specific init */
2691a5766f11SLiam Girdwood 	if (init_data->regulator_init) {
2692a5766f11SLiam Girdwood 		ret = init_data->regulator_init(rdev->reg_data);
26934fca9545SDavid Brownell 		if (ret < 0)
26944fca9545SDavid Brownell 			goto clean;
2695a5766f11SLiam Girdwood 	}
2696a5766f11SLiam Girdwood 
2697a5766f11SLiam Girdwood 	/* register with sysfs */
2698a5766f11SLiam Girdwood 	rdev->dev.class = &regulator_class;
26992c043bcbSRajendra Nayak 	rdev->dev.of_node = of_node;
2700a5766f11SLiam Girdwood 	rdev->dev.parent = dev;
2701812460a9SKay Sievers 	dev_set_name(&rdev->dev, "regulator.%d",
2702812460a9SKay Sievers 		     atomic_inc_return(&regulator_no) - 1);
2703a5766f11SLiam Girdwood 	ret = device_register(&rdev->dev);
2704ad7725cbSVasiliy Kulikov 	if (ret != 0) {
2705ad7725cbSVasiliy Kulikov 		put_device(&rdev->dev);
27064fca9545SDavid Brownell 		goto clean;
2707ad7725cbSVasiliy Kulikov 	}
2708a5766f11SLiam Girdwood 
2709a5766f11SLiam Girdwood 	dev_set_drvdata(&rdev->dev, rdev);
2710a5766f11SLiam Girdwood 
271174f544c1SMike Rapoport 	/* set regulator constraints */
271274f544c1SMike Rapoport 	ret = set_machine_constraints(rdev, &init_data->constraints);
271374f544c1SMike Rapoport 	if (ret < 0)
271474f544c1SMike Rapoport 		goto scrub;
271574f544c1SMike Rapoport 
27167ad68e2fSDavid Brownell 	/* add attributes supported by this regulator */
27177ad68e2fSDavid Brownell 	ret = add_regulator_attributes(rdev);
27187ad68e2fSDavid Brownell 	if (ret < 0)
27197ad68e2fSDavid Brownell 		goto scrub;
27207ad68e2fSDavid Brownell 
27210178f3e2SMark Brown 	if (init_data->supply_regulator) {
27220178f3e2SMark Brown 		struct regulator_dev *r;
27230178f3e2SMark Brown 		int found = 0;
27240178f3e2SMark Brown 
27250178f3e2SMark Brown 		list_for_each_entry(r, &regulator_list, list) {
27260178f3e2SMark Brown 			if (strcmp(rdev_get_name(r),
27270178f3e2SMark Brown 				   init_data->supply_regulator) == 0) {
27280178f3e2SMark Brown 				found = 1;
27290178f3e2SMark Brown 				break;
27300178f3e2SMark Brown 			}
27310178f3e2SMark Brown 		}
27320178f3e2SMark Brown 
27330178f3e2SMark Brown 		if (!found) {
27340178f3e2SMark Brown 			dev_err(dev, "Failed to find supply %s\n",
27350178f3e2SMark Brown 				init_data->supply_regulator);
27367727da22SAxel Lin 			ret = -ENODEV;
27370178f3e2SMark Brown 			goto scrub;
27380178f3e2SMark Brown 		}
27390178f3e2SMark Brown 
27400178f3e2SMark Brown 		ret = set_supply(rdev, r);
27410178f3e2SMark Brown 		if (ret < 0)
27420178f3e2SMark Brown 			goto scrub;
27430178f3e2SMark Brown 	}
27440178f3e2SMark Brown 
2745a5766f11SLiam Girdwood 	/* add consumers devices */
2746a5766f11SLiam Girdwood 	for (i = 0; i < init_data->num_consumer_supplies; i++) {
2747a5766f11SLiam Girdwood 		ret = set_consumer_device_supply(rdev,
2748a5766f11SLiam Girdwood 			init_data->consumer_supplies[i].dev,
274940f9244fSMark Brown 			init_data->consumer_supplies[i].dev_name,
2750a5766f11SLiam Girdwood 			init_data->consumer_supplies[i].supply);
275123c2f041SMark Brown 		if (ret < 0) {
275223c2f041SMark Brown 			dev_err(dev, "Failed to set supply %s\n",
275323c2f041SMark Brown 				init_data->consumer_supplies[i].supply);
2754d4033b54SJani Nikula 			goto unset_supplies;
2755a5766f11SLiam Girdwood 		}
275623c2f041SMark Brown 	}
2757a5766f11SLiam Girdwood 
2758a5766f11SLiam Girdwood 	list_add(&rdev->list, &regulator_list);
27591130e5b3SMark Brown 
27601130e5b3SMark Brown 	rdev_init_debugfs(rdev);
2761a5766f11SLiam Girdwood out:
2762414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2763414c70cbSLiam Girdwood 	return rdev;
27644fca9545SDavid Brownell 
2765d4033b54SJani Nikula unset_supplies:
2766d4033b54SJani Nikula 	unset_regulator_supplies(rdev);
2767d4033b54SJani Nikula 
27684fca9545SDavid Brownell scrub:
27691a6958e7SAxel Lin 	kfree(rdev->constraints);
27704fca9545SDavid Brownell 	device_unregister(&rdev->dev);
277153032dafSPaul Walmsley 	/* device core frees rdev */
277253032dafSPaul Walmsley 	rdev = ERR_PTR(ret);
277353032dafSPaul Walmsley 	goto out;
277453032dafSPaul Walmsley 
27754fca9545SDavid Brownell clean:
27764fca9545SDavid Brownell 	kfree(rdev);
27774fca9545SDavid Brownell 	rdev = ERR_PTR(ret);
27784fca9545SDavid Brownell 	goto out;
2779414c70cbSLiam Girdwood }
2780414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register);
2781414c70cbSLiam Girdwood 
2782414c70cbSLiam Girdwood /**
2783414c70cbSLiam Girdwood  * regulator_unregister - unregister regulator
278469279fb9SMark Brown  * @rdev: regulator to unregister
2785414c70cbSLiam Girdwood  *
2786414c70cbSLiam Girdwood  * Called by regulator drivers to unregister a regulator.
2787414c70cbSLiam Girdwood  */
2788414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev)
2789414c70cbSLiam Girdwood {
2790414c70cbSLiam Girdwood 	if (rdev == NULL)
2791414c70cbSLiam Girdwood 		return;
2792414c70cbSLiam Girdwood 
2793414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
27941130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
27951130e5b3SMark Brown 	debugfs_remove_recursive(rdev->debugfs);
27961130e5b3SMark Brown #endif
2797da07ecd9SMark Brown 	flush_work_sync(&rdev->disable_work.work);
27986bf87d17SMark Brown 	WARN_ON(rdev->open_count);
27990f1d747bSMike Rapoport 	unset_regulator_supplies(rdev);
2800414c70cbSLiam Girdwood 	list_del(&rdev->list);
2801414c70cbSLiam Girdwood 	if (rdev->supply)
28023801b86aSMark Brown 		regulator_put(rdev->supply);
2803414c70cbSLiam Girdwood 	device_unregister(&rdev->dev);
2804f8c12fe3SMark Brown 	kfree(rdev->constraints);
2805414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2806414c70cbSLiam Girdwood }
2807414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister);
2808414c70cbSLiam Girdwood 
2809414c70cbSLiam Girdwood /**
2810cf7bbcdfSMark Brown  * regulator_suspend_prepare - prepare regulators for system wide suspend
2811414c70cbSLiam Girdwood  * @state: system suspend state
2812414c70cbSLiam Girdwood  *
2813414c70cbSLiam Girdwood  * Configure each regulator with it's suspend operating parameters for state.
2814414c70cbSLiam Girdwood  * This will usually be called by machine suspend code prior to supending.
2815414c70cbSLiam Girdwood  */
2816414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state)
2817414c70cbSLiam Girdwood {
2818414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
2819414c70cbSLiam Girdwood 	int ret = 0;
2820414c70cbSLiam Girdwood 
2821414c70cbSLiam Girdwood 	/* ON is handled by regulator active state */
2822414c70cbSLiam Girdwood 	if (state == PM_SUSPEND_ON)
2823414c70cbSLiam Girdwood 		return -EINVAL;
2824414c70cbSLiam Girdwood 
2825414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
2826414c70cbSLiam Girdwood 	list_for_each_entry(rdev, &regulator_list, list) {
2827414c70cbSLiam Girdwood 
2828414c70cbSLiam Girdwood 		mutex_lock(&rdev->mutex);
2829414c70cbSLiam Girdwood 		ret = suspend_prepare(rdev, state);
2830414c70cbSLiam Girdwood 		mutex_unlock(&rdev->mutex);
2831414c70cbSLiam Girdwood 
2832414c70cbSLiam Girdwood 		if (ret < 0) {
28335da84fd9SJoe Perches 			rdev_err(rdev, "failed to prepare\n");
2834414c70cbSLiam Girdwood 			goto out;
2835414c70cbSLiam Girdwood 		}
2836414c70cbSLiam Girdwood 	}
2837414c70cbSLiam Girdwood out:
2838414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2839414c70cbSLiam Girdwood 	return ret;
2840414c70cbSLiam Girdwood }
2841414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
2842414c70cbSLiam Girdwood 
2843414c70cbSLiam Girdwood /**
28447a32b589SMyungJoo Ham  * regulator_suspend_finish - resume regulators from system wide suspend
28457a32b589SMyungJoo Ham  *
28467a32b589SMyungJoo Ham  * Turn on regulators that might be turned off by regulator_suspend_prepare
28477a32b589SMyungJoo Ham  * and that should be turned on according to the regulators properties.
28487a32b589SMyungJoo Ham  */
28497a32b589SMyungJoo Ham int regulator_suspend_finish(void)
28507a32b589SMyungJoo Ham {
28517a32b589SMyungJoo Ham 	struct regulator_dev *rdev;
28527a32b589SMyungJoo Ham 	int ret = 0, error;
28537a32b589SMyungJoo Ham 
28547a32b589SMyungJoo Ham 	mutex_lock(&regulator_list_mutex);
28557a32b589SMyungJoo Ham 	list_for_each_entry(rdev, &regulator_list, list) {
28567a32b589SMyungJoo Ham 		struct regulator_ops *ops = rdev->desc->ops;
28577a32b589SMyungJoo Ham 
28587a32b589SMyungJoo Ham 		mutex_lock(&rdev->mutex);
28597a32b589SMyungJoo Ham 		if ((rdev->use_count > 0  || rdev->constraints->always_on) &&
28607a32b589SMyungJoo Ham 				ops->enable) {
28617a32b589SMyungJoo Ham 			error = ops->enable(rdev);
28627a32b589SMyungJoo Ham 			if (error)
28637a32b589SMyungJoo Ham 				ret = error;
28647a32b589SMyungJoo Ham 		} else {
28657a32b589SMyungJoo Ham 			if (!has_full_constraints)
28667a32b589SMyungJoo Ham 				goto unlock;
28677a32b589SMyungJoo Ham 			if (!ops->disable)
28687a32b589SMyungJoo Ham 				goto unlock;
28697a32b589SMyungJoo Ham 			if (ops->is_enabled && !ops->is_enabled(rdev))
28707a32b589SMyungJoo Ham 				goto unlock;
28717a32b589SMyungJoo Ham 
28727a32b589SMyungJoo Ham 			error = ops->disable(rdev);
28737a32b589SMyungJoo Ham 			if (error)
28747a32b589SMyungJoo Ham 				ret = error;
28757a32b589SMyungJoo Ham 		}
28767a32b589SMyungJoo Ham unlock:
28777a32b589SMyungJoo Ham 		mutex_unlock(&rdev->mutex);
28787a32b589SMyungJoo Ham 	}
28797a32b589SMyungJoo Ham 	mutex_unlock(&regulator_list_mutex);
28807a32b589SMyungJoo Ham 	return ret;
28817a32b589SMyungJoo Ham }
28827a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish);
28837a32b589SMyungJoo Ham 
28847a32b589SMyungJoo Ham /**
2885ca725561SMark Brown  * regulator_has_full_constraints - the system has fully specified constraints
2886ca725561SMark Brown  *
2887ca725561SMark Brown  * Calling this function will cause the regulator API to disable all
2888ca725561SMark Brown  * regulators which have a zero use count and don't have an always_on
2889ca725561SMark Brown  * constraint in a late_initcall.
2890ca725561SMark Brown  *
2891ca725561SMark Brown  * The intention is that this will become the default behaviour in a
2892ca725561SMark Brown  * future kernel release so users are encouraged to use this facility
2893ca725561SMark Brown  * now.
2894ca725561SMark Brown  */
2895ca725561SMark Brown void regulator_has_full_constraints(void)
2896ca725561SMark Brown {
2897ca725561SMark Brown 	has_full_constraints = 1;
2898ca725561SMark Brown }
2899ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
2900ca725561SMark Brown 
2901ca725561SMark Brown /**
2902688fe99aSMark Brown  * regulator_use_dummy_regulator - Provide a dummy regulator when none is found
2903688fe99aSMark Brown  *
2904688fe99aSMark Brown  * Calling this function will cause the regulator API to provide a
2905688fe99aSMark Brown  * dummy regulator to consumers if no physical regulator is found,
2906688fe99aSMark Brown  * allowing most consumers to proceed as though a regulator were
2907688fe99aSMark Brown  * configured.  This allows systems such as those with software
2908688fe99aSMark Brown  * controllable regulators for the CPU core only to be brought up more
2909688fe99aSMark Brown  * readily.
2910688fe99aSMark Brown  */
2911688fe99aSMark Brown void regulator_use_dummy_regulator(void)
2912688fe99aSMark Brown {
2913688fe99aSMark Brown 	board_wants_dummy_regulator = true;
2914688fe99aSMark Brown }
2915688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator);
2916688fe99aSMark Brown 
2917688fe99aSMark Brown /**
2918414c70cbSLiam Girdwood  * rdev_get_drvdata - get rdev regulator driver data
291969279fb9SMark Brown  * @rdev: regulator
2920414c70cbSLiam Girdwood  *
2921414c70cbSLiam Girdwood  * Get rdev regulator driver private data. This call can be used in the
2922414c70cbSLiam Girdwood  * regulator driver context.
2923414c70cbSLiam Girdwood  */
2924414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev)
2925414c70cbSLiam Girdwood {
2926414c70cbSLiam Girdwood 	return rdev->reg_data;
2927414c70cbSLiam Girdwood }
2928414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata);
2929414c70cbSLiam Girdwood 
2930414c70cbSLiam Girdwood /**
2931414c70cbSLiam Girdwood  * regulator_get_drvdata - get regulator driver data
2932414c70cbSLiam Girdwood  * @regulator: regulator
2933414c70cbSLiam Girdwood  *
2934414c70cbSLiam Girdwood  * Get regulator driver private data. This call can be used in the consumer
2935414c70cbSLiam Girdwood  * driver context when non API regulator specific functions need to be called.
2936414c70cbSLiam Girdwood  */
2937414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator)
2938414c70cbSLiam Girdwood {
2939414c70cbSLiam Girdwood 	return regulator->rdev->reg_data;
2940414c70cbSLiam Girdwood }
2941414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata);
2942414c70cbSLiam Girdwood 
2943414c70cbSLiam Girdwood /**
2944414c70cbSLiam Girdwood  * regulator_set_drvdata - set regulator driver data
2945414c70cbSLiam Girdwood  * @regulator: regulator
2946414c70cbSLiam Girdwood  * @data: data
2947414c70cbSLiam Girdwood  */
2948414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data)
2949414c70cbSLiam Girdwood {
2950414c70cbSLiam Girdwood 	regulator->rdev->reg_data = data;
2951414c70cbSLiam Girdwood }
2952414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata);
2953414c70cbSLiam Girdwood 
2954414c70cbSLiam Girdwood /**
2955414c70cbSLiam Girdwood  * regulator_get_id - get regulator ID
295669279fb9SMark Brown  * @rdev: regulator
2957414c70cbSLiam Girdwood  */
2958414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev)
2959414c70cbSLiam Girdwood {
2960414c70cbSLiam Girdwood 	return rdev->desc->id;
2961414c70cbSLiam Girdwood }
2962414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id);
2963414c70cbSLiam Girdwood 
2964a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev)
2965a5766f11SLiam Girdwood {
2966a5766f11SLiam Girdwood 	return &rdev->dev;
2967a5766f11SLiam Girdwood }
2968a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev);
2969a5766f11SLiam Girdwood 
2970a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
2971a5766f11SLiam Girdwood {
2972a5766f11SLiam Girdwood 	return reg_init_data->driver_data;
2973a5766f11SLiam Girdwood }
2974a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
2975a5766f11SLiam Girdwood 
2976ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS
2977ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf,
2978ba55a974SMark Brown 				    size_t count, loff_t *ppos)
2979ba55a974SMark Brown {
2980ba55a974SMark Brown 	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
2981ba55a974SMark Brown 	ssize_t len, ret = 0;
2982ba55a974SMark Brown 	struct regulator_map *map;
2983ba55a974SMark Brown 
2984ba55a974SMark Brown 	if (!buf)
2985ba55a974SMark Brown 		return -ENOMEM;
2986ba55a974SMark Brown 
2987ba55a974SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
2988ba55a974SMark Brown 		len = snprintf(buf + ret, PAGE_SIZE - ret,
2989ba55a974SMark Brown 			       "%s -> %s.%s\n",
2990ba55a974SMark Brown 			       rdev_get_name(map->regulator), map->dev_name,
2991ba55a974SMark Brown 			       map->supply);
2992ba55a974SMark Brown 		if (len >= 0)
2993ba55a974SMark Brown 			ret += len;
2994ba55a974SMark Brown 		if (ret > PAGE_SIZE) {
2995ba55a974SMark Brown 			ret = PAGE_SIZE;
2996ba55a974SMark Brown 			break;
2997ba55a974SMark Brown 		}
2998ba55a974SMark Brown 	}
2999ba55a974SMark Brown 
3000ba55a974SMark Brown 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
3001ba55a974SMark Brown 
3002ba55a974SMark Brown 	kfree(buf);
3003ba55a974SMark Brown 
3004ba55a974SMark Brown 	return ret;
3005ba55a974SMark Brown }
3006ba55a974SMark Brown 
3007ba55a974SMark Brown static const struct file_operations supply_map_fops = {
3008ba55a974SMark Brown 	.read = supply_map_read_file,
3009ba55a974SMark Brown 	.llseek = default_llseek,
3010ba55a974SMark Brown };
3011ba55a974SMark Brown #endif
3012ba55a974SMark Brown 
3013414c70cbSLiam Girdwood static int __init regulator_init(void)
3014414c70cbSLiam Girdwood {
301534abbd68SMark Brown 	int ret;
301634abbd68SMark Brown 
301734abbd68SMark Brown 	ret = class_register(&regulator_class);
301834abbd68SMark Brown 
30191130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
30201130e5b3SMark Brown 	debugfs_root = debugfs_create_dir("regulator", NULL);
30211130e5b3SMark Brown 	if (IS_ERR(debugfs_root) || !debugfs_root) {
30221130e5b3SMark Brown 		pr_warn("regulator: Failed to create debugfs directory\n");
30231130e5b3SMark Brown 		debugfs_root = NULL;
30241130e5b3SMark Brown 	}
3025ba55a974SMark Brown 
3026ba55a974SMark Brown 	if (IS_ERR(debugfs_create_file("supply_map", 0444, debugfs_root,
3027ba55a974SMark Brown 				       NULL, &supply_map_fops)))
3028ba55a974SMark Brown 		pr_warn("regulator: Failed to create supplies debugfs\n");
30291130e5b3SMark Brown #endif
30301130e5b3SMark Brown 
303134abbd68SMark Brown 	regulator_dummy_init();
303234abbd68SMark Brown 
303334abbd68SMark Brown 	return ret;
3034414c70cbSLiam Girdwood }
3035414c70cbSLiam Girdwood 
3036414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */
3037414c70cbSLiam Girdwood core_initcall(regulator_init);
3038ca725561SMark Brown 
3039ca725561SMark Brown static int __init regulator_init_complete(void)
3040ca725561SMark Brown {
3041ca725561SMark Brown 	struct regulator_dev *rdev;
3042ca725561SMark Brown 	struct regulator_ops *ops;
3043ca725561SMark Brown 	struct regulation_constraints *c;
3044ca725561SMark Brown 	int enabled, ret;
3045ca725561SMark Brown 
3046ca725561SMark Brown 	mutex_lock(&regulator_list_mutex);
3047ca725561SMark Brown 
3048ca725561SMark Brown 	/* If we have a full configuration then disable any regulators
3049ca725561SMark Brown 	 * which are not in use or always_on.  This will become the
3050ca725561SMark Brown 	 * default behaviour in the future.
3051ca725561SMark Brown 	 */
3052ca725561SMark Brown 	list_for_each_entry(rdev, &regulator_list, list) {
3053ca725561SMark Brown 		ops = rdev->desc->ops;
3054ca725561SMark Brown 		c = rdev->constraints;
3055ca725561SMark Brown 
3056f25e0b4fSMark Brown 		if (!ops->disable || (c && c->always_on))
3057ca725561SMark Brown 			continue;
3058ca725561SMark Brown 
3059ca725561SMark Brown 		mutex_lock(&rdev->mutex);
3060ca725561SMark Brown 
3061ca725561SMark Brown 		if (rdev->use_count)
3062ca725561SMark Brown 			goto unlock;
3063ca725561SMark Brown 
3064ca725561SMark Brown 		/* If we can't read the status assume it's on. */
3065ca725561SMark Brown 		if (ops->is_enabled)
3066ca725561SMark Brown 			enabled = ops->is_enabled(rdev);
3067ca725561SMark Brown 		else
3068ca725561SMark Brown 			enabled = 1;
3069ca725561SMark Brown 
3070ca725561SMark Brown 		if (!enabled)
3071ca725561SMark Brown 			goto unlock;
3072ca725561SMark Brown 
3073ca725561SMark Brown 		if (has_full_constraints) {
3074ca725561SMark Brown 			/* We log since this may kill the system if it
3075ca725561SMark Brown 			 * goes wrong. */
30765da84fd9SJoe Perches 			rdev_info(rdev, "disabling\n");
3077ca725561SMark Brown 			ret = ops->disable(rdev);
3078ca725561SMark Brown 			if (ret != 0) {
30795da84fd9SJoe Perches 				rdev_err(rdev, "couldn't disable: %d\n", ret);
3080ca725561SMark Brown 			}
3081ca725561SMark Brown 		} else {
3082ca725561SMark Brown 			/* The intention is that in future we will
3083ca725561SMark Brown 			 * assume that full constraints are provided
3084ca725561SMark Brown 			 * so warn even if we aren't going to do
3085ca725561SMark Brown 			 * anything here.
3086ca725561SMark Brown 			 */
30875da84fd9SJoe Perches 			rdev_warn(rdev, "incomplete constraints, leaving on\n");
3088ca725561SMark Brown 		}
3089ca725561SMark Brown 
3090ca725561SMark Brown unlock:
3091ca725561SMark Brown 		mutex_unlock(&rdev->mutex);
3092ca725561SMark Brown 	}
3093ca725561SMark Brown 
3094ca725561SMark Brown 	mutex_unlock(&regulator_list_mutex);
3095ca725561SMark Brown 
3096ca725561SMark Brown 	return 0;
3097ca725561SMark Brown }
3098ca725561SMark Brown late_initcall(regulator_init_complete);
3099