xref: /openbmc/linux/drivers/regulator/core.c (revision d1685e4e)
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>
31414c70cbSLiam Girdwood 
3202fa3ec0SMark Brown #define CREATE_TRACE_POINTS
3302fa3ec0SMark Brown #include <trace/events/regulator.h>
3402fa3ec0SMark Brown 
3534abbd68SMark Brown #include "dummy.h"
3634abbd68SMark Brown 
377d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...)					\
387d51a0dbSMark Brown 	pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
395da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...)					\
405da84fd9SJoe Perches 	pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
415da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...)					\
425da84fd9SJoe Perches 	pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
435da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...)					\
445da84fd9SJoe Perches 	pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
455da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...)					\
465da84fd9SJoe Perches 	pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
475da84fd9SJoe Perches 
48414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex);
49414c70cbSLiam Girdwood static LIST_HEAD(regulator_list);
50414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list);
5121cf891aSMark Brown static bool has_full_constraints;
52688fe99aSMark Brown static bool board_wants_dummy_regulator;
53414c70cbSLiam Girdwood 
541130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
551130e5b3SMark Brown static struct dentry *debugfs_root;
561130e5b3SMark Brown #endif
571130e5b3SMark Brown 
588dc5390dSMark Brown /*
59414c70cbSLiam Girdwood  * struct regulator_map
60414c70cbSLiam Girdwood  *
61414c70cbSLiam Girdwood  * Used to provide symbolic supply names to devices.
62414c70cbSLiam Girdwood  */
63414c70cbSLiam Girdwood struct regulator_map {
64414c70cbSLiam Girdwood 	struct list_head list;
6540f9244fSMark Brown 	const char *dev_name;   /* The dev_name() for the consumer */
66414c70cbSLiam Girdwood 	const char *supply;
67a5766f11SLiam Girdwood 	struct regulator_dev *regulator;
68414c70cbSLiam Girdwood };
69414c70cbSLiam Girdwood 
70414c70cbSLiam Girdwood /*
71414c70cbSLiam Girdwood  * struct regulator
72414c70cbSLiam Girdwood  *
73414c70cbSLiam Girdwood  * One for each consumer device.
74414c70cbSLiam Girdwood  */
75414c70cbSLiam Girdwood struct regulator {
76414c70cbSLiam Girdwood 	struct device *dev;
77414c70cbSLiam Girdwood 	struct list_head list;
78414c70cbSLiam Girdwood 	int uA_load;
79414c70cbSLiam Girdwood 	int min_uV;
80414c70cbSLiam Girdwood 	int max_uV;
81414c70cbSLiam Girdwood 	char *supply_name;
82414c70cbSLiam Girdwood 	struct device_attribute dev_attr;
83414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
845de70519SMark Brown #ifdef CONFIG_DEBUG_FS
855de70519SMark Brown 	struct dentry *debugfs;
865de70519SMark Brown #endif
87414c70cbSLiam Girdwood };
88414c70cbSLiam Girdwood 
89414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev);
903801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev);
91414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev);
92414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev);
93414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
94414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev,
95414c70cbSLiam Girdwood 				  unsigned long event, void *data);
9675790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
9775790251SMark Brown 				     int min_uV, int max_uV);
983801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev,
993801b86aSMark Brown 					  struct device *dev,
1003801b86aSMark Brown 					  const char *supply_name);
101414c70cbSLiam Girdwood 
1021083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev)
1031083c393SMark Brown {
1041083c393SMark Brown 	if (rdev->constraints && rdev->constraints->name)
1051083c393SMark Brown 		return rdev->constraints->name;
1061083c393SMark Brown 	else if (rdev->desc->name)
1071083c393SMark Brown 		return rdev->desc->name;
1081083c393SMark Brown 	else
1091083c393SMark Brown 		return "";
1101083c393SMark Brown }
1111083c393SMark Brown 
112414c70cbSLiam Girdwood /* gets the regulator for a given consumer device */
113414c70cbSLiam Girdwood static struct regulator *get_device_regulator(struct device *dev)
114414c70cbSLiam Girdwood {
115414c70cbSLiam Girdwood 	struct regulator *regulator = NULL;
116414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
117414c70cbSLiam Girdwood 
118414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
119414c70cbSLiam Girdwood 	list_for_each_entry(rdev, &regulator_list, list) {
120414c70cbSLiam Girdwood 		mutex_lock(&rdev->mutex);
121414c70cbSLiam Girdwood 		list_for_each_entry(regulator, &rdev->consumer_list, list) {
122414c70cbSLiam Girdwood 			if (regulator->dev == dev) {
123414c70cbSLiam Girdwood 				mutex_unlock(&rdev->mutex);
124414c70cbSLiam Girdwood 				mutex_unlock(&regulator_list_mutex);
125414c70cbSLiam Girdwood 				return regulator;
126414c70cbSLiam Girdwood 			}
127414c70cbSLiam Girdwood 		}
128414c70cbSLiam Girdwood 		mutex_unlock(&rdev->mutex);
129414c70cbSLiam Girdwood 	}
130414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
131414c70cbSLiam Girdwood 	return NULL;
132414c70cbSLiam Girdwood }
133414c70cbSLiam Girdwood 
134414c70cbSLiam Girdwood /* Platform voltage constraint check */
135414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev,
136414c70cbSLiam Girdwood 				   int *min_uV, int *max_uV)
137414c70cbSLiam Girdwood {
138414c70cbSLiam Girdwood 	BUG_ON(*min_uV > *max_uV);
139414c70cbSLiam Girdwood 
140414c70cbSLiam Girdwood 	if (!rdev->constraints) {
1415da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
142414c70cbSLiam Girdwood 		return -ENODEV;
143414c70cbSLiam Girdwood 	}
144414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
1455da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
146414c70cbSLiam Girdwood 		return -EPERM;
147414c70cbSLiam Girdwood 	}
148414c70cbSLiam Girdwood 
149414c70cbSLiam Girdwood 	if (*max_uV > rdev->constraints->max_uV)
150414c70cbSLiam Girdwood 		*max_uV = rdev->constraints->max_uV;
151414c70cbSLiam Girdwood 	if (*min_uV < rdev->constraints->min_uV)
152414c70cbSLiam Girdwood 		*min_uV = rdev->constraints->min_uV;
153414c70cbSLiam Girdwood 
15489f425edSMark Brown 	if (*min_uV > *max_uV) {
15589f425edSMark Brown 		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
15654abd335SMark Brown 			 *min_uV, *max_uV);
157414c70cbSLiam Girdwood 		return -EINVAL;
15889f425edSMark Brown 	}
159414c70cbSLiam Girdwood 
160414c70cbSLiam Girdwood 	return 0;
161414c70cbSLiam Girdwood }
162414c70cbSLiam Girdwood 
16305fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all
16405fda3b1SThomas Petazzoni  * regulator consumers
16505fda3b1SThomas Petazzoni  */
16605fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev,
16705fda3b1SThomas Petazzoni 				     int *min_uV, int *max_uV)
16805fda3b1SThomas Petazzoni {
16905fda3b1SThomas Petazzoni 	struct regulator *regulator;
17005fda3b1SThomas Petazzoni 
17105fda3b1SThomas Petazzoni 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
1724aa922c0SMark Brown 		/*
1734aa922c0SMark Brown 		 * Assume consumers that didn't say anything are OK
1744aa922c0SMark Brown 		 * with anything in the constraint range.
1754aa922c0SMark Brown 		 */
1764aa922c0SMark Brown 		if (!regulator->min_uV && !regulator->max_uV)
1774aa922c0SMark Brown 			continue;
1784aa922c0SMark Brown 
17905fda3b1SThomas Petazzoni 		if (*max_uV > regulator->max_uV)
18005fda3b1SThomas Petazzoni 			*max_uV = regulator->max_uV;
18105fda3b1SThomas Petazzoni 		if (*min_uV < regulator->min_uV)
18205fda3b1SThomas Petazzoni 			*min_uV = regulator->min_uV;
18305fda3b1SThomas Petazzoni 	}
18405fda3b1SThomas Petazzoni 
18505fda3b1SThomas Petazzoni 	if (*min_uV > *max_uV)
18605fda3b1SThomas Petazzoni 		return -EINVAL;
18705fda3b1SThomas Petazzoni 
18805fda3b1SThomas Petazzoni 	return 0;
18905fda3b1SThomas Petazzoni }
19005fda3b1SThomas Petazzoni 
191414c70cbSLiam Girdwood /* current constraint check */
192414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev,
193414c70cbSLiam Girdwood 					int *min_uA, int *max_uA)
194414c70cbSLiam Girdwood {
195414c70cbSLiam Girdwood 	BUG_ON(*min_uA > *max_uA);
196414c70cbSLiam Girdwood 
197414c70cbSLiam Girdwood 	if (!rdev->constraints) {
1985da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
199414c70cbSLiam Girdwood 		return -ENODEV;
200414c70cbSLiam Girdwood 	}
201414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
2025da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
203414c70cbSLiam Girdwood 		return -EPERM;
204414c70cbSLiam Girdwood 	}
205414c70cbSLiam Girdwood 
206414c70cbSLiam Girdwood 	if (*max_uA > rdev->constraints->max_uA)
207414c70cbSLiam Girdwood 		*max_uA = rdev->constraints->max_uA;
208414c70cbSLiam Girdwood 	if (*min_uA < rdev->constraints->min_uA)
209414c70cbSLiam Girdwood 		*min_uA = rdev->constraints->min_uA;
210414c70cbSLiam Girdwood 
21189f425edSMark Brown 	if (*min_uA > *max_uA) {
21289f425edSMark Brown 		rdev_err(rdev, "unsupportable current range: %d-%duA\n",
21354abd335SMark Brown 			 *min_uA, *max_uA);
214414c70cbSLiam Girdwood 		return -EINVAL;
21589f425edSMark Brown 	}
216414c70cbSLiam Girdwood 
217414c70cbSLiam Girdwood 	return 0;
218414c70cbSLiam Girdwood }
219414c70cbSLiam Girdwood 
220414c70cbSLiam Girdwood /* operating mode constraint check */
2212c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
222414c70cbSLiam Girdwood {
2232c608234SMark Brown 	switch (*mode) {
224e573520bSDavid Brownell 	case REGULATOR_MODE_FAST:
225e573520bSDavid Brownell 	case REGULATOR_MODE_NORMAL:
226e573520bSDavid Brownell 	case REGULATOR_MODE_IDLE:
227e573520bSDavid Brownell 	case REGULATOR_MODE_STANDBY:
228e573520bSDavid Brownell 		break;
229e573520bSDavid Brownell 	default:
23089f425edSMark Brown 		rdev_err(rdev, "invalid mode %x specified\n", *mode);
231e573520bSDavid Brownell 		return -EINVAL;
232e573520bSDavid Brownell 	}
233e573520bSDavid Brownell 
234414c70cbSLiam Girdwood 	if (!rdev->constraints) {
2355da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
236414c70cbSLiam Girdwood 		return -ENODEV;
237414c70cbSLiam Girdwood 	}
238414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
2395da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
240414c70cbSLiam Girdwood 		return -EPERM;
241414c70cbSLiam Girdwood 	}
2422c608234SMark Brown 
2432c608234SMark Brown 	/* The modes are bitmasks, the most power hungry modes having
2442c608234SMark Brown 	 * the lowest values. If the requested mode isn't supported
2452c608234SMark Brown 	 * try higher modes. */
2462c608234SMark Brown 	while (*mode) {
2472c608234SMark Brown 		if (rdev->constraints->valid_modes_mask & *mode)
248414c70cbSLiam Girdwood 			return 0;
2492c608234SMark Brown 		*mode /= 2;
2502c608234SMark Brown 	}
2512c608234SMark Brown 
2522c608234SMark Brown 	return -EINVAL;
253414c70cbSLiam Girdwood }
254414c70cbSLiam Girdwood 
255414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */
256414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev)
257414c70cbSLiam Girdwood {
258414c70cbSLiam Girdwood 	if (!rdev->constraints) {
2595da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
260414c70cbSLiam Girdwood 		return -ENODEV;
261414c70cbSLiam Girdwood 	}
262414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
2635da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
264414c70cbSLiam Girdwood 		return -EPERM;
265414c70cbSLiam Girdwood 	}
266414c70cbSLiam Girdwood 	return 0;
267414c70cbSLiam Girdwood }
268414c70cbSLiam Girdwood 
269414c70cbSLiam Girdwood static ssize_t device_requested_uA_show(struct device *dev,
270414c70cbSLiam Girdwood 			     struct device_attribute *attr, char *buf)
271414c70cbSLiam Girdwood {
272414c70cbSLiam Girdwood 	struct regulator *regulator;
273414c70cbSLiam Girdwood 
274414c70cbSLiam Girdwood 	regulator = get_device_regulator(dev);
275414c70cbSLiam Girdwood 	if (regulator == NULL)
276414c70cbSLiam Girdwood 		return 0;
277414c70cbSLiam Girdwood 
278414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", regulator->uA_load);
279414c70cbSLiam Girdwood }
280414c70cbSLiam Girdwood 
281414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev,
282414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
283414c70cbSLiam Girdwood {
284a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
285414c70cbSLiam Girdwood 	ssize_t ret;
286414c70cbSLiam Girdwood 
287414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
288414c70cbSLiam Girdwood 	ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev));
289414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
290414c70cbSLiam Girdwood 
291414c70cbSLiam Girdwood 	return ret;
292414c70cbSLiam Girdwood }
2937ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);
294414c70cbSLiam Girdwood 
295414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev,
296414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
297414c70cbSLiam Girdwood {
298a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
299414c70cbSLiam Girdwood 
300414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
301414c70cbSLiam Girdwood }
3027ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);
303414c70cbSLiam Girdwood 
304bc558a60SMark Brown static ssize_t regulator_name_show(struct device *dev,
305bc558a60SMark Brown 			     struct device_attribute *attr, char *buf)
306bc558a60SMark Brown {
307bc558a60SMark Brown 	struct regulator_dev *rdev = dev_get_drvdata(dev);
308bc558a60SMark Brown 
3091083c393SMark Brown 	return sprintf(buf, "%s\n", rdev_get_name(rdev));
310bc558a60SMark Brown }
311bc558a60SMark Brown 
3124fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode)
313414c70cbSLiam Girdwood {
314414c70cbSLiam Girdwood 	switch (mode) {
315414c70cbSLiam Girdwood 	case REGULATOR_MODE_FAST:
316414c70cbSLiam Girdwood 		return sprintf(buf, "fast\n");
317414c70cbSLiam Girdwood 	case REGULATOR_MODE_NORMAL:
318414c70cbSLiam Girdwood 		return sprintf(buf, "normal\n");
319414c70cbSLiam Girdwood 	case REGULATOR_MODE_IDLE:
320414c70cbSLiam Girdwood 		return sprintf(buf, "idle\n");
321414c70cbSLiam Girdwood 	case REGULATOR_MODE_STANDBY:
322414c70cbSLiam Girdwood 		return sprintf(buf, "standby\n");
323414c70cbSLiam Girdwood 	}
324414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
325414c70cbSLiam Girdwood }
326414c70cbSLiam Girdwood 
3274fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev,
328414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
329414c70cbSLiam Girdwood {
330a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
331414c70cbSLiam Girdwood 
3324fca9545SDavid Brownell 	return regulator_print_opmode(buf, _regulator_get_mode(rdev));
3334fca9545SDavid Brownell }
3347ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL);
3354fca9545SDavid Brownell 
3364fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state)
3374fca9545SDavid Brownell {
338414c70cbSLiam Girdwood 	if (state > 0)
339414c70cbSLiam Girdwood 		return sprintf(buf, "enabled\n");
340414c70cbSLiam Girdwood 	else if (state == 0)
341414c70cbSLiam Girdwood 		return sprintf(buf, "disabled\n");
342414c70cbSLiam Girdwood 	else
343414c70cbSLiam Girdwood 		return sprintf(buf, "unknown\n");
344414c70cbSLiam Girdwood }
345414c70cbSLiam Girdwood 
3464fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev,
3474fca9545SDavid Brownell 				   struct device_attribute *attr, char *buf)
3484fca9545SDavid Brownell {
3494fca9545SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
3509332546fSMark Brown 	ssize_t ret;
3514fca9545SDavid Brownell 
3529332546fSMark Brown 	mutex_lock(&rdev->mutex);
3539332546fSMark Brown 	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
3549332546fSMark Brown 	mutex_unlock(&rdev->mutex);
3559332546fSMark Brown 
3569332546fSMark Brown 	return ret;
3574fca9545SDavid Brownell }
3587ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
3594fca9545SDavid Brownell 
360853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev,
361853116a1SDavid Brownell 				   struct device_attribute *attr, char *buf)
362853116a1SDavid Brownell {
363853116a1SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
364853116a1SDavid Brownell 	int status;
365853116a1SDavid Brownell 	char *label;
366853116a1SDavid Brownell 
367853116a1SDavid Brownell 	status = rdev->desc->ops->get_status(rdev);
368853116a1SDavid Brownell 	if (status < 0)
369853116a1SDavid Brownell 		return status;
370853116a1SDavid Brownell 
371853116a1SDavid Brownell 	switch (status) {
372853116a1SDavid Brownell 	case REGULATOR_STATUS_OFF:
373853116a1SDavid Brownell 		label = "off";
374853116a1SDavid Brownell 		break;
375853116a1SDavid Brownell 	case REGULATOR_STATUS_ON:
376853116a1SDavid Brownell 		label = "on";
377853116a1SDavid Brownell 		break;
378853116a1SDavid Brownell 	case REGULATOR_STATUS_ERROR:
379853116a1SDavid Brownell 		label = "error";
380853116a1SDavid Brownell 		break;
381853116a1SDavid Brownell 	case REGULATOR_STATUS_FAST:
382853116a1SDavid Brownell 		label = "fast";
383853116a1SDavid Brownell 		break;
384853116a1SDavid Brownell 	case REGULATOR_STATUS_NORMAL:
385853116a1SDavid Brownell 		label = "normal";
386853116a1SDavid Brownell 		break;
387853116a1SDavid Brownell 	case REGULATOR_STATUS_IDLE:
388853116a1SDavid Brownell 		label = "idle";
389853116a1SDavid Brownell 		break;
390853116a1SDavid Brownell 	case REGULATOR_STATUS_STANDBY:
391853116a1SDavid Brownell 		label = "standby";
392853116a1SDavid Brownell 		break;
393853116a1SDavid Brownell 	default:
394853116a1SDavid Brownell 		return -ERANGE;
395853116a1SDavid Brownell 	}
396853116a1SDavid Brownell 
397853116a1SDavid Brownell 	return sprintf(buf, "%s\n", label);
398853116a1SDavid Brownell }
399853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL);
400853116a1SDavid Brownell 
401414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev,
402414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
403414c70cbSLiam Girdwood {
404a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
405414c70cbSLiam Girdwood 
406414c70cbSLiam Girdwood 	if (!rdev->constraints)
407414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
408414c70cbSLiam Girdwood 
409414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uA);
410414c70cbSLiam Girdwood }
4117ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL);
412414c70cbSLiam Girdwood 
413414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev,
414414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
415414c70cbSLiam Girdwood {
416a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
417414c70cbSLiam Girdwood 
418414c70cbSLiam Girdwood 	if (!rdev->constraints)
419414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
420414c70cbSLiam Girdwood 
421414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uA);
422414c70cbSLiam Girdwood }
4237ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL);
424414c70cbSLiam Girdwood 
425414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev,
426414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
427414c70cbSLiam Girdwood {
428a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
429414c70cbSLiam Girdwood 
430414c70cbSLiam Girdwood 	if (!rdev->constraints)
431414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
432414c70cbSLiam Girdwood 
433414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uV);
434414c70cbSLiam Girdwood }
4357ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL);
436414c70cbSLiam Girdwood 
437414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev,
438414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
439414c70cbSLiam Girdwood {
440a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
441414c70cbSLiam Girdwood 
442414c70cbSLiam Girdwood 	if (!rdev->constraints)
443414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
444414c70cbSLiam Girdwood 
445414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uV);
446414c70cbSLiam Girdwood }
4477ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL);
448414c70cbSLiam Girdwood 
449414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev,
450414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
451414c70cbSLiam Girdwood {
452a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
453414c70cbSLiam Girdwood 	struct regulator *regulator;
454414c70cbSLiam Girdwood 	int uA = 0;
455414c70cbSLiam Girdwood 
456414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
457414c70cbSLiam Girdwood 	list_for_each_entry(regulator, &rdev->consumer_list, list)
458414c70cbSLiam Girdwood 		uA += regulator->uA_load;
459414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
460414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", uA);
461414c70cbSLiam Girdwood }
4627ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
463414c70cbSLiam Girdwood 
464414c70cbSLiam Girdwood static ssize_t regulator_num_users_show(struct device *dev,
465414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
466414c70cbSLiam Girdwood {
467a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
468414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->use_count);
469414c70cbSLiam Girdwood }
470414c70cbSLiam Girdwood 
471414c70cbSLiam Girdwood static ssize_t regulator_type_show(struct device *dev,
472414c70cbSLiam Girdwood 				  struct device_attribute *attr, char *buf)
473414c70cbSLiam Girdwood {
474a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
475414c70cbSLiam Girdwood 
476414c70cbSLiam Girdwood 	switch (rdev->desc->type) {
477414c70cbSLiam Girdwood 	case REGULATOR_VOLTAGE:
478414c70cbSLiam Girdwood 		return sprintf(buf, "voltage\n");
479414c70cbSLiam Girdwood 	case REGULATOR_CURRENT:
480414c70cbSLiam Girdwood 		return sprintf(buf, "current\n");
481414c70cbSLiam Girdwood 	}
482414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
483414c70cbSLiam Girdwood }
484414c70cbSLiam Girdwood 
485414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
486414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
487414c70cbSLiam Girdwood {
488a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
489414c70cbSLiam Girdwood 
490414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
491414c70cbSLiam Girdwood }
4927ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444,
4937ad68e2fSDavid Brownell 		regulator_suspend_mem_uV_show, NULL);
494414c70cbSLiam Girdwood 
495414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
496414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
497414c70cbSLiam Girdwood {
498a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
499414c70cbSLiam Girdwood 
500414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
501414c70cbSLiam Girdwood }
5027ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444,
5037ad68e2fSDavid Brownell 		regulator_suspend_disk_uV_show, NULL);
504414c70cbSLiam Girdwood 
505414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
506414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
507414c70cbSLiam Girdwood {
508a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
509414c70cbSLiam Girdwood 
510414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
511414c70cbSLiam Girdwood }
5127ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444,
5137ad68e2fSDavid Brownell 		regulator_suspend_standby_uV_show, NULL);
514414c70cbSLiam Girdwood 
515414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
516414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
517414c70cbSLiam Girdwood {
518a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
519414c70cbSLiam Girdwood 
5204fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5214fca9545SDavid Brownell 		rdev->constraints->state_mem.mode);
522414c70cbSLiam Girdwood }
5237ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444,
5247ad68e2fSDavid Brownell 		regulator_suspend_mem_mode_show, NULL);
525414c70cbSLiam Girdwood 
526414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
527414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
528414c70cbSLiam Girdwood {
529a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
530414c70cbSLiam Girdwood 
5314fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5324fca9545SDavid Brownell 		rdev->constraints->state_disk.mode);
533414c70cbSLiam Girdwood }
5347ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444,
5357ad68e2fSDavid Brownell 		regulator_suspend_disk_mode_show, NULL);
536414c70cbSLiam Girdwood 
537414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
538414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
539414c70cbSLiam Girdwood {
540a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
541414c70cbSLiam Girdwood 
5424fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5434fca9545SDavid Brownell 		rdev->constraints->state_standby.mode);
544414c70cbSLiam Girdwood }
5457ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444,
5467ad68e2fSDavid Brownell 		regulator_suspend_standby_mode_show, NULL);
547414c70cbSLiam Girdwood 
548414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev,
549414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
550414c70cbSLiam Girdwood {
551a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
552414c70cbSLiam Girdwood 
5534fca9545SDavid Brownell 	return regulator_print_state(buf,
5544fca9545SDavid Brownell 			rdev->constraints->state_mem.enabled);
555414c70cbSLiam Girdwood }
5567ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444,
5577ad68e2fSDavid Brownell 		regulator_suspend_mem_state_show, NULL);
558414c70cbSLiam Girdwood 
559414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev,
560414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
561414c70cbSLiam Girdwood {
562a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
563414c70cbSLiam Girdwood 
5644fca9545SDavid Brownell 	return regulator_print_state(buf,
5654fca9545SDavid Brownell 			rdev->constraints->state_disk.enabled);
566414c70cbSLiam Girdwood }
5677ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444,
5687ad68e2fSDavid Brownell 		regulator_suspend_disk_state_show, NULL);
569414c70cbSLiam Girdwood 
570414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev,
571414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
572414c70cbSLiam Girdwood {
573a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
574414c70cbSLiam Girdwood 
5754fca9545SDavid Brownell 	return regulator_print_state(buf,
5764fca9545SDavid Brownell 			rdev->constraints->state_standby.enabled);
577414c70cbSLiam Girdwood }
5787ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444,
5797ad68e2fSDavid Brownell 		regulator_suspend_standby_state_show, NULL);
580bc558a60SMark Brown 
5817ad68e2fSDavid Brownell 
5827ad68e2fSDavid Brownell /*
5837ad68e2fSDavid Brownell  * These are the only attributes are present for all regulators.
5847ad68e2fSDavid Brownell  * Other attributes are a function of regulator functionality.
5857ad68e2fSDavid Brownell  */
586414c70cbSLiam Girdwood static struct device_attribute regulator_dev_attrs[] = {
587bc558a60SMark Brown 	__ATTR(name, 0444, regulator_name_show, NULL),
588414c70cbSLiam Girdwood 	__ATTR(num_users, 0444, regulator_num_users_show, NULL),
589414c70cbSLiam Girdwood 	__ATTR(type, 0444, regulator_type_show, NULL),
590414c70cbSLiam Girdwood 	__ATTR_NULL,
591414c70cbSLiam Girdwood };
592414c70cbSLiam Girdwood 
593414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev)
594414c70cbSLiam Girdwood {
595a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
596414c70cbSLiam Girdwood 	kfree(rdev);
597414c70cbSLiam Girdwood }
598414c70cbSLiam Girdwood 
599414c70cbSLiam Girdwood static struct class regulator_class = {
600414c70cbSLiam Girdwood 	.name = "regulator",
601414c70cbSLiam Girdwood 	.dev_release = regulator_dev_release,
602414c70cbSLiam Girdwood 	.dev_attrs = regulator_dev_attrs,
603414c70cbSLiam Girdwood };
604414c70cbSLiam Girdwood 
605414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total
606414c70cbSLiam Girdwood  * consumer load. All locks held by caller */
607414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev)
608414c70cbSLiam Girdwood {
609414c70cbSLiam Girdwood 	struct regulator *sibling;
610414c70cbSLiam Girdwood 	int current_uA = 0, output_uV, input_uV, err;
611414c70cbSLiam Girdwood 	unsigned int mode;
612414c70cbSLiam Girdwood 
613414c70cbSLiam Girdwood 	err = regulator_check_drms(rdev);
614414c70cbSLiam Girdwood 	if (err < 0 || !rdev->desc->ops->get_optimum_mode ||
615476c2d83SMark Brown 	    (!rdev->desc->ops->get_voltage &&
616476c2d83SMark Brown 	     !rdev->desc->ops->get_voltage_sel) ||
617476c2d83SMark Brown 	    !rdev->desc->ops->set_mode)
618414c70cbSLiam Girdwood 		return;
619414c70cbSLiam Girdwood 
620414c70cbSLiam Girdwood 	/* get output voltage */
6211bf5a1f8SMark Brown 	output_uV = _regulator_get_voltage(rdev);
622414c70cbSLiam Girdwood 	if (output_uV <= 0)
623414c70cbSLiam Girdwood 		return;
624414c70cbSLiam Girdwood 
625414c70cbSLiam Girdwood 	/* get input voltage */
6261bf5a1f8SMark Brown 	input_uV = 0;
6271bf5a1f8SMark Brown 	if (rdev->supply)
6281bf5a1f8SMark Brown 		input_uV = _regulator_get_voltage(rdev);
6291bf5a1f8SMark Brown 	if (input_uV <= 0)
630414c70cbSLiam Girdwood 		input_uV = rdev->constraints->input_uV;
631414c70cbSLiam Girdwood 	if (input_uV <= 0)
632414c70cbSLiam Girdwood 		return;
633414c70cbSLiam Girdwood 
634414c70cbSLiam Girdwood 	/* calc total requested load */
635414c70cbSLiam Girdwood 	list_for_each_entry(sibling, &rdev->consumer_list, list)
636414c70cbSLiam Girdwood 		current_uA += sibling->uA_load;
637414c70cbSLiam Girdwood 
638414c70cbSLiam Girdwood 	/* now get the optimum mode for our new total regulator load */
639414c70cbSLiam Girdwood 	mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
640414c70cbSLiam Girdwood 						  output_uV, current_uA);
641414c70cbSLiam Girdwood 
642414c70cbSLiam Girdwood 	/* check the new mode is allowed */
6432c608234SMark Brown 	err = regulator_mode_constrain(rdev, &mode);
644414c70cbSLiam Girdwood 	if (err == 0)
645414c70cbSLiam Girdwood 		rdev->desc->ops->set_mode(rdev, mode);
646414c70cbSLiam Girdwood }
647414c70cbSLiam Girdwood 
648414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev,
649414c70cbSLiam Girdwood 	struct regulator_state *rstate)
650414c70cbSLiam Girdwood {
651414c70cbSLiam Girdwood 	int ret = 0;
652638f85c5SMark Brown 	bool can_set_state;
653414c70cbSLiam Girdwood 
654638f85c5SMark Brown 	can_set_state = rdev->desc->ops->set_suspend_enable &&
655638f85c5SMark Brown 		rdev->desc->ops->set_suspend_disable;
656638f85c5SMark Brown 
657638f85c5SMark Brown 	/* If we have no suspend mode configration don't set anything;
658638f85c5SMark Brown 	 * only warn if the driver actually makes the suspend mode
659638f85c5SMark Brown 	 * configurable.
660638f85c5SMark Brown 	 */
661638f85c5SMark Brown 	if (!rstate->enabled && !rstate->disabled) {
662638f85c5SMark Brown 		if (can_set_state)
6635da84fd9SJoe Perches 			rdev_warn(rdev, "No configuration\n");
664638f85c5SMark Brown 		return 0;
665638f85c5SMark Brown 	}
666638f85c5SMark Brown 
667638f85c5SMark Brown 	if (rstate->enabled && rstate->disabled) {
6685da84fd9SJoe Perches 		rdev_err(rdev, "invalid configuration\n");
669638f85c5SMark Brown 		return -EINVAL;
670638f85c5SMark Brown 	}
671638f85c5SMark Brown 
672638f85c5SMark Brown 	if (!can_set_state) {
6735da84fd9SJoe Perches 		rdev_err(rdev, "no way to set suspend state\n");
674414c70cbSLiam Girdwood 		return -EINVAL;
675a5766f11SLiam Girdwood 	}
676414c70cbSLiam Girdwood 
677414c70cbSLiam Girdwood 	if (rstate->enabled)
678414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_enable(rdev);
679414c70cbSLiam Girdwood 	else
680414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_disable(rdev);
681414c70cbSLiam Girdwood 	if (ret < 0) {
6825da84fd9SJoe Perches 		rdev_err(rdev, "failed to enabled/disable\n");
683414c70cbSLiam Girdwood 		return ret;
684414c70cbSLiam Girdwood 	}
685414c70cbSLiam Girdwood 
686414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
687414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
688414c70cbSLiam Girdwood 		if (ret < 0) {
6895da84fd9SJoe Perches 			rdev_err(rdev, "failed to set voltage\n");
690414c70cbSLiam Girdwood 			return ret;
691414c70cbSLiam Girdwood 		}
692414c70cbSLiam Girdwood 	}
693414c70cbSLiam Girdwood 
694414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
695414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
696414c70cbSLiam Girdwood 		if (ret < 0) {
6975da84fd9SJoe Perches 			rdev_err(rdev, "failed to set mode\n");
698414c70cbSLiam Girdwood 			return ret;
699414c70cbSLiam Girdwood 		}
700414c70cbSLiam Girdwood 	}
701414c70cbSLiam Girdwood 	return ret;
702414c70cbSLiam Girdwood }
703414c70cbSLiam Girdwood 
704414c70cbSLiam Girdwood /* locks held by caller */
705414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state)
706414c70cbSLiam Girdwood {
707414c70cbSLiam Girdwood 	if (!rdev->constraints)
708414c70cbSLiam Girdwood 		return -EINVAL;
709414c70cbSLiam Girdwood 
710414c70cbSLiam Girdwood 	switch (state) {
711414c70cbSLiam Girdwood 	case PM_SUSPEND_STANDBY:
712414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
713414c70cbSLiam Girdwood 			&rdev->constraints->state_standby);
714414c70cbSLiam Girdwood 	case PM_SUSPEND_MEM:
715414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
716414c70cbSLiam Girdwood 			&rdev->constraints->state_mem);
717414c70cbSLiam Girdwood 	case PM_SUSPEND_MAX:
718414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
719414c70cbSLiam Girdwood 			&rdev->constraints->state_disk);
720414c70cbSLiam Girdwood 	default:
721414c70cbSLiam Girdwood 		return -EINVAL;
722414c70cbSLiam Girdwood 	}
723414c70cbSLiam Girdwood }
724414c70cbSLiam Girdwood 
725414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev)
726414c70cbSLiam Girdwood {
727414c70cbSLiam Girdwood 	struct regulation_constraints *constraints = rdev->constraints;
728973e9a27SMark Brown 	char buf[80] = "";
7298f031b48SMark Brown 	int count = 0;
7308f031b48SMark Brown 	int ret;
731414c70cbSLiam Girdwood 
7328f031b48SMark Brown 	if (constraints->min_uV && constraints->max_uV) {
733414c70cbSLiam Girdwood 		if (constraints->min_uV == constraints->max_uV)
7348f031b48SMark Brown 			count += sprintf(buf + count, "%d mV ",
735414c70cbSLiam Girdwood 					 constraints->min_uV / 1000);
736414c70cbSLiam Girdwood 		else
7378f031b48SMark Brown 			count += sprintf(buf + count, "%d <--> %d mV ",
738414c70cbSLiam Girdwood 					 constraints->min_uV / 1000,
739414c70cbSLiam Girdwood 					 constraints->max_uV / 1000);
7408f031b48SMark Brown 	}
7418f031b48SMark Brown 
7428f031b48SMark Brown 	if (!constraints->min_uV ||
7438f031b48SMark Brown 	    constraints->min_uV != constraints->max_uV) {
7448f031b48SMark Brown 		ret = _regulator_get_voltage(rdev);
7458f031b48SMark Brown 		if (ret > 0)
7468f031b48SMark Brown 			count += sprintf(buf + count, "at %d mV ", ret / 1000);
7478f031b48SMark Brown 	}
7488f031b48SMark Brown 
749bf5892a8SMark Brown 	if (constraints->uV_offset)
750bf5892a8SMark Brown 		count += sprintf(buf, "%dmV offset ",
751bf5892a8SMark Brown 				 constraints->uV_offset / 1000);
752bf5892a8SMark Brown 
7538f031b48SMark Brown 	if (constraints->min_uA && constraints->max_uA) {
754414c70cbSLiam Girdwood 		if (constraints->min_uA == constraints->max_uA)
7558f031b48SMark Brown 			count += sprintf(buf + count, "%d mA ",
756414c70cbSLiam Girdwood 					 constraints->min_uA / 1000);
757414c70cbSLiam Girdwood 		else
7588f031b48SMark Brown 			count += sprintf(buf + count, "%d <--> %d mA ",
759414c70cbSLiam Girdwood 					 constraints->min_uA / 1000,
760414c70cbSLiam Girdwood 					 constraints->max_uA / 1000);
761414c70cbSLiam Girdwood 	}
7628f031b48SMark Brown 
7638f031b48SMark Brown 	if (!constraints->min_uA ||
7648f031b48SMark Brown 	    constraints->min_uA != constraints->max_uA) {
7658f031b48SMark Brown 		ret = _regulator_get_current_limit(rdev);
7668f031b48SMark Brown 		if (ret > 0)
767e4a6376bSCyril Chemparathy 			count += sprintf(buf + count, "at %d mA ", ret / 1000);
7688f031b48SMark Brown 	}
7698f031b48SMark Brown 
770414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
771414c70cbSLiam Girdwood 		count += sprintf(buf + count, "fast ");
772414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
773414c70cbSLiam Girdwood 		count += sprintf(buf + count, "normal ");
774414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
775414c70cbSLiam Girdwood 		count += sprintf(buf + count, "idle ");
776414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
777414c70cbSLiam Girdwood 		count += sprintf(buf + count, "standby");
778414c70cbSLiam Girdwood 
77913ce29f8SMark Brown 	rdev_info(rdev, "%s\n", buf);
780414c70cbSLiam Girdwood }
781414c70cbSLiam Girdwood 
782e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev,
7831083c393SMark Brown 	struct regulation_constraints *constraints)
784e79055d6SMark Brown {
785e79055d6SMark Brown 	struct regulator_ops *ops = rdev->desc->ops;
786af5866c9SMark Brown 	int ret;
787af5866c9SMark Brown 
788af5866c9SMark Brown 	/* do we need to apply the constraint voltage */
789af5866c9SMark Brown 	if (rdev->constraints->apply_uV &&
79075790251SMark Brown 	    rdev->constraints->min_uV == rdev->constraints->max_uV) {
79175790251SMark Brown 		ret = _regulator_do_set_voltage(rdev,
7923a93f2a9SMark Brown 						rdev->constraints->min_uV,
79375790251SMark Brown 						rdev->constraints->max_uV);
794af5866c9SMark Brown 		if (ret < 0) {
7955da84fd9SJoe Perches 			rdev_err(rdev, "failed to apply %duV constraint\n",
7965da84fd9SJoe Perches 				 rdev->constraints->min_uV);
797af5866c9SMark Brown 			return ret;
798af5866c9SMark Brown 		}
799af5866c9SMark Brown 	}
800e79055d6SMark Brown 
801e79055d6SMark Brown 	/* constrain machine-level voltage specs to fit
802e79055d6SMark Brown 	 * the actual range supported by this regulator.
803e79055d6SMark Brown 	 */
804e79055d6SMark Brown 	if (ops->list_voltage && rdev->desc->n_voltages) {
805e79055d6SMark Brown 		int	count = rdev->desc->n_voltages;
806e79055d6SMark Brown 		int	i;
807e79055d6SMark Brown 		int	min_uV = INT_MAX;
808e79055d6SMark Brown 		int	max_uV = INT_MIN;
809e79055d6SMark Brown 		int	cmin = constraints->min_uV;
810e79055d6SMark Brown 		int	cmax = constraints->max_uV;
811e79055d6SMark Brown 
812e79055d6SMark Brown 		/* it's safe to autoconfigure fixed-voltage supplies
813e79055d6SMark Brown 		   and the constraints are used by list_voltage. */
814e79055d6SMark Brown 		if (count == 1 && !cmin) {
815e79055d6SMark Brown 			cmin = 1;
816e79055d6SMark Brown 			cmax = INT_MAX;
817e79055d6SMark Brown 			constraints->min_uV = cmin;
818e79055d6SMark Brown 			constraints->max_uV = cmax;
819e79055d6SMark Brown 		}
820e79055d6SMark Brown 
821e79055d6SMark Brown 		/* voltage constraints are optional */
822e79055d6SMark Brown 		if ((cmin == 0) && (cmax == 0))
823e79055d6SMark Brown 			return 0;
824e79055d6SMark Brown 
825e79055d6SMark Brown 		/* else require explicit machine-level constraints */
826e79055d6SMark Brown 		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
8275da84fd9SJoe Perches 			rdev_err(rdev, "invalid voltage constraints\n");
828e79055d6SMark Brown 			return -EINVAL;
829e79055d6SMark Brown 		}
830e79055d6SMark Brown 
831e79055d6SMark Brown 		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
832e79055d6SMark Brown 		for (i = 0; i < count; i++) {
833e79055d6SMark Brown 			int	value;
834e79055d6SMark Brown 
835e79055d6SMark Brown 			value = ops->list_voltage(rdev, i);
836e79055d6SMark Brown 			if (value <= 0)
837e79055d6SMark Brown 				continue;
838e79055d6SMark Brown 
839e79055d6SMark Brown 			/* maybe adjust [min_uV..max_uV] */
840e79055d6SMark Brown 			if (value >= cmin && value < min_uV)
841e79055d6SMark Brown 				min_uV = value;
842e79055d6SMark Brown 			if (value <= cmax && value > max_uV)
843e79055d6SMark Brown 				max_uV = value;
844e79055d6SMark Brown 		}
845e79055d6SMark Brown 
846e79055d6SMark Brown 		/* final: [min_uV..max_uV] valid iff constraints valid */
847e79055d6SMark Brown 		if (max_uV < min_uV) {
8485da84fd9SJoe Perches 			rdev_err(rdev, "unsupportable voltage constraints\n");
849e79055d6SMark Brown 			return -EINVAL;
850e79055d6SMark Brown 		}
851e79055d6SMark Brown 
852e79055d6SMark Brown 		/* use regulator's subset of machine constraints */
853e79055d6SMark Brown 		if (constraints->min_uV < min_uV) {
8545da84fd9SJoe Perches 			rdev_dbg(rdev, "override min_uV, %d -> %d\n",
8555da84fd9SJoe Perches 				 constraints->min_uV, min_uV);
856e79055d6SMark Brown 			constraints->min_uV = min_uV;
857e79055d6SMark Brown 		}
858e79055d6SMark Brown 		if (constraints->max_uV > max_uV) {
8595da84fd9SJoe Perches 			rdev_dbg(rdev, "override max_uV, %d -> %d\n",
8605da84fd9SJoe Perches 				 constraints->max_uV, max_uV);
861e79055d6SMark Brown 			constraints->max_uV = max_uV;
862e79055d6SMark Brown 		}
863e79055d6SMark Brown 	}
864e79055d6SMark Brown 
865e79055d6SMark Brown 	return 0;
866e79055d6SMark Brown }
867e79055d6SMark Brown 
868a5766f11SLiam Girdwood /**
869a5766f11SLiam Girdwood  * set_machine_constraints - sets regulator constraints
87069279fb9SMark Brown  * @rdev: regulator source
871c8e7e464SMark Brown  * @constraints: constraints to apply
872a5766f11SLiam Girdwood  *
873a5766f11SLiam Girdwood  * Allows platform initialisation code to define and constrain
874a5766f11SLiam Girdwood  * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
875a5766f11SLiam Girdwood  * Constraints *must* be set by platform code in order for some
876a5766f11SLiam Girdwood  * regulator operations to proceed i.e. set_voltage, set_current_limit,
877a5766f11SLiam Girdwood  * set_mode.
878a5766f11SLiam Girdwood  */
879a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev,
880f8c12fe3SMark Brown 	const struct regulation_constraints *constraints)
881a5766f11SLiam Girdwood {
882a5766f11SLiam Girdwood 	int ret = 0;
883e5fda26cSMark Brown 	struct regulator_ops *ops = rdev->desc->ops;
884e06f5b4fSMark Brown 
885f8c12fe3SMark Brown 	rdev->constraints = kmemdup(constraints, sizeof(*constraints),
886f8c12fe3SMark Brown 				    GFP_KERNEL);
887f8c12fe3SMark Brown 	if (!rdev->constraints)
888f8c12fe3SMark Brown 		return -ENOMEM;
889af5866c9SMark Brown 
890f8c12fe3SMark Brown 	ret = machine_constraints_voltage(rdev, rdev->constraints);
891e79055d6SMark Brown 	if (ret != 0)
8923e2b9abdSMark Brown 		goto out;
8933e2b9abdSMark Brown 
894a5766f11SLiam Girdwood 	/* do we need to setup our suspend state */
895e06f5b4fSMark Brown 	if (constraints->initial_state) {
896f8c12fe3SMark Brown 		ret = suspend_prepare(rdev, rdev->constraints->initial_state);
897e06f5b4fSMark Brown 		if (ret < 0) {
8985da84fd9SJoe Perches 			rdev_err(rdev, "failed to set suspend state\n");
899e06f5b4fSMark Brown 			goto out;
900e06f5b4fSMark Brown 		}
901e06f5b4fSMark Brown 	}
902a5766f11SLiam Girdwood 
903a308466cSMark Brown 	if (constraints->initial_mode) {
904a308466cSMark Brown 		if (!ops->set_mode) {
9055da84fd9SJoe Perches 			rdev_err(rdev, "no set_mode operation\n");
906a308466cSMark Brown 			ret = -EINVAL;
907a308466cSMark Brown 			goto out;
908a308466cSMark Brown 		}
909a308466cSMark Brown 
910f8c12fe3SMark Brown 		ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
911a308466cSMark Brown 		if (ret < 0) {
9125da84fd9SJoe Perches 			rdev_err(rdev, "failed to set initial mode: %d\n", ret);
913a308466cSMark Brown 			goto out;
914a308466cSMark Brown 		}
915a308466cSMark Brown 	}
916a308466cSMark Brown 
917cacf90f2SMark Brown 	/* If the constraints say the regulator should be on at this point
918cacf90f2SMark Brown 	 * and we have control then make sure it is enabled.
919cacf90f2SMark Brown 	 */
920f8c12fe3SMark Brown 	if ((rdev->constraints->always_on || rdev->constraints->boot_on) &&
921f8c12fe3SMark Brown 	    ops->enable) {
922e5fda26cSMark Brown 		ret = ops->enable(rdev);
923e5fda26cSMark Brown 		if (ret < 0) {
9245da84fd9SJoe Perches 			rdev_err(rdev, "failed to enable\n");
925e5fda26cSMark Brown 			goto out;
926e5fda26cSMark Brown 		}
927e5fda26cSMark Brown 	}
928e5fda26cSMark Brown 
929a5766f11SLiam Girdwood 	print_constraints(rdev);
9301a6958e7SAxel Lin 	return 0;
931a5766f11SLiam Girdwood out:
9321a6958e7SAxel Lin 	kfree(rdev->constraints);
9331a6958e7SAxel Lin 	rdev->constraints = NULL;
934a5766f11SLiam Girdwood 	return ret;
935a5766f11SLiam Girdwood }
936a5766f11SLiam Girdwood 
937a5766f11SLiam Girdwood /**
938a5766f11SLiam Girdwood  * set_supply - set regulator supply regulator
93969279fb9SMark Brown  * @rdev: regulator name
94069279fb9SMark Brown  * @supply_rdev: supply regulator name
941a5766f11SLiam Girdwood  *
942a5766f11SLiam Girdwood  * Called by platform initialisation code to set the supply regulator for this
943a5766f11SLiam Girdwood  * regulator. This ensures that a regulators supply will also be enabled by the
944a5766f11SLiam Girdwood  * core if it's child is enabled.
945a5766f11SLiam Girdwood  */
946a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev,
947a5766f11SLiam Girdwood 		      struct regulator_dev *supply_rdev)
948a5766f11SLiam Girdwood {
949a5766f11SLiam Girdwood 	int err;
950a5766f11SLiam Girdwood 
9513801b86aSMark Brown 	rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
9523801b86aSMark Brown 
9533801b86aSMark Brown 	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
9543801b86aSMark Brown 	if (IS_ERR(rdev->supply)) {
9553801b86aSMark Brown 		err = PTR_ERR(rdev->supply);
9563801b86aSMark Brown 		rdev->supply = NULL;
957a5766f11SLiam Girdwood 		return err;
958a5766f11SLiam Girdwood 	}
959a5766f11SLiam Girdwood 
9603801b86aSMark Brown 	return 0;
9613801b86aSMark Brown }
9623801b86aSMark Brown 
963a5766f11SLiam Girdwood /**
96406c63f93SRandy Dunlap  * set_consumer_device_supply - Bind a regulator to a symbolic supply
96569279fb9SMark Brown  * @rdev:         regulator source
96669279fb9SMark Brown  * @consumer_dev: device the supply applies to
96740f9244fSMark Brown  * @consumer_dev_name: dev_name() string for device supply applies to
968a5766f11SLiam Girdwood  * @supply:       symbolic name for supply
969a5766f11SLiam Girdwood  *
970a5766f11SLiam Girdwood  * Allows platform initialisation code to map physical regulator
971a5766f11SLiam Girdwood  * sources to symbolic names for supplies for use by devices.  Devices
972a5766f11SLiam Girdwood  * should use these symbolic names to request regulators, avoiding the
973a5766f11SLiam Girdwood  * need to provide board-specific regulator names as platform data.
97440f9244fSMark Brown  *
97540f9244fSMark Brown  * Only one of consumer_dev and consumer_dev_name may be specified.
976a5766f11SLiam Girdwood  */
977a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev,
97840f9244fSMark Brown 	struct device *consumer_dev, const char *consumer_dev_name,
97940f9244fSMark Brown 	const char *supply)
980a5766f11SLiam Girdwood {
981a5766f11SLiam Girdwood 	struct regulator_map *node;
9829ed2099eSMark Brown 	int has_dev;
983a5766f11SLiam Girdwood 
98440f9244fSMark Brown 	if (consumer_dev && consumer_dev_name)
98540f9244fSMark Brown 		return -EINVAL;
98640f9244fSMark Brown 
98740f9244fSMark Brown 	if (!consumer_dev_name && consumer_dev)
98840f9244fSMark Brown 		consumer_dev_name = dev_name(consumer_dev);
98940f9244fSMark Brown 
990a5766f11SLiam Girdwood 	if (supply == NULL)
991a5766f11SLiam Girdwood 		return -EINVAL;
992a5766f11SLiam Girdwood 
9939ed2099eSMark Brown 	if (consumer_dev_name != NULL)
9949ed2099eSMark Brown 		has_dev = 1;
9959ed2099eSMark Brown 	else
9969ed2099eSMark Brown 		has_dev = 0;
9979ed2099eSMark Brown 
9986001e13cSDavid Brownell 	list_for_each_entry(node, &regulator_map_list, list) {
99923b5cc2aSJani Nikula 		if (node->dev_name && consumer_dev_name) {
100023b5cc2aSJani Nikula 			if (strcmp(node->dev_name, consumer_dev_name) != 0)
10016001e13cSDavid Brownell 				continue;
100223b5cc2aSJani Nikula 		} else if (node->dev_name || consumer_dev_name) {
100323b5cc2aSJani Nikula 			continue;
100423b5cc2aSJani Nikula 		}
100523b5cc2aSJani Nikula 
10066001e13cSDavid Brownell 		if (strcmp(node->supply, supply) != 0)
10076001e13cSDavid Brownell 			continue;
10086001e13cSDavid Brownell 
10096001e13cSDavid Brownell 		dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n",
10106001e13cSDavid Brownell 			dev_name(&node->regulator->dev),
10116001e13cSDavid Brownell 			node->regulator->desc->name,
10126001e13cSDavid Brownell 			supply,
10131083c393SMark Brown 			dev_name(&rdev->dev), rdev_get_name(rdev));
10146001e13cSDavid Brownell 		return -EBUSY;
10156001e13cSDavid Brownell 	}
10166001e13cSDavid Brownell 
10179ed2099eSMark Brown 	node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
1018a5766f11SLiam Girdwood 	if (node == NULL)
1019a5766f11SLiam Girdwood 		return -ENOMEM;
1020a5766f11SLiam Girdwood 
1021a5766f11SLiam Girdwood 	node->regulator = rdev;
1022a5766f11SLiam Girdwood 	node->supply = supply;
1023a5766f11SLiam Girdwood 
10249ed2099eSMark Brown 	if (has_dev) {
10259ed2099eSMark Brown 		node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
102640f9244fSMark Brown 		if (node->dev_name == NULL) {
102740f9244fSMark Brown 			kfree(node);
102840f9244fSMark Brown 			return -ENOMEM;
102940f9244fSMark Brown 		}
10309ed2099eSMark Brown 	}
103140f9244fSMark Brown 
1032a5766f11SLiam Girdwood 	list_add(&node->list, &regulator_map_list);
1033a5766f11SLiam Girdwood 	return 0;
1034a5766f11SLiam Girdwood }
1035a5766f11SLiam Girdwood 
10360f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev)
10370f1d747bSMike Rapoport {
10380f1d747bSMike Rapoport 	struct regulator_map *node, *n;
10390f1d747bSMike Rapoport 
10400f1d747bSMike Rapoport 	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
10410f1d747bSMike Rapoport 		if (rdev == node->regulator) {
10420f1d747bSMike Rapoport 			list_del(&node->list);
104340f9244fSMark Brown 			kfree(node->dev_name);
10440f1d747bSMike Rapoport 			kfree(node);
10450f1d747bSMike Rapoport 		}
10460f1d747bSMike Rapoport 	}
10470f1d747bSMike Rapoport }
10480f1d747bSMike Rapoport 
1049f5726ae3SMark Brown #define REG_STR_SIZE	64
1050414c70cbSLiam Girdwood 
1051414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev,
1052414c70cbSLiam Girdwood 					  struct device *dev,
1053414c70cbSLiam Girdwood 					  const char *supply_name)
1054414c70cbSLiam Girdwood {
1055414c70cbSLiam Girdwood 	struct regulator *regulator;
1056414c70cbSLiam Girdwood 	char buf[REG_STR_SIZE];
1057414c70cbSLiam Girdwood 	int err, size;
1058414c70cbSLiam Girdwood 
1059414c70cbSLiam Girdwood 	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
1060414c70cbSLiam Girdwood 	if (regulator == NULL)
1061414c70cbSLiam Girdwood 		return NULL;
1062414c70cbSLiam Girdwood 
1063414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
1064414c70cbSLiam Girdwood 	regulator->rdev = rdev;
1065414c70cbSLiam Girdwood 	list_add(&regulator->list, &rdev->consumer_list);
1066414c70cbSLiam Girdwood 
1067414c70cbSLiam Girdwood 	if (dev) {
1068414c70cbSLiam Girdwood 		/* create a 'requested_microamps_name' sysfs entry */
1069e0eaedefSMark Brown 		size = scnprintf(buf, REG_STR_SIZE,
1070e0eaedefSMark Brown 				 "microamps_requested_%s-%s",
1071e0eaedefSMark Brown 				 dev_name(dev), supply_name);
1072414c70cbSLiam Girdwood 		if (size >= REG_STR_SIZE)
1073414c70cbSLiam Girdwood 			goto overflow_err;
1074414c70cbSLiam Girdwood 
1075414c70cbSLiam Girdwood 		regulator->dev = dev;
10764f26a2abSAmeya Palande 		sysfs_attr_init(&regulator->dev_attr.attr);
1077414c70cbSLiam Girdwood 		regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
1078414c70cbSLiam Girdwood 		if (regulator->dev_attr.attr.name == NULL)
1079414c70cbSLiam Girdwood 			goto attr_name_err;
1080414c70cbSLiam Girdwood 
1081414c70cbSLiam Girdwood 		regulator->dev_attr.attr.mode = 0444;
1082414c70cbSLiam Girdwood 		regulator->dev_attr.show = device_requested_uA_show;
1083414c70cbSLiam Girdwood 		err = device_create_file(dev, &regulator->dev_attr);
1084414c70cbSLiam Girdwood 		if (err < 0) {
10855da84fd9SJoe Perches 			rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
1086414c70cbSLiam Girdwood 			goto attr_name_err;
1087414c70cbSLiam Girdwood 		}
1088414c70cbSLiam Girdwood 
1089414c70cbSLiam Girdwood 		/* also add a link to the device sysfs entry */
1090414c70cbSLiam Girdwood 		size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
1091414c70cbSLiam Girdwood 				 dev->kobj.name, supply_name);
1092414c70cbSLiam Girdwood 		if (size >= REG_STR_SIZE)
1093414c70cbSLiam Girdwood 			goto attr_err;
1094414c70cbSLiam Girdwood 
1095414c70cbSLiam Girdwood 		regulator->supply_name = kstrdup(buf, GFP_KERNEL);
1096414c70cbSLiam Girdwood 		if (regulator->supply_name == NULL)
1097414c70cbSLiam Girdwood 			goto attr_err;
1098414c70cbSLiam Girdwood 
1099414c70cbSLiam Girdwood 		err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
1100414c70cbSLiam Girdwood 					buf);
1101414c70cbSLiam Girdwood 		if (err) {
11025da84fd9SJoe Perches 			rdev_warn(rdev, "could not add device link %s err %d\n",
11031d7372e1SDaniel Walker 				  dev->kobj.name, err);
1104414c70cbSLiam Girdwood 			goto link_name_err;
1105414c70cbSLiam Girdwood 		}
11065de70519SMark Brown 	} else {
11075de70519SMark Brown 		regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
11085de70519SMark Brown 		if (regulator->supply_name == NULL)
11095de70519SMark Brown 			goto attr_err;
1110414c70cbSLiam Girdwood 	}
11115de70519SMark Brown 
11125de70519SMark Brown #ifdef CONFIG_DEBUG_FS
11135de70519SMark Brown 	regulator->debugfs = debugfs_create_dir(regulator->supply_name,
11145de70519SMark Brown 						rdev->debugfs);
11155de70519SMark Brown 	if (IS_ERR_OR_NULL(regulator->debugfs)) {
11165de70519SMark Brown 		rdev_warn(rdev, "Failed to create debugfs directory\n");
11175de70519SMark Brown 		regulator->debugfs = NULL;
11185de70519SMark Brown 	} else {
11195de70519SMark Brown 		debugfs_create_u32("uA_load", 0444, regulator->debugfs,
11205de70519SMark Brown 				   &regulator->uA_load);
11215de70519SMark Brown 		debugfs_create_u32("min_uV", 0444, regulator->debugfs,
11225de70519SMark Brown 				   &regulator->min_uV);
11235de70519SMark Brown 		debugfs_create_u32("max_uV", 0444, regulator->debugfs,
11245de70519SMark Brown 				   &regulator->max_uV);
11255de70519SMark Brown 	}
11265de70519SMark Brown #endif
11275de70519SMark Brown 
1128414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1129414c70cbSLiam Girdwood 	return regulator;
1130414c70cbSLiam Girdwood link_name_err:
1131414c70cbSLiam Girdwood 	kfree(regulator->supply_name);
1132414c70cbSLiam Girdwood attr_err:
1133414c70cbSLiam Girdwood 	device_remove_file(regulator->dev, &regulator->dev_attr);
1134414c70cbSLiam Girdwood attr_name_err:
1135414c70cbSLiam Girdwood 	kfree(regulator->dev_attr.attr.name);
1136414c70cbSLiam Girdwood overflow_err:
1137414c70cbSLiam Girdwood 	list_del(&regulator->list);
1138414c70cbSLiam Girdwood 	kfree(regulator);
1139414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1140414c70cbSLiam Girdwood 	return NULL;
1141414c70cbSLiam Girdwood }
1142414c70cbSLiam Girdwood 
114331aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev)
114431aae2beSMark Brown {
114531aae2beSMark Brown 	if (!rdev->desc->ops->enable_time)
114631aae2beSMark Brown 		return 0;
114731aae2beSMark Brown 	return rdev->desc->ops->enable_time(rdev);
114831aae2beSMark Brown }
114931aae2beSMark Brown 
11505ffbd136SMark Brown /* Internal regulator request function */
11515ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id,
11525ffbd136SMark Brown 					int exclusive)
1153414c70cbSLiam Girdwood {
1154414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
1155414c70cbSLiam Girdwood 	struct regulator_map *map;
1156414c70cbSLiam Girdwood 	struct regulator *regulator = ERR_PTR(-ENODEV);
115740f9244fSMark Brown 	const char *devname = NULL;
11585ffbd136SMark Brown 	int ret;
1159414c70cbSLiam Girdwood 
1160414c70cbSLiam Girdwood 	if (id == NULL) {
11615da84fd9SJoe Perches 		pr_err("get() with no identifier\n");
1162414c70cbSLiam Girdwood 		return regulator;
1163414c70cbSLiam Girdwood 	}
1164414c70cbSLiam Girdwood 
116540f9244fSMark Brown 	if (dev)
116640f9244fSMark Brown 		devname = dev_name(dev);
116740f9244fSMark Brown 
1168414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
1169414c70cbSLiam Girdwood 
1170414c70cbSLiam Girdwood 	list_for_each_entry(map, &regulator_map_list, list) {
117140f9244fSMark Brown 		/* If the mapping has a device set up it must match */
117240f9244fSMark Brown 		if (map->dev_name &&
117340f9244fSMark Brown 		    (!devname || strcmp(map->dev_name, devname)))
117440f9244fSMark Brown 			continue;
117540f9244fSMark Brown 
117640f9244fSMark Brown 		if (strcmp(map->supply, id) == 0) {
1177a5766f11SLiam Girdwood 			rdev = map->regulator;
1178414c70cbSLiam Girdwood 			goto found;
1179414c70cbSLiam Girdwood 		}
1180a5766f11SLiam Girdwood 	}
118134abbd68SMark Brown 
1182688fe99aSMark Brown 	if (board_wants_dummy_regulator) {
1183688fe99aSMark Brown 		rdev = dummy_regulator_rdev;
1184688fe99aSMark Brown 		goto found;
1185688fe99aSMark Brown 	}
1186688fe99aSMark Brown 
118734abbd68SMark Brown #ifdef CONFIG_REGULATOR_DUMMY
118834abbd68SMark Brown 	if (!devname)
118934abbd68SMark Brown 		devname = "deviceless";
119034abbd68SMark Brown 
119134abbd68SMark Brown 	/* If the board didn't flag that it was fully constrained then
119234abbd68SMark Brown 	 * substitute in a dummy regulator so consumers can continue.
119334abbd68SMark Brown 	 */
119434abbd68SMark Brown 	if (!has_full_constraints) {
11955da84fd9SJoe Perches 		pr_warn("%s supply %s not found, using dummy regulator\n",
119634abbd68SMark Brown 			devname, id);
119734abbd68SMark Brown 		rdev = dummy_regulator_rdev;
119834abbd68SMark Brown 		goto found;
119934abbd68SMark Brown 	}
120034abbd68SMark Brown #endif
120134abbd68SMark Brown 
1202414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
1203414c70cbSLiam Girdwood 	return regulator;
1204414c70cbSLiam Girdwood 
1205414c70cbSLiam Girdwood found:
12065ffbd136SMark Brown 	if (rdev->exclusive) {
12075ffbd136SMark Brown 		regulator = ERR_PTR(-EPERM);
12085ffbd136SMark Brown 		goto out;
12095ffbd136SMark Brown 	}
12105ffbd136SMark Brown 
12115ffbd136SMark Brown 	if (exclusive && rdev->open_count) {
12125ffbd136SMark Brown 		regulator = ERR_PTR(-EBUSY);
12135ffbd136SMark Brown 		goto out;
12145ffbd136SMark Brown 	}
12155ffbd136SMark Brown 
1216a5766f11SLiam Girdwood 	if (!try_module_get(rdev->owner))
1217a5766f11SLiam Girdwood 		goto out;
1218a5766f11SLiam Girdwood 
1219414c70cbSLiam Girdwood 	regulator = create_regulator(rdev, dev, id);
1220414c70cbSLiam Girdwood 	if (regulator == NULL) {
1221414c70cbSLiam Girdwood 		regulator = ERR_PTR(-ENOMEM);
1222414c70cbSLiam Girdwood 		module_put(rdev->owner);
1223414c70cbSLiam Girdwood 	}
1224414c70cbSLiam Girdwood 
12255ffbd136SMark Brown 	rdev->open_count++;
12265ffbd136SMark Brown 	if (exclusive) {
12275ffbd136SMark Brown 		rdev->exclusive = 1;
12285ffbd136SMark Brown 
12295ffbd136SMark Brown 		ret = _regulator_is_enabled(rdev);
12305ffbd136SMark Brown 		if (ret > 0)
12315ffbd136SMark Brown 			rdev->use_count = 1;
12325ffbd136SMark Brown 		else
12335ffbd136SMark Brown 			rdev->use_count = 0;
12345ffbd136SMark Brown 	}
12355ffbd136SMark Brown 
1236a5766f11SLiam Girdwood out:
1237414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
12385ffbd136SMark Brown 
1239414c70cbSLiam Girdwood 	return regulator;
1240414c70cbSLiam Girdwood }
12415ffbd136SMark Brown 
12425ffbd136SMark Brown /**
12435ffbd136SMark Brown  * regulator_get - lookup and obtain a reference to a regulator.
12445ffbd136SMark Brown  * @dev: device for regulator "consumer"
12455ffbd136SMark Brown  * @id: Supply name or regulator ID.
12465ffbd136SMark Brown  *
12475ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
12485ffbd136SMark Brown  * or IS_ERR() condition containing errno.
12495ffbd136SMark Brown  *
12505ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
12515ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
12525ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
12535ffbd136SMark Brown  * device pins in the datasheet.
12545ffbd136SMark Brown  */
12555ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id)
12565ffbd136SMark Brown {
12575ffbd136SMark Brown 	return _regulator_get(dev, id, 0);
12585ffbd136SMark Brown }
1259414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get);
1260414c70cbSLiam Girdwood 
1261414c70cbSLiam Girdwood /**
12625ffbd136SMark Brown  * regulator_get_exclusive - obtain exclusive access to a regulator.
12635ffbd136SMark Brown  * @dev: device for regulator "consumer"
12645ffbd136SMark Brown  * @id: Supply name or regulator ID.
12655ffbd136SMark Brown  *
12665ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
12675ffbd136SMark Brown  * or IS_ERR() condition containing errno.  Other consumers will be
12685ffbd136SMark Brown  * unable to obtain this reference is held and the use count for the
12695ffbd136SMark Brown  * regulator will be initialised to reflect the current state of the
12705ffbd136SMark Brown  * regulator.
12715ffbd136SMark Brown  *
12725ffbd136SMark Brown  * This is intended for use by consumers which cannot tolerate shared
12735ffbd136SMark Brown  * use of the regulator such as those which need to force the
12745ffbd136SMark Brown  * regulator off for correct operation of the hardware they are
12755ffbd136SMark Brown  * controlling.
12765ffbd136SMark Brown  *
12775ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
12785ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
12795ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
12805ffbd136SMark Brown  * device pins in the datasheet.
12815ffbd136SMark Brown  */
12825ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
12835ffbd136SMark Brown {
12845ffbd136SMark Brown 	return _regulator_get(dev, id, 1);
12855ffbd136SMark Brown }
12865ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive);
12875ffbd136SMark Brown 
12885ffbd136SMark Brown /**
1289414c70cbSLiam Girdwood  * regulator_put - "free" the regulator source
1290414c70cbSLiam Girdwood  * @regulator: regulator source
1291414c70cbSLiam Girdwood  *
1292414c70cbSLiam Girdwood  * Note: drivers must ensure that all regulator_enable calls made on this
1293414c70cbSLiam Girdwood  * regulator source are balanced by regulator_disable calls prior to calling
1294414c70cbSLiam Girdwood  * this function.
1295414c70cbSLiam Girdwood  */
1296414c70cbSLiam Girdwood void regulator_put(struct regulator *regulator)
1297414c70cbSLiam Girdwood {
1298414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
1299414c70cbSLiam Girdwood 
1300414c70cbSLiam Girdwood 	if (regulator == NULL || IS_ERR(regulator))
1301414c70cbSLiam Girdwood 		return;
1302414c70cbSLiam Girdwood 
1303414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
1304414c70cbSLiam Girdwood 	rdev = regulator->rdev;
1305414c70cbSLiam Girdwood 
13065de70519SMark Brown #ifdef CONFIG_DEBUG_FS
13075de70519SMark Brown 	debugfs_remove_recursive(regulator->debugfs);
13085de70519SMark Brown #endif
13095de70519SMark Brown 
1310414c70cbSLiam Girdwood 	/* remove any sysfs entries */
1311414c70cbSLiam Girdwood 	if (regulator->dev) {
1312414c70cbSLiam Girdwood 		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
1313414c70cbSLiam Girdwood 		device_remove_file(regulator->dev, &regulator->dev_attr);
1314414c70cbSLiam Girdwood 		kfree(regulator->dev_attr.attr.name);
1315414c70cbSLiam Girdwood 	}
13165de70519SMark Brown 	kfree(regulator->supply_name);
1317414c70cbSLiam Girdwood 	list_del(&regulator->list);
1318414c70cbSLiam Girdwood 	kfree(regulator);
1319414c70cbSLiam Girdwood 
13205ffbd136SMark Brown 	rdev->open_count--;
13215ffbd136SMark Brown 	rdev->exclusive = 0;
13225ffbd136SMark Brown 
1323414c70cbSLiam Girdwood 	module_put(rdev->owner);
1324414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
1325414c70cbSLiam Girdwood }
1326414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put);
1327414c70cbSLiam Girdwood 
13289a2372faSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev)
13299a2372faSMark Brown {
13309a2372faSMark Brown 	if (!rdev->constraints)
13319a2372faSMark Brown 		return 0;
13329a2372faSMark Brown 
13339a2372faSMark Brown 	if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
13349a2372faSMark Brown 		return 1;
13359a2372faSMark Brown 	else
13369a2372faSMark Brown 		return 0;
13379a2372faSMark Brown }
13389a2372faSMark Brown 
1339414c70cbSLiam Girdwood /* locks held by regulator_enable() */
1340414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev)
1341414c70cbSLiam Girdwood {
134231aae2beSMark Brown 	int ret, delay;
1343414c70cbSLiam Girdwood 
1344414c70cbSLiam Girdwood 	/* check voltage and requested load before enabling */
1345414c70cbSLiam Girdwood 	if (rdev->constraints &&
13469a2372faSMark Brown 	    (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
1347414c70cbSLiam Girdwood 		drms_uA_update(rdev);
1348414c70cbSLiam Girdwood 
13499a2372faSMark Brown 	if (rdev->use_count == 0) {
13509a2372faSMark Brown 		/* The regulator may on if it's not switchable or left on */
13519a2372faSMark Brown 		ret = _regulator_is_enabled(rdev);
13529a2372faSMark Brown 		if (ret == -EINVAL || ret == 0) {
13539a2372faSMark Brown 			if (!_regulator_can_change_status(rdev))
13549a2372faSMark Brown 				return -EPERM;
13559a2372faSMark Brown 
135631aae2beSMark Brown 			if (!rdev->desc->ops->enable)
135731aae2beSMark Brown 				return -EINVAL;
135831aae2beSMark Brown 
135931aae2beSMark Brown 			/* Query before enabling in case configuration
136025985edcSLucas De Marchi 			 * dependent.  */
136131aae2beSMark Brown 			ret = _regulator_get_enable_time(rdev);
136231aae2beSMark Brown 			if (ret >= 0) {
136331aae2beSMark Brown 				delay = ret;
136431aae2beSMark Brown 			} else {
13655da84fd9SJoe Perches 				rdev_warn(rdev, "enable_time() failed: %d\n",
136631aae2beSMark Brown 					   ret);
136731aae2beSMark Brown 				delay = 0;
136831aae2beSMark Brown 			}
136931aae2beSMark Brown 
137002fa3ec0SMark Brown 			trace_regulator_enable(rdev_get_name(rdev));
137102fa3ec0SMark Brown 
137231aae2beSMark Brown 			/* Allow the regulator to ramp; it would be useful
137331aae2beSMark Brown 			 * to extend this for bulk operations so that the
137431aae2beSMark Brown 			 * regulators can ramp together.  */
1375414c70cbSLiam Girdwood 			ret = rdev->desc->ops->enable(rdev);
13769a2372faSMark Brown 			if (ret < 0)
13779a2372faSMark Brown 				return ret;
137831aae2beSMark Brown 
137902fa3ec0SMark Brown 			trace_regulator_enable_delay(rdev_get_name(rdev));
138002fa3ec0SMark Brown 
1381e36c1df8SAxel Lin 			if (delay >= 1000) {
138231aae2beSMark Brown 				mdelay(delay / 1000);
1383e36c1df8SAxel Lin 				udelay(delay % 1000);
1384e36c1df8SAxel Lin 			} else if (delay) {
138531aae2beSMark Brown 				udelay(delay);
1386e36c1df8SAxel Lin 			}
138731aae2beSMark Brown 
138802fa3ec0SMark Brown 			trace_regulator_enable_complete(rdev_get_name(rdev));
138902fa3ec0SMark Brown 
1390a7433cffSLinus Walleij 		} else if (ret < 0) {
13915da84fd9SJoe Perches 			rdev_err(rdev, "is_enabled() failed: %d\n", ret);
1392414c70cbSLiam Girdwood 			return ret;
1393414c70cbSLiam Girdwood 		}
1394a7433cffSLinus Walleij 		/* Fallthrough on positive return values - already enabled */
1395414c70cbSLiam Girdwood 	}
1396414c70cbSLiam Girdwood 
13979a2372faSMark Brown 	rdev->use_count++;
13989a2372faSMark Brown 
13999a2372faSMark Brown 	return 0;
1400414c70cbSLiam Girdwood }
1401414c70cbSLiam Girdwood 
1402414c70cbSLiam Girdwood /**
1403414c70cbSLiam Girdwood  * regulator_enable - enable regulator output
1404414c70cbSLiam Girdwood  * @regulator: regulator source
1405414c70cbSLiam Girdwood  *
1406cf7bbcdfSMark Brown  * Request that the regulator be enabled with the regulator output at
1407cf7bbcdfSMark Brown  * the predefined voltage or current value.  Calls to regulator_enable()
1408cf7bbcdfSMark Brown  * must be balanced with calls to regulator_disable().
1409cf7bbcdfSMark Brown  *
1410414c70cbSLiam Girdwood  * NOTE: the output value can be set by other drivers, boot loader or may be
1411cf7bbcdfSMark Brown  * hardwired in the regulator.
1412414c70cbSLiam Girdwood  */
1413414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator)
1414414c70cbSLiam Girdwood {
1415412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
1416412aec61SDavid Brownell 	int ret = 0;
1417414c70cbSLiam Girdwood 
14183801b86aSMark Brown 	if (rdev->supply) {
14193801b86aSMark Brown 		ret = regulator_enable(rdev->supply);
14203801b86aSMark Brown 		if (ret != 0)
14213801b86aSMark Brown 			return ret;
14223801b86aSMark Brown 	}
14233801b86aSMark Brown 
1424412aec61SDavid Brownell 	mutex_lock(&rdev->mutex);
1425412aec61SDavid Brownell 	ret = _regulator_enable(rdev);
1426412aec61SDavid Brownell 	mutex_unlock(&rdev->mutex);
14273801b86aSMark Brown 
1428d1685e4eSHeiko Stübner 	if (ret != 0 && rdev->supply)
14293801b86aSMark Brown 		regulator_disable(rdev->supply);
14303801b86aSMark Brown 
1431414c70cbSLiam Girdwood 	return ret;
1432414c70cbSLiam Girdwood }
1433414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable);
1434414c70cbSLiam Girdwood 
1435414c70cbSLiam Girdwood /* locks held by regulator_disable() */
14363801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev)
1437414c70cbSLiam Girdwood {
1438414c70cbSLiam Girdwood 	int ret = 0;
1439414c70cbSLiam Girdwood 
1440cd94b505SDavid Brownell 	if (WARN(rdev->use_count <= 0,
144143e7ee33SJoe Perches 		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
1442cd94b505SDavid Brownell 		return -EIO;
1443cd94b505SDavid Brownell 
1444414c70cbSLiam Girdwood 	/* are we the last user and permitted to disable ? */
144560ef66fcSMark Brown 	if (rdev->use_count == 1 &&
144660ef66fcSMark Brown 	    (rdev->constraints && !rdev->constraints->always_on)) {
1447414c70cbSLiam Girdwood 
1448414c70cbSLiam Girdwood 		/* we are last user */
14499a2372faSMark Brown 		if (_regulator_can_change_status(rdev) &&
14509a2372faSMark Brown 		    rdev->desc->ops->disable) {
145102fa3ec0SMark Brown 			trace_regulator_disable(rdev_get_name(rdev));
145202fa3ec0SMark Brown 
1453414c70cbSLiam Girdwood 			ret = rdev->desc->ops->disable(rdev);
1454414c70cbSLiam Girdwood 			if (ret < 0) {
14555da84fd9SJoe Perches 				rdev_err(rdev, "failed to disable\n");
1456414c70cbSLiam Girdwood 				return ret;
1457414c70cbSLiam Girdwood 			}
145884b68263SMark Brown 
145902fa3ec0SMark Brown 			trace_regulator_disable_complete(rdev_get_name(rdev));
146002fa3ec0SMark Brown 
146184b68263SMark Brown 			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
146284b68263SMark Brown 					     NULL);
1463414c70cbSLiam Girdwood 		}
1464414c70cbSLiam Girdwood 
1465414c70cbSLiam Girdwood 		rdev->use_count = 0;
1466414c70cbSLiam Girdwood 	} else if (rdev->use_count > 1) {
1467414c70cbSLiam Girdwood 
1468414c70cbSLiam Girdwood 		if (rdev->constraints &&
1469414c70cbSLiam Girdwood 			(rdev->constraints->valid_ops_mask &
1470414c70cbSLiam Girdwood 			REGULATOR_CHANGE_DRMS))
1471414c70cbSLiam Girdwood 			drms_uA_update(rdev);
1472414c70cbSLiam Girdwood 
1473414c70cbSLiam Girdwood 		rdev->use_count--;
1474414c70cbSLiam Girdwood 	}
14753801b86aSMark Brown 
1476414c70cbSLiam Girdwood 	return ret;
1477414c70cbSLiam Girdwood }
1478414c70cbSLiam Girdwood 
1479414c70cbSLiam Girdwood /**
1480414c70cbSLiam Girdwood  * regulator_disable - disable regulator output
1481414c70cbSLiam Girdwood  * @regulator: regulator source
1482414c70cbSLiam Girdwood  *
1483cf7bbcdfSMark Brown  * Disable the regulator output voltage or current.  Calls to
1484cf7bbcdfSMark Brown  * regulator_enable() must be balanced with calls to
1485cf7bbcdfSMark Brown  * regulator_disable().
148669279fb9SMark Brown  *
1487414c70cbSLiam Girdwood  * NOTE: this will only disable the regulator output if no other consumer
1488cf7bbcdfSMark Brown  * devices have it enabled, the regulator device supports disabling and
1489cf7bbcdfSMark Brown  * machine constraints permit this operation.
1490414c70cbSLiam Girdwood  */
1491414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator)
1492414c70cbSLiam Girdwood {
1493412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
1494412aec61SDavid Brownell 	int ret = 0;
1495414c70cbSLiam Girdwood 
1496412aec61SDavid Brownell 	mutex_lock(&rdev->mutex);
14973801b86aSMark Brown 	ret = _regulator_disable(rdev);
1498412aec61SDavid Brownell 	mutex_unlock(&rdev->mutex);
14998cbf811dSJeffrey Carlyle 
15003801b86aSMark Brown 	if (ret == 0 && rdev->supply)
15013801b86aSMark Brown 		regulator_disable(rdev->supply);
15028cbf811dSJeffrey Carlyle 
1503414c70cbSLiam Girdwood 	return ret;
1504414c70cbSLiam Girdwood }
1505414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable);
1506414c70cbSLiam Girdwood 
1507414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */
15083801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev)
1509414c70cbSLiam Girdwood {
1510414c70cbSLiam Girdwood 	int ret = 0;
1511414c70cbSLiam Girdwood 
1512414c70cbSLiam Girdwood 	/* force disable */
1513414c70cbSLiam Girdwood 	if (rdev->desc->ops->disable) {
1514414c70cbSLiam Girdwood 		/* ah well, who wants to live forever... */
1515414c70cbSLiam Girdwood 		ret = rdev->desc->ops->disable(rdev);
1516414c70cbSLiam Girdwood 		if (ret < 0) {
15175da84fd9SJoe Perches 			rdev_err(rdev, "failed to force disable\n");
1518414c70cbSLiam Girdwood 			return ret;
1519414c70cbSLiam Girdwood 		}
1520414c70cbSLiam Girdwood 		/* notify other consumers that power has been forced off */
152184b68263SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
152284b68263SMark Brown 			REGULATOR_EVENT_DISABLE, NULL);
1523414c70cbSLiam Girdwood 	}
1524414c70cbSLiam Girdwood 
1525414c70cbSLiam Girdwood 	return ret;
1526414c70cbSLiam Girdwood }
1527414c70cbSLiam Girdwood 
1528414c70cbSLiam Girdwood /**
1529414c70cbSLiam Girdwood  * regulator_force_disable - force disable regulator output
1530414c70cbSLiam Girdwood  * @regulator: regulator source
1531414c70cbSLiam Girdwood  *
1532414c70cbSLiam Girdwood  * Forcibly disable the regulator output voltage or current.
1533414c70cbSLiam Girdwood  * NOTE: this *will* disable the regulator output even if other consumer
1534414c70cbSLiam Girdwood  * devices have it enabled. This should be used for situations when device
1535414c70cbSLiam Girdwood  * damage will likely occur if the regulator is not disabled (e.g. over temp).
1536414c70cbSLiam Girdwood  */
1537414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator)
1538414c70cbSLiam Girdwood {
153982d15839SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
1540414c70cbSLiam Girdwood 	int ret;
1541414c70cbSLiam Girdwood 
154282d15839SMark Brown 	mutex_lock(&rdev->mutex);
1543414c70cbSLiam Girdwood 	regulator->uA_load = 0;
15443801b86aSMark Brown 	ret = _regulator_force_disable(regulator->rdev);
154582d15839SMark Brown 	mutex_unlock(&rdev->mutex);
15468cbf811dSJeffrey Carlyle 
15473801b86aSMark Brown 	if (rdev->supply)
15483801b86aSMark Brown 		while (rdev->open_count--)
15493801b86aSMark Brown 			regulator_disable(rdev->supply);
15508cbf811dSJeffrey Carlyle 
1551414c70cbSLiam Girdwood 	return ret;
1552414c70cbSLiam Girdwood }
1553414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable);
1554414c70cbSLiam Girdwood 
1555414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev)
1556414c70cbSLiam Girdwood {
15579a7f6a4cSMark Brown 	/* If we don't know then assume that the regulator is always on */
15589332546fSMark Brown 	if (!rdev->desc->ops->is_enabled)
15599a7f6a4cSMark Brown 		return 1;
1560414c70cbSLiam Girdwood 
15619332546fSMark Brown 	return rdev->desc->ops->is_enabled(rdev);
1562414c70cbSLiam Girdwood }
1563414c70cbSLiam Girdwood 
1564414c70cbSLiam Girdwood /**
1565414c70cbSLiam Girdwood  * regulator_is_enabled - is the regulator output enabled
1566414c70cbSLiam Girdwood  * @regulator: regulator source
1567414c70cbSLiam Girdwood  *
1568412aec61SDavid Brownell  * Returns positive if the regulator driver backing the source/client
1569412aec61SDavid Brownell  * has requested that the device be enabled, zero if it hasn't, else a
1570412aec61SDavid Brownell  * negative errno code.
1571412aec61SDavid Brownell  *
1572412aec61SDavid Brownell  * Note that the device backing this regulator handle can have multiple
1573412aec61SDavid Brownell  * users, so it might be enabled even if regulator_enable() was never
1574412aec61SDavid Brownell  * called for this particular source.
1575414c70cbSLiam Girdwood  */
1576414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator)
1577414c70cbSLiam Girdwood {
15789332546fSMark Brown 	int ret;
15799332546fSMark Brown 
15809332546fSMark Brown 	mutex_lock(&regulator->rdev->mutex);
15819332546fSMark Brown 	ret = _regulator_is_enabled(regulator->rdev);
15829332546fSMark Brown 	mutex_unlock(&regulator->rdev->mutex);
15839332546fSMark Brown 
15849332546fSMark Brown 	return ret;
1585414c70cbSLiam Girdwood }
1586414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled);
1587414c70cbSLiam Girdwood 
1588414c70cbSLiam Girdwood /**
15894367cfdcSDavid Brownell  * regulator_count_voltages - count regulator_list_voltage() selectors
15904367cfdcSDavid Brownell  * @regulator: regulator source
15914367cfdcSDavid Brownell  *
15924367cfdcSDavid Brownell  * Returns number of selectors, or negative errno.  Selectors are
15934367cfdcSDavid Brownell  * numbered starting at zero, and typically correspond to bitfields
15944367cfdcSDavid Brownell  * in hardware registers.
15954367cfdcSDavid Brownell  */
15964367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator)
15974367cfdcSDavid Brownell {
15984367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
15994367cfdcSDavid Brownell 
16004367cfdcSDavid Brownell 	return rdev->desc->n_voltages ? : -EINVAL;
16014367cfdcSDavid Brownell }
16024367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages);
16034367cfdcSDavid Brownell 
16044367cfdcSDavid Brownell /**
16054367cfdcSDavid Brownell  * regulator_list_voltage - enumerate supported voltages
16064367cfdcSDavid Brownell  * @regulator: regulator source
16074367cfdcSDavid Brownell  * @selector: identify voltage to list
16084367cfdcSDavid Brownell  * Context: can sleep
16094367cfdcSDavid Brownell  *
16104367cfdcSDavid Brownell  * Returns a voltage that can be passed to @regulator_set_voltage(),
161188393161SThomas Weber  * zero if this selector code can't be used on this system, or a
16124367cfdcSDavid Brownell  * negative errno.
16134367cfdcSDavid Brownell  */
16144367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector)
16154367cfdcSDavid Brownell {
16164367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
16174367cfdcSDavid Brownell 	struct regulator_ops	*ops = rdev->desc->ops;
16184367cfdcSDavid Brownell 	int			ret;
16194367cfdcSDavid Brownell 
16204367cfdcSDavid Brownell 	if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
16214367cfdcSDavid Brownell 		return -EINVAL;
16224367cfdcSDavid Brownell 
16234367cfdcSDavid Brownell 	mutex_lock(&rdev->mutex);
16244367cfdcSDavid Brownell 	ret = ops->list_voltage(rdev, selector);
16254367cfdcSDavid Brownell 	mutex_unlock(&rdev->mutex);
16264367cfdcSDavid Brownell 
16274367cfdcSDavid Brownell 	if (ret > 0) {
16284367cfdcSDavid Brownell 		if (ret < rdev->constraints->min_uV)
16294367cfdcSDavid Brownell 			ret = 0;
16304367cfdcSDavid Brownell 		else if (ret > rdev->constraints->max_uV)
16314367cfdcSDavid Brownell 			ret = 0;
16324367cfdcSDavid Brownell 	}
16334367cfdcSDavid Brownell 
16344367cfdcSDavid Brownell 	return ret;
16354367cfdcSDavid Brownell }
16364367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage);
16374367cfdcSDavid Brownell 
16384367cfdcSDavid Brownell /**
1639a7a1ad90SMark Brown  * regulator_is_supported_voltage - check if a voltage range can be supported
1640a7a1ad90SMark Brown  *
1641a7a1ad90SMark Brown  * @regulator: Regulator to check.
1642a7a1ad90SMark Brown  * @min_uV: Minimum required voltage in uV.
1643a7a1ad90SMark Brown  * @max_uV: Maximum required voltage in uV.
1644a7a1ad90SMark Brown  *
1645a7a1ad90SMark Brown  * Returns a boolean or a negative error code.
1646a7a1ad90SMark Brown  */
1647a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator,
1648a7a1ad90SMark Brown 				   int min_uV, int max_uV)
1649a7a1ad90SMark Brown {
1650a7a1ad90SMark Brown 	int i, voltages, ret;
1651a7a1ad90SMark Brown 
1652a7a1ad90SMark Brown 	ret = regulator_count_voltages(regulator);
1653a7a1ad90SMark Brown 	if (ret < 0)
1654a7a1ad90SMark Brown 		return ret;
1655a7a1ad90SMark Brown 	voltages = ret;
1656a7a1ad90SMark Brown 
1657a7a1ad90SMark Brown 	for (i = 0; i < voltages; i++) {
1658a7a1ad90SMark Brown 		ret = regulator_list_voltage(regulator, i);
1659a7a1ad90SMark Brown 
1660a7a1ad90SMark Brown 		if (ret >= min_uV && ret <= max_uV)
1661a7a1ad90SMark Brown 			return 1;
1662a7a1ad90SMark Brown 	}
1663a7a1ad90SMark Brown 
1664a7a1ad90SMark Brown 	return 0;
1665a7a1ad90SMark Brown }
1666a7a1ad90SMark Brown 
166775790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
166875790251SMark Brown 				     int min_uV, int max_uV)
166975790251SMark Brown {
167075790251SMark Brown 	int ret;
167177af1b26SLinus Walleij 	int delay = 0;
167275790251SMark Brown 	unsigned int selector;
167375790251SMark Brown 
167475790251SMark Brown 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
167575790251SMark Brown 
1676bf5892a8SMark Brown 	min_uV += rdev->constraints->uV_offset;
1677bf5892a8SMark Brown 	max_uV += rdev->constraints->uV_offset;
1678bf5892a8SMark Brown 
167975790251SMark Brown 	if (rdev->desc->ops->set_voltage) {
168075790251SMark Brown 		ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
168175790251SMark Brown 						   &selector);
168275790251SMark Brown 
168375790251SMark Brown 		if (rdev->desc->ops->list_voltage)
168475790251SMark Brown 			selector = rdev->desc->ops->list_voltage(rdev,
168575790251SMark Brown 								 selector);
168675790251SMark Brown 		else
168775790251SMark Brown 			selector = -1;
1688e8eef82bSMark Brown 	} else if (rdev->desc->ops->set_voltage_sel) {
1689e8eef82bSMark Brown 		int best_val = INT_MAX;
1690e8eef82bSMark Brown 		int i;
1691e8eef82bSMark Brown 
1692e8eef82bSMark Brown 		selector = 0;
1693e8eef82bSMark Brown 
1694e8eef82bSMark Brown 		/* Find the smallest voltage that falls within the specified
1695e8eef82bSMark Brown 		 * range.
1696e8eef82bSMark Brown 		 */
1697e8eef82bSMark Brown 		for (i = 0; i < rdev->desc->n_voltages; i++) {
1698e8eef82bSMark Brown 			ret = rdev->desc->ops->list_voltage(rdev, i);
1699e8eef82bSMark Brown 			if (ret < 0)
1700e8eef82bSMark Brown 				continue;
1701e8eef82bSMark Brown 
1702e8eef82bSMark Brown 			if (ret < best_val && ret >= min_uV && ret <= max_uV) {
1703e8eef82bSMark Brown 				best_val = ret;
1704e8eef82bSMark Brown 				selector = i;
1705e8eef82bSMark Brown 			}
1706e8eef82bSMark Brown 		}
1707e8eef82bSMark Brown 
170877af1b26SLinus Walleij 		/*
170977af1b26SLinus Walleij 		 * If we can't obtain the old selector there is not enough
171077af1b26SLinus Walleij 		 * info to call set_voltage_time_sel().
171177af1b26SLinus Walleij 		 */
171277af1b26SLinus Walleij 		if (rdev->desc->ops->set_voltage_time_sel &&
171377af1b26SLinus Walleij 		    rdev->desc->ops->get_voltage_sel) {
171477af1b26SLinus Walleij 			unsigned int old_selector = 0;
171577af1b26SLinus Walleij 
171677af1b26SLinus Walleij 			ret = rdev->desc->ops->get_voltage_sel(rdev);
171777af1b26SLinus Walleij 			if (ret < 0)
171877af1b26SLinus Walleij 				return ret;
171977af1b26SLinus Walleij 			old_selector = ret;
172077af1b26SLinus Walleij 			delay = rdev->desc->ops->set_voltage_time_sel(rdev,
172177af1b26SLinus Walleij 						old_selector, selector);
172277af1b26SLinus Walleij 		}
172377af1b26SLinus Walleij 
1724e8eef82bSMark Brown 		if (best_val != INT_MAX) {
1725e8eef82bSMark Brown 			ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
1726e8eef82bSMark Brown 			selector = best_val;
1727e8eef82bSMark Brown 		} else {
1728e8eef82bSMark Brown 			ret = -EINVAL;
1729e8eef82bSMark Brown 		}
173075790251SMark Brown 	} else {
173175790251SMark Brown 		ret = -EINVAL;
173275790251SMark Brown 	}
173375790251SMark Brown 
173477af1b26SLinus Walleij 	/* Insert any necessary delays */
173577af1b26SLinus Walleij 	if (delay >= 1000) {
173677af1b26SLinus Walleij 		mdelay(delay / 1000);
173777af1b26SLinus Walleij 		udelay(delay % 1000);
173877af1b26SLinus Walleij 	} else if (delay) {
173977af1b26SLinus Walleij 		udelay(delay);
174077af1b26SLinus Walleij 	}
174177af1b26SLinus Walleij 
1742ded06a52SMark Brown 	if (ret == 0)
1743ded06a52SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
1744ded06a52SMark Brown 				     NULL);
1745ded06a52SMark Brown 
174675790251SMark Brown 	trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector);
174775790251SMark Brown 
174875790251SMark Brown 	return ret;
174975790251SMark Brown }
175075790251SMark Brown 
1751a7a1ad90SMark Brown /**
1752414c70cbSLiam Girdwood  * regulator_set_voltage - set regulator output voltage
1753414c70cbSLiam Girdwood  * @regulator: regulator source
1754414c70cbSLiam Girdwood  * @min_uV: Minimum required voltage in uV
1755414c70cbSLiam Girdwood  * @max_uV: Maximum acceptable voltage in uV
1756414c70cbSLiam Girdwood  *
1757414c70cbSLiam Girdwood  * Sets a voltage regulator to the desired output voltage. This can be set
1758414c70cbSLiam Girdwood  * during any regulator state. IOW, regulator can be disabled or enabled.
1759414c70cbSLiam Girdwood  *
1760414c70cbSLiam Girdwood  * If the regulator is enabled then the voltage will change to the new value
1761414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
1762414c70cbSLiam Girdwood  * output at the new voltage when enabled.
1763414c70cbSLiam Girdwood  *
1764414c70cbSLiam Girdwood  * NOTE: If the regulator is shared between several devices then the lowest
1765414c70cbSLiam Girdwood  * request voltage that meets the system constraints will be used.
176669279fb9SMark Brown  * Regulator system constraints must be set for this regulator before
1767414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
1768414c70cbSLiam Girdwood  */
1769414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
1770414c70cbSLiam Girdwood {
1771414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
177295a3c23aSMark Brown 	int ret = 0;
1773414c70cbSLiam Girdwood 
1774414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
1775414c70cbSLiam Girdwood 
177695a3c23aSMark Brown 	/* If we're setting the same range as last time the change
177795a3c23aSMark Brown 	 * should be a noop (some cpufreq implementations use the same
177895a3c23aSMark Brown 	 * voltage for multiple frequencies, for example).
177995a3c23aSMark Brown 	 */
178095a3c23aSMark Brown 	if (regulator->min_uV == min_uV && regulator->max_uV == max_uV)
178195a3c23aSMark Brown 		goto out;
178295a3c23aSMark Brown 
1783414c70cbSLiam Girdwood 	/* sanity check */
1784e8eef82bSMark Brown 	if (!rdev->desc->ops->set_voltage &&
1785e8eef82bSMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
1786414c70cbSLiam Girdwood 		ret = -EINVAL;
1787414c70cbSLiam Girdwood 		goto out;
1788414c70cbSLiam Girdwood 	}
1789414c70cbSLiam Girdwood 
1790414c70cbSLiam Girdwood 	/* constraints check */
1791414c70cbSLiam Girdwood 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
1792414c70cbSLiam Girdwood 	if (ret < 0)
1793414c70cbSLiam Girdwood 		goto out;
1794414c70cbSLiam Girdwood 	regulator->min_uV = min_uV;
1795414c70cbSLiam Girdwood 	regulator->max_uV = max_uV;
17963a93f2a9SMark Brown 
179705fda3b1SThomas Petazzoni 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
179805fda3b1SThomas Petazzoni 	if (ret < 0)
179905fda3b1SThomas Petazzoni 		goto out;
180005fda3b1SThomas Petazzoni 
180175790251SMark Brown 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
180202fa3ec0SMark Brown 
1803414c70cbSLiam Girdwood out:
1804414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1805414c70cbSLiam Girdwood 	return ret;
1806414c70cbSLiam Girdwood }
1807414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage);
1808414c70cbSLiam Girdwood 
1809606a2562SMark Brown /**
181088cd222bSLinus Walleij  * regulator_set_voltage_time - get raise/fall time
181188cd222bSLinus Walleij  * @regulator: regulator source
181288cd222bSLinus Walleij  * @old_uV: starting voltage in microvolts
181388cd222bSLinus Walleij  * @new_uV: target voltage in microvolts
181488cd222bSLinus Walleij  *
181588cd222bSLinus Walleij  * Provided with the starting and ending voltage, this function attempts to
181688cd222bSLinus Walleij  * calculate the time in microseconds required to rise or fall to this new
181788cd222bSLinus Walleij  * voltage.
181888cd222bSLinus Walleij  */
181988cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator,
182088cd222bSLinus Walleij 			       int old_uV, int new_uV)
182188cd222bSLinus Walleij {
182288cd222bSLinus Walleij 	struct regulator_dev	*rdev = regulator->rdev;
182388cd222bSLinus Walleij 	struct regulator_ops	*ops = rdev->desc->ops;
182488cd222bSLinus Walleij 	int old_sel = -1;
182588cd222bSLinus Walleij 	int new_sel = -1;
182688cd222bSLinus Walleij 	int voltage;
182788cd222bSLinus Walleij 	int i;
182888cd222bSLinus Walleij 
182988cd222bSLinus Walleij 	/* Currently requires operations to do this */
183088cd222bSLinus Walleij 	if (!ops->list_voltage || !ops->set_voltage_time_sel
183188cd222bSLinus Walleij 	    || !rdev->desc->n_voltages)
183288cd222bSLinus Walleij 		return -EINVAL;
183388cd222bSLinus Walleij 
183488cd222bSLinus Walleij 	for (i = 0; i < rdev->desc->n_voltages; i++) {
183588cd222bSLinus Walleij 		/* We only look for exact voltage matches here */
183688cd222bSLinus Walleij 		voltage = regulator_list_voltage(regulator, i);
183788cd222bSLinus Walleij 		if (voltage < 0)
183888cd222bSLinus Walleij 			return -EINVAL;
183988cd222bSLinus Walleij 		if (voltage == 0)
184088cd222bSLinus Walleij 			continue;
184188cd222bSLinus Walleij 		if (voltage == old_uV)
184288cd222bSLinus Walleij 			old_sel = i;
184388cd222bSLinus Walleij 		if (voltage == new_uV)
184488cd222bSLinus Walleij 			new_sel = i;
184588cd222bSLinus Walleij 	}
184688cd222bSLinus Walleij 
184788cd222bSLinus Walleij 	if (old_sel < 0 || new_sel < 0)
184888cd222bSLinus Walleij 		return -EINVAL;
184988cd222bSLinus Walleij 
185088cd222bSLinus Walleij 	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
185188cd222bSLinus Walleij }
185288cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
185388cd222bSLinus Walleij 
185488cd222bSLinus Walleij /**
1855606a2562SMark Brown  * regulator_sync_voltage - re-apply last regulator output voltage
1856606a2562SMark Brown  * @regulator: regulator source
1857606a2562SMark Brown  *
1858606a2562SMark Brown  * Re-apply the last configured voltage.  This is intended to be used
1859606a2562SMark Brown  * where some external control source the consumer is cooperating with
1860606a2562SMark Brown  * has caused the configured voltage to change.
1861606a2562SMark Brown  */
1862606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator)
1863606a2562SMark Brown {
1864606a2562SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
1865606a2562SMark Brown 	int ret, min_uV, max_uV;
1866606a2562SMark Brown 
1867606a2562SMark Brown 	mutex_lock(&rdev->mutex);
1868606a2562SMark Brown 
1869606a2562SMark Brown 	if (!rdev->desc->ops->set_voltage &&
1870606a2562SMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
1871606a2562SMark Brown 		ret = -EINVAL;
1872606a2562SMark Brown 		goto out;
1873606a2562SMark Brown 	}
1874606a2562SMark Brown 
1875606a2562SMark Brown 	/* This is only going to work if we've had a voltage configured. */
1876606a2562SMark Brown 	if (!regulator->min_uV && !regulator->max_uV) {
1877606a2562SMark Brown 		ret = -EINVAL;
1878606a2562SMark Brown 		goto out;
1879606a2562SMark Brown 	}
1880606a2562SMark Brown 
1881606a2562SMark Brown 	min_uV = regulator->min_uV;
1882606a2562SMark Brown 	max_uV = regulator->max_uV;
1883606a2562SMark Brown 
1884606a2562SMark Brown 	/* This should be a paranoia check... */
1885606a2562SMark Brown 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
1886606a2562SMark Brown 	if (ret < 0)
1887606a2562SMark Brown 		goto out;
1888606a2562SMark Brown 
1889606a2562SMark Brown 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
1890606a2562SMark Brown 	if (ret < 0)
1891606a2562SMark Brown 		goto out;
1892606a2562SMark Brown 
1893606a2562SMark Brown 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
1894606a2562SMark Brown 
1895606a2562SMark Brown out:
1896606a2562SMark Brown 	mutex_unlock(&rdev->mutex);
1897606a2562SMark Brown 	return ret;
1898606a2562SMark Brown }
1899606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage);
1900606a2562SMark Brown 
1901414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev)
1902414c70cbSLiam Girdwood {
1903bf5892a8SMark Brown 	int sel, ret;
1904476c2d83SMark Brown 
1905476c2d83SMark Brown 	if (rdev->desc->ops->get_voltage_sel) {
1906476c2d83SMark Brown 		sel = rdev->desc->ops->get_voltage_sel(rdev);
1907476c2d83SMark Brown 		if (sel < 0)
1908476c2d83SMark Brown 			return sel;
1909bf5892a8SMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, sel);
1910cb220d16SAxel Lin 	} else if (rdev->desc->ops->get_voltage) {
1911bf5892a8SMark Brown 		ret = rdev->desc->ops->get_voltage(rdev);
1912cb220d16SAxel Lin 	} else {
1913414c70cbSLiam Girdwood 		return -EINVAL;
1914cb220d16SAxel Lin 	}
1915bf5892a8SMark Brown 
1916cb220d16SAxel Lin 	if (ret < 0)
1917cb220d16SAxel Lin 		return ret;
1918bf5892a8SMark Brown 	return ret - rdev->constraints->uV_offset;
1919414c70cbSLiam Girdwood }
1920414c70cbSLiam Girdwood 
1921414c70cbSLiam Girdwood /**
1922414c70cbSLiam Girdwood  * regulator_get_voltage - get regulator output voltage
1923414c70cbSLiam Girdwood  * @regulator: regulator source
1924414c70cbSLiam Girdwood  *
1925414c70cbSLiam Girdwood  * This returns the current regulator voltage in uV.
1926414c70cbSLiam Girdwood  *
1927414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the voltage value. This
1928414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
1929414c70cbSLiam Girdwood  */
1930414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator)
1931414c70cbSLiam Girdwood {
1932414c70cbSLiam Girdwood 	int ret;
1933414c70cbSLiam Girdwood 
1934414c70cbSLiam Girdwood 	mutex_lock(&regulator->rdev->mutex);
1935414c70cbSLiam Girdwood 
1936414c70cbSLiam Girdwood 	ret = _regulator_get_voltage(regulator->rdev);
1937414c70cbSLiam Girdwood 
1938414c70cbSLiam Girdwood 	mutex_unlock(&regulator->rdev->mutex);
1939414c70cbSLiam Girdwood 
1940414c70cbSLiam Girdwood 	return ret;
1941414c70cbSLiam Girdwood }
1942414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage);
1943414c70cbSLiam Girdwood 
1944414c70cbSLiam Girdwood /**
1945414c70cbSLiam Girdwood  * regulator_set_current_limit - set regulator output current limit
1946414c70cbSLiam Girdwood  * @regulator: regulator source
1947414c70cbSLiam Girdwood  * @min_uA: Minimuum supported current in uA
1948414c70cbSLiam Girdwood  * @max_uA: Maximum supported current in uA
1949414c70cbSLiam Girdwood  *
1950414c70cbSLiam Girdwood  * Sets current sink to the desired output current. This can be set during
1951414c70cbSLiam Girdwood  * any regulator state. IOW, regulator can be disabled or enabled.
1952414c70cbSLiam Girdwood  *
1953414c70cbSLiam Girdwood  * If the regulator is enabled then the current will change to the new value
1954414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
1955414c70cbSLiam Girdwood  * output at the new current when enabled.
1956414c70cbSLiam Girdwood  *
1957414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
1958414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
1959414c70cbSLiam Girdwood  */
1960414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator,
1961414c70cbSLiam Girdwood 			       int min_uA, int max_uA)
1962414c70cbSLiam Girdwood {
1963414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
1964414c70cbSLiam Girdwood 	int ret;
1965414c70cbSLiam Girdwood 
1966414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
1967414c70cbSLiam Girdwood 
1968414c70cbSLiam Girdwood 	/* sanity check */
1969414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_current_limit) {
1970414c70cbSLiam Girdwood 		ret = -EINVAL;
1971414c70cbSLiam Girdwood 		goto out;
1972414c70cbSLiam Girdwood 	}
1973414c70cbSLiam Girdwood 
1974414c70cbSLiam Girdwood 	/* constraints check */
1975414c70cbSLiam Girdwood 	ret = regulator_check_current_limit(rdev, &min_uA, &max_uA);
1976414c70cbSLiam Girdwood 	if (ret < 0)
1977414c70cbSLiam Girdwood 		goto out;
1978414c70cbSLiam Girdwood 
1979414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
1980414c70cbSLiam Girdwood out:
1981414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1982414c70cbSLiam Girdwood 	return ret;
1983414c70cbSLiam Girdwood }
1984414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit);
1985414c70cbSLiam Girdwood 
1986414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev)
1987414c70cbSLiam Girdwood {
1988414c70cbSLiam Girdwood 	int ret;
1989414c70cbSLiam Girdwood 
1990414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
1991414c70cbSLiam Girdwood 
1992414c70cbSLiam Girdwood 	/* sanity check */
1993414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_current_limit) {
1994414c70cbSLiam Girdwood 		ret = -EINVAL;
1995414c70cbSLiam Girdwood 		goto out;
1996414c70cbSLiam Girdwood 	}
1997414c70cbSLiam Girdwood 
1998414c70cbSLiam Girdwood 	ret = rdev->desc->ops->get_current_limit(rdev);
1999414c70cbSLiam Girdwood out:
2000414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2001414c70cbSLiam Girdwood 	return ret;
2002414c70cbSLiam Girdwood }
2003414c70cbSLiam Girdwood 
2004414c70cbSLiam Girdwood /**
2005414c70cbSLiam Girdwood  * regulator_get_current_limit - get regulator output current
2006414c70cbSLiam Girdwood  * @regulator: regulator source
2007414c70cbSLiam Girdwood  *
2008414c70cbSLiam Girdwood  * This returns the current supplied by the specified current sink in uA.
2009414c70cbSLiam Girdwood  *
2010414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the current value. This
2011414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
2012414c70cbSLiam Girdwood  */
2013414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator)
2014414c70cbSLiam Girdwood {
2015414c70cbSLiam Girdwood 	return _regulator_get_current_limit(regulator->rdev);
2016414c70cbSLiam Girdwood }
2017414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit);
2018414c70cbSLiam Girdwood 
2019414c70cbSLiam Girdwood /**
2020414c70cbSLiam Girdwood  * regulator_set_mode - set regulator operating mode
2021414c70cbSLiam Girdwood  * @regulator: regulator source
2022414c70cbSLiam Girdwood  * @mode: operating mode - one of the REGULATOR_MODE constants
2023414c70cbSLiam Girdwood  *
2024414c70cbSLiam Girdwood  * Set regulator operating mode to increase regulator efficiency or improve
2025414c70cbSLiam Girdwood  * regulation performance.
2026414c70cbSLiam Girdwood  *
2027414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
2028414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
2029414c70cbSLiam Girdwood  */
2030414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode)
2031414c70cbSLiam Girdwood {
2032414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2033414c70cbSLiam Girdwood 	int ret;
2034500b4ac9SSundar R Iyer 	int regulator_curr_mode;
2035414c70cbSLiam Girdwood 
2036414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2037414c70cbSLiam Girdwood 
2038414c70cbSLiam Girdwood 	/* sanity check */
2039414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_mode) {
2040414c70cbSLiam Girdwood 		ret = -EINVAL;
2041414c70cbSLiam Girdwood 		goto out;
2042414c70cbSLiam Girdwood 	}
2043414c70cbSLiam Girdwood 
2044500b4ac9SSundar R Iyer 	/* return if the same mode is requested */
2045500b4ac9SSundar R Iyer 	if (rdev->desc->ops->get_mode) {
2046500b4ac9SSundar R Iyer 		regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
2047500b4ac9SSundar R Iyer 		if (regulator_curr_mode == mode) {
2048500b4ac9SSundar R Iyer 			ret = 0;
2049500b4ac9SSundar R Iyer 			goto out;
2050500b4ac9SSundar R Iyer 		}
2051500b4ac9SSundar R Iyer 	}
2052500b4ac9SSundar R Iyer 
2053414c70cbSLiam Girdwood 	/* constraints check */
205422c51b47SAxel Lin 	ret = regulator_mode_constrain(rdev, &mode);
2055414c70cbSLiam Girdwood 	if (ret < 0)
2056414c70cbSLiam Girdwood 		goto out;
2057414c70cbSLiam Girdwood 
2058414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
2059414c70cbSLiam Girdwood out:
2060414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2061414c70cbSLiam Girdwood 	return ret;
2062414c70cbSLiam Girdwood }
2063414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode);
2064414c70cbSLiam Girdwood 
2065414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
2066414c70cbSLiam Girdwood {
2067414c70cbSLiam Girdwood 	int ret;
2068414c70cbSLiam Girdwood 
2069414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2070414c70cbSLiam Girdwood 
2071414c70cbSLiam Girdwood 	/* sanity check */
2072414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_mode) {
2073414c70cbSLiam Girdwood 		ret = -EINVAL;
2074414c70cbSLiam Girdwood 		goto out;
2075414c70cbSLiam Girdwood 	}
2076414c70cbSLiam Girdwood 
2077414c70cbSLiam Girdwood 	ret = rdev->desc->ops->get_mode(rdev);
2078414c70cbSLiam Girdwood out:
2079414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2080414c70cbSLiam Girdwood 	return ret;
2081414c70cbSLiam Girdwood }
2082414c70cbSLiam Girdwood 
2083414c70cbSLiam Girdwood /**
2084414c70cbSLiam Girdwood  * regulator_get_mode - get regulator operating mode
2085414c70cbSLiam Girdwood  * @regulator: regulator source
2086414c70cbSLiam Girdwood  *
2087414c70cbSLiam Girdwood  * Get the current regulator operating mode.
2088414c70cbSLiam Girdwood  */
2089414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator)
2090414c70cbSLiam Girdwood {
2091414c70cbSLiam Girdwood 	return _regulator_get_mode(regulator->rdev);
2092414c70cbSLiam Girdwood }
2093414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode);
2094414c70cbSLiam Girdwood 
2095414c70cbSLiam Girdwood /**
2096414c70cbSLiam Girdwood  * regulator_set_optimum_mode - set regulator optimum operating mode
2097414c70cbSLiam Girdwood  * @regulator: regulator source
2098414c70cbSLiam Girdwood  * @uA_load: load current
2099414c70cbSLiam Girdwood  *
2100414c70cbSLiam Girdwood  * Notifies the regulator core of a new device load. This is then used by
2101414c70cbSLiam Girdwood  * DRMS (if enabled by constraints) to set the most efficient regulator
2102414c70cbSLiam Girdwood  * operating mode for the new regulator loading.
2103414c70cbSLiam Girdwood  *
2104414c70cbSLiam Girdwood  * Consumer devices notify their supply regulator of the maximum power
2105414c70cbSLiam Girdwood  * they will require (can be taken from device datasheet in the power
2106414c70cbSLiam Girdwood  * consumption tables) when they change operational status and hence power
2107414c70cbSLiam Girdwood  * state. Examples of operational state changes that can affect power
2108414c70cbSLiam Girdwood  * consumption are :-
2109414c70cbSLiam Girdwood  *
2110414c70cbSLiam Girdwood  *    o Device is opened / closed.
2111414c70cbSLiam Girdwood  *    o Device I/O is about to begin or has just finished.
2112414c70cbSLiam Girdwood  *    o Device is idling in between work.
2113414c70cbSLiam Girdwood  *
2114414c70cbSLiam Girdwood  * This information is also exported via sysfs to userspace.
2115414c70cbSLiam Girdwood  *
2116414c70cbSLiam Girdwood  * DRMS will sum the total requested load on the regulator and change
2117414c70cbSLiam Girdwood  * to the most efficient operating mode if platform constraints allow.
2118414c70cbSLiam Girdwood  *
2119414c70cbSLiam Girdwood  * Returns the new regulator mode or error.
2120414c70cbSLiam Girdwood  */
2121414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
2122414c70cbSLiam Girdwood {
2123414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2124414c70cbSLiam Girdwood 	struct regulator *consumer;
2125414c70cbSLiam Girdwood 	int ret, output_uV, input_uV, total_uA_load = 0;
2126414c70cbSLiam Girdwood 	unsigned int mode;
2127414c70cbSLiam Girdwood 
2128414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2129414c70cbSLiam Girdwood 
2130a4b41483SMark Brown 	/*
2131a4b41483SMark Brown 	 * first check to see if we can set modes at all, otherwise just
2132a4b41483SMark Brown 	 * tell the consumer everything is OK.
2133a4b41483SMark Brown 	 */
2134414c70cbSLiam Girdwood 	regulator->uA_load = uA_load;
2135414c70cbSLiam Girdwood 	ret = regulator_check_drms(rdev);
2136a4b41483SMark Brown 	if (ret < 0) {
2137a4b41483SMark Brown 		ret = 0;
2138414c70cbSLiam Girdwood 		goto out;
2139a4b41483SMark Brown 	}
2140414c70cbSLiam Girdwood 
2141414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_optimum_mode)
2142414c70cbSLiam Girdwood 		goto out;
2143414c70cbSLiam Girdwood 
2144a4b41483SMark Brown 	/*
2145a4b41483SMark Brown 	 * we can actually do this so any errors are indicators of
2146a4b41483SMark Brown 	 * potential real failure.
2147a4b41483SMark Brown 	 */
2148a4b41483SMark Brown 	ret = -EINVAL;
2149a4b41483SMark Brown 
2150414c70cbSLiam Girdwood 	/* get output voltage */
21511bf5a1f8SMark Brown 	output_uV = _regulator_get_voltage(rdev);
2152414c70cbSLiam Girdwood 	if (output_uV <= 0) {
21535da84fd9SJoe Perches 		rdev_err(rdev, "invalid output voltage found\n");
2154414c70cbSLiam Girdwood 		goto out;
2155414c70cbSLiam Girdwood 	}
2156414c70cbSLiam Girdwood 
2157414c70cbSLiam Girdwood 	/* get input voltage */
21581bf5a1f8SMark Brown 	input_uV = 0;
21591bf5a1f8SMark Brown 	if (rdev->supply)
21603801b86aSMark Brown 		input_uV = regulator_get_voltage(rdev->supply);
21611bf5a1f8SMark Brown 	if (input_uV <= 0)
2162414c70cbSLiam Girdwood 		input_uV = rdev->constraints->input_uV;
2163414c70cbSLiam Girdwood 	if (input_uV <= 0) {
21645da84fd9SJoe Perches 		rdev_err(rdev, "invalid input voltage found\n");
2165414c70cbSLiam Girdwood 		goto out;
2166414c70cbSLiam Girdwood 	}
2167414c70cbSLiam Girdwood 
2168414c70cbSLiam Girdwood 	/* calc total requested load for this regulator */
2169414c70cbSLiam Girdwood 	list_for_each_entry(consumer, &rdev->consumer_list, list)
2170414c70cbSLiam Girdwood 		total_uA_load += consumer->uA_load;
2171414c70cbSLiam Girdwood 
2172414c70cbSLiam Girdwood 	mode = rdev->desc->ops->get_optimum_mode(rdev,
2173414c70cbSLiam Girdwood 						 input_uV, output_uV,
2174414c70cbSLiam Girdwood 						 total_uA_load);
21752c608234SMark Brown 	ret = regulator_mode_constrain(rdev, &mode);
2176e573520bSDavid Brownell 	if (ret < 0) {
21775da84fd9SJoe Perches 		rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
2178414c70cbSLiam Girdwood 			 total_uA_load, input_uV, output_uV);
2179414c70cbSLiam Girdwood 		goto out;
2180414c70cbSLiam Girdwood 	}
2181414c70cbSLiam Girdwood 
2182414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
2183e573520bSDavid Brownell 	if (ret < 0) {
21845da84fd9SJoe Perches 		rdev_err(rdev, "failed to set optimum mode %x\n", mode);
2185414c70cbSLiam Girdwood 		goto out;
2186414c70cbSLiam Girdwood 	}
2187414c70cbSLiam Girdwood 	ret = mode;
2188414c70cbSLiam Girdwood out:
2189414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2190414c70cbSLiam Girdwood 	return ret;
2191414c70cbSLiam Girdwood }
2192414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
2193414c70cbSLiam Girdwood 
2194414c70cbSLiam Girdwood /**
2195414c70cbSLiam Girdwood  * regulator_register_notifier - register regulator event notifier
2196414c70cbSLiam Girdwood  * @regulator: regulator source
219769279fb9SMark Brown  * @nb: notifier block
2198414c70cbSLiam Girdwood  *
2199414c70cbSLiam Girdwood  * Register notifier block to receive regulator events.
2200414c70cbSLiam Girdwood  */
2201414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator,
2202414c70cbSLiam Girdwood 			      struct notifier_block *nb)
2203414c70cbSLiam Girdwood {
2204414c70cbSLiam Girdwood 	return blocking_notifier_chain_register(&regulator->rdev->notifier,
2205414c70cbSLiam Girdwood 						nb);
2206414c70cbSLiam Girdwood }
2207414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier);
2208414c70cbSLiam Girdwood 
2209414c70cbSLiam Girdwood /**
2210414c70cbSLiam Girdwood  * regulator_unregister_notifier - unregister regulator event notifier
2211414c70cbSLiam Girdwood  * @regulator: regulator source
221269279fb9SMark Brown  * @nb: notifier block
2213414c70cbSLiam Girdwood  *
2214414c70cbSLiam Girdwood  * Unregister regulator event notifier block.
2215414c70cbSLiam Girdwood  */
2216414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator,
2217414c70cbSLiam Girdwood 				struct notifier_block *nb)
2218414c70cbSLiam Girdwood {
2219414c70cbSLiam Girdwood 	return blocking_notifier_chain_unregister(&regulator->rdev->notifier,
2220414c70cbSLiam Girdwood 						  nb);
2221414c70cbSLiam Girdwood }
2222414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
2223414c70cbSLiam Girdwood 
2224b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers.
2225b136fb44SJonathan Cameron  * Note mutex must be held by caller.
2226b136fb44SJonathan Cameron  */
2227414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev,
2228414c70cbSLiam Girdwood 				  unsigned long event, void *data)
2229414c70cbSLiam Girdwood {
2230414c70cbSLiam Girdwood 	/* call rdev chain first */
2231414c70cbSLiam Girdwood 	blocking_notifier_call_chain(&rdev->notifier, event, NULL);
2232414c70cbSLiam Girdwood }
2233414c70cbSLiam Girdwood 
2234414c70cbSLiam Girdwood /**
2235414c70cbSLiam Girdwood  * regulator_bulk_get - get multiple regulator consumers
2236414c70cbSLiam Girdwood  *
2237414c70cbSLiam Girdwood  * @dev:           Device to supply
2238414c70cbSLiam Girdwood  * @num_consumers: Number of consumers to register
2239414c70cbSLiam Girdwood  * @consumers:     Configuration of consumers; clients are stored here.
2240414c70cbSLiam Girdwood  *
2241414c70cbSLiam Girdwood  * @return 0 on success, an errno on failure.
2242414c70cbSLiam Girdwood  *
2243414c70cbSLiam Girdwood  * This helper function allows drivers to get several regulator
2244414c70cbSLiam Girdwood  * consumers in one operation.  If any of the regulators cannot be
2245414c70cbSLiam Girdwood  * acquired then any regulators that were allocated will be freed
2246414c70cbSLiam Girdwood  * before returning to the caller.
2247414c70cbSLiam Girdwood  */
2248414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers,
2249414c70cbSLiam Girdwood 		       struct regulator_bulk_data *consumers)
2250414c70cbSLiam Girdwood {
2251414c70cbSLiam Girdwood 	int i;
2252414c70cbSLiam Girdwood 	int ret;
2253414c70cbSLiam Girdwood 
2254414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++)
2255414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
2256414c70cbSLiam Girdwood 
2257414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2258414c70cbSLiam Girdwood 		consumers[i].consumer = regulator_get(dev,
2259414c70cbSLiam Girdwood 						      consumers[i].supply);
2260414c70cbSLiam Girdwood 		if (IS_ERR(consumers[i].consumer)) {
2261414c70cbSLiam Girdwood 			ret = PTR_ERR(consumers[i].consumer);
22625b307627SMark Brown 			dev_err(dev, "Failed to get supply '%s': %d\n",
22635b307627SMark Brown 				consumers[i].supply, ret);
2264414c70cbSLiam Girdwood 			consumers[i].consumer = NULL;
2265414c70cbSLiam Girdwood 			goto err;
2266414c70cbSLiam Girdwood 		}
2267414c70cbSLiam Girdwood 	}
2268414c70cbSLiam Girdwood 
2269414c70cbSLiam Girdwood 	return 0;
2270414c70cbSLiam Girdwood 
2271414c70cbSLiam Girdwood err:
2272414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
2273414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
2274414c70cbSLiam Girdwood 
2275414c70cbSLiam Girdwood 	return ret;
2276414c70cbSLiam Girdwood }
2277414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get);
2278414c70cbSLiam Girdwood 
2279f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
2280f21e0e81SMark Brown {
2281f21e0e81SMark Brown 	struct regulator_bulk_data *bulk = data;
2282f21e0e81SMark Brown 
2283f21e0e81SMark Brown 	bulk->ret = regulator_enable(bulk->consumer);
2284f21e0e81SMark Brown }
2285f21e0e81SMark Brown 
2286414c70cbSLiam Girdwood /**
2287414c70cbSLiam Girdwood  * regulator_bulk_enable - enable multiple regulator consumers
2288414c70cbSLiam Girdwood  *
2289414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2290414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2291414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
2292414c70cbSLiam Girdwood  *
2293414c70cbSLiam Girdwood  * This convenience API allows consumers to enable multiple regulator
2294414c70cbSLiam Girdwood  * clients in a single API call.  If any consumers cannot be enabled
2295414c70cbSLiam Girdwood  * then any others that were enabled will be disabled again prior to
2296414c70cbSLiam Girdwood  * return.
2297414c70cbSLiam Girdwood  */
2298414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers,
2299414c70cbSLiam Girdwood 			  struct regulator_bulk_data *consumers)
2300414c70cbSLiam Girdwood {
2301f21e0e81SMark Brown 	LIST_HEAD(async_domain);
2302414c70cbSLiam Girdwood 	int i;
2303f21e0e81SMark Brown 	int ret = 0;
2304414c70cbSLiam Girdwood 
2305f21e0e81SMark Brown 	for (i = 0; i < num_consumers; i++)
2306f21e0e81SMark Brown 		async_schedule_domain(regulator_bulk_enable_async,
2307f21e0e81SMark Brown 				      &consumers[i], &async_domain);
2308f21e0e81SMark Brown 
2309f21e0e81SMark Brown 	async_synchronize_full_domain(&async_domain);
2310f21e0e81SMark Brown 
2311f21e0e81SMark Brown 	/* If any consumer failed we need to unwind any that succeeded */
2312414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2313f21e0e81SMark Brown 		if (consumers[i].ret != 0) {
2314f21e0e81SMark Brown 			ret = consumers[i].ret;
2315414c70cbSLiam Girdwood 			goto err;
2316414c70cbSLiam Girdwood 		}
2317f21e0e81SMark Brown 	}
2318414c70cbSLiam Girdwood 
2319414c70cbSLiam Girdwood 	return 0;
2320414c70cbSLiam Girdwood 
2321414c70cbSLiam Girdwood err:
2322f21e0e81SMark Brown 	for (i = 0; i < num_consumers; i++)
2323f21e0e81SMark Brown 		if (consumers[i].ret == 0)
2324414c70cbSLiam Girdwood 			regulator_disable(consumers[i].consumer);
2325f21e0e81SMark Brown 		else
2326f21e0e81SMark Brown 			pr_err("Failed to enable %s: %d\n",
2327f21e0e81SMark Brown 			       consumers[i].supply, consumers[i].ret);
2328414c70cbSLiam Girdwood 
2329414c70cbSLiam Girdwood 	return ret;
2330414c70cbSLiam Girdwood }
2331414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable);
2332414c70cbSLiam Girdwood 
2333414c70cbSLiam Girdwood /**
2334414c70cbSLiam Girdwood  * regulator_bulk_disable - disable multiple regulator consumers
2335414c70cbSLiam Girdwood  *
2336414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2337414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2338414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
2339414c70cbSLiam Girdwood  *
2340414c70cbSLiam Girdwood  * This convenience API allows consumers to disable multiple regulator
2341414c70cbSLiam Girdwood  * clients in a single API call.  If any consumers cannot be enabled
2342414c70cbSLiam Girdwood  * then any others that were disabled will be disabled again prior to
2343414c70cbSLiam Girdwood  * return.
2344414c70cbSLiam Girdwood  */
2345414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers,
2346414c70cbSLiam Girdwood 			   struct regulator_bulk_data *consumers)
2347414c70cbSLiam Girdwood {
2348414c70cbSLiam Girdwood 	int i;
2349414c70cbSLiam Girdwood 	int ret;
2350414c70cbSLiam Girdwood 
2351414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2352414c70cbSLiam Girdwood 		ret = regulator_disable(consumers[i].consumer);
2353414c70cbSLiam Girdwood 		if (ret != 0)
2354414c70cbSLiam Girdwood 			goto err;
2355414c70cbSLiam Girdwood 	}
2356414c70cbSLiam Girdwood 
2357414c70cbSLiam Girdwood 	return 0;
2358414c70cbSLiam Girdwood 
2359414c70cbSLiam Girdwood err:
23605da84fd9SJoe Perches 	pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
2361eb143ac1SLars-Peter Clausen 	for (--i; i >= 0; --i)
2362414c70cbSLiam Girdwood 		regulator_enable(consumers[i].consumer);
2363414c70cbSLiam Girdwood 
2364414c70cbSLiam Girdwood 	return ret;
2365414c70cbSLiam Girdwood }
2366414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable);
2367414c70cbSLiam Girdwood 
2368414c70cbSLiam Girdwood /**
2369414c70cbSLiam Girdwood  * regulator_bulk_free - free multiple regulator consumers
2370414c70cbSLiam Girdwood  *
2371414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2372414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2373414c70cbSLiam Girdwood  *
2374414c70cbSLiam Girdwood  * This convenience API allows consumers to free multiple regulator
2375414c70cbSLiam Girdwood  * clients in a single API call.
2376414c70cbSLiam Girdwood  */
2377414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers,
2378414c70cbSLiam Girdwood 			 struct regulator_bulk_data *consumers)
2379414c70cbSLiam Girdwood {
2380414c70cbSLiam Girdwood 	int i;
2381414c70cbSLiam Girdwood 
2382414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2383414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
2384414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
2385414c70cbSLiam Girdwood 	}
2386414c70cbSLiam Girdwood }
2387414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free);
2388414c70cbSLiam Girdwood 
2389414c70cbSLiam Girdwood /**
2390414c70cbSLiam Girdwood  * regulator_notifier_call_chain - call regulator event notifier
239169279fb9SMark Brown  * @rdev: regulator source
2392414c70cbSLiam Girdwood  * @event: notifier block
239369279fb9SMark Brown  * @data: callback-specific data.
2394414c70cbSLiam Girdwood  *
2395414c70cbSLiam Girdwood  * Called by regulator drivers to notify clients a regulator event has
2396414c70cbSLiam Girdwood  * occurred. We also notify regulator clients downstream.
2397b136fb44SJonathan Cameron  * Note lock must be held by caller.
2398414c70cbSLiam Girdwood  */
2399414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev,
2400414c70cbSLiam Girdwood 				  unsigned long event, void *data)
2401414c70cbSLiam Girdwood {
2402414c70cbSLiam Girdwood 	_notifier_call_chain(rdev, event, data);
2403414c70cbSLiam Girdwood 	return NOTIFY_DONE;
2404414c70cbSLiam Girdwood 
2405414c70cbSLiam Girdwood }
2406414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
2407414c70cbSLiam Girdwood 
2408be721979SMark Brown /**
2409be721979SMark Brown  * regulator_mode_to_status - convert a regulator mode into a status
2410be721979SMark Brown  *
2411be721979SMark Brown  * @mode: Mode to convert
2412be721979SMark Brown  *
2413be721979SMark Brown  * Convert a regulator mode into a status.
2414be721979SMark Brown  */
2415be721979SMark Brown int regulator_mode_to_status(unsigned int mode)
2416be721979SMark Brown {
2417be721979SMark Brown 	switch (mode) {
2418be721979SMark Brown 	case REGULATOR_MODE_FAST:
2419be721979SMark Brown 		return REGULATOR_STATUS_FAST;
2420be721979SMark Brown 	case REGULATOR_MODE_NORMAL:
2421be721979SMark Brown 		return REGULATOR_STATUS_NORMAL;
2422be721979SMark Brown 	case REGULATOR_MODE_IDLE:
2423be721979SMark Brown 		return REGULATOR_STATUS_IDLE;
2424be721979SMark Brown 	case REGULATOR_STATUS_STANDBY:
2425be721979SMark Brown 		return REGULATOR_STATUS_STANDBY;
2426be721979SMark Brown 	default:
2427be721979SMark Brown 		return 0;
2428be721979SMark Brown 	}
2429be721979SMark Brown }
2430be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status);
2431be721979SMark Brown 
24327ad68e2fSDavid Brownell /*
24337ad68e2fSDavid Brownell  * To avoid cluttering sysfs (and memory) with useless state, only
24347ad68e2fSDavid Brownell  * create attributes that can be meaningfully displayed.
24357ad68e2fSDavid Brownell  */
24367ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev)
24377ad68e2fSDavid Brownell {
24387ad68e2fSDavid Brownell 	struct device		*dev = &rdev->dev;
24397ad68e2fSDavid Brownell 	struct regulator_ops	*ops = rdev->desc->ops;
24407ad68e2fSDavid Brownell 	int			status = 0;
24417ad68e2fSDavid Brownell 
24427ad68e2fSDavid Brownell 	/* some attributes need specific methods to be displayed */
2443476c2d83SMark Brown 	if (ops->get_voltage || ops->get_voltage_sel) {
24447ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_microvolts);
24457ad68e2fSDavid Brownell 		if (status < 0)
24467ad68e2fSDavid Brownell 			return status;
24477ad68e2fSDavid Brownell 	}
24487ad68e2fSDavid Brownell 	if (ops->get_current_limit) {
24497ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_microamps);
24507ad68e2fSDavid Brownell 		if (status < 0)
24517ad68e2fSDavid Brownell 			return status;
24527ad68e2fSDavid Brownell 	}
24537ad68e2fSDavid Brownell 	if (ops->get_mode) {
24547ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_opmode);
24557ad68e2fSDavid Brownell 		if (status < 0)
24567ad68e2fSDavid Brownell 			return status;
24577ad68e2fSDavid Brownell 	}
24587ad68e2fSDavid Brownell 	if (ops->is_enabled) {
24597ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_state);
24607ad68e2fSDavid Brownell 		if (status < 0)
24617ad68e2fSDavid Brownell 			return status;
24627ad68e2fSDavid Brownell 	}
2463853116a1SDavid Brownell 	if (ops->get_status) {
2464853116a1SDavid Brownell 		status = device_create_file(dev, &dev_attr_status);
2465853116a1SDavid Brownell 		if (status < 0)
2466853116a1SDavid Brownell 			return status;
2467853116a1SDavid Brownell 	}
24687ad68e2fSDavid Brownell 
24697ad68e2fSDavid Brownell 	/* some attributes are type-specific */
24707ad68e2fSDavid Brownell 	if (rdev->desc->type == REGULATOR_CURRENT) {
24717ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_requested_microamps);
24727ad68e2fSDavid Brownell 		if (status < 0)
24737ad68e2fSDavid Brownell 			return status;
24747ad68e2fSDavid Brownell 	}
24757ad68e2fSDavid Brownell 
24767ad68e2fSDavid Brownell 	/* all the other attributes exist to support constraints;
24777ad68e2fSDavid Brownell 	 * don't show them if there are no constraints, or if the
24787ad68e2fSDavid Brownell 	 * relevant supporting methods are missing.
24797ad68e2fSDavid Brownell 	 */
24807ad68e2fSDavid Brownell 	if (!rdev->constraints)
24817ad68e2fSDavid Brownell 		return status;
24827ad68e2fSDavid Brownell 
24837ad68e2fSDavid Brownell 	/* constraints need specific supporting methods */
2484e8eef82bSMark Brown 	if (ops->set_voltage || ops->set_voltage_sel) {
24857ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_min_microvolts);
24867ad68e2fSDavid Brownell 		if (status < 0)
24877ad68e2fSDavid Brownell 			return status;
24887ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_max_microvolts);
24897ad68e2fSDavid Brownell 		if (status < 0)
24907ad68e2fSDavid Brownell 			return status;
24917ad68e2fSDavid Brownell 	}
24927ad68e2fSDavid Brownell 	if (ops->set_current_limit) {
24937ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_min_microamps);
24947ad68e2fSDavid Brownell 		if (status < 0)
24957ad68e2fSDavid Brownell 			return status;
24967ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_max_microamps);
24977ad68e2fSDavid Brownell 		if (status < 0)
24987ad68e2fSDavid Brownell 			return status;
24997ad68e2fSDavid Brownell 	}
25007ad68e2fSDavid Brownell 
25017ad68e2fSDavid Brownell 	/* suspend mode constraints need multiple supporting methods */
25027ad68e2fSDavid Brownell 	if (!(ops->set_suspend_enable && ops->set_suspend_disable))
25037ad68e2fSDavid Brownell 		return status;
25047ad68e2fSDavid Brownell 
25057ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_standby_state);
25067ad68e2fSDavid Brownell 	if (status < 0)
25077ad68e2fSDavid Brownell 		return status;
25087ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_mem_state);
25097ad68e2fSDavid Brownell 	if (status < 0)
25107ad68e2fSDavid Brownell 		return status;
25117ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_disk_state);
25127ad68e2fSDavid Brownell 	if (status < 0)
25137ad68e2fSDavid Brownell 		return status;
25147ad68e2fSDavid Brownell 
25157ad68e2fSDavid Brownell 	if (ops->set_suspend_voltage) {
25167ad68e2fSDavid Brownell 		status = device_create_file(dev,
25177ad68e2fSDavid Brownell 				&dev_attr_suspend_standby_microvolts);
25187ad68e2fSDavid Brownell 		if (status < 0)
25197ad68e2fSDavid Brownell 			return status;
25207ad68e2fSDavid Brownell 		status = device_create_file(dev,
25217ad68e2fSDavid Brownell 				&dev_attr_suspend_mem_microvolts);
25227ad68e2fSDavid Brownell 		if (status < 0)
25237ad68e2fSDavid Brownell 			return status;
25247ad68e2fSDavid Brownell 		status = device_create_file(dev,
25257ad68e2fSDavid Brownell 				&dev_attr_suspend_disk_microvolts);
25267ad68e2fSDavid Brownell 		if (status < 0)
25277ad68e2fSDavid Brownell 			return status;
25287ad68e2fSDavid Brownell 	}
25297ad68e2fSDavid Brownell 
25307ad68e2fSDavid Brownell 	if (ops->set_suspend_mode) {
25317ad68e2fSDavid Brownell 		status = device_create_file(dev,
25327ad68e2fSDavid Brownell 				&dev_attr_suspend_standby_mode);
25337ad68e2fSDavid Brownell 		if (status < 0)
25347ad68e2fSDavid Brownell 			return status;
25357ad68e2fSDavid Brownell 		status = device_create_file(dev,
25367ad68e2fSDavid Brownell 				&dev_attr_suspend_mem_mode);
25377ad68e2fSDavid Brownell 		if (status < 0)
25387ad68e2fSDavid Brownell 			return status;
25397ad68e2fSDavid Brownell 		status = device_create_file(dev,
25407ad68e2fSDavid Brownell 				&dev_attr_suspend_disk_mode);
25417ad68e2fSDavid Brownell 		if (status < 0)
25427ad68e2fSDavid Brownell 			return status;
25437ad68e2fSDavid Brownell 	}
25447ad68e2fSDavid Brownell 
25457ad68e2fSDavid Brownell 	return status;
25467ad68e2fSDavid Brownell }
25477ad68e2fSDavid Brownell 
25481130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev)
25491130e5b3SMark Brown {
25501130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
25511130e5b3SMark Brown 	rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
25521130e5b3SMark Brown 	if (IS_ERR(rdev->debugfs) || !rdev->debugfs) {
25531130e5b3SMark Brown 		rdev_warn(rdev, "Failed to create debugfs directory\n");
25541130e5b3SMark Brown 		rdev->debugfs = NULL;
25551130e5b3SMark Brown 		return;
25561130e5b3SMark Brown 	}
25571130e5b3SMark Brown 
25581130e5b3SMark Brown 	debugfs_create_u32("use_count", 0444, rdev->debugfs,
25591130e5b3SMark Brown 			   &rdev->use_count);
25601130e5b3SMark Brown 	debugfs_create_u32("open_count", 0444, rdev->debugfs,
25611130e5b3SMark Brown 			   &rdev->open_count);
25621130e5b3SMark Brown #endif
25631130e5b3SMark Brown }
25641130e5b3SMark Brown 
2565414c70cbSLiam Girdwood /**
2566414c70cbSLiam Girdwood  * regulator_register - register regulator
256769279fb9SMark Brown  * @regulator_desc: regulator to register
256869279fb9SMark Brown  * @dev: struct device for the regulator
25690527100fSMark Brown  * @init_data: platform provided init data, passed through by driver
257069279fb9SMark Brown  * @driver_data: private regulator data
2571414c70cbSLiam Girdwood  *
2572414c70cbSLiam Girdwood  * Called by regulator drivers to register a regulator.
2573414c70cbSLiam Girdwood  * Returns 0 on success.
2574414c70cbSLiam Girdwood  */
2575414c70cbSLiam Girdwood struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2576f8c12fe3SMark Brown 	struct device *dev, const struct regulator_init_data *init_data,
25770527100fSMark Brown 	void *driver_data)
2578414c70cbSLiam Girdwood {
2579414c70cbSLiam Girdwood 	static atomic_t regulator_no = ATOMIC_INIT(0);
2580414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
2581a5766f11SLiam Girdwood 	int ret, i;
2582414c70cbSLiam Girdwood 
2583414c70cbSLiam Girdwood 	if (regulator_desc == NULL)
2584414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
2585414c70cbSLiam Girdwood 
2586414c70cbSLiam Girdwood 	if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
2587414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
2588414c70cbSLiam Girdwood 
2589cd78dfc6SDiego Liziero 	if (regulator_desc->type != REGULATOR_VOLTAGE &&
2590cd78dfc6SDiego Liziero 	    regulator_desc->type != REGULATOR_CURRENT)
2591414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
2592414c70cbSLiam Girdwood 
259346fabe1eSMark Brown 	if (!init_data)
259446fabe1eSMark Brown 		return ERR_PTR(-EINVAL);
259546fabe1eSMark Brown 
2596476c2d83SMark Brown 	/* Only one of each should be implemented */
2597476c2d83SMark Brown 	WARN_ON(regulator_desc->ops->get_voltage &&
2598476c2d83SMark Brown 		regulator_desc->ops->get_voltage_sel);
2599e8eef82bSMark Brown 	WARN_ON(regulator_desc->ops->set_voltage &&
2600e8eef82bSMark Brown 		regulator_desc->ops->set_voltage_sel);
2601476c2d83SMark Brown 
2602476c2d83SMark Brown 	/* If we're using selectors we must implement list_voltage. */
2603476c2d83SMark Brown 	if (regulator_desc->ops->get_voltage_sel &&
2604476c2d83SMark Brown 	    !regulator_desc->ops->list_voltage) {
2605476c2d83SMark Brown 		return ERR_PTR(-EINVAL);
2606476c2d83SMark Brown 	}
2607e8eef82bSMark Brown 	if (regulator_desc->ops->set_voltage_sel &&
2608e8eef82bSMark Brown 	    !regulator_desc->ops->list_voltage) {
2609e8eef82bSMark Brown 		return ERR_PTR(-EINVAL);
2610e8eef82bSMark Brown 	}
2611476c2d83SMark Brown 
2612414c70cbSLiam Girdwood 	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
2613414c70cbSLiam Girdwood 	if (rdev == NULL)
2614414c70cbSLiam Girdwood 		return ERR_PTR(-ENOMEM);
2615414c70cbSLiam Girdwood 
2616414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
2617414c70cbSLiam Girdwood 
2618414c70cbSLiam Girdwood 	mutex_init(&rdev->mutex);
2619a5766f11SLiam Girdwood 	rdev->reg_data = driver_data;
2620414c70cbSLiam Girdwood 	rdev->owner = regulator_desc->owner;
2621414c70cbSLiam Girdwood 	rdev->desc = regulator_desc;
2622414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->consumer_list);
2623414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->list);
2624414c70cbSLiam Girdwood 	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
2625414c70cbSLiam Girdwood 
2626a5766f11SLiam Girdwood 	/* preform any regulator specific init */
2627a5766f11SLiam Girdwood 	if (init_data->regulator_init) {
2628a5766f11SLiam Girdwood 		ret = init_data->regulator_init(rdev->reg_data);
26294fca9545SDavid Brownell 		if (ret < 0)
26304fca9545SDavid Brownell 			goto clean;
2631a5766f11SLiam Girdwood 	}
2632a5766f11SLiam Girdwood 
2633a5766f11SLiam Girdwood 	/* register with sysfs */
2634a5766f11SLiam Girdwood 	rdev->dev.class = &regulator_class;
2635a5766f11SLiam Girdwood 	rdev->dev.parent = dev;
2636812460a9SKay Sievers 	dev_set_name(&rdev->dev, "regulator.%d",
2637812460a9SKay Sievers 		     atomic_inc_return(&regulator_no) - 1);
2638a5766f11SLiam Girdwood 	ret = device_register(&rdev->dev);
2639ad7725cbSVasiliy Kulikov 	if (ret != 0) {
2640ad7725cbSVasiliy Kulikov 		put_device(&rdev->dev);
26414fca9545SDavid Brownell 		goto clean;
2642ad7725cbSVasiliy Kulikov 	}
2643a5766f11SLiam Girdwood 
2644a5766f11SLiam Girdwood 	dev_set_drvdata(&rdev->dev, rdev);
2645a5766f11SLiam Girdwood 
264674f544c1SMike Rapoport 	/* set regulator constraints */
264774f544c1SMike Rapoport 	ret = set_machine_constraints(rdev, &init_data->constraints);
264874f544c1SMike Rapoport 	if (ret < 0)
264974f544c1SMike Rapoport 		goto scrub;
265074f544c1SMike Rapoport 
26517ad68e2fSDavid Brownell 	/* add attributes supported by this regulator */
26527ad68e2fSDavid Brownell 	ret = add_regulator_attributes(rdev);
26537ad68e2fSDavid Brownell 	if (ret < 0)
26547ad68e2fSDavid Brownell 		goto scrub;
26557ad68e2fSDavid Brownell 
26560178f3e2SMark Brown 	if (init_data->supply_regulator) {
26570178f3e2SMark Brown 		struct regulator_dev *r;
26580178f3e2SMark Brown 		int found = 0;
26590178f3e2SMark Brown 
26600178f3e2SMark Brown 		list_for_each_entry(r, &regulator_list, list) {
26610178f3e2SMark Brown 			if (strcmp(rdev_get_name(r),
26620178f3e2SMark Brown 				   init_data->supply_regulator) == 0) {
26630178f3e2SMark Brown 				found = 1;
26640178f3e2SMark Brown 				break;
26650178f3e2SMark Brown 			}
26660178f3e2SMark Brown 		}
26670178f3e2SMark Brown 
26680178f3e2SMark Brown 		if (!found) {
26690178f3e2SMark Brown 			dev_err(dev, "Failed to find supply %s\n",
26700178f3e2SMark Brown 				init_data->supply_regulator);
26717727da22SAxel Lin 			ret = -ENODEV;
26720178f3e2SMark Brown 			goto scrub;
26730178f3e2SMark Brown 		}
26740178f3e2SMark Brown 
26750178f3e2SMark Brown 		ret = set_supply(rdev, r);
26760178f3e2SMark Brown 		if (ret < 0)
26770178f3e2SMark Brown 			goto scrub;
26780178f3e2SMark Brown 	}
26790178f3e2SMark Brown 
2680a5766f11SLiam Girdwood 	/* add consumers devices */
2681a5766f11SLiam Girdwood 	for (i = 0; i < init_data->num_consumer_supplies; i++) {
2682a5766f11SLiam Girdwood 		ret = set_consumer_device_supply(rdev,
2683a5766f11SLiam Girdwood 			init_data->consumer_supplies[i].dev,
268440f9244fSMark Brown 			init_data->consumer_supplies[i].dev_name,
2685a5766f11SLiam Girdwood 			init_data->consumer_supplies[i].supply);
268623c2f041SMark Brown 		if (ret < 0) {
268723c2f041SMark Brown 			dev_err(dev, "Failed to set supply %s\n",
268823c2f041SMark Brown 				init_data->consumer_supplies[i].supply);
2689d4033b54SJani Nikula 			goto unset_supplies;
2690a5766f11SLiam Girdwood 		}
269123c2f041SMark Brown 	}
2692a5766f11SLiam Girdwood 
2693a5766f11SLiam Girdwood 	list_add(&rdev->list, &regulator_list);
26941130e5b3SMark Brown 
26951130e5b3SMark Brown 	rdev_init_debugfs(rdev);
2696a5766f11SLiam Girdwood out:
2697414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2698414c70cbSLiam Girdwood 	return rdev;
26994fca9545SDavid Brownell 
2700d4033b54SJani Nikula unset_supplies:
2701d4033b54SJani Nikula 	unset_regulator_supplies(rdev);
2702d4033b54SJani Nikula 
27034fca9545SDavid Brownell scrub:
27041a6958e7SAxel Lin 	kfree(rdev->constraints);
27054fca9545SDavid Brownell 	device_unregister(&rdev->dev);
270653032dafSPaul Walmsley 	/* device core frees rdev */
270753032dafSPaul Walmsley 	rdev = ERR_PTR(ret);
270853032dafSPaul Walmsley 	goto out;
270953032dafSPaul Walmsley 
27104fca9545SDavid Brownell clean:
27114fca9545SDavid Brownell 	kfree(rdev);
27124fca9545SDavid Brownell 	rdev = ERR_PTR(ret);
27134fca9545SDavid Brownell 	goto out;
2714414c70cbSLiam Girdwood }
2715414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register);
2716414c70cbSLiam Girdwood 
2717414c70cbSLiam Girdwood /**
2718414c70cbSLiam Girdwood  * regulator_unregister - unregister regulator
271969279fb9SMark Brown  * @rdev: regulator to unregister
2720414c70cbSLiam Girdwood  *
2721414c70cbSLiam Girdwood  * Called by regulator drivers to unregister a regulator.
2722414c70cbSLiam Girdwood  */
2723414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev)
2724414c70cbSLiam Girdwood {
2725414c70cbSLiam Girdwood 	if (rdev == NULL)
2726414c70cbSLiam Girdwood 		return;
2727414c70cbSLiam Girdwood 
2728414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
27291130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
27301130e5b3SMark Brown 	debugfs_remove_recursive(rdev->debugfs);
27311130e5b3SMark Brown #endif
27326bf87d17SMark Brown 	WARN_ON(rdev->open_count);
27330f1d747bSMike Rapoport 	unset_regulator_supplies(rdev);
2734414c70cbSLiam Girdwood 	list_del(&rdev->list);
2735414c70cbSLiam Girdwood 	if (rdev->supply)
27363801b86aSMark Brown 		regulator_put(rdev->supply);
2737414c70cbSLiam Girdwood 	device_unregister(&rdev->dev);
2738f8c12fe3SMark Brown 	kfree(rdev->constraints);
2739414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2740414c70cbSLiam Girdwood }
2741414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister);
2742414c70cbSLiam Girdwood 
2743414c70cbSLiam Girdwood /**
2744cf7bbcdfSMark Brown  * regulator_suspend_prepare - prepare regulators for system wide suspend
2745414c70cbSLiam Girdwood  * @state: system suspend state
2746414c70cbSLiam Girdwood  *
2747414c70cbSLiam Girdwood  * Configure each regulator with it's suspend operating parameters for state.
2748414c70cbSLiam Girdwood  * This will usually be called by machine suspend code prior to supending.
2749414c70cbSLiam Girdwood  */
2750414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state)
2751414c70cbSLiam Girdwood {
2752414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
2753414c70cbSLiam Girdwood 	int ret = 0;
2754414c70cbSLiam Girdwood 
2755414c70cbSLiam Girdwood 	/* ON is handled by regulator active state */
2756414c70cbSLiam Girdwood 	if (state == PM_SUSPEND_ON)
2757414c70cbSLiam Girdwood 		return -EINVAL;
2758414c70cbSLiam Girdwood 
2759414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
2760414c70cbSLiam Girdwood 	list_for_each_entry(rdev, &regulator_list, list) {
2761414c70cbSLiam Girdwood 
2762414c70cbSLiam Girdwood 		mutex_lock(&rdev->mutex);
2763414c70cbSLiam Girdwood 		ret = suspend_prepare(rdev, state);
2764414c70cbSLiam Girdwood 		mutex_unlock(&rdev->mutex);
2765414c70cbSLiam Girdwood 
2766414c70cbSLiam Girdwood 		if (ret < 0) {
27675da84fd9SJoe Perches 			rdev_err(rdev, "failed to prepare\n");
2768414c70cbSLiam Girdwood 			goto out;
2769414c70cbSLiam Girdwood 		}
2770414c70cbSLiam Girdwood 	}
2771414c70cbSLiam Girdwood out:
2772414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
2773414c70cbSLiam Girdwood 	return ret;
2774414c70cbSLiam Girdwood }
2775414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
2776414c70cbSLiam Girdwood 
2777414c70cbSLiam Girdwood /**
27787a32b589SMyungJoo Ham  * regulator_suspend_finish - resume regulators from system wide suspend
27797a32b589SMyungJoo Ham  *
27807a32b589SMyungJoo Ham  * Turn on regulators that might be turned off by regulator_suspend_prepare
27817a32b589SMyungJoo Ham  * and that should be turned on according to the regulators properties.
27827a32b589SMyungJoo Ham  */
27837a32b589SMyungJoo Ham int regulator_suspend_finish(void)
27847a32b589SMyungJoo Ham {
27857a32b589SMyungJoo Ham 	struct regulator_dev *rdev;
27867a32b589SMyungJoo Ham 	int ret = 0, error;
27877a32b589SMyungJoo Ham 
27887a32b589SMyungJoo Ham 	mutex_lock(&regulator_list_mutex);
27897a32b589SMyungJoo Ham 	list_for_each_entry(rdev, &regulator_list, list) {
27907a32b589SMyungJoo Ham 		struct regulator_ops *ops = rdev->desc->ops;
27917a32b589SMyungJoo Ham 
27927a32b589SMyungJoo Ham 		mutex_lock(&rdev->mutex);
27937a32b589SMyungJoo Ham 		if ((rdev->use_count > 0  || rdev->constraints->always_on) &&
27947a32b589SMyungJoo Ham 				ops->enable) {
27957a32b589SMyungJoo Ham 			error = ops->enable(rdev);
27967a32b589SMyungJoo Ham 			if (error)
27977a32b589SMyungJoo Ham 				ret = error;
27987a32b589SMyungJoo Ham 		} else {
27997a32b589SMyungJoo Ham 			if (!has_full_constraints)
28007a32b589SMyungJoo Ham 				goto unlock;
28017a32b589SMyungJoo Ham 			if (!ops->disable)
28027a32b589SMyungJoo Ham 				goto unlock;
28037a32b589SMyungJoo Ham 			if (ops->is_enabled && !ops->is_enabled(rdev))
28047a32b589SMyungJoo Ham 				goto unlock;
28057a32b589SMyungJoo Ham 
28067a32b589SMyungJoo Ham 			error = ops->disable(rdev);
28077a32b589SMyungJoo Ham 			if (error)
28087a32b589SMyungJoo Ham 				ret = error;
28097a32b589SMyungJoo Ham 		}
28107a32b589SMyungJoo Ham unlock:
28117a32b589SMyungJoo Ham 		mutex_unlock(&rdev->mutex);
28127a32b589SMyungJoo Ham 	}
28137a32b589SMyungJoo Ham 	mutex_unlock(&regulator_list_mutex);
28147a32b589SMyungJoo Ham 	return ret;
28157a32b589SMyungJoo Ham }
28167a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish);
28177a32b589SMyungJoo Ham 
28187a32b589SMyungJoo Ham /**
2819ca725561SMark Brown  * regulator_has_full_constraints - the system has fully specified constraints
2820ca725561SMark Brown  *
2821ca725561SMark Brown  * Calling this function will cause the regulator API to disable all
2822ca725561SMark Brown  * regulators which have a zero use count and don't have an always_on
2823ca725561SMark Brown  * constraint in a late_initcall.
2824ca725561SMark Brown  *
2825ca725561SMark Brown  * The intention is that this will become the default behaviour in a
2826ca725561SMark Brown  * future kernel release so users are encouraged to use this facility
2827ca725561SMark Brown  * now.
2828ca725561SMark Brown  */
2829ca725561SMark Brown void regulator_has_full_constraints(void)
2830ca725561SMark Brown {
2831ca725561SMark Brown 	has_full_constraints = 1;
2832ca725561SMark Brown }
2833ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
2834ca725561SMark Brown 
2835ca725561SMark Brown /**
2836688fe99aSMark Brown  * regulator_use_dummy_regulator - Provide a dummy regulator when none is found
2837688fe99aSMark Brown  *
2838688fe99aSMark Brown  * Calling this function will cause the regulator API to provide a
2839688fe99aSMark Brown  * dummy regulator to consumers if no physical regulator is found,
2840688fe99aSMark Brown  * allowing most consumers to proceed as though a regulator were
2841688fe99aSMark Brown  * configured.  This allows systems such as those with software
2842688fe99aSMark Brown  * controllable regulators for the CPU core only to be brought up more
2843688fe99aSMark Brown  * readily.
2844688fe99aSMark Brown  */
2845688fe99aSMark Brown void regulator_use_dummy_regulator(void)
2846688fe99aSMark Brown {
2847688fe99aSMark Brown 	board_wants_dummy_regulator = true;
2848688fe99aSMark Brown }
2849688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator);
2850688fe99aSMark Brown 
2851688fe99aSMark Brown /**
2852414c70cbSLiam Girdwood  * rdev_get_drvdata - get rdev regulator driver data
285369279fb9SMark Brown  * @rdev: regulator
2854414c70cbSLiam Girdwood  *
2855414c70cbSLiam Girdwood  * Get rdev regulator driver private data. This call can be used in the
2856414c70cbSLiam Girdwood  * regulator driver context.
2857414c70cbSLiam Girdwood  */
2858414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev)
2859414c70cbSLiam Girdwood {
2860414c70cbSLiam Girdwood 	return rdev->reg_data;
2861414c70cbSLiam Girdwood }
2862414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata);
2863414c70cbSLiam Girdwood 
2864414c70cbSLiam Girdwood /**
2865414c70cbSLiam Girdwood  * regulator_get_drvdata - get regulator driver data
2866414c70cbSLiam Girdwood  * @regulator: regulator
2867414c70cbSLiam Girdwood  *
2868414c70cbSLiam Girdwood  * Get regulator driver private data. This call can be used in the consumer
2869414c70cbSLiam Girdwood  * driver context when non API regulator specific functions need to be called.
2870414c70cbSLiam Girdwood  */
2871414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator)
2872414c70cbSLiam Girdwood {
2873414c70cbSLiam Girdwood 	return regulator->rdev->reg_data;
2874414c70cbSLiam Girdwood }
2875414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata);
2876414c70cbSLiam Girdwood 
2877414c70cbSLiam Girdwood /**
2878414c70cbSLiam Girdwood  * regulator_set_drvdata - set regulator driver data
2879414c70cbSLiam Girdwood  * @regulator: regulator
2880414c70cbSLiam Girdwood  * @data: data
2881414c70cbSLiam Girdwood  */
2882414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data)
2883414c70cbSLiam Girdwood {
2884414c70cbSLiam Girdwood 	regulator->rdev->reg_data = data;
2885414c70cbSLiam Girdwood }
2886414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata);
2887414c70cbSLiam Girdwood 
2888414c70cbSLiam Girdwood /**
2889414c70cbSLiam Girdwood  * regulator_get_id - get regulator ID
289069279fb9SMark Brown  * @rdev: regulator
2891414c70cbSLiam Girdwood  */
2892414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev)
2893414c70cbSLiam Girdwood {
2894414c70cbSLiam Girdwood 	return rdev->desc->id;
2895414c70cbSLiam Girdwood }
2896414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id);
2897414c70cbSLiam Girdwood 
2898a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev)
2899a5766f11SLiam Girdwood {
2900a5766f11SLiam Girdwood 	return &rdev->dev;
2901a5766f11SLiam Girdwood }
2902a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev);
2903a5766f11SLiam Girdwood 
2904a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
2905a5766f11SLiam Girdwood {
2906a5766f11SLiam Girdwood 	return reg_init_data->driver_data;
2907a5766f11SLiam Girdwood }
2908a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
2909a5766f11SLiam Girdwood 
2910ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS
2911ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf,
2912ba55a974SMark Brown 				    size_t count, loff_t *ppos)
2913ba55a974SMark Brown {
2914ba55a974SMark Brown 	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
2915ba55a974SMark Brown 	ssize_t len, ret = 0;
2916ba55a974SMark Brown 	struct regulator_map *map;
2917ba55a974SMark Brown 
2918ba55a974SMark Brown 	if (!buf)
2919ba55a974SMark Brown 		return -ENOMEM;
2920ba55a974SMark Brown 
2921ba55a974SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
2922ba55a974SMark Brown 		len = snprintf(buf + ret, PAGE_SIZE - ret,
2923ba55a974SMark Brown 			       "%s -> %s.%s\n",
2924ba55a974SMark Brown 			       rdev_get_name(map->regulator), map->dev_name,
2925ba55a974SMark Brown 			       map->supply);
2926ba55a974SMark Brown 		if (len >= 0)
2927ba55a974SMark Brown 			ret += len;
2928ba55a974SMark Brown 		if (ret > PAGE_SIZE) {
2929ba55a974SMark Brown 			ret = PAGE_SIZE;
2930ba55a974SMark Brown 			break;
2931ba55a974SMark Brown 		}
2932ba55a974SMark Brown 	}
2933ba55a974SMark Brown 
2934ba55a974SMark Brown 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
2935ba55a974SMark Brown 
2936ba55a974SMark Brown 	kfree(buf);
2937ba55a974SMark Brown 
2938ba55a974SMark Brown 	return ret;
2939ba55a974SMark Brown }
2940ba55a974SMark Brown 
2941ba55a974SMark Brown static const struct file_operations supply_map_fops = {
2942ba55a974SMark Brown 	.read = supply_map_read_file,
2943ba55a974SMark Brown 	.llseek = default_llseek,
2944ba55a974SMark Brown };
2945ba55a974SMark Brown #endif
2946ba55a974SMark Brown 
2947414c70cbSLiam Girdwood static int __init regulator_init(void)
2948414c70cbSLiam Girdwood {
294934abbd68SMark Brown 	int ret;
295034abbd68SMark Brown 
295134abbd68SMark Brown 	ret = class_register(&regulator_class);
295234abbd68SMark Brown 
29531130e5b3SMark Brown #ifdef CONFIG_DEBUG_FS
29541130e5b3SMark Brown 	debugfs_root = debugfs_create_dir("regulator", NULL);
29551130e5b3SMark Brown 	if (IS_ERR(debugfs_root) || !debugfs_root) {
29561130e5b3SMark Brown 		pr_warn("regulator: Failed to create debugfs directory\n");
29571130e5b3SMark Brown 		debugfs_root = NULL;
29581130e5b3SMark Brown 	}
2959ba55a974SMark Brown 
2960ba55a974SMark Brown 	if (IS_ERR(debugfs_create_file("supply_map", 0444, debugfs_root,
2961ba55a974SMark Brown 				       NULL, &supply_map_fops)))
2962ba55a974SMark Brown 		pr_warn("regulator: Failed to create supplies debugfs\n");
29631130e5b3SMark Brown #endif
29641130e5b3SMark Brown 
296534abbd68SMark Brown 	regulator_dummy_init();
296634abbd68SMark Brown 
296734abbd68SMark Brown 	return ret;
2968414c70cbSLiam Girdwood }
2969414c70cbSLiam Girdwood 
2970414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */
2971414c70cbSLiam Girdwood core_initcall(regulator_init);
2972ca725561SMark Brown 
2973ca725561SMark Brown static int __init regulator_init_complete(void)
2974ca725561SMark Brown {
2975ca725561SMark Brown 	struct regulator_dev *rdev;
2976ca725561SMark Brown 	struct regulator_ops *ops;
2977ca725561SMark Brown 	struct regulation_constraints *c;
2978ca725561SMark Brown 	int enabled, ret;
2979ca725561SMark Brown 
2980ca725561SMark Brown 	mutex_lock(&regulator_list_mutex);
2981ca725561SMark Brown 
2982ca725561SMark Brown 	/* If we have a full configuration then disable any regulators
2983ca725561SMark Brown 	 * which are not in use or always_on.  This will become the
2984ca725561SMark Brown 	 * default behaviour in the future.
2985ca725561SMark Brown 	 */
2986ca725561SMark Brown 	list_for_each_entry(rdev, &regulator_list, list) {
2987ca725561SMark Brown 		ops = rdev->desc->ops;
2988ca725561SMark Brown 		c = rdev->constraints;
2989ca725561SMark Brown 
2990f25e0b4fSMark Brown 		if (!ops->disable || (c && c->always_on))
2991ca725561SMark Brown 			continue;
2992ca725561SMark Brown 
2993ca725561SMark Brown 		mutex_lock(&rdev->mutex);
2994ca725561SMark Brown 
2995ca725561SMark Brown 		if (rdev->use_count)
2996ca725561SMark Brown 			goto unlock;
2997ca725561SMark Brown 
2998ca725561SMark Brown 		/* If we can't read the status assume it's on. */
2999ca725561SMark Brown 		if (ops->is_enabled)
3000ca725561SMark Brown 			enabled = ops->is_enabled(rdev);
3001ca725561SMark Brown 		else
3002ca725561SMark Brown 			enabled = 1;
3003ca725561SMark Brown 
3004ca725561SMark Brown 		if (!enabled)
3005ca725561SMark Brown 			goto unlock;
3006ca725561SMark Brown 
3007ca725561SMark Brown 		if (has_full_constraints) {
3008ca725561SMark Brown 			/* We log since this may kill the system if it
3009ca725561SMark Brown 			 * goes wrong. */
30105da84fd9SJoe Perches 			rdev_info(rdev, "disabling\n");
3011ca725561SMark Brown 			ret = ops->disable(rdev);
3012ca725561SMark Brown 			if (ret != 0) {
30135da84fd9SJoe Perches 				rdev_err(rdev, "couldn't disable: %d\n", ret);
3014ca725561SMark Brown 			}
3015ca725561SMark Brown 		} else {
3016ca725561SMark Brown 			/* The intention is that in future we will
3017ca725561SMark Brown 			 * assume that full constraints are provided
3018ca725561SMark Brown 			 * so warn even if we aren't going to do
3019ca725561SMark Brown 			 * anything here.
3020ca725561SMark Brown 			 */
30215da84fd9SJoe Perches 			rdev_warn(rdev, "incomplete constraints, leaving on\n");
3022ca725561SMark Brown 		}
3023ca725561SMark Brown 
3024ca725561SMark Brown unlock:
3025ca725561SMark Brown 		mutex_unlock(&rdev->mutex);
3026ca725561SMark Brown 	}
3027ca725561SMark Brown 
3028ca725561SMark Brown 	mutex_unlock(&regulator_list_mutex);
3029ca725561SMark Brown 
3030ca725561SMark Brown 	return 0;
3031ca725561SMark Brown }
3032ca725561SMark Brown late_initcall(regulator_init_complete);
3033