xref: /openbmc/linux/drivers/regulator/core.c (revision 398715ab)
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 
16414c70cbSLiam Girdwood #include <linux/kernel.h>
17414c70cbSLiam Girdwood #include <linux/init.h>
181130e5b3SMark Brown #include <linux/debugfs.h>
19414c70cbSLiam Girdwood #include <linux/device.h>
205a0e3ad6STejun Heo #include <linux/slab.h>
21f21e0e81SMark Brown #include <linux/async.h>
22414c70cbSLiam Girdwood #include <linux/err.h>
23414c70cbSLiam Girdwood #include <linux/mutex.h>
24414c70cbSLiam Girdwood #include <linux/suspend.h>
2531aae2beSMark Brown #include <linux/delay.h>
2669511a45SRajendra Nayak #include <linux/of.h>
2765b19ce6SMark Brown #include <linux/regmap.h>
2869511a45SRajendra Nayak #include <linux/regulator/of_regulator.h>
29414c70cbSLiam Girdwood #include <linux/regulator/consumer.h>
30414c70cbSLiam Girdwood #include <linux/regulator/driver.h>
31414c70cbSLiam Girdwood #include <linux/regulator/machine.h>
3265602c32SPaul Gortmaker #include <linux/module.h>
33414c70cbSLiam Girdwood 
3402fa3ec0SMark Brown #define CREATE_TRACE_POINTS
3502fa3ec0SMark Brown #include <trace/events/regulator.h>
3602fa3ec0SMark Brown 
3734abbd68SMark Brown #include "dummy.h"
3834abbd68SMark Brown 
397d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...)					\
407d51a0dbSMark Brown 	pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
415da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...)					\
425da84fd9SJoe Perches 	pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
435da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...)					\
445da84fd9SJoe Perches 	pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
455da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...)					\
465da84fd9SJoe Perches 	pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
475da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...)					\
485da84fd9SJoe Perches 	pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
495da84fd9SJoe Perches 
50414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex);
51414c70cbSLiam Girdwood static LIST_HEAD(regulator_list);
52414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list);
5321cf891aSMark Brown static bool has_full_constraints;
54688fe99aSMark Brown static bool board_wants_dummy_regulator;
55414c70cbSLiam Girdwood 
561130e5b3SMark Brown static struct dentry *debugfs_root;
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;
786492bc1bSMark Brown 	unsigned int always_on:1;
79414c70cbSLiam Girdwood 	int uA_load;
80414c70cbSLiam Girdwood 	int min_uV;
81414c70cbSLiam Girdwood 	int max_uV;
82414c70cbSLiam Girdwood 	char *supply_name;
83414c70cbSLiam Girdwood 	struct device_attribute dev_attr;
84414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
855de70519SMark Brown 	struct dentry *debugfs;
86414c70cbSLiam Girdwood };
87414c70cbSLiam Girdwood 
88414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev);
893801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev);
90414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev);
91414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev);
92414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
93414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev,
94414c70cbSLiam Girdwood 				  unsigned long event, void *data);
9575790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
9675790251SMark Brown 				     int min_uV, int max_uV);
973801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev,
983801b86aSMark Brown 					  struct device *dev,
993801b86aSMark Brown 					  const char *supply_name);
100414c70cbSLiam Girdwood 
1011083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev)
1021083c393SMark Brown {
1031083c393SMark Brown 	if (rdev->constraints && rdev->constraints->name)
1041083c393SMark Brown 		return rdev->constraints->name;
1051083c393SMark Brown 	else if (rdev->desc->name)
1061083c393SMark Brown 		return rdev->desc->name;
1071083c393SMark Brown 	else
1081083c393SMark Brown 		return "";
1091083c393SMark Brown }
1101083c393SMark Brown 
111414c70cbSLiam Girdwood /* gets the regulator for a given consumer device */
112414c70cbSLiam Girdwood static struct regulator *get_device_regulator(struct device *dev)
113414c70cbSLiam Girdwood {
114414c70cbSLiam Girdwood 	struct regulator *regulator = NULL;
115414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
116414c70cbSLiam Girdwood 
117414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
118414c70cbSLiam Girdwood 	list_for_each_entry(rdev, &regulator_list, list) {
119414c70cbSLiam Girdwood 		mutex_lock(&rdev->mutex);
120414c70cbSLiam Girdwood 		list_for_each_entry(regulator, &rdev->consumer_list, list) {
121414c70cbSLiam Girdwood 			if (regulator->dev == dev) {
122414c70cbSLiam Girdwood 				mutex_unlock(&rdev->mutex);
123414c70cbSLiam Girdwood 				mutex_unlock(&regulator_list_mutex);
124414c70cbSLiam Girdwood 				return regulator;
125414c70cbSLiam Girdwood 			}
126414c70cbSLiam Girdwood 		}
127414c70cbSLiam Girdwood 		mutex_unlock(&rdev->mutex);
128414c70cbSLiam Girdwood 	}
129414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
130414c70cbSLiam Girdwood 	return NULL;
131414c70cbSLiam Girdwood }
132414c70cbSLiam Girdwood 
13369511a45SRajendra Nayak /**
13469511a45SRajendra Nayak  * of_get_regulator - get a regulator device node based on supply name
13569511a45SRajendra Nayak  * @dev: Device pointer for the consumer (of regulator) device
13669511a45SRajendra Nayak  * @supply: regulator supply name
13769511a45SRajendra Nayak  *
13869511a45SRajendra Nayak  * Extract the regulator device node corresponding to the supply name.
13969511a45SRajendra Nayak  * retruns the device node corresponding to the regulator if found, else
14069511a45SRajendra Nayak  * returns NULL.
14169511a45SRajendra Nayak  */
14269511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply)
14369511a45SRajendra Nayak {
14469511a45SRajendra Nayak 	struct device_node *regnode = NULL;
14569511a45SRajendra Nayak 	char prop_name[32]; /* 32 is max size of property name */
14669511a45SRajendra Nayak 
14769511a45SRajendra Nayak 	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
14869511a45SRajendra Nayak 
14969511a45SRajendra Nayak 	snprintf(prop_name, 32, "%s-supply", supply);
15069511a45SRajendra Nayak 	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
15169511a45SRajendra Nayak 
15269511a45SRajendra Nayak 	if (!regnode) {
15316fbcc3bSRajendra Nayak 		dev_dbg(dev, "Looking up %s property in node %s failed",
15469511a45SRajendra Nayak 				prop_name, dev->of_node->full_name);
15569511a45SRajendra Nayak 		return NULL;
15669511a45SRajendra Nayak 	}
15769511a45SRajendra Nayak 	return regnode;
15869511a45SRajendra Nayak }
15969511a45SRajendra Nayak 
1606492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev)
1616492bc1bSMark Brown {
1626492bc1bSMark Brown 	if (!rdev->constraints)
1636492bc1bSMark Brown 		return 0;
1646492bc1bSMark Brown 
1656492bc1bSMark Brown 	if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
1666492bc1bSMark Brown 		return 1;
1676492bc1bSMark Brown 	else
1686492bc1bSMark Brown 		return 0;
1696492bc1bSMark Brown }
1706492bc1bSMark Brown 
171414c70cbSLiam Girdwood /* Platform voltage constraint check */
172414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev,
173414c70cbSLiam Girdwood 				   int *min_uV, int *max_uV)
174414c70cbSLiam Girdwood {
175414c70cbSLiam Girdwood 	BUG_ON(*min_uV > *max_uV);
176414c70cbSLiam Girdwood 
177414c70cbSLiam Girdwood 	if (!rdev->constraints) {
1785da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
179414c70cbSLiam Girdwood 		return -ENODEV;
180414c70cbSLiam Girdwood 	}
181414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
1825da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
183414c70cbSLiam Girdwood 		return -EPERM;
184414c70cbSLiam Girdwood 	}
185414c70cbSLiam Girdwood 
186414c70cbSLiam Girdwood 	if (*max_uV > rdev->constraints->max_uV)
187414c70cbSLiam Girdwood 		*max_uV = rdev->constraints->max_uV;
188414c70cbSLiam Girdwood 	if (*min_uV < rdev->constraints->min_uV)
189414c70cbSLiam Girdwood 		*min_uV = rdev->constraints->min_uV;
190414c70cbSLiam Girdwood 
19189f425edSMark Brown 	if (*min_uV > *max_uV) {
19289f425edSMark Brown 		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
19354abd335SMark Brown 			 *min_uV, *max_uV);
194414c70cbSLiam Girdwood 		return -EINVAL;
19589f425edSMark Brown 	}
196414c70cbSLiam Girdwood 
197414c70cbSLiam Girdwood 	return 0;
198414c70cbSLiam Girdwood }
199414c70cbSLiam Girdwood 
20005fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all
20105fda3b1SThomas Petazzoni  * regulator consumers
20205fda3b1SThomas Petazzoni  */
20305fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev,
20405fda3b1SThomas Petazzoni 				     int *min_uV, int *max_uV)
20505fda3b1SThomas Petazzoni {
20605fda3b1SThomas Petazzoni 	struct regulator *regulator;
20705fda3b1SThomas Petazzoni 
20805fda3b1SThomas Petazzoni 	list_for_each_entry(regulator, &rdev->consumer_list, list) {
2094aa922c0SMark Brown 		/*
2104aa922c0SMark Brown 		 * Assume consumers that didn't say anything are OK
2114aa922c0SMark Brown 		 * with anything in the constraint range.
2124aa922c0SMark Brown 		 */
2134aa922c0SMark Brown 		if (!regulator->min_uV && !regulator->max_uV)
2144aa922c0SMark Brown 			continue;
2154aa922c0SMark Brown 
21605fda3b1SThomas Petazzoni 		if (*max_uV > regulator->max_uV)
21705fda3b1SThomas Petazzoni 			*max_uV = regulator->max_uV;
21805fda3b1SThomas Petazzoni 		if (*min_uV < regulator->min_uV)
21905fda3b1SThomas Petazzoni 			*min_uV = regulator->min_uV;
22005fda3b1SThomas Petazzoni 	}
22105fda3b1SThomas Petazzoni 
22205fda3b1SThomas Petazzoni 	if (*min_uV > *max_uV)
22305fda3b1SThomas Petazzoni 		return -EINVAL;
22405fda3b1SThomas Petazzoni 
22505fda3b1SThomas Petazzoni 	return 0;
22605fda3b1SThomas Petazzoni }
22705fda3b1SThomas Petazzoni 
228414c70cbSLiam Girdwood /* current constraint check */
229414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev,
230414c70cbSLiam Girdwood 					int *min_uA, int *max_uA)
231414c70cbSLiam Girdwood {
232414c70cbSLiam Girdwood 	BUG_ON(*min_uA > *max_uA);
233414c70cbSLiam Girdwood 
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_CURRENT)) {
2395da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
240414c70cbSLiam Girdwood 		return -EPERM;
241414c70cbSLiam Girdwood 	}
242414c70cbSLiam Girdwood 
243414c70cbSLiam Girdwood 	if (*max_uA > rdev->constraints->max_uA)
244414c70cbSLiam Girdwood 		*max_uA = rdev->constraints->max_uA;
245414c70cbSLiam Girdwood 	if (*min_uA < rdev->constraints->min_uA)
246414c70cbSLiam Girdwood 		*min_uA = rdev->constraints->min_uA;
247414c70cbSLiam Girdwood 
24889f425edSMark Brown 	if (*min_uA > *max_uA) {
24989f425edSMark Brown 		rdev_err(rdev, "unsupportable current range: %d-%duA\n",
25054abd335SMark Brown 			 *min_uA, *max_uA);
251414c70cbSLiam Girdwood 		return -EINVAL;
25289f425edSMark Brown 	}
253414c70cbSLiam Girdwood 
254414c70cbSLiam Girdwood 	return 0;
255414c70cbSLiam Girdwood }
256414c70cbSLiam Girdwood 
257414c70cbSLiam Girdwood /* operating mode constraint check */
2582c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
259414c70cbSLiam Girdwood {
2602c608234SMark Brown 	switch (*mode) {
261e573520bSDavid Brownell 	case REGULATOR_MODE_FAST:
262e573520bSDavid Brownell 	case REGULATOR_MODE_NORMAL:
263e573520bSDavid Brownell 	case REGULATOR_MODE_IDLE:
264e573520bSDavid Brownell 	case REGULATOR_MODE_STANDBY:
265e573520bSDavid Brownell 		break;
266e573520bSDavid Brownell 	default:
26789f425edSMark Brown 		rdev_err(rdev, "invalid mode %x specified\n", *mode);
268e573520bSDavid Brownell 		return -EINVAL;
269e573520bSDavid Brownell 	}
270e573520bSDavid Brownell 
271414c70cbSLiam Girdwood 	if (!rdev->constraints) {
2725da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
273414c70cbSLiam Girdwood 		return -ENODEV;
274414c70cbSLiam Girdwood 	}
275414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
2765da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
277414c70cbSLiam Girdwood 		return -EPERM;
278414c70cbSLiam Girdwood 	}
2792c608234SMark Brown 
2802c608234SMark Brown 	/* The modes are bitmasks, the most power hungry modes having
2812c608234SMark Brown 	 * the lowest values. If the requested mode isn't supported
2822c608234SMark Brown 	 * try higher modes. */
2832c608234SMark Brown 	while (*mode) {
2842c608234SMark Brown 		if (rdev->constraints->valid_modes_mask & *mode)
285414c70cbSLiam Girdwood 			return 0;
2862c608234SMark Brown 		*mode /= 2;
2872c608234SMark Brown 	}
2882c608234SMark Brown 
2892c608234SMark Brown 	return -EINVAL;
290414c70cbSLiam Girdwood }
291414c70cbSLiam Girdwood 
292414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */
293414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev)
294414c70cbSLiam Girdwood {
295414c70cbSLiam Girdwood 	if (!rdev->constraints) {
2965da84fd9SJoe Perches 		rdev_err(rdev, "no constraints\n");
297414c70cbSLiam Girdwood 		return -ENODEV;
298414c70cbSLiam Girdwood 	}
299414c70cbSLiam Girdwood 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
3005da84fd9SJoe Perches 		rdev_err(rdev, "operation not allowed\n");
301414c70cbSLiam Girdwood 		return -EPERM;
302414c70cbSLiam Girdwood 	}
303414c70cbSLiam Girdwood 	return 0;
304414c70cbSLiam Girdwood }
305414c70cbSLiam Girdwood 
306414c70cbSLiam Girdwood static ssize_t device_requested_uA_show(struct device *dev,
307414c70cbSLiam Girdwood 			     struct device_attribute *attr, char *buf)
308414c70cbSLiam Girdwood {
309414c70cbSLiam Girdwood 	struct regulator *regulator;
310414c70cbSLiam Girdwood 
311414c70cbSLiam Girdwood 	regulator = get_device_regulator(dev);
312414c70cbSLiam Girdwood 	if (regulator == NULL)
313414c70cbSLiam Girdwood 		return 0;
314414c70cbSLiam Girdwood 
315414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", regulator->uA_load);
316414c70cbSLiam Girdwood }
317414c70cbSLiam Girdwood 
318414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev,
319414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
320414c70cbSLiam Girdwood {
321a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
322414c70cbSLiam Girdwood 	ssize_t ret;
323414c70cbSLiam Girdwood 
324414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
325414c70cbSLiam Girdwood 	ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev));
326414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
327414c70cbSLiam Girdwood 
328414c70cbSLiam Girdwood 	return ret;
329414c70cbSLiam Girdwood }
3307ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);
331414c70cbSLiam Girdwood 
332414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev,
333414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
334414c70cbSLiam Girdwood {
335a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
336414c70cbSLiam Girdwood 
337414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
338414c70cbSLiam Girdwood }
3397ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);
340414c70cbSLiam Girdwood 
341bc558a60SMark Brown static ssize_t regulator_name_show(struct device *dev,
342bc558a60SMark Brown 			     struct device_attribute *attr, char *buf)
343bc558a60SMark Brown {
344bc558a60SMark Brown 	struct regulator_dev *rdev = dev_get_drvdata(dev);
345bc558a60SMark Brown 
3461083c393SMark Brown 	return sprintf(buf, "%s\n", rdev_get_name(rdev));
347bc558a60SMark Brown }
348bc558a60SMark Brown 
3494fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode)
350414c70cbSLiam Girdwood {
351414c70cbSLiam Girdwood 	switch (mode) {
352414c70cbSLiam Girdwood 	case REGULATOR_MODE_FAST:
353414c70cbSLiam Girdwood 		return sprintf(buf, "fast\n");
354414c70cbSLiam Girdwood 	case REGULATOR_MODE_NORMAL:
355414c70cbSLiam Girdwood 		return sprintf(buf, "normal\n");
356414c70cbSLiam Girdwood 	case REGULATOR_MODE_IDLE:
357414c70cbSLiam Girdwood 		return sprintf(buf, "idle\n");
358414c70cbSLiam Girdwood 	case REGULATOR_MODE_STANDBY:
359414c70cbSLiam Girdwood 		return sprintf(buf, "standby\n");
360414c70cbSLiam Girdwood 	}
361414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
362414c70cbSLiam Girdwood }
363414c70cbSLiam Girdwood 
3644fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev,
365414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
366414c70cbSLiam Girdwood {
367a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
368414c70cbSLiam Girdwood 
3694fca9545SDavid Brownell 	return regulator_print_opmode(buf, _regulator_get_mode(rdev));
3704fca9545SDavid Brownell }
3717ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL);
3724fca9545SDavid Brownell 
3734fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state)
3744fca9545SDavid Brownell {
375414c70cbSLiam Girdwood 	if (state > 0)
376414c70cbSLiam Girdwood 		return sprintf(buf, "enabled\n");
377414c70cbSLiam Girdwood 	else if (state == 0)
378414c70cbSLiam Girdwood 		return sprintf(buf, "disabled\n");
379414c70cbSLiam Girdwood 	else
380414c70cbSLiam Girdwood 		return sprintf(buf, "unknown\n");
381414c70cbSLiam Girdwood }
382414c70cbSLiam Girdwood 
3834fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev,
3844fca9545SDavid Brownell 				   struct device_attribute *attr, char *buf)
3854fca9545SDavid Brownell {
3864fca9545SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
3879332546fSMark Brown 	ssize_t ret;
3884fca9545SDavid Brownell 
3899332546fSMark Brown 	mutex_lock(&rdev->mutex);
3909332546fSMark Brown 	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
3919332546fSMark Brown 	mutex_unlock(&rdev->mutex);
3929332546fSMark Brown 
3939332546fSMark Brown 	return ret;
3944fca9545SDavid Brownell }
3957ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
3964fca9545SDavid Brownell 
397853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev,
398853116a1SDavid Brownell 				   struct device_attribute *attr, char *buf)
399853116a1SDavid Brownell {
400853116a1SDavid Brownell 	struct regulator_dev *rdev = dev_get_drvdata(dev);
401853116a1SDavid Brownell 	int status;
402853116a1SDavid Brownell 	char *label;
403853116a1SDavid Brownell 
404853116a1SDavid Brownell 	status = rdev->desc->ops->get_status(rdev);
405853116a1SDavid Brownell 	if (status < 0)
406853116a1SDavid Brownell 		return status;
407853116a1SDavid Brownell 
408853116a1SDavid Brownell 	switch (status) {
409853116a1SDavid Brownell 	case REGULATOR_STATUS_OFF:
410853116a1SDavid Brownell 		label = "off";
411853116a1SDavid Brownell 		break;
412853116a1SDavid Brownell 	case REGULATOR_STATUS_ON:
413853116a1SDavid Brownell 		label = "on";
414853116a1SDavid Brownell 		break;
415853116a1SDavid Brownell 	case REGULATOR_STATUS_ERROR:
416853116a1SDavid Brownell 		label = "error";
417853116a1SDavid Brownell 		break;
418853116a1SDavid Brownell 	case REGULATOR_STATUS_FAST:
419853116a1SDavid Brownell 		label = "fast";
420853116a1SDavid Brownell 		break;
421853116a1SDavid Brownell 	case REGULATOR_STATUS_NORMAL:
422853116a1SDavid Brownell 		label = "normal";
423853116a1SDavid Brownell 		break;
424853116a1SDavid Brownell 	case REGULATOR_STATUS_IDLE:
425853116a1SDavid Brownell 		label = "idle";
426853116a1SDavid Brownell 		break;
427853116a1SDavid Brownell 	case REGULATOR_STATUS_STANDBY:
428853116a1SDavid Brownell 		label = "standby";
429853116a1SDavid Brownell 		break;
430853116a1SDavid Brownell 	default:
431853116a1SDavid Brownell 		return -ERANGE;
432853116a1SDavid Brownell 	}
433853116a1SDavid Brownell 
434853116a1SDavid Brownell 	return sprintf(buf, "%s\n", label);
435853116a1SDavid Brownell }
436853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL);
437853116a1SDavid Brownell 
438414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev,
439414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
440414c70cbSLiam Girdwood {
441a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
442414c70cbSLiam Girdwood 
443414c70cbSLiam Girdwood 	if (!rdev->constraints)
444414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
445414c70cbSLiam Girdwood 
446414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uA);
447414c70cbSLiam Girdwood }
4487ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL);
449414c70cbSLiam Girdwood 
450414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev,
451414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
452414c70cbSLiam Girdwood {
453a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
454414c70cbSLiam Girdwood 
455414c70cbSLiam Girdwood 	if (!rdev->constraints)
456414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
457414c70cbSLiam Girdwood 
458414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uA);
459414c70cbSLiam Girdwood }
4607ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL);
461414c70cbSLiam Girdwood 
462414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev,
463414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
464414c70cbSLiam Girdwood {
465a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
466414c70cbSLiam Girdwood 
467414c70cbSLiam Girdwood 	if (!rdev->constraints)
468414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
469414c70cbSLiam Girdwood 
470414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->min_uV);
471414c70cbSLiam Girdwood }
4727ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL);
473414c70cbSLiam Girdwood 
474414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev,
475414c70cbSLiam Girdwood 				    struct device_attribute *attr, char *buf)
476414c70cbSLiam Girdwood {
477a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
478414c70cbSLiam Girdwood 
479414c70cbSLiam Girdwood 	if (!rdev->constraints)
480414c70cbSLiam Girdwood 		return sprintf(buf, "constraint not defined\n");
481414c70cbSLiam Girdwood 
482414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->max_uV);
483414c70cbSLiam Girdwood }
4847ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL);
485414c70cbSLiam Girdwood 
486414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev,
487414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
488414c70cbSLiam Girdwood {
489a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
490414c70cbSLiam Girdwood 	struct regulator *regulator;
491414c70cbSLiam Girdwood 	int uA = 0;
492414c70cbSLiam Girdwood 
493414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
494414c70cbSLiam Girdwood 	list_for_each_entry(regulator, &rdev->consumer_list, list)
495414c70cbSLiam Girdwood 		uA += regulator->uA_load;
496414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
497414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", uA);
498414c70cbSLiam Girdwood }
4997ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
500414c70cbSLiam Girdwood 
501414c70cbSLiam Girdwood static ssize_t regulator_num_users_show(struct device *dev,
502414c70cbSLiam Girdwood 				      struct device_attribute *attr, char *buf)
503414c70cbSLiam Girdwood {
504a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
505414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->use_count);
506414c70cbSLiam Girdwood }
507414c70cbSLiam Girdwood 
508414c70cbSLiam Girdwood static ssize_t regulator_type_show(struct device *dev,
509414c70cbSLiam Girdwood 				  struct device_attribute *attr, char *buf)
510414c70cbSLiam Girdwood {
511a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
512414c70cbSLiam Girdwood 
513414c70cbSLiam Girdwood 	switch (rdev->desc->type) {
514414c70cbSLiam Girdwood 	case REGULATOR_VOLTAGE:
515414c70cbSLiam Girdwood 		return sprintf(buf, "voltage\n");
516414c70cbSLiam Girdwood 	case REGULATOR_CURRENT:
517414c70cbSLiam Girdwood 		return sprintf(buf, "current\n");
518414c70cbSLiam Girdwood 	}
519414c70cbSLiam Girdwood 	return sprintf(buf, "unknown\n");
520414c70cbSLiam Girdwood }
521414c70cbSLiam Girdwood 
522414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
523414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
524414c70cbSLiam Girdwood {
525a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
526414c70cbSLiam Girdwood 
527414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
528414c70cbSLiam Girdwood }
5297ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444,
5307ad68e2fSDavid Brownell 		regulator_suspend_mem_uV_show, NULL);
531414c70cbSLiam Girdwood 
532414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
533414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
534414c70cbSLiam Girdwood {
535a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
536414c70cbSLiam Girdwood 
537414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
538414c70cbSLiam Girdwood }
5397ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444,
5407ad68e2fSDavid Brownell 		regulator_suspend_disk_uV_show, NULL);
541414c70cbSLiam Girdwood 
542414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
543414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
544414c70cbSLiam Girdwood {
545a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
546414c70cbSLiam Girdwood 
547414c70cbSLiam Girdwood 	return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
548414c70cbSLiam Girdwood }
5497ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444,
5507ad68e2fSDavid Brownell 		regulator_suspend_standby_uV_show, NULL);
551414c70cbSLiam Girdwood 
552414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
553414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
554414c70cbSLiam Girdwood {
555a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
556414c70cbSLiam Girdwood 
5574fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5584fca9545SDavid Brownell 		rdev->constraints->state_mem.mode);
559414c70cbSLiam Girdwood }
5607ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444,
5617ad68e2fSDavid Brownell 		regulator_suspend_mem_mode_show, NULL);
562414c70cbSLiam Girdwood 
563414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
564414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
565414c70cbSLiam Girdwood {
566a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
567414c70cbSLiam Girdwood 
5684fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5694fca9545SDavid Brownell 		rdev->constraints->state_disk.mode);
570414c70cbSLiam Girdwood }
5717ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444,
5727ad68e2fSDavid Brownell 		regulator_suspend_disk_mode_show, NULL);
573414c70cbSLiam Girdwood 
574414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
575414c70cbSLiam Girdwood 				struct device_attribute *attr, char *buf)
576414c70cbSLiam Girdwood {
577a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
578414c70cbSLiam Girdwood 
5794fca9545SDavid Brownell 	return regulator_print_opmode(buf,
5804fca9545SDavid Brownell 		rdev->constraints->state_standby.mode);
581414c70cbSLiam Girdwood }
5827ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444,
5837ad68e2fSDavid Brownell 		regulator_suspend_standby_mode_show, NULL);
584414c70cbSLiam Girdwood 
585414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev,
586414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
587414c70cbSLiam Girdwood {
588a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
589414c70cbSLiam Girdwood 
5904fca9545SDavid Brownell 	return regulator_print_state(buf,
5914fca9545SDavid Brownell 			rdev->constraints->state_mem.enabled);
592414c70cbSLiam Girdwood }
5937ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444,
5947ad68e2fSDavid Brownell 		regulator_suspend_mem_state_show, NULL);
595414c70cbSLiam Girdwood 
596414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev,
597414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
598414c70cbSLiam Girdwood {
599a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
600414c70cbSLiam Girdwood 
6014fca9545SDavid Brownell 	return regulator_print_state(buf,
6024fca9545SDavid Brownell 			rdev->constraints->state_disk.enabled);
603414c70cbSLiam Girdwood }
6047ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444,
6057ad68e2fSDavid Brownell 		regulator_suspend_disk_state_show, NULL);
606414c70cbSLiam Girdwood 
607414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev,
608414c70cbSLiam Girdwood 				   struct device_attribute *attr, char *buf)
609414c70cbSLiam Girdwood {
610a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
611414c70cbSLiam Girdwood 
6124fca9545SDavid Brownell 	return regulator_print_state(buf,
6134fca9545SDavid Brownell 			rdev->constraints->state_standby.enabled);
614414c70cbSLiam Girdwood }
6157ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444,
6167ad68e2fSDavid Brownell 		regulator_suspend_standby_state_show, NULL);
617bc558a60SMark Brown 
6187ad68e2fSDavid Brownell 
6197ad68e2fSDavid Brownell /*
6207ad68e2fSDavid Brownell  * These are the only attributes are present for all regulators.
6217ad68e2fSDavid Brownell  * Other attributes are a function of regulator functionality.
6227ad68e2fSDavid Brownell  */
623414c70cbSLiam Girdwood static struct device_attribute regulator_dev_attrs[] = {
624bc558a60SMark Brown 	__ATTR(name, 0444, regulator_name_show, NULL),
625414c70cbSLiam Girdwood 	__ATTR(num_users, 0444, regulator_num_users_show, NULL),
626414c70cbSLiam Girdwood 	__ATTR(type, 0444, regulator_type_show, NULL),
627414c70cbSLiam Girdwood 	__ATTR_NULL,
628414c70cbSLiam Girdwood };
629414c70cbSLiam Girdwood 
630414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev)
631414c70cbSLiam Girdwood {
632a5766f11SLiam Girdwood 	struct regulator_dev *rdev = dev_get_drvdata(dev);
633414c70cbSLiam Girdwood 	kfree(rdev);
634414c70cbSLiam Girdwood }
635414c70cbSLiam Girdwood 
636414c70cbSLiam Girdwood static struct class regulator_class = {
637414c70cbSLiam Girdwood 	.name = "regulator",
638414c70cbSLiam Girdwood 	.dev_release = regulator_dev_release,
639414c70cbSLiam Girdwood 	.dev_attrs = regulator_dev_attrs,
640414c70cbSLiam Girdwood };
641414c70cbSLiam Girdwood 
642414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total
643414c70cbSLiam Girdwood  * consumer load. All locks held by caller */
644414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev)
645414c70cbSLiam Girdwood {
646414c70cbSLiam Girdwood 	struct regulator *sibling;
647414c70cbSLiam Girdwood 	int current_uA = 0, output_uV, input_uV, err;
648414c70cbSLiam Girdwood 	unsigned int mode;
649414c70cbSLiam Girdwood 
650414c70cbSLiam Girdwood 	err = regulator_check_drms(rdev);
651414c70cbSLiam Girdwood 	if (err < 0 || !rdev->desc->ops->get_optimum_mode ||
652476c2d83SMark Brown 	    (!rdev->desc->ops->get_voltage &&
653476c2d83SMark Brown 	     !rdev->desc->ops->get_voltage_sel) ||
654476c2d83SMark Brown 	    !rdev->desc->ops->set_mode)
655414c70cbSLiam Girdwood 		return;
656414c70cbSLiam Girdwood 
657414c70cbSLiam Girdwood 	/* get output voltage */
6581bf5a1f8SMark Brown 	output_uV = _regulator_get_voltage(rdev);
659414c70cbSLiam Girdwood 	if (output_uV <= 0)
660414c70cbSLiam Girdwood 		return;
661414c70cbSLiam Girdwood 
662414c70cbSLiam Girdwood 	/* get input voltage */
6631bf5a1f8SMark Brown 	input_uV = 0;
6641bf5a1f8SMark Brown 	if (rdev->supply)
6653f24f5adSAxel Lin 		input_uV = regulator_get_voltage(rdev->supply);
6661bf5a1f8SMark Brown 	if (input_uV <= 0)
667414c70cbSLiam Girdwood 		input_uV = rdev->constraints->input_uV;
668414c70cbSLiam Girdwood 	if (input_uV <= 0)
669414c70cbSLiam Girdwood 		return;
670414c70cbSLiam Girdwood 
671414c70cbSLiam Girdwood 	/* calc total requested load */
672414c70cbSLiam Girdwood 	list_for_each_entry(sibling, &rdev->consumer_list, list)
673414c70cbSLiam Girdwood 		current_uA += sibling->uA_load;
674414c70cbSLiam Girdwood 
675414c70cbSLiam Girdwood 	/* now get the optimum mode for our new total regulator load */
676414c70cbSLiam Girdwood 	mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
677414c70cbSLiam Girdwood 						  output_uV, current_uA);
678414c70cbSLiam Girdwood 
679414c70cbSLiam Girdwood 	/* check the new mode is allowed */
6802c608234SMark Brown 	err = regulator_mode_constrain(rdev, &mode);
681414c70cbSLiam Girdwood 	if (err == 0)
682414c70cbSLiam Girdwood 		rdev->desc->ops->set_mode(rdev, mode);
683414c70cbSLiam Girdwood }
684414c70cbSLiam Girdwood 
685414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev,
686414c70cbSLiam Girdwood 	struct regulator_state *rstate)
687414c70cbSLiam Girdwood {
688414c70cbSLiam Girdwood 	int ret = 0;
689638f85c5SMark Brown 
690638f85c5SMark Brown 	/* If we have no suspend mode configration don't set anything;
6918ac0e95dSAxel Lin 	 * only warn if the driver implements set_suspend_voltage or
6928ac0e95dSAxel Lin 	 * set_suspend_mode callback.
693638f85c5SMark Brown 	 */
694638f85c5SMark Brown 	if (!rstate->enabled && !rstate->disabled) {
6958ac0e95dSAxel Lin 		if (rdev->desc->ops->set_suspend_voltage ||
6968ac0e95dSAxel Lin 		    rdev->desc->ops->set_suspend_mode)
6975da84fd9SJoe Perches 			rdev_warn(rdev, "No configuration\n");
698638f85c5SMark Brown 		return 0;
699638f85c5SMark Brown 	}
700638f85c5SMark Brown 
701638f85c5SMark Brown 	if (rstate->enabled && rstate->disabled) {
7025da84fd9SJoe Perches 		rdev_err(rdev, "invalid configuration\n");
703638f85c5SMark Brown 		return -EINVAL;
704638f85c5SMark Brown 	}
705638f85c5SMark Brown 
7068ac0e95dSAxel Lin 	if (rstate->enabled && rdev->desc->ops->set_suspend_enable)
707414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_enable(rdev);
7088ac0e95dSAxel Lin 	else if (rstate->disabled && rdev->desc->ops->set_suspend_disable)
709414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_disable(rdev);
7108ac0e95dSAxel Lin 	else /* OK if set_suspend_enable or set_suspend_disable is NULL */
7118ac0e95dSAxel Lin 		ret = 0;
7128ac0e95dSAxel Lin 
713414c70cbSLiam Girdwood 	if (ret < 0) {
7145da84fd9SJoe Perches 		rdev_err(rdev, "failed to enabled/disable\n");
715414c70cbSLiam Girdwood 		return ret;
716414c70cbSLiam Girdwood 	}
717414c70cbSLiam Girdwood 
718414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
719414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
720414c70cbSLiam Girdwood 		if (ret < 0) {
7215da84fd9SJoe Perches 			rdev_err(rdev, "failed to set voltage\n");
722414c70cbSLiam Girdwood 			return ret;
723414c70cbSLiam Girdwood 		}
724414c70cbSLiam Girdwood 	}
725414c70cbSLiam Girdwood 
726414c70cbSLiam Girdwood 	if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
727414c70cbSLiam Girdwood 		ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
728414c70cbSLiam Girdwood 		if (ret < 0) {
7295da84fd9SJoe Perches 			rdev_err(rdev, "failed to set mode\n");
730414c70cbSLiam Girdwood 			return ret;
731414c70cbSLiam Girdwood 		}
732414c70cbSLiam Girdwood 	}
733414c70cbSLiam Girdwood 	return ret;
734414c70cbSLiam Girdwood }
735414c70cbSLiam Girdwood 
736414c70cbSLiam Girdwood /* locks held by caller */
737414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state)
738414c70cbSLiam Girdwood {
739414c70cbSLiam Girdwood 	if (!rdev->constraints)
740414c70cbSLiam Girdwood 		return -EINVAL;
741414c70cbSLiam Girdwood 
742414c70cbSLiam Girdwood 	switch (state) {
743414c70cbSLiam Girdwood 	case PM_SUSPEND_STANDBY:
744414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
745414c70cbSLiam Girdwood 			&rdev->constraints->state_standby);
746414c70cbSLiam Girdwood 	case PM_SUSPEND_MEM:
747414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
748414c70cbSLiam Girdwood 			&rdev->constraints->state_mem);
749414c70cbSLiam Girdwood 	case PM_SUSPEND_MAX:
750414c70cbSLiam Girdwood 		return suspend_set_state(rdev,
751414c70cbSLiam Girdwood 			&rdev->constraints->state_disk);
752414c70cbSLiam Girdwood 	default:
753414c70cbSLiam Girdwood 		return -EINVAL;
754414c70cbSLiam Girdwood 	}
755414c70cbSLiam Girdwood }
756414c70cbSLiam Girdwood 
757414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev)
758414c70cbSLiam Girdwood {
759414c70cbSLiam Girdwood 	struct regulation_constraints *constraints = rdev->constraints;
760973e9a27SMark Brown 	char buf[80] = "";
7618f031b48SMark Brown 	int count = 0;
7628f031b48SMark Brown 	int ret;
763414c70cbSLiam Girdwood 
7648f031b48SMark Brown 	if (constraints->min_uV && constraints->max_uV) {
765414c70cbSLiam Girdwood 		if (constraints->min_uV == constraints->max_uV)
7668f031b48SMark Brown 			count += sprintf(buf + count, "%d mV ",
767414c70cbSLiam Girdwood 					 constraints->min_uV / 1000);
768414c70cbSLiam Girdwood 		else
7698f031b48SMark Brown 			count += sprintf(buf + count, "%d <--> %d mV ",
770414c70cbSLiam Girdwood 					 constraints->min_uV / 1000,
771414c70cbSLiam Girdwood 					 constraints->max_uV / 1000);
7728f031b48SMark Brown 	}
7738f031b48SMark Brown 
7748f031b48SMark Brown 	if (!constraints->min_uV ||
7758f031b48SMark Brown 	    constraints->min_uV != constraints->max_uV) {
7768f031b48SMark Brown 		ret = _regulator_get_voltage(rdev);
7778f031b48SMark Brown 		if (ret > 0)
7788f031b48SMark Brown 			count += sprintf(buf + count, "at %d mV ", ret / 1000);
7798f031b48SMark Brown 	}
7808f031b48SMark Brown 
781bf5892a8SMark Brown 	if (constraints->uV_offset)
782bf5892a8SMark Brown 		count += sprintf(buf, "%dmV offset ",
783bf5892a8SMark Brown 				 constraints->uV_offset / 1000);
784bf5892a8SMark Brown 
7858f031b48SMark Brown 	if (constraints->min_uA && constraints->max_uA) {
786414c70cbSLiam Girdwood 		if (constraints->min_uA == constraints->max_uA)
7878f031b48SMark Brown 			count += sprintf(buf + count, "%d mA ",
788414c70cbSLiam Girdwood 					 constraints->min_uA / 1000);
789414c70cbSLiam Girdwood 		else
7908f031b48SMark Brown 			count += sprintf(buf + count, "%d <--> %d mA ",
791414c70cbSLiam Girdwood 					 constraints->min_uA / 1000,
792414c70cbSLiam Girdwood 					 constraints->max_uA / 1000);
793414c70cbSLiam Girdwood 	}
7948f031b48SMark Brown 
7958f031b48SMark Brown 	if (!constraints->min_uA ||
7968f031b48SMark Brown 	    constraints->min_uA != constraints->max_uA) {
7978f031b48SMark Brown 		ret = _regulator_get_current_limit(rdev);
7988f031b48SMark Brown 		if (ret > 0)
799e4a6376bSCyril Chemparathy 			count += sprintf(buf + count, "at %d mA ", ret / 1000);
8008f031b48SMark Brown 	}
8018f031b48SMark Brown 
802414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
803414c70cbSLiam Girdwood 		count += sprintf(buf + count, "fast ");
804414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
805414c70cbSLiam Girdwood 		count += sprintf(buf + count, "normal ");
806414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
807414c70cbSLiam Girdwood 		count += sprintf(buf + count, "idle ");
808414c70cbSLiam Girdwood 	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
809414c70cbSLiam Girdwood 		count += sprintf(buf + count, "standby");
810414c70cbSLiam Girdwood 
81113ce29f8SMark Brown 	rdev_info(rdev, "%s\n", buf);
8124a682922SMark Brown 
8134a682922SMark Brown 	if ((constraints->min_uV != constraints->max_uV) &&
8144a682922SMark Brown 	    !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE))
8154a682922SMark Brown 		rdev_warn(rdev,
8164a682922SMark Brown 			  "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
817414c70cbSLiam Girdwood }
818414c70cbSLiam Girdwood 
819e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev,
8201083c393SMark Brown 	struct regulation_constraints *constraints)
821e79055d6SMark Brown {
822e79055d6SMark Brown 	struct regulator_ops *ops = rdev->desc->ops;
823af5866c9SMark Brown 	int ret;
824af5866c9SMark Brown 
825af5866c9SMark Brown 	/* do we need to apply the constraint voltage */
826af5866c9SMark Brown 	if (rdev->constraints->apply_uV &&
82775790251SMark Brown 	    rdev->constraints->min_uV == rdev->constraints->max_uV) {
82875790251SMark Brown 		ret = _regulator_do_set_voltage(rdev,
8293a93f2a9SMark Brown 						rdev->constraints->min_uV,
83075790251SMark Brown 						rdev->constraints->max_uV);
831af5866c9SMark Brown 		if (ret < 0) {
8325da84fd9SJoe Perches 			rdev_err(rdev, "failed to apply %duV constraint\n",
8335da84fd9SJoe Perches 				 rdev->constraints->min_uV);
834af5866c9SMark Brown 			return ret;
835af5866c9SMark Brown 		}
836af5866c9SMark Brown 	}
837e79055d6SMark Brown 
838e79055d6SMark Brown 	/* constrain machine-level voltage specs to fit
839e79055d6SMark Brown 	 * the actual range supported by this regulator.
840e79055d6SMark Brown 	 */
841e79055d6SMark Brown 	if (ops->list_voltage && rdev->desc->n_voltages) {
842e79055d6SMark Brown 		int	count = rdev->desc->n_voltages;
843e79055d6SMark Brown 		int	i;
844e79055d6SMark Brown 		int	min_uV = INT_MAX;
845e79055d6SMark Brown 		int	max_uV = INT_MIN;
846e79055d6SMark Brown 		int	cmin = constraints->min_uV;
847e79055d6SMark Brown 		int	cmax = constraints->max_uV;
848e79055d6SMark Brown 
849e79055d6SMark Brown 		/* it's safe to autoconfigure fixed-voltage supplies
850e79055d6SMark Brown 		   and the constraints are used by list_voltage. */
851e79055d6SMark Brown 		if (count == 1 && !cmin) {
852e79055d6SMark Brown 			cmin = 1;
853e79055d6SMark Brown 			cmax = INT_MAX;
854e79055d6SMark Brown 			constraints->min_uV = cmin;
855e79055d6SMark Brown 			constraints->max_uV = cmax;
856e79055d6SMark Brown 		}
857e79055d6SMark Brown 
858e79055d6SMark Brown 		/* voltage constraints are optional */
859e79055d6SMark Brown 		if ((cmin == 0) && (cmax == 0))
860e79055d6SMark Brown 			return 0;
861e79055d6SMark Brown 
862e79055d6SMark Brown 		/* else require explicit machine-level constraints */
863e79055d6SMark Brown 		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
8645da84fd9SJoe Perches 			rdev_err(rdev, "invalid voltage constraints\n");
865e79055d6SMark Brown 			return -EINVAL;
866e79055d6SMark Brown 		}
867e79055d6SMark Brown 
868e79055d6SMark Brown 		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
869e79055d6SMark Brown 		for (i = 0; i < count; i++) {
870e79055d6SMark Brown 			int	value;
871e79055d6SMark Brown 
872e79055d6SMark Brown 			value = ops->list_voltage(rdev, i);
873e79055d6SMark Brown 			if (value <= 0)
874e79055d6SMark Brown 				continue;
875e79055d6SMark Brown 
876e79055d6SMark Brown 			/* maybe adjust [min_uV..max_uV] */
877e79055d6SMark Brown 			if (value >= cmin && value < min_uV)
878e79055d6SMark Brown 				min_uV = value;
879e79055d6SMark Brown 			if (value <= cmax && value > max_uV)
880e79055d6SMark Brown 				max_uV = value;
881e79055d6SMark Brown 		}
882e79055d6SMark Brown 
883e79055d6SMark Brown 		/* final: [min_uV..max_uV] valid iff constraints valid */
884e79055d6SMark Brown 		if (max_uV < min_uV) {
8855da84fd9SJoe Perches 			rdev_err(rdev, "unsupportable voltage constraints\n");
886e79055d6SMark Brown 			return -EINVAL;
887e79055d6SMark Brown 		}
888e79055d6SMark Brown 
889e79055d6SMark Brown 		/* use regulator's subset of machine constraints */
890e79055d6SMark Brown 		if (constraints->min_uV < min_uV) {
8915da84fd9SJoe Perches 			rdev_dbg(rdev, "override min_uV, %d -> %d\n",
8925da84fd9SJoe Perches 				 constraints->min_uV, min_uV);
893e79055d6SMark Brown 			constraints->min_uV = min_uV;
894e79055d6SMark Brown 		}
895e79055d6SMark Brown 		if (constraints->max_uV > max_uV) {
8965da84fd9SJoe Perches 			rdev_dbg(rdev, "override max_uV, %d -> %d\n",
8975da84fd9SJoe Perches 				 constraints->max_uV, max_uV);
898e79055d6SMark Brown 			constraints->max_uV = max_uV;
899e79055d6SMark Brown 		}
900e79055d6SMark Brown 	}
901e79055d6SMark Brown 
902e79055d6SMark Brown 	return 0;
903e79055d6SMark Brown }
904e79055d6SMark Brown 
905a5766f11SLiam Girdwood /**
906a5766f11SLiam Girdwood  * set_machine_constraints - sets regulator constraints
90769279fb9SMark Brown  * @rdev: regulator source
908c8e7e464SMark Brown  * @constraints: constraints to apply
909a5766f11SLiam Girdwood  *
910a5766f11SLiam Girdwood  * Allows platform initialisation code to define and constrain
911a5766f11SLiam Girdwood  * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
912a5766f11SLiam Girdwood  * Constraints *must* be set by platform code in order for some
913a5766f11SLiam Girdwood  * regulator operations to proceed i.e. set_voltage, set_current_limit,
914a5766f11SLiam Girdwood  * set_mode.
915a5766f11SLiam Girdwood  */
916a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev,
917f8c12fe3SMark Brown 	const struct regulation_constraints *constraints)
918a5766f11SLiam Girdwood {
919a5766f11SLiam Girdwood 	int ret = 0;
920e5fda26cSMark Brown 	struct regulator_ops *ops = rdev->desc->ops;
921e06f5b4fSMark Brown 
9229a8f5e07SMark Brown 	if (constraints)
923f8c12fe3SMark Brown 		rdev->constraints = kmemdup(constraints, sizeof(*constraints),
924f8c12fe3SMark Brown 					    GFP_KERNEL);
9259a8f5e07SMark Brown 	else
9269a8f5e07SMark Brown 		rdev->constraints = kzalloc(sizeof(*constraints),
9279a8f5e07SMark Brown 					    GFP_KERNEL);
928f8c12fe3SMark Brown 	if (!rdev->constraints)
929f8c12fe3SMark Brown 		return -ENOMEM;
930af5866c9SMark Brown 
931f8c12fe3SMark Brown 	ret = machine_constraints_voltage(rdev, rdev->constraints);
932e79055d6SMark Brown 	if (ret != 0)
9333e2b9abdSMark Brown 		goto out;
9343e2b9abdSMark Brown 
935a5766f11SLiam Girdwood 	/* do we need to setup our suspend state */
9369a8f5e07SMark Brown 	if (rdev->constraints->initial_state) {
937f8c12fe3SMark Brown 		ret = suspend_prepare(rdev, rdev->constraints->initial_state);
938e06f5b4fSMark Brown 		if (ret < 0) {
9395da84fd9SJoe Perches 			rdev_err(rdev, "failed to set suspend state\n");
940e06f5b4fSMark Brown 			goto out;
941e06f5b4fSMark Brown 		}
942e06f5b4fSMark Brown 	}
943a5766f11SLiam Girdwood 
9449a8f5e07SMark Brown 	if (rdev->constraints->initial_mode) {
945a308466cSMark Brown 		if (!ops->set_mode) {
9465da84fd9SJoe Perches 			rdev_err(rdev, "no set_mode operation\n");
947a308466cSMark Brown 			ret = -EINVAL;
948a308466cSMark Brown 			goto out;
949a308466cSMark Brown 		}
950a308466cSMark Brown 
951f8c12fe3SMark Brown 		ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
952a308466cSMark Brown 		if (ret < 0) {
9535da84fd9SJoe Perches 			rdev_err(rdev, "failed to set initial mode: %d\n", ret);
954a308466cSMark Brown 			goto out;
955a308466cSMark Brown 		}
956a308466cSMark Brown 	}
957a308466cSMark Brown 
958cacf90f2SMark Brown 	/* If the constraints say the regulator should be on at this point
959cacf90f2SMark Brown 	 * and we have control then make sure it is enabled.
960cacf90f2SMark Brown 	 */
961f8c12fe3SMark Brown 	if ((rdev->constraints->always_on || rdev->constraints->boot_on) &&
962f8c12fe3SMark Brown 	    ops->enable) {
963e5fda26cSMark Brown 		ret = ops->enable(rdev);
964e5fda26cSMark Brown 		if (ret < 0) {
9655da84fd9SJoe Perches 			rdev_err(rdev, "failed to enable\n");
966e5fda26cSMark Brown 			goto out;
967e5fda26cSMark Brown 		}
968e5fda26cSMark Brown 	}
969e5fda26cSMark Brown 
9706f0b2c69SYadwinder Singh Brar 	if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
9716f0b2c69SYadwinder Singh Brar 		ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
9726f0b2c69SYadwinder Singh Brar 		if (ret < 0) {
9736f0b2c69SYadwinder Singh Brar 			rdev_err(rdev, "failed to set ramp_delay\n");
9746f0b2c69SYadwinder Singh Brar 			goto out;
9756f0b2c69SYadwinder Singh Brar 		}
9766f0b2c69SYadwinder Singh Brar 	}
9776f0b2c69SYadwinder Singh Brar 
978a5766f11SLiam Girdwood 	print_constraints(rdev);
9791a6958e7SAxel Lin 	return 0;
980a5766f11SLiam Girdwood out:
9811a6958e7SAxel Lin 	kfree(rdev->constraints);
9821a6958e7SAxel Lin 	rdev->constraints = NULL;
983a5766f11SLiam Girdwood 	return ret;
984a5766f11SLiam Girdwood }
985a5766f11SLiam Girdwood 
986a5766f11SLiam Girdwood /**
987a5766f11SLiam Girdwood  * set_supply - set regulator supply regulator
98869279fb9SMark Brown  * @rdev: regulator name
98969279fb9SMark Brown  * @supply_rdev: supply regulator name
990a5766f11SLiam Girdwood  *
991a5766f11SLiam Girdwood  * Called by platform initialisation code to set the supply regulator for this
992a5766f11SLiam Girdwood  * regulator. This ensures that a regulators supply will also be enabled by the
993a5766f11SLiam Girdwood  * core if it's child is enabled.
994a5766f11SLiam Girdwood  */
995a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev,
996a5766f11SLiam Girdwood 		      struct regulator_dev *supply_rdev)
997a5766f11SLiam Girdwood {
998a5766f11SLiam Girdwood 	int err;
999a5766f11SLiam Girdwood 
10003801b86aSMark Brown 	rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
10013801b86aSMark Brown 
10023801b86aSMark Brown 	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
100332c78de8SAxel Lin 	if (rdev->supply == NULL) {
100432c78de8SAxel Lin 		err = -ENOMEM;
1005a5766f11SLiam Girdwood 		return err;
1006a5766f11SLiam Girdwood 	}
1007a5766f11SLiam Girdwood 
10083801b86aSMark Brown 	return 0;
10093801b86aSMark Brown }
10103801b86aSMark Brown 
1011a5766f11SLiam Girdwood /**
101206c63f93SRandy Dunlap  * set_consumer_device_supply - Bind a regulator to a symbolic supply
101369279fb9SMark Brown  * @rdev:         regulator source
101440f9244fSMark Brown  * @consumer_dev_name: dev_name() string for device supply applies to
1015a5766f11SLiam Girdwood  * @supply:       symbolic name for supply
1016a5766f11SLiam Girdwood  *
1017a5766f11SLiam Girdwood  * Allows platform initialisation code to map physical regulator
1018a5766f11SLiam Girdwood  * sources to symbolic names for supplies for use by devices.  Devices
1019a5766f11SLiam Girdwood  * should use these symbolic names to request regulators, avoiding the
1020a5766f11SLiam Girdwood  * need to provide board-specific regulator names as platform data.
1021a5766f11SLiam Girdwood  */
1022a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev,
1023737f360dSMark Brown 				      const char *consumer_dev_name,
102440f9244fSMark Brown 				      const char *supply)
1025a5766f11SLiam Girdwood {
1026a5766f11SLiam Girdwood 	struct regulator_map *node;
10279ed2099eSMark Brown 	int has_dev;
1028a5766f11SLiam Girdwood 
1029a5766f11SLiam Girdwood 	if (supply == NULL)
1030a5766f11SLiam Girdwood 		return -EINVAL;
1031a5766f11SLiam Girdwood 
10329ed2099eSMark Brown 	if (consumer_dev_name != NULL)
10339ed2099eSMark Brown 		has_dev = 1;
10349ed2099eSMark Brown 	else
10359ed2099eSMark Brown 		has_dev = 0;
10369ed2099eSMark Brown 
10376001e13cSDavid Brownell 	list_for_each_entry(node, &regulator_map_list, list) {
103823b5cc2aSJani Nikula 		if (node->dev_name && consumer_dev_name) {
103923b5cc2aSJani Nikula 			if (strcmp(node->dev_name, consumer_dev_name) != 0)
10406001e13cSDavid Brownell 				continue;
104123b5cc2aSJani Nikula 		} else if (node->dev_name || consumer_dev_name) {
104223b5cc2aSJani Nikula 			continue;
104323b5cc2aSJani Nikula 		}
104423b5cc2aSJani Nikula 
10456001e13cSDavid Brownell 		if (strcmp(node->supply, supply) != 0)
10466001e13cSDavid Brownell 			continue;
10476001e13cSDavid Brownell 
1048737f360dSMark Brown 		pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n",
1049737f360dSMark Brown 			 consumer_dev_name,
10506001e13cSDavid Brownell 			 dev_name(&node->regulator->dev),
10516001e13cSDavid Brownell 			 node->regulator->desc->name,
10526001e13cSDavid Brownell 			 supply,
10531083c393SMark Brown 			 dev_name(&rdev->dev), rdev_get_name(rdev));
10546001e13cSDavid Brownell 		return -EBUSY;
10556001e13cSDavid Brownell 	}
10566001e13cSDavid Brownell 
10579ed2099eSMark Brown 	node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
1058a5766f11SLiam Girdwood 	if (node == NULL)
1059a5766f11SLiam Girdwood 		return -ENOMEM;
1060a5766f11SLiam Girdwood 
1061a5766f11SLiam Girdwood 	node->regulator = rdev;
1062a5766f11SLiam Girdwood 	node->supply = supply;
1063a5766f11SLiam Girdwood 
10649ed2099eSMark Brown 	if (has_dev) {
10659ed2099eSMark Brown 		node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
106640f9244fSMark Brown 		if (node->dev_name == NULL) {
106740f9244fSMark Brown 			kfree(node);
106840f9244fSMark Brown 			return -ENOMEM;
106940f9244fSMark Brown 		}
10709ed2099eSMark Brown 	}
107140f9244fSMark Brown 
1072a5766f11SLiam Girdwood 	list_add(&node->list, &regulator_map_list);
1073a5766f11SLiam Girdwood 	return 0;
1074a5766f11SLiam Girdwood }
1075a5766f11SLiam Girdwood 
10760f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev)
10770f1d747bSMike Rapoport {
10780f1d747bSMike Rapoport 	struct regulator_map *node, *n;
10790f1d747bSMike Rapoport 
10800f1d747bSMike Rapoport 	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
10810f1d747bSMike Rapoport 		if (rdev == node->regulator) {
10820f1d747bSMike Rapoport 			list_del(&node->list);
108340f9244fSMark Brown 			kfree(node->dev_name);
10840f1d747bSMike Rapoport 			kfree(node);
10850f1d747bSMike Rapoport 		}
10860f1d747bSMike Rapoport 	}
10870f1d747bSMike Rapoport }
10880f1d747bSMike Rapoport 
1089f5726ae3SMark Brown #define REG_STR_SIZE	64
1090414c70cbSLiam Girdwood 
1091414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev,
1092414c70cbSLiam Girdwood 					  struct device *dev,
1093414c70cbSLiam Girdwood 					  const char *supply_name)
1094414c70cbSLiam Girdwood {
1095414c70cbSLiam Girdwood 	struct regulator *regulator;
1096414c70cbSLiam Girdwood 	char buf[REG_STR_SIZE];
1097414c70cbSLiam Girdwood 	int err, size;
1098414c70cbSLiam Girdwood 
1099414c70cbSLiam Girdwood 	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
1100414c70cbSLiam Girdwood 	if (regulator == NULL)
1101414c70cbSLiam Girdwood 		return NULL;
1102414c70cbSLiam Girdwood 
1103414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
1104414c70cbSLiam Girdwood 	regulator->rdev = rdev;
1105414c70cbSLiam Girdwood 	list_add(&regulator->list, &rdev->consumer_list);
1106414c70cbSLiam Girdwood 
1107414c70cbSLiam Girdwood 	if (dev) {
1108414c70cbSLiam Girdwood 		/* create a 'requested_microamps_name' sysfs entry */
1109e0eaedefSMark Brown 		size = scnprintf(buf, REG_STR_SIZE,
1110e0eaedefSMark Brown 				 "microamps_requested_%s-%s",
1111e0eaedefSMark Brown 				 dev_name(dev), supply_name);
1112414c70cbSLiam Girdwood 		if (size >= REG_STR_SIZE)
1113414c70cbSLiam Girdwood 			goto overflow_err;
1114414c70cbSLiam Girdwood 
1115414c70cbSLiam Girdwood 		regulator->dev = dev;
11164f26a2abSAmeya Palande 		sysfs_attr_init(&regulator->dev_attr.attr);
1117414c70cbSLiam Girdwood 		regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
1118414c70cbSLiam Girdwood 		if (regulator->dev_attr.attr.name == NULL)
1119414c70cbSLiam Girdwood 			goto attr_name_err;
1120414c70cbSLiam Girdwood 
1121414c70cbSLiam Girdwood 		regulator->dev_attr.attr.mode = 0444;
1122414c70cbSLiam Girdwood 		regulator->dev_attr.show = device_requested_uA_show;
1123414c70cbSLiam Girdwood 		err = device_create_file(dev, &regulator->dev_attr);
1124414c70cbSLiam Girdwood 		if (err < 0) {
11255da84fd9SJoe Perches 			rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
1126414c70cbSLiam Girdwood 			goto attr_name_err;
1127414c70cbSLiam Girdwood 		}
1128414c70cbSLiam Girdwood 
1129414c70cbSLiam Girdwood 		/* also add a link to the device sysfs entry */
1130414c70cbSLiam Girdwood 		size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
1131414c70cbSLiam Girdwood 				 dev->kobj.name, supply_name);
1132414c70cbSLiam Girdwood 		if (size >= REG_STR_SIZE)
1133414c70cbSLiam Girdwood 			goto attr_err;
1134414c70cbSLiam Girdwood 
1135414c70cbSLiam Girdwood 		regulator->supply_name = kstrdup(buf, GFP_KERNEL);
1136414c70cbSLiam Girdwood 		if (regulator->supply_name == NULL)
1137414c70cbSLiam Girdwood 			goto attr_err;
1138414c70cbSLiam Girdwood 
1139414c70cbSLiam Girdwood 		err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
1140414c70cbSLiam Girdwood 					buf);
1141414c70cbSLiam Girdwood 		if (err) {
11425da84fd9SJoe Perches 			rdev_warn(rdev, "could not add device link %s err %d\n",
11431d7372e1SDaniel Walker 				  dev->kobj.name, err);
1144414c70cbSLiam Girdwood 			goto link_name_err;
1145414c70cbSLiam Girdwood 		}
11465de70519SMark Brown 	} else {
11475de70519SMark Brown 		regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
11485de70519SMark Brown 		if (regulator->supply_name == NULL)
11495de70519SMark Brown 			goto attr_err;
1150414c70cbSLiam Girdwood 	}
11515de70519SMark Brown 
11525de70519SMark Brown 	regulator->debugfs = debugfs_create_dir(regulator->supply_name,
11535de70519SMark Brown 						rdev->debugfs);
115424751434SStephen Boyd 	if (!regulator->debugfs) {
11555de70519SMark Brown 		rdev_warn(rdev, "Failed to create debugfs directory\n");
11565de70519SMark Brown 	} else {
11575de70519SMark Brown 		debugfs_create_u32("uA_load", 0444, regulator->debugfs,
11585de70519SMark Brown 				   &regulator->uA_load);
11595de70519SMark Brown 		debugfs_create_u32("min_uV", 0444, regulator->debugfs,
11605de70519SMark Brown 				   &regulator->min_uV);
11615de70519SMark Brown 		debugfs_create_u32("max_uV", 0444, regulator->debugfs,
11625de70519SMark Brown 				   &regulator->max_uV);
11635de70519SMark Brown 	}
11645de70519SMark Brown 
11656492bc1bSMark Brown 	/*
11666492bc1bSMark Brown 	 * Check now if the regulator is an always on regulator - if
11676492bc1bSMark Brown 	 * it is then we don't need to do nearly so much work for
11686492bc1bSMark Brown 	 * enable/disable calls.
11696492bc1bSMark Brown 	 */
11706492bc1bSMark Brown 	if (!_regulator_can_change_status(rdev) &&
11716492bc1bSMark Brown 	    _regulator_is_enabled(rdev))
11726492bc1bSMark Brown 		regulator->always_on = true;
11736492bc1bSMark Brown 
1174414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1175414c70cbSLiam Girdwood 	return regulator;
1176414c70cbSLiam Girdwood link_name_err:
1177414c70cbSLiam Girdwood 	kfree(regulator->supply_name);
1178414c70cbSLiam Girdwood attr_err:
1179414c70cbSLiam Girdwood 	device_remove_file(regulator->dev, &regulator->dev_attr);
1180414c70cbSLiam Girdwood attr_name_err:
1181414c70cbSLiam Girdwood 	kfree(regulator->dev_attr.attr.name);
1182414c70cbSLiam Girdwood overflow_err:
1183414c70cbSLiam Girdwood 	list_del(&regulator->list);
1184414c70cbSLiam Girdwood 	kfree(regulator);
1185414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
1186414c70cbSLiam Girdwood 	return NULL;
1187414c70cbSLiam Girdwood }
1188414c70cbSLiam Girdwood 
118931aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev)
119031aae2beSMark Brown {
119131aae2beSMark Brown 	if (!rdev->desc->ops->enable_time)
119231aae2beSMark Brown 		return 0;
119331aae2beSMark Brown 	return rdev->desc->ops->enable_time(rdev);
119431aae2beSMark Brown }
119531aae2beSMark Brown 
119669511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev,
11976d191a5fSMark Brown 						  const char *supply,
11986d191a5fSMark Brown 						  int *ret)
119969511a45SRajendra Nayak {
120069511a45SRajendra Nayak 	struct regulator_dev *r;
120169511a45SRajendra Nayak 	struct device_node *node;
1202576ca436SMark Brown 	struct regulator_map *map;
1203576ca436SMark Brown 	const char *devname = NULL;
120469511a45SRajendra Nayak 
120569511a45SRajendra Nayak 	/* first do a dt based lookup */
120669511a45SRajendra Nayak 	if (dev && dev->of_node) {
120769511a45SRajendra Nayak 		node = of_get_regulator(dev, supply);
12086d191a5fSMark Brown 		if (node) {
120969511a45SRajendra Nayak 			list_for_each_entry(r, &regulator_list, list)
121069511a45SRajendra Nayak 				if (r->dev.parent &&
121169511a45SRajendra Nayak 					node == r->dev.of_node)
121269511a45SRajendra Nayak 					return r;
12136d191a5fSMark Brown 		} else {
12146d191a5fSMark Brown 			/*
12156d191a5fSMark Brown 			 * If we couldn't even get the node then it's
12166d191a5fSMark Brown 			 * not just that the device didn't register
12176d191a5fSMark Brown 			 * yet, there's no node and we'll never
12186d191a5fSMark Brown 			 * succeed.
12196d191a5fSMark Brown 			 */
12206d191a5fSMark Brown 			*ret = -ENODEV;
12216d191a5fSMark Brown 		}
122269511a45SRajendra Nayak 	}
122369511a45SRajendra Nayak 
122469511a45SRajendra Nayak 	/* if not found, try doing it non-dt way */
1225576ca436SMark Brown 	if (dev)
1226576ca436SMark Brown 		devname = dev_name(dev);
1227576ca436SMark Brown 
122869511a45SRajendra Nayak 	list_for_each_entry(r, &regulator_list, list)
122969511a45SRajendra Nayak 		if (strcmp(rdev_get_name(r), supply) == 0)
123069511a45SRajendra Nayak 			return r;
123169511a45SRajendra Nayak 
1232576ca436SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
1233576ca436SMark Brown 		/* If the mapping has a device set up it must match */
1234576ca436SMark Brown 		if (map->dev_name &&
1235576ca436SMark Brown 		    (!devname || strcmp(map->dev_name, devname)))
1236576ca436SMark Brown 			continue;
1237576ca436SMark Brown 
1238576ca436SMark Brown 		if (strcmp(map->supply, supply) == 0)
1239576ca436SMark Brown 			return map->regulator;
1240576ca436SMark Brown 	}
1241576ca436SMark Brown 
1242576ca436SMark Brown 
124369511a45SRajendra Nayak 	return NULL;
124469511a45SRajendra Nayak }
124569511a45SRajendra Nayak 
12465ffbd136SMark Brown /* Internal regulator request function */
12475ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id,
12485ffbd136SMark Brown 					int exclusive)
1249414c70cbSLiam Girdwood {
1250414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
125104bf3011SMark Brown 	struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
125240f9244fSMark Brown 	const char *devname = NULL;
12535ffbd136SMark Brown 	int ret;
1254414c70cbSLiam Girdwood 
1255414c70cbSLiam Girdwood 	if (id == NULL) {
12565da84fd9SJoe Perches 		pr_err("get() with no identifier\n");
1257414c70cbSLiam Girdwood 		return regulator;
1258414c70cbSLiam Girdwood 	}
1259414c70cbSLiam Girdwood 
126040f9244fSMark Brown 	if (dev)
126140f9244fSMark Brown 		devname = dev_name(dev);
126240f9244fSMark Brown 
1263414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
1264414c70cbSLiam Girdwood 
12656d191a5fSMark Brown 	rdev = regulator_dev_lookup(dev, id, &ret);
126669511a45SRajendra Nayak 	if (rdev)
126769511a45SRajendra Nayak 		goto found;
126869511a45SRajendra Nayak 
1269688fe99aSMark Brown 	if (board_wants_dummy_regulator) {
1270688fe99aSMark Brown 		rdev = dummy_regulator_rdev;
1271688fe99aSMark Brown 		goto found;
1272688fe99aSMark Brown 	}
1273688fe99aSMark Brown 
127434abbd68SMark Brown #ifdef CONFIG_REGULATOR_DUMMY
127534abbd68SMark Brown 	if (!devname)
127634abbd68SMark Brown 		devname = "deviceless";
127734abbd68SMark Brown 
127834abbd68SMark Brown 	/* If the board didn't flag that it was fully constrained then
127934abbd68SMark Brown 	 * substitute in a dummy regulator so consumers can continue.
128034abbd68SMark Brown 	 */
128134abbd68SMark Brown 	if (!has_full_constraints) {
12825da84fd9SJoe Perches 		pr_warn("%s supply %s not found, using dummy regulator\n",
128334abbd68SMark Brown 			devname, id);
128434abbd68SMark Brown 		rdev = dummy_regulator_rdev;
128534abbd68SMark Brown 		goto found;
128634abbd68SMark Brown 	}
128734abbd68SMark Brown #endif
128834abbd68SMark Brown 
1289414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
1290414c70cbSLiam Girdwood 	return regulator;
1291414c70cbSLiam Girdwood 
1292414c70cbSLiam Girdwood found:
12935ffbd136SMark Brown 	if (rdev->exclusive) {
12945ffbd136SMark Brown 		regulator = ERR_PTR(-EPERM);
12955ffbd136SMark Brown 		goto out;
12965ffbd136SMark Brown 	}
12975ffbd136SMark Brown 
12985ffbd136SMark Brown 	if (exclusive && rdev->open_count) {
12995ffbd136SMark Brown 		regulator = ERR_PTR(-EBUSY);
13005ffbd136SMark Brown 		goto out;
13015ffbd136SMark Brown 	}
13025ffbd136SMark Brown 
1303a5766f11SLiam Girdwood 	if (!try_module_get(rdev->owner))
1304a5766f11SLiam Girdwood 		goto out;
1305a5766f11SLiam Girdwood 
1306414c70cbSLiam Girdwood 	regulator = create_regulator(rdev, dev, id);
1307414c70cbSLiam Girdwood 	if (regulator == NULL) {
1308414c70cbSLiam Girdwood 		regulator = ERR_PTR(-ENOMEM);
1309414c70cbSLiam Girdwood 		module_put(rdev->owner);
1310bcda4321SAxel Lin 		goto out;
1311414c70cbSLiam Girdwood 	}
1312414c70cbSLiam Girdwood 
13135ffbd136SMark Brown 	rdev->open_count++;
13145ffbd136SMark Brown 	if (exclusive) {
13155ffbd136SMark Brown 		rdev->exclusive = 1;
13165ffbd136SMark Brown 
13175ffbd136SMark Brown 		ret = _regulator_is_enabled(rdev);
13185ffbd136SMark Brown 		if (ret > 0)
13195ffbd136SMark Brown 			rdev->use_count = 1;
13205ffbd136SMark Brown 		else
13215ffbd136SMark Brown 			rdev->use_count = 0;
13225ffbd136SMark Brown 	}
13235ffbd136SMark Brown 
1324a5766f11SLiam Girdwood out:
1325414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
13265ffbd136SMark Brown 
1327414c70cbSLiam Girdwood 	return regulator;
1328414c70cbSLiam Girdwood }
13295ffbd136SMark Brown 
13305ffbd136SMark Brown /**
13315ffbd136SMark Brown  * regulator_get - lookup and obtain a reference to a regulator.
13325ffbd136SMark Brown  * @dev: device for regulator "consumer"
13335ffbd136SMark Brown  * @id: Supply name or regulator ID.
13345ffbd136SMark Brown  *
13355ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
13365ffbd136SMark Brown  * or IS_ERR() condition containing errno.
13375ffbd136SMark Brown  *
13385ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
13395ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
13405ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
13415ffbd136SMark Brown  * device pins in the datasheet.
13425ffbd136SMark Brown  */
13435ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id)
13445ffbd136SMark Brown {
13455ffbd136SMark Brown 	return _regulator_get(dev, id, 0);
13465ffbd136SMark Brown }
1347414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get);
1348414c70cbSLiam Girdwood 
1349070b9079SStephen Boyd static void devm_regulator_release(struct device *dev, void *res)
1350070b9079SStephen Boyd {
1351070b9079SStephen Boyd 	regulator_put(*(struct regulator **)res);
1352070b9079SStephen Boyd }
1353070b9079SStephen Boyd 
1354070b9079SStephen Boyd /**
1355070b9079SStephen Boyd  * devm_regulator_get - Resource managed regulator_get()
1356070b9079SStephen Boyd  * @dev: device for regulator "consumer"
1357070b9079SStephen Boyd  * @id: Supply name or regulator ID.
1358070b9079SStephen Boyd  *
1359070b9079SStephen Boyd  * Managed regulator_get(). Regulators returned from this function are
1360070b9079SStephen Boyd  * automatically regulator_put() on driver detach. See regulator_get() for more
1361070b9079SStephen Boyd  * information.
1362070b9079SStephen Boyd  */
1363070b9079SStephen Boyd struct regulator *devm_regulator_get(struct device *dev, const char *id)
1364070b9079SStephen Boyd {
1365070b9079SStephen Boyd 	struct regulator **ptr, *regulator;
1366070b9079SStephen Boyd 
1367070b9079SStephen Boyd 	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
1368070b9079SStephen Boyd 	if (!ptr)
1369070b9079SStephen Boyd 		return ERR_PTR(-ENOMEM);
1370070b9079SStephen Boyd 
1371070b9079SStephen Boyd 	regulator = regulator_get(dev, id);
1372070b9079SStephen Boyd 	if (!IS_ERR(regulator)) {
1373070b9079SStephen Boyd 		*ptr = regulator;
1374070b9079SStephen Boyd 		devres_add(dev, ptr);
1375070b9079SStephen Boyd 	} else {
1376070b9079SStephen Boyd 		devres_free(ptr);
1377070b9079SStephen Boyd 	}
1378070b9079SStephen Boyd 
1379070b9079SStephen Boyd 	return regulator;
1380070b9079SStephen Boyd }
1381070b9079SStephen Boyd EXPORT_SYMBOL_GPL(devm_regulator_get);
1382070b9079SStephen Boyd 
1383414c70cbSLiam Girdwood /**
13845ffbd136SMark Brown  * regulator_get_exclusive - obtain exclusive access to a regulator.
13855ffbd136SMark Brown  * @dev: device for regulator "consumer"
13865ffbd136SMark Brown  * @id: Supply name or regulator ID.
13875ffbd136SMark Brown  *
13885ffbd136SMark Brown  * Returns a struct regulator corresponding to the regulator producer,
13895ffbd136SMark Brown  * or IS_ERR() condition containing errno.  Other consumers will be
13905ffbd136SMark Brown  * unable to obtain this reference is held and the use count for the
13915ffbd136SMark Brown  * regulator will be initialised to reflect the current state of the
13925ffbd136SMark Brown  * regulator.
13935ffbd136SMark Brown  *
13945ffbd136SMark Brown  * This is intended for use by consumers which cannot tolerate shared
13955ffbd136SMark Brown  * use of the regulator such as those which need to force the
13965ffbd136SMark Brown  * regulator off for correct operation of the hardware they are
13975ffbd136SMark Brown  * controlling.
13985ffbd136SMark Brown  *
13995ffbd136SMark Brown  * Use of supply names configured via regulator_set_device_supply() is
14005ffbd136SMark Brown  * strongly encouraged.  It is recommended that the supply name used
14015ffbd136SMark Brown  * should match the name used for the supply and/or the relevant
14025ffbd136SMark Brown  * device pins in the datasheet.
14035ffbd136SMark Brown  */
14045ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
14055ffbd136SMark Brown {
14065ffbd136SMark Brown 	return _regulator_get(dev, id, 1);
14075ffbd136SMark Brown }
14085ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive);
14095ffbd136SMark Brown 
14105ffbd136SMark Brown /**
1411414c70cbSLiam Girdwood  * regulator_put - "free" the regulator source
1412414c70cbSLiam Girdwood  * @regulator: regulator source
1413414c70cbSLiam Girdwood  *
1414414c70cbSLiam Girdwood  * Note: drivers must ensure that all regulator_enable calls made on this
1415414c70cbSLiam Girdwood  * regulator source are balanced by regulator_disable calls prior to calling
1416414c70cbSLiam Girdwood  * this function.
1417414c70cbSLiam Girdwood  */
1418414c70cbSLiam Girdwood void regulator_put(struct regulator *regulator)
1419414c70cbSLiam Girdwood {
1420414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
1421414c70cbSLiam Girdwood 
1422414c70cbSLiam Girdwood 	if (regulator == NULL || IS_ERR(regulator))
1423414c70cbSLiam Girdwood 		return;
1424414c70cbSLiam Girdwood 
1425414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
1426414c70cbSLiam Girdwood 	rdev = regulator->rdev;
1427414c70cbSLiam Girdwood 
14285de70519SMark Brown 	debugfs_remove_recursive(regulator->debugfs);
14295de70519SMark Brown 
1430414c70cbSLiam Girdwood 	/* remove any sysfs entries */
1431414c70cbSLiam Girdwood 	if (regulator->dev) {
1432414c70cbSLiam Girdwood 		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
1433414c70cbSLiam Girdwood 		device_remove_file(regulator->dev, &regulator->dev_attr);
1434414c70cbSLiam Girdwood 		kfree(regulator->dev_attr.attr.name);
1435414c70cbSLiam Girdwood 	}
14365de70519SMark Brown 	kfree(regulator->supply_name);
1437414c70cbSLiam Girdwood 	list_del(&regulator->list);
1438414c70cbSLiam Girdwood 	kfree(regulator);
1439414c70cbSLiam Girdwood 
14405ffbd136SMark Brown 	rdev->open_count--;
14415ffbd136SMark Brown 	rdev->exclusive = 0;
14425ffbd136SMark Brown 
1443414c70cbSLiam Girdwood 	module_put(rdev->owner);
1444414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
1445414c70cbSLiam Girdwood }
1446414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put);
1447414c70cbSLiam Girdwood 
1448d5ad34f7SMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data)
1449d5ad34f7SMark Brown {
1450d5ad34f7SMark Brown 	struct regulator **r = res;
1451d5ad34f7SMark Brown 	if (!r || !*r) {
1452d5ad34f7SMark Brown 		WARN_ON(!r || !*r);
1453d5ad34f7SMark Brown 		return 0;
1454d5ad34f7SMark Brown 	}
1455d5ad34f7SMark Brown 	return *r == data;
1456d5ad34f7SMark Brown }
1457d5ad34f7SMark Brown 
1458d5ad34f7SMark Brown /**
1459d5ad34f7SMark Brown  * devm_regulator_put - Resource managed regulator_put()
1460d5ad34f7SMark Brown  * @regulator: regulator to free
1461d5ad34f7SMark Brown  *
1462d5ad34f7SMark Brown  * Deallocate a regulator allocated with devm_regulator_get(). Normally
1463d5ad34f7SMark Brown  * this function will not need to be called and the resource management
1464d5ad34f7SMark Brown  * code will ensure that the resource is freed.
1465d5ad34f7SMark Brown  */
1466d5ad34f7SMark Brown void devm_regulator_put(struct regulator *regulator)
1467d5ad34f7SMark Brown {
1468d5ad34f7SMark Brown 	int rc;
1469d5ad34f7SMark Brown 
1470361ff501SMark Brown 	rc = devres_release(regulator->dev, devm_regulator_release,
1471d5ad34f7SMark Brown 			    devm_regulator_match, regulator);
1472968c2c17SMark Brown 	if (rc == 0)
1473968c2c17SMark Brown 		regulator_put(regulator);
1474968c2c17SMark Brown 	else
1475d5ad34f7SMark Brown 		WARN_ON(rc);
1476d5ad34f7SMark Brown }
1477d5ad34f7SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put);
1478d5ad34f7SMark Brown 
1479414c70cbSLiam Girdwood /* locks held by regulator_enable() */
1480414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev)
1481414c70cbSLiam Girdwood {
148231aae2beSMark Brown 	int ret, delay;
1483414c70cbSLiam Girdwood 
1484414c70cbSLiam Girdwood 	/* check voltage and requested load before enabling */
1485414c70cbSLiam Girdwood 	if (rdev->constraints &&
14869a2372faSMark Brown 	    (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
1487414c70cbSLiam Girdwood 		drms_uA_update(rdev);
1488414c70cbSLiam Girdwood 
14899a2372faSMark Brown 	if (rdev->use_count == 0) {
14909a2372faSMark Brown 		/* The regulator may on if it's not switchable or left on */
14919a2372faSMark Brown 		ret = _regulator_is_enabled(rdev);
14929a2372faSMark Brown 		if (ret == -EINVAL || ret == 0) {
14939a2372faSMark Brown 			if (!_regulator_can_change_status(rdev))
14949a2372faSMark Brown 				return -EPERM;
14959a2372faSMark Brown 
149631aae2beSMark Brown 			if (!rdev->desc->ops->enable)
149731aae2beSMark Brown 				return -EINVAL;
149831aae2beSMark Brown 
149931aae2beSMark Brown 			/* Query before enabling in case configuration
150025985edcSLucas De Marchi 			 * dependent.  */
150131aae2beSMark Brown 			ret = _regulator_get_enable_time(rdev);
150231aae2beSMark Brown 			if (ret >= 0) {
150331aae2beSMark Brown 				delay = ret;
150431aae2beSMark Brown 			} else {
15055da84fd9SJoe Perches 				rdev_warn(rdev, "enable_time() failed: %d\n",
150631aae2beSMark Brown 					   ret);
150731aae2beSMark Brown 				delay = 0;
150831aae2beSMark Brown 			}
150931aae2beSMark Brown 
151002fa3ec0SMark Brown 			trace_regulator_enable(rdev_get_name(rdev));
151102fa3ec0SMark Brown 
151231aae2beSMark Brown 			/* Allow the regulator to ramp; it would be useful
151331aae2beSMark Brown 			 * to extend this for bulk operations so that the
151431aae2beSMark Brown 			 * regulators can ramp together.  */
1515414c70cbSLiam Girdwood 			ret = rdev->desc->ops->enable(rdev);
15169a2372faSMark Brown 			if (ret < 0)
15179a2372faSMark Brown 				return ret;
151831aae2beSMark Brown 
151902fa3ec0SMark Brown 			trace_regulator_enable_delay(rdev_get_name(rdev));
152002fa3ec0SMark Brown 
1521e36c1df8SAxel Lin 			if (delay >= 1000) {
152231aae2beSMark Brown 				mdelay(delay / 1000);
1523e36c1df8SAxel Lin 				udelay(delay % 1000);
1524e36c1df8SAxel Lin 			} else if (delay) {
152531aae2beSMark Brown 				udelay(delay);
1526e36c1df8SAxel Lin 			}
152731aae2beSMark Brown 
152802fa3ec0SMark Brown 			trace_regulator_enable_complete(rdev_get_name(rdev));
152902fa3ec0SMark Brown 
1530a7433cffSLinus Walleij 		} else if (ret < 0) {
15315da84fd9SJoe Perches 			rdev_err(rdev, "is_enabled() failed: %d\n", ret);
1532414c70cbSLiam Girdwood 			return ret;
1533414c70cbSLiam Girdwood 		}
1534a7433cffSLinus Walleij 		/* Fallthrough on positive return values - already enabled */
1535414c70cbSLiam Girdwood 	}
1536414c70cbSLiam Girdwood 
15379a2372faSMark Brown 	rdev->use_count++;
15389a2372faSMark Brown 
15399a2372faSMark Brown 	return 0;
1540414c70cbSLiam Girdwood }
1541414c70cbSLiam Girdwood 
1542414c70cbSLiam Girdwood /**
1543414c70cbSLiam Girdwood  * regulator_enable - enable regulator output
1544414c70cbSLiam Girdwood  * @regulator: regulator source
1545414c70cbSLiam Girdwood  *
1546cf7bbcdfSMark Brown  * Request that the regulator be enabled with the regulator output at
1547cf7bbcdfSMark Brown  * the predefined voltage or current value.  Calls to regulator_enable()
1548cf7bbcdfSMark Brown  * must be balanced with calls to regulator_disable().
1549cf7bbcdfSMark Brown  *
1550414c70cbSLiam Girdwood  * NOTE: the output value can be set by other drivers, boot loader or may be
1551cf7bbcdfSMark Brown  * hardwired in the regulator.
1552414c70cbSLiam Girdwood  */
1553414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator)
1554414c70cbSLiam Girdwood {
1555412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
1556412aec61SDavid Brownell 	int ret = 0;
1557414c70cbSLiam Girdwood 
15586492bc1bSMark Brown 	if (regulator->always_on)
15596492bc1bSMark Brown 		return 0;
15606492bc1bSMark Brown 
15613801b86aSMark Brown 	if (rdev->supply) {
15623801b86aSMark Brown 		ret = regulator_enable(rdev->supply);
15633801b86aSMark Brown 		if (ret != 0)
15643801b86aSMark Brown 			return ret;
15653801b86aSMark Brown 	}
15663801b86aSMark Brown 
1567412aec61SDavid Brownell 	mutex_lock(&rdev->mutex);
1568412aec61SDavid Brownell 	ret = _regulator_enable(rdev);
1569412aec61SDavid Brownell 	mutex_unlock(&rdev->mutex);
15703801b86aSMark Brown 
1571d1685e4eSHeiko Stübner 	if (ret != 0 && rdev->supply)
15723801b86aSMark Brown 		regulator_disable(rdev->supply);
15733801b86aSMark Brown 
1574414c70cbSLiam Girdwood 	return ret;
1575414c70cbSLiam Girdwood }
1576414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable);
1577414c70cbSLiam Girdwood 
1578414c70cbSLiam Girdwood /* locks held by regulator_disable() */
15793801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev)
1580414c70cbSLiam Girdwood {
1581414c70cbSLiam Girdwood 	int ret = 0;
1582414c70cbSLiam Girdwood 
1583cd94b505SDavid Brownell 	if (WARN(rdev->use_count <= 0,
158443e7ee33SJoe Perches 		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
1585cd94b505SDavid Brownell 		return -EIO;
1586cd94b505SDavid Brownell 
1587414c70cbSLiam Girdwood 	/* are we the last user and permitted to disable ? */
158860ef66fcSMark Brown 	if (rdev->use_count == 1 &&
158960ef66fcSMark Brown 	    (rdev->constraints && !rdev->constraints->always_on)) {
1590414c70cbSLiam Girdwood 
1591414c70cbSLiam Girdwood 		/* we are last user */
15929a2372faSMark Brown 		if (_regulator_can_change_status(rdev) &&
15939a2372faSMark Brown 		    rdev->desc->ops->disable) {
159402fa3ec0SMark Brown 			trace_regulator_disable(rdev_get_name(rdev));
159502fa3ec0SMark Brown 
1596414c70cbSLiam Girdwood 			ret = rdev->desc->ops->disable(rdev);
1597414c70cbSLiam Girdwood 			if (ret < 0) {
15985da84fd9SJoe Perches 				rdev_err(rdev, "failed to disable\n");
1599414c70cbSLiam Girdwood 				return ret;
1600414c70cbSLiam Girdwood 			}
160184b68263SMark Brown 
160202fa3ec0SMark Brown 			trace_regulator_disable_complete(rdev_get_name(rdev));
160302fa3ec0SMark Brown 
160484b68263SMark Brown 			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
160584b68263SMark Brown 					     NULL);
1606414c70cbSLiam Girdwood 		}
1607414c70cbSLiam Girdwood 
1608414c70cbSLiam Girdwood 		rdev->use_count = 0;
1609414c70cbSLiam Girdwood 	} else if (rdev->use_count > 1) {
1610414c70cbSLiam Girdwood 
1611414c70cbSLiam Girdwood 		if (rdev->constraints &&
1612414c70cbSLiam Girdwood 			(rdev->constraints->valid_ops_mask &
1613414c70cbSLiam Girdwood 			REGULATOR_CHANGE_DRMS))
1614414c70cbSLiam Girdwood 			drms_uA_update(rdev);
1615414c70cbSLiam Girdwood 
1616414c70cbSLiam Girdwood 		rdev->use_count--;
1617414c70cbSLiam Girdwood 	}
16183801b86aSMark Brown 
1619414c70cbSLiam Girdwood 	return ret;
1620414c70cbSLiam Girdwood }
1621414c70cbSLiam Girdwood 
1622414c70cbSLiam Girdwood /**
1623414c70cbSLiam Girdwood  * regulator_disable - disable regulator output
1624414c70cbSLiam Girdwood  * @regulator: regulator source
1625414c70cbSLiam Girdwood  *
1626cf7bbcdfSMark Brown  * Disable the regulator output voltage or current.  Calls to
1627cf7bbcdfSMark Brown  * regulator_enable() must be balanced with calls to
1628cf7bbcdfSMark Brown  * regulator_disable().
162969279fb9SMark Brown  *
1630414c70cbSLiam Girdwood  * NOTE: this will only disable the regulator output if no other consumer
1631cf7bbcdfSMark Brown  * devices have it enabled, the regulator device supports disabling and
1632cf7bbcdfSMark Brown  * machine constraints permit this operation.
1633414c70cbSLiam Girdwood  */
1634414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator)
1635414c70cbSLiam Girdwood {
1636412aec61SDavid Brownell 	struct regulator_dev *rdev = regulator->rdev;
1637412aec61SDavid Brownell 	int ret = 0;
1638414c70cbSLiam Girdwood 
16396492bc1bSMark Brown 	if (regulator->always_on)
16406492bc1bSMark Brown 		return 0;
16416492bc1bSMark Brown 
1642412aec61SDavid Brownell 	mutex_lock(&rdev->mutex);
16433801b86aSMark Brown 	ret = _regulator_disable(rdev);
1644412aec61SDavid Brownell 	mutex_unlock(&rdev->mutex);
16458cbf811dSJeffrey Carlyle 
16463801b86aSMark Brown 	if (ret == 0 && rdev->supply)
16473801b86aSMark Brown 		regulator_disable(rdev->supply);
16488cbf811dSJeffrey Carlyle 
1649414c70cbSLiam Girdwood 	return ret;
1650414c70cbSLiam Girdwood }
1651414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable);
1652414c70cbSLiam Girdwood 
1653414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */
16543801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev)
1655414c70cbSLiam Girdwood {
1656414c70cbSLiam Girdwood 	int ret = 0;
1657414c70cbSLiam Girdwood 
1658414c70cbSLiam Girdwood 	/* force disable */
1659414c70cbSLiam Girdwood 	if (rdev->desc->ops->disable) {
1660414c70cbSLiam Girdwood 		/* ah well, who wants to live forever... */
1661414c70cbSLiam Girdwood 		ret = rdev->desc->ops->disable(rdev);
1662414c70cbSLiam Girdwood 		if (ret < 0) {
16635da84fd9SJoe Perches 			rdev_err(rdev, "failed to force disable\n");
1664414c70cbSLiam Girdwood 			return ret;
1665414c70cbSLiam Girdwood 		}
1666414c70cbSLiam Girdwood 		/* notify other consumers that power has been forced off */
166784b68263SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
166884b68263SMark Brown 			REGULATOR_EVENT_DISABLE, NULL);
1669414c70cbSLiam Girdwood 	}
1670414c70cbSLiam Girdwood 
1671414c70cbSLiam Girdwood 	return ret;
1672414c70cbSLiam Girdwood }
1673414c70cbSLiam Girdwood 
1674414c70cbSLiam Girdwood /**
1675414c70cbSLiam Girdwood  * regulator_force_disable - force disable regulator output
1676414c70cbSLiam Girdwood  * @regulator: regulator source
1677414c70cbSLiam Girdwood  *
1678414c70cbSLiam Girdwood  * Forcibly disable the regulator output voltage or current.
1679414c70cbSLiam Girdwood  * NOTE: this *will* disable the regulator output even if other consumer
1680414c70cbSLiam Girdwood  * devices have it enabled. This should be used for situations when device
1681414c70cbSLiam Girdwood  * damage will likely occur if the regulator is not disabled (e.g. over temp).
1682414c70cbSLiam Girdwood  */
1683414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator)
1684414c70cbSLiam Girdwood {
168582d15839SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
1686414c70cbSLiam Girdwood 	int ret;
1687414c70cbSLiam Girdwood 
168882d15839SMark Brown 	mutex_lock(&rdev->mutex);
1689414c70cbSLiam Girdwood 	regulator->uA_load = 0;
16903801b86aSMark Brown 	ret = _regulator_force_disable(regulator->rdev);
169182d15839SMark Brown 	mutex_unlock(&rdev->mutex);
16928cbf811dSJeffrey Carlyle 
16933801b86aSMark Brown 	if (rdev->supply)
16943801b86aSMark Brown 		while (rdev->open_count--)
16953801b86aSMark Brown 			regulator_disable(rdev->supply);
16968cbf811dSJeffrey Carlyle 
1697414c70cbSLiam Girdwood 	return ret;
1698414c70cbSLiam Girdwood }
1699414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable);
1700414c70cbSLiam Girdwood 
1701da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work)
1702da07ecd9SMark Brown {
1703da07ecd9SMark Brown 	struct regulator_dev *rdev = container_of(work, struct regulator_dev,
1704da07ecd9SMark Brown 						  disable_work.work);
1705da07ecd9SMark Brown 	int count, i, ret;
1706da07ecd9SMark Brown 
1707da07ecd9SMark Brown 	mutex_lock(&rdev->mutex);
1708da07ecd9SMark Brown 
1709da07ecd9SMark Brown 	BUG_ON(!rdev->deferred_disables);
1710da07ecd9SMark Brown 
1711da07ecd9SMark Brown 	count = rdev->deferred_disables;
1712da07ecd9SMark Brown 	rdev->deferred_disables = 0;
1713da07ecd9SMark Brown 
1714da07ecd9SMark Brown 	for (i = 0; i < count; i++) {
1715da07ecd9SMark Brown 		ret = _regulator_disable(rdev);
1716da07ecd9SMark Brown 		if (ret != 0)
1717da07ecd9SMark Brown 			rdev_err(rdev, "Deferred disable failed: %d\n", ret);
1718da07ecd9SMark Brown 	}
1719da07ecd9SMark Brown 
1720da07ecd9SMark Brown 	mutex_unlock(&rdev->mutex);
1721da07ecd9SMark Brown 
1722da07ecd9SMark Brown 	if (rdev->supply) {
1723da07ecd9SMark Brown 		for (i = 0; i < count; i++) {
1724da07ecd9SMark Brown 			ret = regulator_disable(rdev->supply);
1725da07ecd9SMark Brown 			if (ret != 0) {
1726da07ecd9SMark Brown 				rdev_err(rdev,
1727da07ecd9SMark Brown 					 "Supply disable failed: %d\n", ret);
1728da07ecd9SMark Brown 			}
1729da07ecd9SMark Brown 		}
1730da07ecd9SMark Brown 	}
1731da07ecd9SMark Brown }
1732da07ecd9SMark Brown 
1733da07ecd9SMark Brown /**
1734da07ecd9SMark Brown  * regulator_disable_deferred - disable regulator output with delay
1735da07ecd9SMark Brown  * @regulator: regulator source
1736da07ecd9SMark Brown  * @ms: miliseconds until the regulator is disabled
1737da07ecd9SMark Brown  *
1738da07ecd9SMark Brown  * Execute regulator_disable() on the regulator after a delay.  This
1739da07ecd9SMark Brown  * is intended for use with devices that require some time to quiesce.
1740da07ecd9SMark Brown  *
1741da07ecd9SMark Brown  * NOTE: this will only disable the regulator output if no other consumer
1742da07ecd9SMark Brown  * devices have it enabled, the regulator device supports disabling and
1743da07ecd9SMark Brown  * machine constraints permit this operation.
1744da07ecd9SMark Brown  */
1745da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms)
1746da07ecd9SMark Brown {
1747da07ecd9SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
1748aa59802dSMark Brown 	int ret;
1749da07ecd9SMark Brown 
17506492bc1bSMark Brown 	if (regulator->always_on)
17516492bc1bSMark Brown 		return 0;
17526492bc1bSMark Brown 
1753da07ecd9SMark Brown 	mutex_lock(&rdev->mutex);
1754da07ecd9SMark Brown 	rdev->deferred_disables++;
1755da07ecd9SMark Brown 	mutex_unlock(&rdev->mutex);
1756da07ecd9SMark Brown 
1757aa59802dSMark Brown 	ret = schedule_delayed_work(&rdev->disable_work,
1758da07ecd9SMark Brown 				    msecs_to_jiffies(ms));
1759aa59802dSMark Brown 	if (ret < 0)
1760aa59802dSMark Brown 		return ret;
1761aa59802dSMark Brown 	else
1762aa59802dSMark Brown 		return 0;
1763da07ecd9SMark Brown }
1764da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred);
1765da07ecd9SMark Brown 
1766cd6dffb4SMark Brown /**
1767cd6dffb4SMark Brown  * regulator_is_enabled_regmap - standard is_enabled() for regmap users
1768cd6dffb4SMark Brown  *
1769cd6dffb4SMark Brown  * @rdev: regulator to operate on
1770cd6dffb4SMark Brown  *
1771cd6dffb4SMark Brown  * Regulators that use regmap for their register I/O can set the
1772cd6dffb4SMark Brown  * enable_reg and enable_mask fields in their descriptor and then use
1773cd6dffb4SMark Brown  * this as their is_enabled operation, saving some code.
1774cd6dffb4SMark Brown  */
1775cd6dffb4SMark Brown int regulator_is_enabled_regmap(struct regulator_dev *rdev)
1776cd6dffb4SMark Brown {
1777cd6dffb4SMark Brown 	unsigned int val;
1778cd6dffb4SMark Brown 	int ret;
1779cd6dffb4SMark Brown 
1780cd6dffb4SMark Brown 	ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
1781cd6dffb4SMark Brown 	if (ret != 0)
1782cd6dffb4SMark Brown 		return ret;
1783cd6dffb4SMark Brown 
1784cd6dffb4SMark Brown 	return (val & rdev->desc->enable_mask) != 0;
1785cd6dffb4SMark Brown }
1786cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
1787cd6dffb4SMark Brown 
1788cd6dffb4SMark Brown /**
1789cd6dffb4SMark Brown  * regulator_enable_regmap - standard enable() for regmap users
1790cd6dffb4SMark Brown  *
1791cd6dffb4SMark Brown  * @rdev: regulator to operate on
1792cd6dffb4SMark Brown  *
1793cd6dffb4SMark Brown  * Regulators that use regmap for their register I/O can set the
1794cd6dffb4SMark Brown  * enable_reg and enable_mask fields in their descriptor and then use
1795cd6dffb4SMark Brown  * this as their enable() operation, saving some code.
1796cd6dffb4SMark Brown  */
1797cd6dffb4SMark Brown int regulator_enable_regmap(struct regulator_dev *rdev)
1798cd6dffb4SMark Brown {
1799cd6dffb4SMark Brown 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
1800cd6dffb4SMark Brown 				  rdev->desc->enable_mask,
1801cd6dffb4SMark Brown 				  rdev->desc->enable_mask);
1802cd6dffb4SMark Brown }
1803cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_enable_regmap);
1804cd6dffb4SMark Brown 
1805cd6dffb4SMark Brown /**
1806cd6dffb4SMark Brown  * regulator_disable_regmap - standard disable() for regmap users
1807cd6dffb4SMark Brown  *
1808cd6dffb4SMark Brown  * @rdev: regulator to operate on
1809cd6dffb4SMark Brown  *
1810cd6dffb4SMark Brown  * Regulators that use regmap for their register I/O can set the
1811cd6dffb4SMark Brown  * enable_reg and enable_mask fields in their descriptor and then use
1812cd6dffb4SMark Brown  * this as their disable() operation, saving some code.
1813cd6dffb4SMark Brown  */
1814cd6dffb4SMark Brown int regulator_disable_regmap(struct regulator_dev *rdev)
1815cd6dffb4SMark Brown {
1816cd6dffb4SMark Brown 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
1817cd6dffb4SMark Brown 				  rdev->desc->enable_mask, 0);
1818cd6dffb4SMark Brown }
1819cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_regmap);
1820cd6dffb4SMark Brown 
1821414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev)
1822414c70cbSLiam Girdwood {
18239a7f6a4cSMark Brown 	/* If we don't know then assume that the regulator is always on */
18249332546fSMark Brown 	if (!rdev->desc->ops->is_enabled)
18259a7f6a4cSMark Brown 		return 1;
1826414c70cbSLiam Girdwood 
18279332546fSMark Brown 	return rdev->desc->ops->is_enabled(rdev);
1828414c70cbSLiam Girdwood }
1829414c70cbSLiam Girdwood 
1830414c70cbSLiam Girdwood /**
1831414c70cbSLiam Girdwood  * regulator_is_enabled - is the regulator output enabled
1832414c70cbSLiam Girdwood  * @regulator: regulator source
1833414c70cbSLiam Girdwood  *
1834412aec61SDavid Brownell  * Returns positive if the regulator driver backing the source/client
1835412aec61SDavid Brownell  * has requested that the device be enabled, zero if it hasn't, else a
1836412aec61SDavid Brownell  * negative errno code.
1837412aec61SDavid Brownell  *
1838412aec61SDavid Brownell  * Note that the device backing this regulator handle can have multiple
1839412aec61SDavid Brownell  * users, so it might be enabled even if regulator_enable() was never
1840412aec61SDavid Brownell  * called for this particular source.
1841414c70cbSLiam Girdwood  */
1842414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator)
1843414c70cbSLiam Girdwood {
18449332546fSMark Brown 	int ret;
18459332546fSMark Brown 
18466492bc1bSMark Brown 	if (regulator->always_on)
18476492bc1bSMark Brown 		return 1;
18486492bc1bSMark Brown 
18499332546fSMark Brown 	mutex_lock(&regulator->rdev->mutex);
18509332546fSMark Brown 	ret = _regulator_is_enabled(regulator->rdev);
18519332546fSMark Brown 	mutex_unlock(&regulator->rdev->mutex);
18529332546fSMark Brown 
18539332546fSMark Brown 	return ret;
1854414c70cbSLiam Girdwood }
1855414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled);
1856414c70cbSLiam Girdwood 
1857414c70cbSLiam Girdwood /**
18584367cfdcSDavid Brownell  * regulator_count_voltages - count regulator_list_voltage() selectors
18594367cfdcSDavid Brownell  * @regulator: regulator source
18604367cfdcSDavid Brownell  *
18614367cfdcSDavid Brownell  * Returns number of selectors, or negative errno.  Selectors are
18624367cfdcSDavid Brownell  * numbered starting at zero, and typically correspond to bitfields
18634367cfdcSDavid Brownell  * in hardware registers.
18644367cfdcSDavid Brownell  */
18654367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator)
18664367cfdcSDavid Brownell {
18674367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
18684367cfdcSDavid Brownell 
18694367cfdcSDavid Brownell 	return rdev->desc->n_voltages ? : -EINVAL;
18704367cfdcSDavid Brownell }
18714367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages);
18724367cfdcSDavid Brownell 
18734367cfdcSDavid Brownell /**
1874bca7bbffSMark Brown  * regulator_list_voltage_linear - List voltages with simple calculation
1875bca7bbffSMark Brown  *
1876bca7bbffSMark Brown  * @rdev: Regulator device
1877bca7bbffSMark Brown  * @selector: Selector to convert into a voltage
1878bca7bbffSMark Brown  *
1879bca7bbffSMark Brown  * Regulators with a simple linear mapping between voltages and
1880bca7bbffSMark Brown  * selectors can set min_uV and uV_step in the regulator descriptor
1881bca7bbffSMark Brown  * and then use this function as their list_voltage() operation,
1882bca7bbffSMark Brown  */
1883bca7bbffSMark Brown int regulator_list_voltage_linear(struct regulator_dev *rdev,
1884bca7bbffSMark Brown 				  unsigned int selector)
1885bca7bbffSMark Brown {
1886bca7bbffSMark Brown 	if (selector >= rdev->desc->n_voltages)
1887bca7bbffSMark Brown 		return -EINVAL;
1888bca7bbffSMark Brown 
1889bca7bbffSMark Brown 	return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
1890bca7bbffSMark Brown }
1891bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
1892bca7bbffSMark Brown 
1893bca7bbffSMark Brown /**
1894cffc9592SAxel Lin  * regulator_list_voltage_table - List voltages with table based mapping
1895cffc9592SAxel Lin  *
1896cffc9592SAxel Lin  * @rdev: Regulator device
1897cffc9592SAxel Lin  * @selector: Selector to convert into a voltage
1898cffc9592SAxel Lin  *
1899cffc9592SAxel Lin  * Regulators with table based mapping between voltages and
1900cffc9592SAxel Lin  * selectors can set volt_table in the regulator descriptor
1901cffc9592SAxel Lin  * and then use this function as their list_voltage() operation.
1902cffc9592SAxel Lin  */
1903cffc9592SAxel Lin int regulator_list_voltage_table(struct regulator_dev *rdev,
1904cffc9592SAxel Lin 				 unsigned int selector)
1905cffc9592SAxel Lin {
1906cffc9592SAxel Lin 	if (!rdev->desc->volt_table) {
1907cffc9592SAxel Lin 		BUG_ON(!rdev->desc->volt_table);
1908cffc9592SAxel Lin 		return -EINVAL;
1909cffc9592SAxel Lin 	}
1910cffc9592SAxel Lin 
1911cffc9592SAxel Lin 	if (selector >= rdev->desc->n_voltages)
1912cffc9592SAxel Lin 		return -EINVAL;
1913cffc9592SAxel Lin 
1914cffc9592SAxel Lin 	return rdev->desc->volt_table[selector];
1915cffc9592SAxel Lin }
1916cffc9592SAxel Lin EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
1917cffc9592SAxel Lin 
1918cffc9592SAxel Lin /**
19194367cfdcSDavid Brownell  * regulator_list_voltage - enumerate supported voltages
19204367cfdcSDavid Brownell  * @regulator: regulator source
19214367cfdcSDavid Brownell  * @selector: identify voltage to list
19224367cfdcSDavid Brownell  * Context: can sleep
19234367cfdcSDavid Brownell  *
19244367cfdcSDavid Brownell  * Returns a voltage that can be passed to @regulator_set_voltage(),
192588393161SThomas Weber  * zero if this selector code can't be used on this system, or a
19264367cfdcSDavid Brownell  * negative errno.
19274367cfdcSDavid Brownell  */
19284367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector)
19294367cfdcSDavid Brownell {
19304367cfdcSDavid Brownell 	struct regulator_dev	*rdev = regulator->rdev;
19314367cfdcSDavid Brownell 	struct regulator_ops	*ops = rdev->desc->ops;
19324367cfdcSDavid Brownell 	int			ret;
19334367cfdcSDavid Brownell 
19344367cfdcSDavid Brownell 	if (!ops->list_voltage || selector >= rdev->desc->n_voltages)
19354367cfdcSDavid Brownell 		return -EINVAL;
19364367cfdcSDavid Brownell 
19374367cfdcSDavid Brownell 	mutex_lock(&rdev->mutex);
19384367cfdcSDavid Brownell 	ret = ops->list_voltage(rdev, selector);
19394367cfdcSDavid Brownell 	mutex_unlock(&rdev->mutex);
19404367cfdcSDavid Brownell 
19414367cfdcSDavid Brownell 	if (ret > 0) {
19424367cfdcSDavid Brownell 		if (ret < rdev->constraints->min_uV)
19434367cfdcSDavid Brownell 			ret = 0;
19444367cfdcSDavid Brownell 		else if (ret > rdev->constraints->max_uV)
19454367cfdcSDavid Brownell 			ret = 0;
19464367cfdcSDavid Brownell 	}
19474367cfdcSDavid Brownell 
19484367cfdcSDavid Brownell 	return ret;
19494367cfdcSDavid Brownell }
19504367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage);
19514367cfdcSDavid Brownell 
19524367cfdcSDavid Brownell /**
1953a7a1ad90SMark Brown  * regulator_is_supported_voltage - check if a voltage range can be supported
1954a7a1ad90SMark Brown  *
1955a7a1ad90SMark Brown  * @regulator: Regulator to check.
1956a7a1ad90SMark Brown  * @min_uV: Minimum required voltage in uV.
1957a7a1ad90SMark Brown  * @max_uV: Maximum required voltage in uV.
1958a7a1ad90SMark Brown  *
1959a7a1ad90SMark Brown  * Returns a boolean or a negative error code.
1960a7a1ad90SMark Brown  */
1961a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator,
1962a7a1ad90SMark Brown 				   int min_uV, int max_uV)
1963a7a1ad90SMark Brown {
1964a7a1ad90SMark Brown 	int i, voltages, ret;
1965a7a1ad90SMark Brown 
1966a7a1ad90SMark Brown 	ret = regulator_count_voltages(regulator);
1967a7a1ad90SMark Brown 	if (ret < 0)
1968a7a1ad90SMark Brown 		return ret;
1969a7a1ad90SMark Brown 	voltages = ret;
1970a7a1ad90SMark Brown 
1971a7a1ad90SMark Brown 	for (i = 0; i < voltages; i++) {
1972a7a1ad90SMark Brown 		ret = regulator_list_voltage(regulator, i);
1973a7a1ad90SMark Brown 
1974a7a1ad90SMark Brown 		if (ret >= min_uV && ret <= max_uV)
1975a7a1ad90SMark Brown 			return 1;
1976a7a1ad90SMark Brown 	}
1977a7a1ad90SMark Brown 
1978a7a1ad90SMark Brown 	return 0;
1979a7a1ad90SMark Brown }
1980a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
1981a7a1ad90SMark Brown 
19824ab5b3d9SMark Brown /**
19834ab5b3d9SMark Brown  * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
19844ab5b3d9SMark Brown  *
19854ab5b3d9SMark Brown  * @rdev: regulator to operate on
19864ab5b3d9SMark Brown  *
19874ab5b3d9SMark Brown  * Regulators that use regmap for their register I/O can set the
19884ab5b3d9SMark Brown  * vsel_reg and vsel_mask fields in their descriptor and then use this
19894ab5b3d9SMark Brown  * as their get_voltage_vsel operation, saving some code.
19904ab5b3d9SMark Brown  */
19914ab5b3d9SMark Brown int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
19924ab5b3d9SMark Brown {
19934ab5b3d9SMark Brown 	unsigned int val;
19944ab5b3d9SMark Brown 	int ret;
19954ab5b3d9SMark Brown 
19964ab5b3d9SMark Brown 	ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
19974ab5b3d9SMark Brown 	if (ret != 0)
19984ab5b3d9SMark Brown 		return ret;
19994ab5b3d9SMark Brown 
20004ab5b3d9SMark Brown 	val &= rdev->desc->vsel_mask;
20014ab5b3d9SMark Brown 	val >>= ffs(rdev->desc->vsel_mask) - 1;
20024ab5b3d9SMark Brown 
20034ab5b3d9SMark Brown 	return val;
20044ab5b3d9SMark Brown }
20054ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
20064ab5b3d9SMark Brown 
20074ab5b3d9SMark Brown /**
20084ab5b3d9SMark Brown  * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
20094ab5b3d9SMark Brown  *
20104ab5b3d9SMark Brown  * @rdev: regulator to operate on
20114ab5b3d9SMark Brown  * @sel: Selector to set
20124ab5b3d9SMark Brown  *
20134ab5b3d9SMark Brown  * Regulators that use regmap for their register I/O can set the
20144ab5b3d9SMark Brown  * vsel_reg and vsel_mask fields in their descriptor and then use this
20154ab5b3d9SMark Brown  * as their set_voltage_vsel operation, saving some code.
20164ab5b3d9SMark Brown  */
20174ab5b3d9SMark Brown int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
20184ab5b3d9SMark Brown {
20194ab5b3d9SMark Brown 	sel <<= ffs(rdev->desc->vsel_mask) - 1;
20204ab5b3d9SMark Brown 
20214ab5b3d9SMark Brown 	return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
20224ab5b3d9SMark Brown 				  rdev->desc->vsel_mask, sel);
20234ab5b3d9SMark Brown }
20244ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
20254ab5b3d9SMark Brown 
2026e843fc46SMark Brown /**
2027e843fc46SMark Brown  * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
2028e843fc46SMark Brown  *
2029e843fc46SMark Brown  * @rdev: Regulator to operate on
2030e843fc46SMark Brown  * @min_uV: Lower bound for voltage
2031e843fc46SMark Brown  * @max_uV: Upper bound for voltage
2032e843fc46SMark Brown  *
2033e843fc46SMark Brown  * Drivers implementing set_voltage_sel() and list_voltage() can use
2034e843fc46SMark Brown  * this as their map_voltage() operation.  It will find a suitable
2035e843fc46SMark Brown  * voltage by calling list_voltage() until it gets something in bounds
2036e843fc46SMark Brown  * for the requested voltages.
2037e843fc46SMark Brown  */
2038e843fc46SMark Brown int regulator_map_voltage_iterate(struct regulator_dev *rdev,
203975790251SMark Brown 				  int min_uV, int max_uV)
204075790251SMark Brown {
2041e8eef82bSMark Brown 	int best_val = INT_MAX;
2042e843fc46SMark Brown 	int selector = 0;
2043e843fc46SMark Brown 	int i, ret;
2044e8eef82bSMark Brown 
2045e8eef82bSMark Brown 	/* Find the smallest voltage that falls within the specified
2046e8eef82bSMark Brown 	 * range.
2047e8eef82bSMark Brown 	 */
2048e8eef82bSMark Brown 	for (i = 0; i < rdev->desc->n_voltages; i++) {
2049e8eef82bSMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, i);
2050e8eef82bSMark Brown 		if (ret < 0)
2051e8eef82bSMark Brown 			continue;
2052e8eef82bSMark Brown 
2053e8eef82bSMark Brown 		if (ret < best_val && ret >= min_uV && ret <= max_uV) {
2054e8eef82bSMark Brown 			best_val = ret;
2055e8eef82bSMark Brown 			selector = i;
2056e8eef82bSMark Brown 		}
2057e8eef82bSMark Brown 	}
2058e8eef82bSMark Brown 
2059e843fc46SMark Brown 	if (best_val != INT_MAX)
2060e843fc46SMark Brown 		return selector;
2061e843fc46SMark Brown 	else
2062e843fc46SMark Brown 		return -EINVAL;
2063e843fc46SMark Brown }
2064e843fc46SMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
2065e843fc46SMark Brown 
2066bca7bbffSMark Brown /**
2067bca7bbffSMark Brown  * regulator_map_voltage_linear - map_voltage() for simple linear mappings
2068bca7bbffSMark Brown  *
2069bca7bbffSMark Brown  * @rdev: Regulator to operate on
2070bca7bbffSMark Brown  * @min_uV: Lower bound for voltage
2071bca7bbffSMark Brown  * @max_uV: Upper bound for voltage
2072bca7bbffSMark Brown  *
2073bca7bbffSMark Brown  * Drivers providing min_uV and uV_step in their regulator_desc can
2074bca7bbffSMark Brown  * use this as their map_voltage() operation.
2075bca7bbffSMark Brown  */
2076bca7bbffSMark Brown int regulator_map_voltage_linear(struct regulator_dev *rdev,
2077bca7bbffSMark Brown 				 int min_uV, int max_uV)
2078bca7bbffSMark Brown {
2079bca7bbffSMark Brown 	int ret, voltage;
2080bca7bbffSMark Brown 
20815a6881e8SAxel Lin 	/* Allow uV_step to be 0 for fixed voltage */
20825a6881e8SAxel Lin 	if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
20835a6881e8SAxel Lin 		if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
20845a6881e8SAxel Lin 			return 0;
20855a6881e8SAxel Lin 		else
20865a6881e8SAxel Lin 			return -EINVAL;
20875a6881e8SAxel Lin 	}
20885a6881e8SAxel Lin 
2089bca7bbffSMark Brown 	if (!rdev->desc->uV_step) {
2090bca7bbffSMark Brown 		BUG_ON(!rdev->desc->uV_step);
2091bca7bbffSMark Brown 		return -EINVAL;
2092bca7bbffSMark Brown 	}
2093bca7bbffSMark Brown 
2094ccfcb1c3SAxel Lin 	ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
2095bca7bbffSMark Brown 	if (ret < 0)
2096bca7bbffSMark Brown 		return ret;
2097bca7bbffSMark Brown 
2098bca7bbffSMark Brown 	/* Map back into a voltage to verify we're still in bounds */
2099bca7bbffSMark Brown 	voltage = rdev->desc->ops->list_voltage(rdev, ret);
2100bca7bbffSMark Brown 	if (voltage < min_uV || voltage > max_uV)
2101bca7bbffSMark Brown 		return -EINVAL;
2102bca7bbffSMark Brown 
2103bca7bbffSMark Brown 	return ret;
2104bca7bbffSMark Brown }
2105bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
2106bca7bbffSMark Brown 
2107a7a1ad90SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev,
2108a7a1ad90SMark Brown 				     int min_uV, int max_uV)
2109a7a1ad90SMark Brown {
2110a7a1ad90SMark Brown 	int ret;
211175790251SMark Brown 	int delay = 0;
2112e843fc46SMark Brown 	int best_val;
211375790251SMark Brown 	unsigned int selector;
2114eba41a5eSAxel Lin 	int old_selector = -1;
211575790251SMark Brown 
211675790251SMark Brown 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
211775790251SMark Brown 
211875790251SMark Brown 	min_uV += rdev->constraints->uV_offset;
211975790251SMark Brown 	max_uV += rdev->constraints->uV_offset;
212075790251SMark Brown 
212177af1b26SLinus Walleij 	/*
212277af1b26SLinus Walleij 	 * If we can't obtain the old selector there is not enough
212377af1b26SLinus Walleij 	 * info to call set_voltage_time_sel().
212477af1b26SLinus Walleij 	 */
21258b7485efSAxel Lin 	if (_regulator_is_enabled(rdev) &&
21268b7485efSAxel Lin 	    rdev->desc->ops->set_voltage_time_sel &&
212777af1b26SLinus Walleij 	    rdev->desc->ops->get_voltage_sel) {
2128eba41a5eSAxel Lin 		old_selector = rdev->desc->ops->get_voltage_sel(rdev);
2129eba41a5eSAxel Lin 		if (old_selector < 0)
2130eba41a5eSAxel Lin 			return old_selector;
2131eba41a5eSAxel Lin 	}
213277af1b26SLinus Walleij 
213375790251SMark Brown 	if (rdev->desc->ops->set_voltage) {
213475790251SMark Brown 		ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
213575790251SMark Brown 						   &selector);
2136e8eef82bSMark Brown 	} else if (rdev->desc->ops->set_voltage_sel) {
2137e843fc46SMark Brown 		if (rdev->desc->ops->map_voltage)
2138e843fc46SMark Brown 			ret = rdev->desc->ops->map_voltage(rdev, min_uV,
2139e843fc46SMark Brown 							   max_uV);
214007351233SAxel Lin 		else
2141e843fc46SMark Brown 			ret = regulator_map_voltage_iterate(rdev, min_uV,
2142e843fc46SMark Brown 							    max_uV);
2143e843fc46SMark Brown 
2144e843fc46SMark Brown 		if (ret >= 0) {
2145e843fc46SMark Brown 			selector = ret;
2146e843fc46SMark Brown 			ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
2147e843fc46SMark Brown 		}
2148e8eef82bSMark Brown 	} else {
2149e8eef82bSMark Brown 		ret = -EINVAL;
2150e8eef82bSMark Brown 	}
2151e8eef82bSMark Brown 
2152e843fc46SMark Brown 	if (rdev->desc->ops->list_voltage)
2153e843fc46SMark Brown 		best_val = rdev->desc->ops->list_voltage(rdev, selector);
2154e843fc46SMark Brown 	else
2155e843fc46SMark Brown 		best_val = -1;
2156e843fc46SMark Brown 
2157eba41a5eSAxel Lin 	/* Call set_voltage_time_sel if successfully obtained old_selector */
21588b7485efSAxel Lin 	if (_regulator_is_enabled(rdev) && ret == 0 && old_selector >= 0 &&
2159eba41a5eSAxel Lin 	    rdev->desc->ops->set_voltage_time_sel) {
2160eba41a5eSAxel Lin 
2161eba41a5eSAxel Lin 		delay = rdev->desc->ops->set_voltage_time_sel(rdev,
2162eba41a5eSAxel Lin 						old_selector, selector);
2163eba41a5eSAxel Lin 		if (delay < 0) {
2164eba41a5eSAxel Lin 			rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n",
2165eba41a5eSAxel Lin 				  delay);
2166eba41a5eSAxel Lin 			delay = 0;
2167e8eef82bSMark Brown 		}
216875790251SMark Brown 	}
216975790251SMark Brown 
217077af1b26SLinus Walleij 	/* Insert any necessary delays */
217177af1b26SLinus Walleij 	if (delay >= 1000) {
217277af1b26SLinus Walleij 		mdelay(delay / 1000);
217377af1b26SLinus Walleij 		udelay(delay % 1000);
217477af1b26SLinus Walleij 	} else if (delay) {
217577af1b26SLinus Walleij 		udelay(delay);
217677af1b26SLinus Walleij 	}
217777af1b26SLinus Walleij 
2178ded06a52SMark Brown 	if (ret == 0)
2179ded06a52SMark Brown 		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
2180ded06a52SMark Brown 				     NULL);
2181ded06a52SMark Brown 
2182eba41a5eSAxel Lin 	trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
218375790251SMark Brown 
218475790251SMark Brown 	return ret;
218575790251SMark Brown }
218675790251SMark Brown 
2187a7a1ad90SMark Brown /**
2188414c70cbSLiam Girdwood  * regulator_set_voltage - set regulator output voltage
2189414c70cbSLiam Girdwood  * @regulator: regulator source
2190414c70cbSLiam Girdwood  * @min_uV: Minimum required voltage in uV
2191414c70cbSLiam Girdwood  * @max_uV: Maximum acceptable voltage in uV
2192414c70cbSLiam Girdwood  *
2193414c70cbSLiam Girdwood  * Sets a voltage regulator to the desired output voltage. This can be set
2194414c70cbSLiam Girdwood  * during any regulator state. IOW, regulator can be disabled or enabled.
2195414c70cbSLiam Girdwood  *
2196414c70cbSLiam Girdwood  * If the regulator is enabled then the voltage will change to the new value
2197414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
2198414c70cbSLiam Girdwood  * output at the new voltage when enabled.
2199414c70cbSLiam Girdwood  *
2200414c70cbSLiam Girdwood  * NOTE: If the regulator is shared between several devices then the lowest
2201414c70cbSLiam Girdwood  * request voltage that meets the system constraints will be used.
220269279fb9SMark Brown  * Regulator system constraints must be set for this regulator before
2203414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
2204414c70cbSLiam Girdwood  */
2205414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
2206414c70cbSLiam Girdwood {
2207414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
220895a3c23aSMark Brown 	int ret = 0;
2209414c70cbSLiam Girdwood 
2210414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2211414c70cbSLiam Girdwood 
221295a3c23aSMark Brown 	/* If we're setting the same range as last time the change
221395a3c23aSMark Brown 	 * should be a noop (some cpufreq implementations use the same
221495a3c23aSMark Brown 	 * voltage for multiple frequencies, for example).
221595a3c23aSMark Brown 	 */
221695a3c23aSMark Brown 	if (regulator->min_uV == min_uV && regulator->max_uV == max_uV)
221795a3c23aSMark Brown 		goto out;
221895a3c23aSMark Brown 
2219414c70cbSLiam Girdwood 	/* sanity check */
2220e8eef82bSMark Brown 	if (!rdev->desc->ops->set_voltage &&
2221e8eef82bSMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
2222414c70cbSLiam Girdwood 		ret = -EINVAL;
2223414c70cbSLiam Girdwood 		goto out;
2224414c70cbSLiam Girdwood 	}
2225414c70cbSLiam Girdwood 
2226414c70cbSLiam Girdwood 	/* constraints check */
2227414c70cbSLiam Girdwood 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
2228414c70cbSLiam Girdwood 	if (ret < 0)
2229414c70cbSLiam Girdwood 		goto out;
2230414c70cbSLiam Girdwood 	regulator->min_uV = min_uV;
2231414c70cbSLiam Girdwood 	regulator->max_uV = max_uV;
22323a93f2a9SMark Brown 
223305fda3b1SThomas Petazzoni 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
223405fda3b1SThomas Petazzoni 	if (ret < 0)
223505fda3b1SThomas Petazzoni 		goto out;
223605fda3b1SThomas Petazzoni 
223775790251SMark Brown 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
223802fa3ec0SMark Brown 
2239414c70cbSLiam Girdwood out:
2240414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2241414c70cbSLiam Girdwood 	return ret;
2242414c70cbSLiam Girdwood }
2243414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage);
2244414c70cbSLiam Girdwood 
2245606a2562SMark Brown /**
224688cd222bSLinus Walleij  * regulator_set_voltage_time - get raise/fall time
224788cd222bSLinus Walleij  * @regulator: regulator source
224888cd222bSLinus Walleij  * @old_uV: starting voltage in microvolts
224988cd222bSLinus Walleij  * @new_uV: target voltage in microvolts
225088cd222bSLinus Walleij  *
225188cd222bSLinus Walleij  * Provided with the starting and ending voltage, this function attempts to
225288cd222bSLinus Walleij  * calculate the time in microseconds required to rise or fall to this new
225388cd222bSLinus Walleij  * voltage.
225488cd222bSLinus Walleij  */
225588cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator,
225688cd222bSLinus Walleij 			       int old_uV, int new_uV)
225788cd222bSLinus Walleij {
225888cd222bSLinus Walleij 	struct regulator_dev	*rdev = regulator->rdev;
225988cd222bSLinus Walleij 	struct regulator_ops	*ops = rdev->desc->ops;
226088cd222bSLinus Walleij 	int old_sel = -1;
226188cd222bSLinus Walleij 	int new_sel = -1;
226288cd222bSLinus Walleij 	int voltage;
226388cd222bSLinus Walleij 	int i;
226488cd222bSLinus Walleij 
226588cd222bSLinus Walleij 	/* Currently requires operations to do this */
226688cd222bSLinus Walleij 	if (!ops->list_voltage || !ops->set_voltage_time_sel
226788cd222bSLinus Walleij 	    || !rdev->desc->n_voltages)
226888cd222bSLinus Walleij 		return -EINVAL;
226988cd222bSLinus Walleij 
227088cd222bSLinus Walleij 	for (i = 0; i < rdev->desc->n_voltages; i++) {
227188cd222bSLinus Walleij 		/* We only look for exact voltage matches here */
227288cd222bSLinus Walleij 		voltage = regulator_list_voltage(regulator, i);
227388cd222bSLinus Walleij 		if (voltage < 0)
227488cd222bSLinus Walleij 			return -EINVAL;
227588cd222bSLinus Walleij 		if (voltage == 0)
227688cd222bSLinus Walleij 			continue;
227788cd222bSLinus Walleij 		if (voltage == old_uV)
227888cd222bSLinus Walleij 			old_sel = i;
227988cd222bSLinus Walleij 		if (voltage == new_uV)
228088cd222bSLinus Walleij 			new_sel = i;
228188cd222bSLinus Walleij 	}
228288cd222bSLinus Walleij 
228388cd222bSLinus Walleij 	if (old_sel < 0 || new_sel < 0)
228488cd222bSLinus Walleij 		return -EINVAL;
228588cd222bSLinus Walleij 
228688cd222bSLinus Walleij 	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
228788cd222bSLinus Walleij }
228888cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
228988cd222bSLinus Walleij 
229088cd222bSLinus Walleij /**
229198a175b6SYadwinder Singh Brar  *regulator_set_voltage_time_sel - get raise/fall time
229298a175b6SYadwinder Singh Brar  * @regulator: regulator source
229398a175b6SYadwinder Singh Brar  * @old_selector: selector for starting voltage
229498a175b6SYadwinder Singh Brar  * @new_selector: selector for target voltage
229598a175b6SYadwinder Singh Brar  *
229698a175b6SYadwinder Singh Brar  * Provided with the starting and target voltage selectors, this function
229798a175b6SYadwinder Singh Brar  * returns time in microseconds required to rise or fall to this new voltage
229898a175b6SYadwinder Singh Brar  *
2299398715abSAxel Lin  * Drivers providing uV_step or volt_table in their regulator_desc and
2300398715abSAxel Lin  * ramp_delay in regulation_constraints can use this as their
2301398715abSAxel Lin  * set_voltage_time_sel() operation.
230298a175b6SYadwinder Singh Brar  */
230398a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
230498a175b6SYadwinder Singh Brar 				   unsigned int old_selector,
230598a175b6SYadwinder Singh Brar 				   unsigned int new_selector)
230698a175b6SYadwinder Singh Brar {
2307398715abSAxel Lin 	unsigned int ramp_delay = 0;
2308398715abSAxel Lin 
23096f0b2c69SYadwinder Singh Brar 	if (rdev->constraints->ramp_delay)
2310398715abSAxel Lin 		ramp_delay = rdev->constraints->ramp_delay;
2311398715abSAxel Lin 	else if (rdev->desc->ramp_delay)
2312398715abSAxel Lin 		ramp_delay = rdev->desc->ramp_delay;
2313398715abSAxel Lin 
2314398715abSAxel Lin 	if (ramp_delay == 0) {
23156f0b2c69SYadwinder Singh Brar 		rdev_warn(rdev, "ramp_delay not set\n");
2316398715abSAxel Lin 		return 0;
23176f0b2c69SYadwinder Singh Brar 	}
2318398715abSAxel Lin 
2319398715abSAxel Lin 	if (rdev->desc->uV_step) {
2320398715abSAxel Lin 		return DIV_ROUND_UP(rdev->desc->uV_step *
2321398715abSAxel Lin 				    abs(new_selector - old_selector),
2322398715abSAxel Lin 				    ramp_delay * 1000);
2323398715abSAxel Lin 	} else if (rdev->desc->volt_table) {
2324398715abSAxel Lin 		return DIV_ROUND_UP(abs(rdev->desc->volt_table[new_selector] -
2325398715abSAxel Lin 					rdev->desc->volt_table[old_selector]),
2326398715abSAxel Lin 				    ramp_delay * 1000);
2327398715abSAxel Lin 	} else {
2328398715abSAxel Lin 		rdev_warn(rdev, "Unsupported voltage mapping settings\n");
2329398715abSAxel Lin 	}
2330398715abSAxel Lin 
233198a175b6SYadwinder Singh Brar 	return 0;
233298a175b6SYadwinder Singh Brar }
233398a175b6SYadwinder Singh Brar 
233498a175b6SYadwinder Singh Brar /**
2335606a2562SMark Brown  * regulator_sync_voltage - re-apply last regulator output voltage
2336606a2562SMark Brown  * @regulator: regulator source
2337606a2562SMark Brown  *
2338606a2562SMark Brown  * Re-apply the last configured voltage.  This is intended to be used
2339606a2562SMark Brown  * where some external control source the consumer is cooperating with
2340606a2562SMark Brown  * has caused the configured voltage to change.
2341606a2562SMark Brown  */
2342606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator)
2343606a2562SMark Brown {
2344606a2562SMark Brown 	struct regulator_dev *rdev = regulator->rdev;
2345606a2562SMark Brown 	int ret, min_uV, max_uV;
2346606a2562SMark Brown 
2347606a2562SMark Brown 	mutex_lock(&rdev->mutex);
2348606a2562SMark Brown 
2349606a2562SMark Brown 	if (!rdev->desc->ops->set_voltage &&
2350606a2562SMark Brown 	    !rdev->desc->ops->set_voltage_sel) {
2351606a2562SMark Brown 		ret = -EINVAL;
2352606a2562SMark Brown 		goto out;
2353606a2562SMark Brown 	}
2354606a2562SMark Brown 
2355606a2562SMark Brown 	/* This is only going to work if we've had a voltage configured. */
2356606a2562SMark Brown 	if (!regulator->min_uV && !regulator->max_uV) {
2357606a2562SMark Brown 		ret = -EINVAL;
2358606a2562SMark Brown 		goto out;
2359606a2562SMark Brown 	}
2360606a2562SMark Brown 
2361606a2562SMark Brown 	min_uV = regulator->min_uV;
2362606a2562SMark Brown 	max_uV = regulator->max_uV;
2363606a2562SMark Brown 
2364606a2562SMark Brown 	/* This should be a paranoia check... */
2365606a2562SMark Brown 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
2366606a2562SMark Brown 	if (ret < 0)
2367606a2562SMark Brown 		goto out;
2368606a2562SMark Brown 
2369606a2562SMark Brown 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
2370606a2562SMark Brown 	if (ret < 0)
2371606a2562SMark Brown 		goto out;
2372606a2562SMark Brown 
2373606a2562SMark Brown 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
2374606a2562SMark Brown 
2375606a2562SMark Brown out:
2376606a2562SMark Brown 	mutex_unlock(&rdev->mutex);
2377606a2562SMark Brown 	return ret;
2378606a2562SMark Brown }
2379606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage);
2380606a2562SMark Brown 
2381414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev)
2382414c70cbSLiam Girdwood {
2383bf5892a8SMark Brown 	int sel, ret;
2384476c2d83SMark Brown 
2385476c2d83SMark Brown 	if (rdev->desc->ops->get_voltage_sel) {
2386476c2d83SMark Brown 		sel = rdev->desc->ops->get_voltage_sel(rdev);
2387476c2d83SMark Brown 		if (sel < 0)
2388476c2d83SMark Brown 			return sel;
2389bf5892a8SMark Brown 		ret = rdev->desc->ops->list_voltage(rdev, sel);
2390cb220d16SAxel Lin 	} else if (rdev->desc->ops->get_voltage) {
2391bf5892a8SMark Brown 		ret = rdev->desc->ops->get_voltage(rdev);
2392cb220d16SAxel Lin 	} else {
2393414c70cbSLiam Girdwood 		return -EINVAL;
2394cb220d16SAxel Lin 	}
2395bf5892a8SMark Brown 
2396cb220d16SAxel Lin 	if (ret < 0)
2397cb220d16SAxel Lin 		return ret;
2398bf5892a8SMark Brown 	return ret - rdev->constraints->uV_offset;
2399414c70cbSLiam Girdwood }
2400414c70cbSLiam Girdwood 
2401414c70cbSLiam Girdwood /**
2402414c70cbSLiam Girdwood  * regulator_get_voltage - get regulator output voltage
2403414c70cbSLiam Girdwood  * @regulator: regulator source
2404414c70cbSLiam Girdwood  *
2405414c70cbSLiam Girdwood  * This returns the current regulator voltage in uV.
2406414c70cbSLiam Girdwood  *
2407414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the voltage value. This
2408414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
2409414c70cbSLiam Girdwood  */
2410414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator)
2411414c70cbSLiam Girdwood {
2412414c70cbSLiam Girdwood 	int ret;
2413414c70cbSLiam Girdwood 
2414414c70cbSLiam Girdwood 	mutex_lock(&regulator->rdev->mutex);
2415414c70cbSLiam Girdwood 
2416414c70cbSLiam Girdwood 	ret = _regulator_get_voltage(regulator->rdev);
2417414c70cbSLiam Girdwood 
2418414c70cbSLiam Girdwood 	mutex_unlock(&regulator->rdev->mutex);
2419414c70cbSLiam Girdwood 
2420414c70cbSLiam Girdwood 	return ret;
2421414c70cbSLiam Girdwood }
2422414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage);
2423414c70cbSLiam Girdwood 
2424414c70cbSLiam Girdwood /**
2425414c70cbSLiam Girdwood  * regulator_set_current_limit - set regulator output current limit
2426414c70cbSLiam Girdwood  * @regulator: regulator source
2427414c70cbSLiam Girdwood  * @min_uA: Minimuum supported current in uA
2428414c70cbSLiam Girdwood  * @max_uA: Maximum supported current in uA
2429414c70cbSLiam Girdwood  *
2430414c70cbSLiam Girdwood  * Sets current sink to the desired output current. This can be set during
2431414c70cbSLiam Girdwood  * any regulator state. IOW, regulator can be disabled or enabled.
2432414c70cbSLiam Girdwood  *
2433414c70cbSLiam Girdwood  * If the regulator is enabled then the current will change to the new value
2434414c70cbSLiam Girdwood  * immediately otherwise if the regulator is disabled the regulator will
2435414c70cbSLiam Girdwood  * output at the new current when enabled.
2436414c70cbSLiam Girdwood  *
2437414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
2438414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
2439414c70cbSLiam Girdwood  */
2440414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator,
2441414c70cbSLiam Girdwood 			       int min_uA, int max_uA)
2442414c70cbSLiam Girdwood {
2443414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2444414c70cbSLiam Girdwood 	int ret;
2445414c70cbSLiam Girdwood 
2446414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2447414c70cbSLiam Girdwood 
2448414c70cbSLiam Girdwood 	/* sanity check */
2449414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_current_limit) {
2450414c70cbSLiam Girdwood 		ret = -EINVAL;
2451414c70cbSLiam Girdwood 		goto out;
2452414c70cbSLiam Girdwood 	}
2453414c70cbSLiam Girdwood 
2454414c70cbSLiam Girdwood 	/* constraints check */
2455414c70cbSLiam Girdwood 	ret = regulator_check_current_limit(rdev, &min_uA, &max_uA);
2456414c70cbSLiam Girdwood 	if (ret < 0)
2457414c70cbSLiam Girdwood 		goto out;
2458414c70cbSLiam Girdwood 
2459414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
2460414c70cbSLiam Girdwood out:
2461414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2462414c70cbSLiam Girdwood 	return ret;
2463414c70cbSLiam Girdwood }
2464414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit);
2465414c70cbSLiam Girdwood 
2466414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev)
2467414c70cbSLiam Girdwood {
2468414c70cbSLiam Girdwood 	int ret;
2469414c70cbSLiam Girdwood 
2470414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2471414c70cbSLiam Girdwood 
2472414c70cbSLiam Girdwood 	/* sanity check */
2473414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_current_limit) {
2474414c70cbSLiam Girdwood 		ret = -EINVAL;
2475414c70cbSLiam Girdwood 		goto out;
2476414c70cbSLiam Girdwood 	}
2477414c70cbSLiam Girdwood 
2478414c70cbSLiam Girdwood 	ret = rdev->desc->ops->get_current_limit(rdev);
2479414c70cbSLiam Girdwood out:
2480414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2481414c70cbSLiam Girdwood 	return ret;
2482414c70cbSLiam Girdwood }
2483414c70cbSLiam Girdwood 
2484414c70cbSLiam Girdwood /**
2485414c70cbSLiam Girdwood  * regulator_get_current_limit - get regulator output current
2486414c70cbSLiam Girdwood  * @regulator: regulator source
2487414c70cbSLiam Girdwood  *
2488414c70cbSLiam Girdwood  * This returns the current supplied by the specified current sink in uA.
2489414c70cbSLiam Girdwood  *
2490414c70cbSLiam Girdwood  * NOTE: If the regulator is disabled it will return the current value. This
2491414c70cbSLiam Girdwood  * function should not be used to determine regulator state.
2492414c70cbSLiam Girdwood  */
2493414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator)
2494414c70cbSLiam Girdwood {
2495414c70cbSLiam Girdwood 	return _regulator_get_current_limit(regulator->rdev);
2496414c70cbSLiam Girdwood }
2497414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit);
2498414c70cbSLiam Girdwood 
2499414c70cbSLiam Girdwood /**
2500414c70cbSLiam Girdwood  * regulator_set_mode - set regulator operating mode
2501414c70cbSLiam Girdwood  * @regulator: regulator source
2502414c70cbSLiam Girdwood  * @mode: operating mode - one of the REGULATOR_MODE constants
2503414c70cbSLiam Girdwood  *
2504414c70cbSLiam Girdwood  * Set regulator operating mode to increase regulator efficiency or improve
2505414c70cbSLiam Girdwood  * regulation performance.
2506414c70cbSLiam Girdwood  *
2507414c70cbSLiam Girdwood  * NOTE: Regulator system constraints must be set for this regulator before
2508414c70cbSLiam Girdwood  * calling this function otherwise this call will fail.
2509414c70cbSLiam Girdwood  */
2510414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode)
2511414c70cbSLiam Girdwood {
2512414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2513414c70cbSLiam Girdwood 	int ret;
2514500b4ac9SSundar R Iyer 	int regulator_curr_mode;
2515414c70cbSLiam Girdwood 
2516414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2517414c70cbSLiam Girdwood 
2518414c70cbSLiam Girdwood 	/* sanity check */
2519414c70cbSLiam Girdwood 	if (!rdev->desc->ops->set_mode) {
2520414c70cbSLiam Girdwood 		ret = -EINVAL;
2521414c70cbSLiam Girdwood 		goto out;
2522414c70cbSLiam Girdwood 	}
2523414c70cbSLiam Girdwood 
2524500b4ac9SSundar R Iyer 	/* return if the same mode is requested */
2525500b4ac9SSundar R Iyer 	if (rdev->desc->ops->get_mode) {
2526500b4ac9SSundar R Iyer 		regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
2527500b4ac9SSundar R Iyer 		if (regulator_curr_mode == mode) {
2528500b4ac9SSundar R Iyer 			ret = 0;
2529500b4ac9SSundar R Iyer 			goto out;
2530500b4ac9SSundar R Iyer 		}
2531500b4ac9SSundar R Iyer 	}
2532500b4ac9SSundar R Iyer 
2533414c70cbSLiam Girdwood 	/* constraints check */
253422c51b47SAxel Lin 	ret = regulator_mode_constrain(rdev, &mode);
2535414c70cbSLiam Girdwood 	if (ret < 0)
2536414c70cbSLiam Girdwood 		goto out;
2537414c70cbSLiam Girdwood 
2538414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
2539414c70cbSLiam Girdwood out:
2540414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2541414c70cbSLiam Girdwood 	return ret;
2542414c70cbSLiam Girdwood }
2543414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode);
2544414c70cbSLiam Girdwood 
2545414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
2546414c70cbSLiam Girdwood {
2547414c70cbSLiam Girdwood 	int ret;
2548414c70cbSLiam Girdwood 
2549414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2550414c70cbSLiam Girdwood 
2551414c70cbSLiam Girdwood 	/* sanity check */
2552414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_mode) {
2553414c70cbSLiam Girdwood 		ret = -EINVAL;
2554414c70cbSLiam Girdwood 		goto out;
2555414c70cbSLiam Girdwood 	}
2556414c70cbSLiam Girdwood 
2557414c70cbSLiam Girdwood 	ret = rdev->desc->ops->get_mode(rdev);
2558414c70cbSLiam Girdwood out:
2559414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2560414c70cbSLiam Girdwood 	return ret;
2561414c70cbSLiam Girdwood }
2562414c70cbSLiam Girdwood 
2563414c70cbSLiam Girdwood /**
2564414c70cbSLiam Girdwood  * regulator_get_mode - get regulator operating mode
2565414c70cbSLiam Girdwood  * @regulator: regulator source
2566414c70cbSLiam Girdwood  *
2567414c70cbSLiam Girdwood  * Get the current regulator operating mode.
2568414c70cbSLiam Girdwood  */
2569414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator)
2570414c70cbSLiam Girdwood {
2571414c70cbSLiam Girdwood 	return _regulator_get_mode(regulator->rdev);
2572414c70cbSLiam Girdwood }
2573414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode);
2574414c70cbSLiam Girdwood 
2575414c70cbSLiam Girdwood /**
2576414c70cbSLiam Girdwood  * regulator_set_optimum_mode - set regulator optimum operating mode
2577414c70cbSLiam Girdwood  * @regulator: regulator source
2578414c70cbSLiam Girdwood  * @uA_load: load current
2579414c70cbSLiam Girdwood  *
2580414c70cbSLiam Girdwood  * Notifies the regulator core of a new device load. This is then used by
2581414c70cbSLiam Girdwood  * DRMS (if enabled by constraints) to set the most efficient regulator
2582414c70cbSLiam Girdwood  * operating mode for the new regulator loading.
2583414c70cbSLiam Girdwood  *
2584414c70cbSLiam Girdwood  * Consumer devices notify their supply regulator of the maximum power
2585414c70cbSLiam Girdwood  * they will require (can be taken from device datasheet in the power
2586414c70cbSLiam Girdwood  * consumption tables) when they change operational status and hence power
2587414c70cbSLiam Girdwood  * state. Examples of operational state changes that can affect power
2588414c70cbSLiam Girdwood  * consumption are :-
2589414c70cbSLiam Girdwood  *
2590414c70cbSLiam Girdwood  *    o Device is opened / closed.
2591414c70cbSLiam Girdwood  *    o Device I/O is about to begin or has just finished.
2592414c70cbSLiam Girdwood  *    o Device is idling in between work.
2593414c70cbSLiam Girdwood  *
2594414c70cbSLiam Girdwood  * This information is also exported via sysfs to userspace.
2595414c70cbSLiam Girdwood  *
2596414c70cbSLiam Girdwood  * DRMS will sum the total requested load on the regulator and change
2597414c70cbSLiam Girdwood  * to the most efficient operating mode if platform constraints allow.
2598414c70cbSLiam Girdwood  *
2599414c70cbSLiam Girdwood  * Returns the new regulator mode or error.
2600414c70cbSLiam Girdwood  */
2601414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
2602414c70cbSLiam Girdwood {
2603414c70cbSLiam Girdwood 	struct regulator_dev *rdev = regulator->rdev;
2604414c70cbSLiam Girdwood 	struct regulator *consumer;
2605414c70cbSLiam Girdwood 	int ret, output_uV, input_uV, total_uA_load = 0;
2606414c70cbSLiam Girdwood 	unsigned int mode;
2607414c70cbSLiam Girdwood 
2608414c70cbSLiam Girdwood 	mutex_lock(&rdev->mutex);
2609414c70cbSLiam Girdwood 
2610a4b41483SMark Brown 	/*
2611a4b41483SMark Brown 	 * first check to see if we can set modes at all, otherwise just
2612a4b41483SMark Brown 	 * tell the consumer everything is OK.
2613a4b41483SMark Brown 	 */
2614414c70cbSLiam Girdwood 	regulator->uA_load = uA_load;
2615414c70cbSLiam Girdwood 	ret = regulator_check_drms(rdev);
2616a4b41483SMark Brown 	if (ret < 0) {
2617a4b41483SMark Brown 		ret = 0;
2618414c70cbSLiam Girdwood 		goto out;
2619a4b41483SMark Brown 	}
2620414c70cbSLiam Girdwood 
2621414c70cbSLiam Girdwood 	if (!rdev->desc->ops->get_optimum_mode)
2622414c70cbSLiam Girdwood 		goto out;
2623414c70cbSLiam Girdwood 
2624a4b41483SMark Brown 	/*
2625a4b41483SMark Brown 	 * we can actually do this so any errors are indicators of
2626a4b41483SMark Brown 	 * potential real failure.
2627a4b41483SMark Brown 	 */
2628a4b41483SMark Brown 	ret = -EINVAL;
2629a4b41483SMark Brown 
2630854ccbaeSAxel Lin 	if (!rdev->desc->ops->set_mode)
2631854ccbaeSAxel Lin 		goto out;
2632854ccbaeSAxel Lin 
2633414c70cbSLiam Girdwood 	/* get output voltage */
26341bf5a1f8SMark Brown 	output_uV = _regulator_get_voltage(rdev);
2635414c70cbSLiam Girdwood 	if (output_uV <= 0) {
26365da84fd9SJoe Perches 		rdev_err(rdev, "invalid output voltage found\n");
2637414c70cbSLiam Girdwood 		goto out;
2638414c70cbSLiam Girdwood 	}
2639414c70cbSLiam Girdwood 
2640414c70cbSLiam Girdwood 	/* get input voltage */
26411bf5a1f8SMark Brown 	input_uV = 0;
26421bf5a1f8SMark Brown 	if (rdev->supply)
26433801b86aSMark Brown 		input_uV = regulator_get_voltage(rdev->supply);
26441bf5a1f8SMark Brown 	if (input_uV <= 0)
2645414c70cbSLiam Girdwood 		input_uV = rdev->constraints->input_uV;
2646414c70cbSLiam Girdwood 	if (input_uV <= 0) {
26475da84fd9SJoe Perches 		rdev_err(rdev, "invalid input voltage found\n");
2648414c70cbSLiam Girdwood 		goto out;
2649414c70cbSLiam Girdwood 	}
2650414c70cbSLiam Girdwood 
2651414c70cbSLiam Girdwood 	/* calc total requested load for this regulator */
2652414c70cbSLiam Girdwood 	list_for_each_entry(consumer, &rdev->consumer_list, list)
2653414c70cbSLiam Girdwood 		total_uA_load += consumer->uA_load;
2654414c70cbSLiam Girdwood 
2655414c70cbSLiam Girdwood 	mode = rdev->desc->ops->get_optimum_mode(rdev,
2656414c70cbSLiam Girdwood 						 input_uV, output_uV,
2657414c70cbSLiam Girdwood 						 total_uA_load);
26582c608234SMark Brown 	ret = regulator_mode_constrain(rdev, &mode);
2659e573520bSDavid Brownell 	if (ret < 0) {
26605da84fd9SJoe Perches 		rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n",
2661414c70cbSLiam Girdwood 			 total_uA_load, input_uV, output_uV);
2662414c70cbSLiam Girdwood 		goto out;
2663414c70cbSLiam Girdwood 	}
2664414c70cbSLiam Girdwood 
2665414c70cbSLiam Girdwood 	ret = rdev->desc->ops->set_mode(rdev, mode);
2666e573520bSDavid Brownell 	if (ret < 0) {
26675da84fd9SJoe Perches 		rdev_err(rdev, "failed to set optimum mode %x\n", mode);
2668414c70cbSLiam Girdwood 		goto out;
2669414c70cbSLiam Girdwood 	}
2670414c70cbSLiam Girdwood 	ret = mode;
2671414c70cbSLiam Girdwood out:
2672414c70cbSLiam Girdwood 	mutex_unlock(&rdev->mutex);
2673414c70cbSLiam Girdwood 	return ret;
2674414c70cbSLiam Girdwood }
2675414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
2676414c70cbSLiam Girdwood 
2677414c70cbSLiam Girdwood /**
2678414c70cbSLiam Girdwood  * regulator_register_notifier - register regulator event notifier
2679414c70cbSLiam Girdwood  * @regulator: regulator source
268069279fb9SMark Brown  * @nb: notifier block
2681414c70cbSLiam Girdwood  *
2682414c70cbSLiam Girdwood  * Register notifier block to receive regulator events.
2683414c70cbSLiam Girdwood  */
2684414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator,
2685414c70cbSLiam Girdwood 			      struct notifier_block *nb)
2686414c70cbSLiam Girdwood {
2687414c70cbSLiam Girdwood 	return blocking_notifier_chain_register(&regulator->rdev->notifier,
2688414c70cbSLiam Girdwood 						nb);
2689414c70cbSLiam Girdwood }
2690414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier);
2691414c70cbSLiam Girdwood 
2692414c70cbSLiam Girdwood /**
2693414c70cbSLiam Girdwood  * regulator_unregister_notifier - unregister regulator event notifier
2694414c70cbSLiam Girdwood  * @regulator: regulator source
269569279fb9SMark Brown  * @nb: notifier block
2696414c70cbSLiam Girdwood  *
2697414c70cbSLiam Girdwood  * Unregister regulator event notifier block.
2698414c70cbSLiam Girdwood  */
2699414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator,
2700414c70cbSLiam Girdwood 				struct notifier_block *nb)
2701414c70cbSLiam Girdwood {
2702414c70cbSLiam Girdwood 	return blocking_notifier_chain_unregister(&regulator->rdev->notifier,
2703414c70cbSLiam Girdwood 						  nb);
2704414c70cbSLiam Girdwood }
2705414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
2706414c70cbSLiam Girdwood 
2707b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers.
2708b136fb44SJonathan Cameron  * Note mutex must be held by caller.
2709b136fb44SJonathan Cameron  */
2710414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev,
2711414c70cbSLiam Girdwood 				  unsigned long event, void *data)
2712414c70cbSLiam Girdwood {
2713414c70cbSLiam Girdwood 	/* call rdev chain first */
2714414c70cbSLiam Girdwood 	blocking_notifier_call_chain(&rdev->notifier, event, NULL);
2715414c70cbSLiam Girdwood }
2716414c70cbSLiam Girdwood 
2717414c70cbSLiam Girdwood /**
2718414c70cbSLiam Girdwood  * regulator_bulk_get - get multiple regulator consumers
2719414c70cbSLiam Girdwood  *
2720414c70cbSLiam Girdwood  * @dev:           Device to supply
2721414c70cbSLiam Girdwood  * @num_consumers: Number of consumers to register
2722414c70cbSLiam Girdwood  * @consumers:     Configuration of consumers; clients are stored here.
2723414c70cbSLiam Girdwood  *
2724414c70cbSLiam Girdwood  * @return 0 on success, an errno on failure.
2725414c70cbSLiam Girdwood  *
2726414c70cbSLiam Girdwood  * This helper function allows drivers to get several regulator
2727414c70cbSLiam Girdwood  * consumers in one operation.  If any of the regulators cannot be
2728414c70cbSLiam Girdwood  * acquired then any regulators that were allocated will be freed
2729414c70cbSLiam Girdwood  * before returning to the caller.
2730414c70cbSLiam Girdwood  */
2731414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers,
2732414c70cbSLiam Girdwood 		       struct regulator_bulk_data *consumers)
2733414c70cbSLiam Girdwood {
2734414c70cbSLiam Girdwood 	int i;
2735414c70cbSLiam Girdwood 	int ret;
2736414c70cbSLiam Girdwood 
2737414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++)
2738414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
2739414c70cbSLiam Girdwood 
2740414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2741414c70cbSLiam Girdwood 		consumers[i].consumer = regulator_get(dev,
2742414c70cbSLiam Girdwood 						      consumers[i].supply);
2743414c70cbSLiam Girdwood 		if (IS_ERR(consumers[i].consumer)) {
2744414c70cbSLiam Girdwood 			ret = PTR_ERR(consumers[i].consumer);
27455b307627SMark Brown 			dev_err(dev, "Failed to get supply '%s': %d\n",
27465b307627SMark Brown 				consumers[i].supply, ret);
2747414c70cbSLiam Girdwood 			consumers[i].consumer = NULL;
2748414c70cbSLiam Girdwood 			goto err;
2749414c70cbSLiam Girdwood 		}
2750414c70cbSLiam Girdwood 	}
2751414c70cbSLiam Girdwood 
2752414c70cbSLiam Girdwood 	return 0;
2753414c70cbSLiam Girdwood 
2754414c70cbSLiam Girdwood err:
2755b29c7690SAxel Lin 	while (--i >= 0)
2756414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
2757414c70cbSLiam Girdwood 
2758414c70cbSLiam Girdwood 	return ret;
2759414c70cbSLiam Girdwood }
2760414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get);
2761414c70cbSLiam Girdwood 
2762e6e74030SMark Brown /**
2763e6e74030SMark Brown  * devm_regulator_bulk_get - managed get multiple regulator consumers
2764e6e74030SMark Brown  *
2765e6e74030SMark Brown  * @dev:           Device to supply
2766e6e74030SMark Brown  * @num_consumers: Number of consumers to register
2767e6e74030SMark Brown  * @consumers:     Configuration of consumers; clients are stored here.
2768e6e74030SMark Brown  *
2769e6e74030SMark Brown  * @return 0 on success, an errno on failure.
2770e6e74030SMark Brown  *
2771e6e74030SMark Brown  * This helper function allows drivers to get several regulator
2772e6e74030SMark Brown  * consumers in one operation with management, the regulators will
2773e6e74030SMark Brown  * automatically be freed when the device is unbound.  If any of the
2774e6e74030SMark Brown  * regulators cannot be acquired then any regulators that were
2775e6e74030SMark Brown  * allocated will be freed before returning to the caller.
2776e6e74030SMark Brown  */
2777e6e74030SMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers,
2778e6e74030SMark Brown 			    struct regulator_bulk_data *consumers)
2779e6e74030SMark Brown {
2780e6e74030SMark Brown 	int i;
2781e6e74030SMark Brown 	int ret;
2782e6e74030SMark Brown 
2783e6e74030SMark Brown 	for (i = 0; i < num_consumers; i++)
2784e6e74030SMark Brown 		consumers[i].consumer = NULL;
2785e6e74030SMark Brown 
2786e6e74030SMark Brown 	for (i = 0; i < num_consumers; i++) {
2787e6e74030SMark Brown 		consumers[i].consumer = devm_regulator_get(dev,
2788e6e74030SMark Brown 							   consumers[i].supply);
2789e6e74030SMark Brown 		if (IS_ERR(consumers[i].consumer)) {
2790e6e74030SMark Brown 			ret = PTR_ERR(consumers[i].consumer);
2791e6e74030SMark Brown 			dev_err(dev, "Failed to get supply '%s': %d\n",
2792e6e74030SMark Brown 				consumers[i].supply, ret);
2793e6e74030SMark Brown 			consumers[i].consumer = NULL;
2794e6e74030SMark Brown 			goto err;
2795e6e74030SMark Brown 		}
2796e6e74030SMark Brown 	}
2797e6e74030SMark Brown 
2798e6e74030SMark Brown 	return 0;
2799e6e74030SMark Brown 
2800e6e74030SMark Brown err:
2801e6e74030SMark Brown 	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
2802e6e74030SMark Brown 		devm_regulator_put(consumers[i].consumer);
2803e6e74030SMark Brown 
2804e6e74030SMark Brown 	return ret;
2805e6e74030SMark Brown }
2806e6e74030SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
2807e6e74030SMark Brown 
2808f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
2809f21e0e81SMark Brown {
2810f21e0e81SMark Brown 	struct regulator_bulk_data *bulk = data;
2811f21e0e81SMark Brown 
2812f21e0e81SMark Brown 	bulk->ret = regulator_enable(bulk->consumer);
2813f21e0e81SMark Brown }
2814f21e0e81SMark Brown 
2815414c70cbSLiam Girdwood /**
2816414c70cbSLiam Girdwood  * regulator_bulk_enable - enable multiple regulator consumers
2817414c70cbSLiam Girdwood  *
2818414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2819414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2820414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
2821414c70cbSLiam Girdwood  *
2822414c70cbSLiam Girdwood  * This convenience API allows consumers to enable multiple regulator
2823414c70cbSLiam Girdwood  * clients in a single API call.  If any consumers cannot be enabled
2824414c70cbSLiam Girdwood  * then any others that were enabled will be disabled again prior to
2825414c70cbSLiam Girdwood  * return.
2826414c70cbSLiam Girdwood  */
2827414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers,
2828414c70cbSLiam Girdwood 			  struct regulator_bulk_data *consumers)
2829414c70cbSLiam Girdwood {
2830f21e0e81SMark Brown 	LIST_HEAD(async_domain);
2831414c70cbSLiam Girdwood 	int i;
2832f21e0e81SMark Brown 	int ret = 0;
2833414c70cbSLiam Girdwood 
28346492bc1bSMark Brown 	for (i = 0; i < num_consumers; i++) {
28356492bc1bSMark Brown 		if (consumers[i].consumer->always_on)
28366492bc1bSMark Brown 			consumers[i].ret = 0;
28376492bc1bSMark Brown 		else
2838f21e0e81SMark Brown 			async_schedule_domain(regulator_bulk_enable_async,
2839f21e0e81SMark Brown 					      &consumers[i], &async_domain);
28406492bc1bSMark Brown 	}
2841f21e0e81SMark Brown 
2842f21e0e81SMark Brown 	async_synchronize_full_domain(&async_domain);
2843f21e0e81SMark Brown 
2844f21e0e81SMark Brown 	/* If any consumer failed we need to unwind any that succeeded */
2845414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2846f21e0e81SMark Brown 		if (consumers[i].ret != 0) {
2847f21e0e81SMark Brown 			ret = consumers[i].ret;
2848414c70cbSLiam Girdwood 			goto err;
2849414c70cbSLiam Girdwood 		}
2850f21e0e81SMark Brown 	}
2851414c70cbSLiam Girdwood 
2852414c70cbSLiam Girdwood 	return 0;
2853414c70cbSLiam Girdwood 
2854414c70cbSLiam Girdwood err:
2855b29c7690SAxel Lin 	pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
2856b29c7690SAxel Lin 	while (--i >= 0)
2857414c70cbSLiam Girdwood 		regulator_disable(consumers[i].consumer);
2858414c70cbSLiam Girdwood 
2859414c70cbSLiam Girdwood 	return ret;
2860414c70cbSLiam Girdwood }
2861414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable);
2862414c70cbSLiam Girdwood 
2863414c70cbSLiam Girdwood /**
2864414c70cbSLiam Girdwood  * regulator_bulk_disable - disable multiple regulator consumers
2865414c70cbSLiam Girdwood  *
2866414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2867414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2868414c70cbSLiam Girdwood  * @return         0 on success, an errno on failure
2869414c70cbSLiam Girdwood  *
2870414c70cbSLiam Girdwood  * This convenience API allows consumers to disable multiple regulator
287149e22632SSylwester Nawrocki  * clients in a single API call.  If any consumers cannot be disabled
287249e22632SSylwester Nawrocki  * then any others that were disabled will be enabled again prior to
2873414c70cbSLiam Girdwood  * return.
2874414c70cbSLiam Girdwood  */
2875414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers,
2876414c70cbSLiam Girdwood 			   struct regulator_bulk_data *consumers)
2877414c70cbSLiam Girdwood {
2878414c70cbSLiam Girdwood 	int i;
287901e86f49SMark Brown 	int ret, r;
2880414c70cbSLiam Girdwood 
288149e22632SSylwester Nawrocki 	for (i = num_consumers - 1; i >= 0; --i) {
2882414c70cbSLiam Girdwood 		ret = regulator_disable(consumers[i].consumer);
2883414c70cbSLiam Girdwood 		if (ret != 0)
2884414c70cbSLiam Girdwood 			goto err;
2885414c70cbSLiam Girdwood 	}
2886414c70cbSLiam Girdwood 
2887414c70cbSLiam Girdwood 	return 0;
2888414c70cbSLiam Girdwood 
2889414c70cbSLiam Girdwood err:
28905da84fd9SJoe Perches 	pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
289101e86f49SMark Brown 	for (++i; i < num_consumers; ++i) {
289201e86f49SMark Brown 		r = regulator_enable(consumers[i].consumer);
289301e86f49SMark Brown 		if (r != 0)
289401e86f49SMark Brown 			pr_err("Failed to reename %s: %d\n",
289501e86f49SMark Brown 			       consumers[i].supply, r);
289601e86f49SMark Brown 	}
2897414c70cbSLiam Girdwood 
2898414c70cbSLiam Girdwood 	return ret;
2899414c70cbSLiam Girdwood }
2900414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable);
2901414c70cbSLiam Girdwood 
2902414c70cbSLiam Girdwood /**
2903e1de2f42SDonggeun Kim  * regulator_bulk_force_disable - force disable multiple regulator consumers
2904e1de2f42SDonggeun Kim  *
2905e1de2f42SDonggeun Kim  * @num_consumers: Number of consumers
2906e1de2f42SDonggeun Kim  * @consumers:     Consumer data; clients are stored here.
2907e1de2f42SDonggeun Kim  * @return         0 on success, an errno on failure
2908e1de2f42SDonggeun Kim  *
2909e1de2f42SDonggeun Kim  * This convenience API allows consumers to forcibly disable multiple regulator
2910e1de2f42SDonggeun Kim  * clients in a single API call.
2911e1de2f42SDonggeun Kim  * NOTE: This should be used for situations when device damage will
2912e1de2f42SDonggeun Kim  * likely occur if the regulators are not disabled (e.g. over temp).
2913e1de2f42SDonggeun Kim  * Although regulator_force_disable function call for some consumers can
2914e1de2f42SDonggeun Kim  * return error numbers, the function is called for all consumers.
2915e1de2f42SDonggeun Kim  */
2916e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers,
2917e1de2f42SDonggeun Kim 			   struct regulator_bulk_data *consumers)
2918e1de2f42SDonggeun Kim {
2919e1de2f42SDonggeun Kim 	int i;
2920e1de2f42SDonggeun Kim 	int ret;
2921e1de2f42SDonggeun Kim 
2922e1de2f42SDonggeun Kim 	for (i = 0; i < num_consumers; i++)
2923e1de2f42SDonggeun Kim 		consumers[i].ret =
2924e1de2f42SDonggeun Kim 			    regulator_force_disable(consumers[i].consumer);
2925e1de2f42SDonggeun Kim 
2926e1de2f42SDonggeun Kim 	for (i = 0; i < num_consumers; i++) {
2927e1de2f42SDonggeun Kim 		if (consumers[i].ret != 0) {
2928e1de2f42SDonggeun Kim 			ret = consumers[i].ret;
2929e1de2f42SDonggeun Kim 			goto out;
2930e1de2f42SDonggeun Kim 		}
2931e1de2f42SDonggeun Kim 	}
2932e1de2f42SDonggeun Kim 
2933e1de2f42SDonggeun Kim 	return 0;
2934e1de2f42SDonggeun Kim out:
2935e1de2f42SDonggeun Kim 	return ret;
2936e1de2f42SDonggeun Kim }
2937e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
2938e1de2f42SDonggeun Kim 
2939e1de2f42SDonggeun Kim /**
2940414c70cbSLiam Girdwood  * regulator_bulk_free - free multiple regulator consumers
2941414c70cbSLiam Girdwood  *
2942414c70cbSLiam Girdwood  * @num_consumers: Number of consumers
2943414c70cbSLiam Girdwood  * @consumers:     Consumer data; clients are stored here.
2944414c70cbSLiam Girdwood  *
2945414c70cbSLiam Girdwood  * This convenience API allows consumers to free multiple regulator
2946414c70cbSLiam Girdwood  * clients in a single API call.
2947414c70cbSLiam Girdwood  */
2948414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers,
2949414c70cbSLiam Girdwood 			 struct regulator_bulk_data *consumers)
2950414c70cbSLiam Girdwood {
2951414c70cbSLiam Girdwood 	int i;
2952414c70cbSLiam Girdwood 
2953414c70cbSLiam Girdwood 	for (i = 0; i < num_consumers; i++) {
2954414c70cbSLiam Girdwood 		regulator_put(consumers[i].consumer);
2955414c70cbSLiam Girdwood 		consumers[i].consumer = NULL;
2956414c70cbSLiam Girdwood 	}
2957414c70cbSLiam Girdwood }
2958414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free);
2959414c70cbSLiam Girdwood 
2960414c70cbSLiam Girdwood /**
2961414c70cbSLiam Girdwood  * regulator_notifier_call_chain - call regulator event notifier
296269279fb9SMark Brown  * @rdev: regulator source
2963414c70cbSLiam Girdwood  * @event: notifier block
296469279fb9SMark Brown  * @data: callback-specific data.
2965414c70cbSLiam Girdwood  *
2966414c70cbSLiam Girdwood  * Called by regulator drivers to notify clients a regulator event has
2967414c70cbSLiam Girdwood  * occurred. We also notify regulator clients downstream.
2968b136fb44SJonathan Cameron  * Note lock must be held by caller.
2969414c70cbSLiam Girdwood  */
2970414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev,
2971414c70cbSLiam Girdwood 				  unsigned long event, void *data)
2972414c70cbSLiam Girdwood {
2973414c70cbSLiam Girdwood 	_notifier_call_chain(rdev, event, data);
2974414c70cbSLiam Girdwood 	return NOTIFY_DONE;
2975414c70cbSLiam Girdwood 
2976414c70cbSLiam Girdwood }
2977414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
2978414c70cbSLiam Girdwood 
2979be721979SMark Brown /**
2980be721979SMark Brown  * regulator_mode_to_status - convert a regulator mode into a status
2981be721979SMark Brown  *
2982be721979SMark Brown  * @mode: Mode to convert
2983be721979SMark Brown  *
2984be721979SMark Brown  * Convert a regulator mode into a status.
2985be721979SMark Brown  */
2986be721979SMark Brown int regulator_mode_to_status(unsigned int mode)
2987be721979SMark Brown {
2988be721979SMark Brown 	switch (mode) {
2989be721979SMark Brown 	case REGULATOR_MODE_FAST:
2990be721979SMark Brown 		return REGULATOR_STATUS_FAST;
2991be721979SMark Brown 	case REGULATOR_MODE_NORMAL:
2992be721979SMark Brown 		return REGULATOR_STATUS_NORMAL;
2993be721979SMark Brown 	case REGULATOR_MODE_IDLE:
2994be721979SMark Brown 		return REGULATOR_STATUS_IDLE;
2995be721979SMark Brown 	case REGULATOR_STATUS_STANDBY:
2996be721979SMark Brown 		return REGULATOR_STATUS_STANDBY;
2997be721979SMark Brown 	default:
2998be721979SMark Brown 		return 0;
2999be721979SMark Brown 	}
3000be721979SMark Brown }
3001be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status);
3002be721979SMark Brown 
30037ad68e2fSDavid Brownell /*
30047ad68e2fSDavid Brownell  * To avoid cluttering sysfs (and memory) with useless state, only
30057ad68e2fSDavid Brownell  * create attributes that can be meaningfully displayed.
30067ad68e2fSDavid Brownell  */
30077ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev)
30087ad68e2fSDavid Brownell {
30097ad68e2fSDavid Brownell 	struct device		*dev = &rdev->dev;
30107ad68e2fSDavid Brownell 	struct regulator_ops	*ops = rdev->desc->ops;
30117ad68e2fSDavid Brownell 	int			status = 0;
30127ad68e2fSDavid Brownell 
30137ad68e2fSDavid Brownell 	/* some attributes need specific methods to be displayed */
30144c78899bSMark Brown 	if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
30154c78899bSMark Brown 	    (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) {
30167ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_microvolts);
30177ad68e2fSDavid Brownell 		if (status < 0)
30187ad68e2fSDavid Brownell 			return status;
30197ad68e2fSDavid Brownell 	}
30207ad68e2fSDavid Brownell 	if (ops->get_current_limit) {
30217ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_microamps);
30227ad68e2fSDavid Brownell 		if (status < 0)
30237ad68e2fSDavid Brownell 			return status;
30247ad68e2fSDavid Brownell 	}
30257ad68e2fSDavid Brownell 	if (ops->get_mode) {
30267ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_opmode);
30277ad68e2fSDavid Brownell 		if (status < 0)
30287ad68e2fSDavid Brownell 			return status;
30297ad68e2fSDavid Brownell 	}
30307ad68e2fSDavid Brownell 	if (ops->is_enabled) {
30317ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_state);
30327ad68e2fSDavid Brownell 		if (status < 0)
30337ad68e2fSDavid Brownell 			return status;
30347ad68e2fSDavid Brownell 	}
3035853116a1SDavid Brownell 	if (ops->get_status) {
3036853116a1SDavid Brownell 		status = device_create_file(dev, &dev_attr_status);
3037853116a1SDavid Brownell 		if (status < 0)
3038853116a1SDavid Brownell 			return status;
3039853116a1SDavid Brownell 	}
30407ad68e2fSDavid Brownell 
30417ad68e2fSDavid Brownell 	/* some attributes are type-specific */
30427ad68e2fSDavid Brownell 	if (rdev->desc->type == REGULATOR_CURRENT) {
30437ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_requested_microamps);
30447ad68e2fSDavid Brownell 		if (status < 0)
30457ad68e2fSDavid Brownell 			return status;
30467ad68e2fSDavid Brownell 	}
30477ad68e2fSDavid Brownell 
30487ad68e2fSDavid Brownell 	/* all the other attributes exist to support constraints;
30497ad68e2fSDavid Brownell 	 * don't show them if there are no constraints, or if the
30507ad68e2fSDavid Brownell 	 * relevant supporting methods are missing.
30517ad68e2fSDavid Brownell 	 */
30527ad68e2fSDavid Brownell 	if (!rdev->constraints)
30537ad68e2fSDavid Brownell 		return status;
30547ad68e2fSDavid Brownell 
30557ad68e2fSDavid Brownell 	/* constraints need specific supporting methods */
3056e8eef82bSMark Brown 	if (ops->set_voltage || ops->set_voltage_sel) {
30577ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_min_microvolts);
30587ad68e2fSDavid Brownell 		if (status < 0)
30597ad68e2fSDavid Brownell 			return status;
30607ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_max_microvolts);
30617ad68e2fSDavid Brownell 		if (status < 0)
30627ad68e2fSDavid Brownell 			return status;
30637ad68e2fSDavid Brownell 	}
30647ad68e2fSDavid Brownell 	if (ops->set_current_limit) {
30657ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_min_microamps);
30667ad68e2fSDavid Brownell 		if (status < 0)
30677ad68e2fSDavid Brownell 			return status;
30687ad68e2fSDavid Brownell 		status = device_create_file(dev, &dev_attr_max_microamps);
30697ad68e2fSDavid Brownell 		if (status < 0)
30707ad68e2fSDavid Brownell 			return status;
30717ad68e2fSDavid Brownell 	}
30727ad68e2fSDavid Brownell 
30737ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_standby_state);
30747ad68e2fSDavid Brownell 	if (status < 0)
30757ad68e2fSDavid Brownell 		return status;
30767ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_mem_state);
30777ad68e2fSDavid Brownell 	if (status < 0)
30787ad68e2fSDavid Brownell 		return status;
30797ad68e2fSDavid Brownell 	status = device_create_file(dev, &dev_attr_suspend_disk_state);
30807ad68e2fSDavid Brownell 	if (status < 0)
30817ad68e2fSDavid Brownell 		return status;
30827ad68e2fSDavid Brownell 
30837ad68e2fSDavid Brownell 	if (ops->set_suspend_voltage) {
30847ad68e2fSDavid Brownell 		status = device_create_file(dev,
30857ad68e2fSDavid Brownell 				&dev_attr_suspend_standby_microvolts);
30867ad68e2fSDavid Brownell 		if (status < 0)
30877ad68e2fSDavid Brownell 			return status;
30887ad68e2fSDavid Brownell 		status = device_create_file(dev,
30897ad68e2fSDavid Brownell 				&dev_attr_suspend_mem_microvolts);
30907ad68e2fSDavid Brownell 		if (status < 0)
30917ad68e2fSDavid Brownell 			return status;
30927ad68e2fSDavid Brownell 		status = device_create_file(dev,
30937ad68e2fSDavid Brownell 				&dev_attr_suspend_disk_microvolts);
30947ad68e2fSDavid Brownell 		if (status < 0)
30957ad68e2fSDavid Brownell 			return status;
30967ad68e2fSDavid Brownell 	}
30977ad68e2fSDavid Brownell 
30987ad68e2fSDavid Brownell 	if (ops->set_suspend_mode) {
30997ad68e2fSDavid Brownell 		status = device_create_file(dev,
31007ad68e2fSDavid Brownell 				&dev_attr_suspend_standby_mode);
31017ad68e2fSDavid Brownell 		if (status < 0)
31027ad68e2fSDavid Brownell 			return status;
31037ad68e2fSDavid Brownell 		status = device_create_file(dev,
31047ad68e2fSDavid Brownell 				&dev_attr_suspend_mem_mode);
31057ad68e2fSDavid Brownell 		if (status < 0)
31067ad68e2fSDavid Brownell 			return status;
31077ad68e2fSDavid Brownell 		status = device_create_file(dev,
31087ad68e2fSDavid Brownell 				&dev_attr_suspend_disk_mode);
31097ad68e2fSDavid Brownell 		if (status < 0)
31107ad68e2fSDavid Brownell 			return status;
31117ad68e2fSDavid Brownell 	}
31127ad68e2fSDavid Brownell 
31137ad68e2fSDavid Brownell 	return status;
31147ad68e2fSDavid Brownell }
31157ad68e2fSDavid Brownell 
31161130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev)
31171130e5b3SMark Brown {
31181130e5b3SMark Brown 	rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root);
311924751434SStephen Boyd 	if (!rdev->debugfs) {
31201130e5b3SMark Brown 		rdev_warn(rdev, "Failed to create debugfs directory\n");
31211130e5b3SMark Brown 		return;
31221130e5b3SMark Brown 	}
31231130e5b3SMark Brown 
31241130e5b3SMark Brown 	debugfs_create_u32("use_count", 0444, rdev->debugfs,
31251130e5b3SMark Brown 			   &rdev->use_count);
31261130e5b3SMark Brown 	debugfs_create_u32("open_count", 0444, rdev->debugfs,
31271130e5b3SMark Brown 			   &rdev->open_count);
31281130e5b3SMark Brown }
31291130e5b3SMark Brown 
3130414c70cbSLiam Girdwood /**
3131414c70cbSLiam Girdwood  * regulator_register - register regulator
313269279fb9SMark Brown  * @regulator_desc: regulator to register
3133c172708dSMark Brown  * @config: runtime configuration for regulator
3134414c70cbSLiam Girdwood  *
3135414c70cbSLiam Girdwood  * Called by regulator drivers to register a regulator.
3136414c70cbSLiam Girdwood  * Returns 0 on success.
3137414c70cbSLiam Girdwood  */
313865f26846SMark Brown struct regulator_dev *
313965f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc,
3140c172708dSMark Brown 		   const struct regulator_config *config)
3141414c70cbSLiam Girdwood {
31429a8f5e07SMark Brown 	const struct regulation_constraints *constraints = NULL;
3143c172708dSMark Brown 	const struct regulator_init_data *init_data;
3144414c70cbSLiam Girdwood 	static atomic_t regulator_no = ATOMIC_INIT(0);
3145414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
314632c8fad4SMark Brown 	struct device *dev;
3147a5766f11SLiam Girdwood 	int ret, i;
314869511a45SRajendra Nayak 	const char *supply = NULL;
3149414c70cbSLiam Girdwood 
3150c172708dSMark Brown 	if (regulator_desc == NULL || config == NULL)
3151414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
3152414c70cbSLiam Girdwood 
315332c8fad4SMark Brown 	dev = config->dev;
3154dcf70112SMark Brown 	WARN_ON(!dev);
315532c8fad4SMark Brown 
3156414c70cbSLiam Girdwood 	if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
3157414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
3158414c70cbSLiam Girdwood 
3159cd78dfc6SDiego Liziero 	if (regulator_desc->type != REGULATOR_VOLTAGE &&
3160cd78dfc6SDiego Liziero 	    regulator_desc->type != REGULATOR_CURRENT)
3161414c70cbSLiam Girdwood 		return ERR_PTR(-EINVAL);
3162414c70cbSLiam Girdwood 
3163476c2d83SMark Brown 	/* Only one of each should be implemented */
3164476c2d83SMark Brown 	WARN_ON(regulator_desc->ops->get_voltage &&
3165476c2d83SMark Brown 		regulator_desc->ops->get_voltage_sel);
3166e8eef82bSMark Brown 	WARN_ON(regulator_desc->ops->set_voltage &&
3167e8eef82bSMark Brown 		regulator_desc->ops->set_voltage_sel);
3168476c2d83SMark Brown 
3169476c2d83SMark Brown 	/* If we're using selectors we must implement list_voltage. */
3170476c2d83SMark Brown 	if (regulator_desc->ops->get_voltage_sel &&
3171476c2d83SMark Brown 	    !regulator_desc->ops->list_voltage) {
3172476c2d83SMark Brown 		return ERR_PTR(-EINVAL);
3173476c2d83SMark Brown 	}
3174e8eef82bSMark Brown 	if (regulator_desc->ops->set_voltage_sel &&
3175e8eef82bSMark Brown 	    !regulator_desc->ops->list_voltage) {
3176e8eef82bSMark Brown 		return ERR_PTR(-EINVAL);
3177e8eef82bSMark Brown 	}
3178476c2d83SMark Brown 
3179c172708dSMark Brown 	init_data = config->init_data;
3180c172708dSMark Brown 
3181414c70cbSLiam Girdwood 	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
3182414c70cbSLiam Girdwood 	if (rdev == NULL)
3183414c70cbSLiam Girdwood 		return ERR_PTR(-ENOMEM);
3184414c70cbSLiam Girdwood 
3185414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
3186414c70cbSLiam Girdwood 
3187414c70cbSLiam Girdwood 	mutex_init(&rdev->mutex);
3188c172708dSMark Brown 	rdev->reg_data = config->driver_data;
3189414c70cbSLiam Girdwood 	rdev->owner = regulator_desc->owner;
3190414c70cbSLiam Girdwood 	rdev->desc = regulator_desc;
31913a4b0a07SMark Brown 	if (config->regmap)
319265b19ce6SMark Brown 		rdev->regmap = config->regmap;
31933a4b0a07SMark Brown 	else
31943a4b0a07SMark Brown 		rdev->regmap = dev_get_regmap(dev, NULL);
3195414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->consumer_list);
3196414c70cbSLiam Girdwood 	INIT_LIST_HEAD(&rdev->list);
3197414c70cbSLiam Girdwood 	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
3198da07ecd9SMark Brown 	INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
3199414c70cbSLiam Girdwood 
3200a5766f11SLiam Girdwood 	/* preform any regulator specific init */
32019a8f5e07SMark Brown 	if (init_data && init_data->regulator_init) {
3202a5766f11SLiam Girdwood 		ret = init_data->regulator_init(rdev->reg_data);
32034fca9545SDavid Brownell 		if (ret < 0)
32044fca9545SDavid Brownell 			goto clean;
3205a5766f11SLiam Girdwood 	}
3206a5766f11SLiam Girdwood 
3207a5766f11SLiam Girdwood 	/* register with sysfs */
3208a5766f11SLiam Girdwood 	rdev->dev.class = &regulator_class;
3209c172708dSMark Brown 	rdev->dev.of_node = config->of_node;
3210a5766f11SLiam Girdwood 	rdev->dev.parent = dev;
3211812460a9SKay Sievers 	dev_set_name(&rdev->dev, "regulator.%d",
3212812460a9SKay Sievers 		     atomic_inc_return(&regulator_no) - 1);
3213a5766f11SLiam Girdwood 	ret = device_register(&rdev->dev);
3214ad7725cbSVasiliy Kulikov 	if (ret != 0) {
3215ad7725cbSVasiliy Kulikov 		put_device(&rdev->dev);
32164fca9545SDavid Brownell 		goto clean;
3217ad7725cbSVasiliy Kulikov 	}
3218a5766f11SLiam Girdwood 
3219a5766f11SLiam Girdwood 	dev_set_drvdata(&rdev->dev, rdev);
3220a5766f11SLiam Girdwood 
322174f544c1SMike Rapoport 	/* set regulator constraints */
32229a8f5e07SMark Brown 	if (init_data)
32239a8f5e07SMark Brown 		constraints = &init_data->constraints;
32249a8f5e07SMark Brown 
32259a8f5e07SMark Brown 	ret = set_machine_constraints(rdev, constraints);
322674f544c1SMike Rapoport 	if (ret < 0)
322774f544c1SMike Rapoport 		goto scrub;
322874f544c1SMike Rapoport 
32297ad68e2fSDavid Brownell 	/* add attributes supported by this regulator */
32307ad68e2fSDavid Brownell 	ret = add_regulator_attributes(rdev);
32317ad68e2fSDavid Brownell 	if (ret < 0)
32327ad68e2fSDavid Brownell 		goto scrub;
32337ad68e2fSDavid Brownell 
32349a8f5e07SMark Brown 	if (init_data && init_data->supply_regulator)
323569511a45SRajendra Nayak 		supply = init_data->supply_regulator;
323669511a45SRajendra Nayak 	else if (regulator_desc->supply_name)
323769511a45SRajendra Nayak 		supply = regulator_desc->supply_name;
323869511a45SRajendra Nayak 
323969511a45SRajendra Nayak 	if (supply) {
32400178f3e2SMark Brown 		struct regulator_dev *r;
32410178f3e2SMark Brown 
32426d191a5fSMark Brown 		r = regulator_dev_lookup(dev, supply, &ret);
32430178f3e2SMark Brown 
324469511a45SRajendra Nayak 		if (!r) {
324569511a45SRajendra Nayak 			dev_err(dev, "Failed to find supply %s\n", supply);
324604bf3011SMark Brown 			ret = -EPROBE_DEFER;
32470178f3e2SMark Brown 			goto scrub;
32480178f3e2SMark Brown 		}
32490178f3e2SMark Brown 
32500178f3e2SMark Brown 		ret = set_supply(rdev, r);
32510178f3e2SMark Brown 		if (ret < 0)
32520178f3e2SMark Brown 			goto scrub;
3253b2296bd4SLaxman Dewangan 
3254b2296bd4SLaxman Dewangan 		/* Enable supply if rail is enabled */
3255b1a86831SMark Brown 		if (_regulator_is_enabled(rdev)) {
3256b2296bd4SLaxman Dewangan 			ret = regulator_enable(rdev->supply);
3257b2296bd4SLaxman Dewangan 			if (ret < 0)
3258b2296bd4SLaxman Dewangan 				goto scrub;
3259b2296bd4SLaxman Dewangan 		}
32600178f3e2SMark Brown 	}
32610178f3e2SMark Brown 
3262a5766f11SLiam Girdwood 	/* add consumers devices */
32639a8f5e07SMark Brown 	if (init_data) {
3264a5766f11SLiam Girdwood 		for (i = 0; i < init_data->num_consumer_supplies; i++) {
3265a5766f11SLiam Girdwood 			ret = set_consumer_device_supply(rdev,
326640f9244fSMark Brown 				init_data->consumer_supplies[i].dev_name,
3267a5766f11SLiam Girdwood 				init_data->consumer_supplies[i].supply);
326823c2f041SMark Brown 			if (ret < 0) {
326923c2f041SMark Brown 				dev_err(dev, "Failed to set supply %s\n",
327023c2f041SMark Brown 					init_data->consumer_supplies[i].supply);
3271d4033b54SJani Nikula 				goto unset_supplies;
3272a5766f11SLiam Girdwood 			}
327323c2f041SMark Brown 		}
32749a8f5e07SMark Brown 	}
3275a5766f11SLiam Girdwood 
3276a5766f11SLiam Girdwood 	list_add(&rdev->list, &regulator_list);
32771130e5b3SMark Brown 
32781130e5b3SMark Brown 	rdev_init_debugfs(rdev);
3279a5766f11SLiam Girdwood out:
3280414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
3281414c70cbSLiam Girdwood 	return rdev;
32824fca9545SDavid Brownell 
3283d4033b54SJani Nikula unset_supplies:
3284d4033b54SJani Nikula 	unset_regulator_supplies(rdev);
3285d4033b54SJani Nikula 
32864fca9545SDavid Brownell scrub:
3287e81dba85SMark Brown 	if (rdev->supply)
3288e81dba85SMark Brown 		regulator_put(rdev->supply);
32891a6958e7SAxel Lin 	kfree(rdev->constraints);
32904fca9545SDavid Brownell 	device_unregister(&rdev->dev);
329153032dafSPaul Walmsley 	/* device core frees rdev */
329253032dafSPaul Walmsley 	rdev = ERR_PTR(ret);
329353032dafSPaul Walmsley 	goto out;
329453032dafSPaul Walmsley 
32954fca9545SDavid Brownell clean:
32964fca9545SDavid Brownell 	kfree(rdev);
32974fca9545SDavid Brownell 	rdev = ERR_PTR(ret);
32984fca9545SDavid Brownell 	goto out;
3299414c70cbSLiam Girdwood }
3300414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register);
3301414c70cbSLiam Girdwood 
3302414c70cbSLiam Girdwood /**
3303414c70cbSLiam Girdwood  * regulator_unregister - unregister regulator
330469279fb9SMark Brown  * @rdev: regulator to unregister
3305414c70cbSLiam Girdwood  *
3306414c70cbSLiam Girdwood  * Called by regulator drivers to unregister a regulator.
3307414c70cbSLiam Girdwood  */
3308414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev)
3309414c70cbSLiam Girdwood {
3310414c70cbSLiam Girdwood 	if (rdev == NULL)
3311414c70cbSLiam Girdwood 		return;
3312414c70cbSLiam Girdwood 
3313e032b376SMark Brown 	if (rdev->supply)
3314e032b376SMark Brown 		regulator_put(rdev->supply);
3315414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
33161130e5b3SMark Brown 	debugfs_remove_recursive(rdev->debugfs);
3317da07ecd9SMark Brown 	flush_work_sync(&rdev->disable_work.work);
33186bf87d17SMark Brown 	WARN_ON(rdev->open_count);
33190f1d747bSMike Rapoport 	unset_regulator_supplies(rdev);
3320414c70cbSLiam Girdwood 	list_del(&rdev->list);
3321f8c12fe3SMark Brown 	kfree(rdev->constraints);
332258fb5cf5SLothar Waßmann 	device_unregister(&rdev->dev);
3323414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
3324414c70cbSLiam Girdwood }
3325414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister);
3326414c70cbSLiam Girdwood 
3327414c70cbSLiam Girdwood /**
3328cf7bbcdfSMark Brown  * regulator_suspend_prepare - prepare regulators for system wide suspend
3329414c70cbSLiam Girdwood  * @state: system suspend state
3330414c70cbSLiam Girdwood  *
3331414c70cbSLiam Girdwood  * Configure each regulator with it's suspend operating parameters for state.
3332414c70cbSLiam Girdwood  * This will usually be called by machine suspend code prior to supending.
3333414c70cbSLiam Girdwood  */
3334414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state)
3335414c70cbSLiam Girdwood {
3336414c70cbSLiam Girdwood 	struct regulator_dev *rdev;
3337414c70cbSLiam Girdwood 	int ret = 0;
3338414c70cbSLiam Girdwood 
3339414c70cbSLiam Girdwood 	/* ON is handled by regulator active state */
3340414c70cbSLiam Girdwood 	if (state == PM_SUSPEND_ON)
3341414c70cbSLiam Girdwood 		return -EINVAL;
3342414c70cbSLiam Girdwood 
3343414c70cbSLiam Girdwood 	mutex_lock(&regulator_list_mutex);
3344414c70cbSLiam Girdwood 	list_for_each_entry(rdev, &regulator_list, list) {
3345414c70cbSLiam Girdwood 
3346414c70cbSLiam Girdwood 		mutex_lock(&rdev->mutex);
3347414c70cbSLiam Girdwood 		ret = suspend_prepare(rdev, state);
3348414c70cbSLiam Girdwood 		mutex_unlock(&rdev->mutex);
3349414c70cbSLiam Girdwood 
3350414c70cbSLiam Girdwood 		if (ret < 0) {
33515da84fd9SJoe Perches 			rdev_err(rdev, "failed to prepare\n");
3352414c70cbSLiam Girdwood 			goto out;
3353414c70cbSLiam Girdwood 		}
3354414c70cbSLiam Girdwood 	}
3355414c70cbSLiam Girdwood out:
3356414c70cbSLiam Girdwood 	mutex_unlock(&regulator_list_mutex);
3357414c70cbSLiam Girdwood 	return ret;
3358414c70cbSLiam Girdwood }
3359414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
3360414c70cbSLiam Girdwood 
3361414c70cbSLiam Girdwood /**
33627a32b589SMyungJoo Ham  * regulator_suspend_finish - resume regulators from system wide suspend
33637a32b589SMyungJoo Ham  *
33647a32b589SMyungJoo Ham  * Turn on regulators that might be turned off by regulator_suspend_prepare
33657a32b589SMyungJoo Ham  * and that should be turned on according to the regulators properties.
33667a32b589SMyungJoo Ham  */
33677a32b589SMyungJoo Ham int regulator_suspend_finish(void)
33687a32b589SMyungJoo Ham {
33697a32b589SMyungJoo Ham 	struct regulator_dev *rdev;
33707a32b589SMyungJoo Ham 	int ret = 0, error;
33717a32b589SMyungJoo Ham 
33727a32b589SMyungJoo Ham 	mutex_lock(&regulator_list_mutex);
33737a32b589SMyungJoo Ham 	list_for_each_entry(rdev, &regulator_list, list) {
33747a32b589SMyungJoo Ham 		struct regulator_ops *ops = rdev->desc->ops;
33757a32b589SMyungJoo Ham 
33767a32b589SMyungJoo Ham 		mutex_lock(&rdev->mutex);
33777a32b589SMyungJoo Ham 		if ((rdev->use_count > 0  || rdev->constraints->always_on) &&
33787a32b589SMyungJoo Ham 				ops->enable) {
33797a32b589SMyungJoo Ham 			error = ops->enable(rdev);
33807a32b589SMyungJoo Ham 			if (error)
33817a32b589SMyungJoo Ham 				ret = error;
33827a32b589SMyungJoo Ham 		} else {
33837a32b589SMyungJoo Ham 			if (!has_full_constraints)
33847a32b589SMyungJoo Ham 				goto unlock;
33857a32b589SMyungJoo Ham 			if (!ops->disable)
33867a32b589SMyungJoo Ham 				goto unlock;
3387b1a86831SMark Brown 			if (!_regulator_is_enabled(rdev))
33887a32b589SMyungJoo Ham 				goto unlock;
33897a32b589SMyungJoo Ham 
33907a32b589SMyungJoo Ham 			error = ops->disable(rdev);
33917a32b589SMyungJoo Ham 			if (error)
33927a32b589SMyungJoo Ham 				ret = error;
33937a32b589SMyungJoo Ham 		}
33947a32b589SMyungJoo Ham unlock:
33957a32b589SMyungJoo Ham 		mutex_unlock(&rdev->mutex);
33967a32b589SMyungJoo Ham 	}
33977a32b589SMyungJoo Ham 	mutex_unlock(&regulator_list_mutex);
33987a32b589SMyungJoo Ham 	return ret;
33997a32b589SMyungJoo Ham }
34007a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish);
34017a32b589SMyungJoo Ham 
34027a32b589SMyungJoo Ham /**
3403ca725561SMark Brown  * regulator_has_full_constraints - the system has fully specified constraints
3404ca725561SMark Brown  *
3405ca725561SMark Brown  * Calling this function will cause the regulator API to disable all
3406ca725561SMark Brown  * regulators which have a zero use count and don't have an always_on
3407ca725561SMark Brown  * constraint in a late_initcall.
3408ca725561SMark Brown  *
3409ca725561SMark Brown  * The intention is that this will become the default behaviour in a
3410ca725561SMark Brown  * future kernel release so users are encouraged to use this facility
3411ca725561SMark Brown  * now.
3412ca725561SMark Brown  */
3413ca725561SMark Brown void regulator_has_full_constraints(void)
3414ca725561SMark Brown {
3415ca725561SMark Brown 	has_full_constraints = 1;
3416ca725561SMark Brown }
3417ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
3418ca725561SMark Brown 
3419ca725561SMark Brown /**
3420688fe99aSMark Brown  * regulator_use_dummy_regulator - Provide a dummy regulator when none is found
3421688fe99aSMark Brown  *
3422688fe99aSMark Brown  * Calling this function will cause the regulator API to provide a
3423688fe99aSMark Brown  * dummy regulator to consumers if no physical regulator is found,
3424688fe99aSMark Brown  * allowing most consumers to proceed as though a regulator were
3425688fe99aSMark Brown  * configured.  This allows systems such as those with software
3426688fe99aSMark Brown  * controllable regulators for the CPU core only to be brought up more
3427688fe99aSMark Brown  * readily.
3428688fe99aSMark Brown  */
3429688fe99aSMark Brown void regulator_use_dummy_regulator(void)
3430688fe99aSMark Brown {
3431688fe99aSMark Brown 	board_wants_dummy_regulator = true;
3432688fe99aSMark Brown }
3433688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator);
3434688fe99aSMark Brown 
3435688fe99aSMark Brown /**
3436414c70cbSLiam Girdwood  * rdev_get_drvdata - get rdev regulator driver data
343769279fb9SMark Brown  * @rdev: regulator
3438414c70cbSLiam Girdwood  *
3439414c70cbSLiam Girdwood  * Get rdev regulator driver private data. This call can be used in the
3440414c70cbSLiam Girdwood  * regulator driver context.
3441414c70cbSLiam Girdwood  */
3442414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev)
3443414c70cbSLiam Girdwood {
3444414c70cbSLiam Girdwood 	return rdev->reg_data;
3445414c70cbSLiam Girdwood }
3446414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata);
3447414c70cbSLiam Girdwood 
3448414c70cbSLiam Girdwood /**
3449414c70cbSLiam Girdwood  * regulator_get_drvdata - get regulator driver data
3450414c70cbSLiam Girdwood  * @regulator: regulator
3451414c70cbSLiam Girdwood  *
3452414c70cbSLiam Girdwood  * Get regulator driver private data. This call can be used in the consumer
3453414c70cbSLiam Girdwood  * driver context when non API regulator specific functions need to be called.
3454414c70cbSLiam Girdwood  */
3455414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator)
3456414c70cbSLiam Girdwood {
3457414c70cbSLiam Girdwood 	return regulator->rdev->reg_data;
3458414c70cbSLiam Girdwood }
3459414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata);
3460414c70cbSLiam Girdwood 
3461414c70cbSLiam Girdwood /**
3462414c70cbSLiam Girdwood  * regulator_set_drvdata - set regulator driver data
3463414c70cbSLiam Girdwood  * @regulator: regulator
3464414c70cbSLiam Girdwood  * @data: data
3465414c70cbSLiam Girdwood  */
3466414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data)
3467414c70cbSLiam Girdwood {
3468414c70cbSLiam Girdwood 	regulator->rdev->reg_data = data;
3469414c70cbSLiam Girdwood }
3470414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata);
3471414c70cbSLiam Girdwood 
3472414c70cbSLiam Girdwood /**
3473414c70cbSLiam Girdwood  * regulator_get_id - get regulator ID
347469279fb9SMark Brown  * @rdev: regulator
3475414c70cbSLiam Girdwood  */
3476414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev)
3477414c70cbSLiam Girdwood {
3478414c70cbSLiam Girdwood 	return rdev->desc->id;
3479414c70cbSLiam Girdwood }
3480414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id);
3481414c70cbSLiam Girdwood 
3482a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev)
3483a5766f11SLiam Girdwood {
3484a5766f11SLiam Girdwood 	return &rdev->dev;
3485a5766f11SLiam Girdwood }
3486a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev);
3487a5766f11SLiam Girdwood 
3488a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
3489a5766f11SLiam Girdwood {
3490a5766f11SLiam Girdwood 	return reg_init_data->driver_data;
3491a5766f11SLiam Girdwood }
3492a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
3493a5766f11SLiam Girdwood 
3494ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS
3495ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf,
3496ba55a974SMark Brown 				    size_t count, loff_t *ppos)
3497ba55a974SMark Brown {
3498ba55a974SMark Brown 	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
3499ba55a974SMark Brown 	ssize_t len, ret = 0;
3500ba55a974SMark Brown 	struct regulator_map *map;
3501ba55a974SMark Brown 
3502ba55a974SMark Brown 	if (!buf)
3503ba55a974SMark Brown 		return -ENOMEM;
3504ba55a974SMark Brown 
3505ba55a974SMark Brown 	list_for_each_entry(map, &regulator_map_list, list) {
3506ba55a974SMark Brown 		len = snprintf(buf + ret, PAGE_SIZE - ret,
3507ba55a974SMark Brown 			       "%s -> %s.%s\n",
3508ba55a974SMark Brown 			       rdev_get_name(map->regulator), map->dev_name,
3509ba55a974SMark Brown 			       map->supply);
3510ba55a974SMark Brown 		if (len >= 0)
3511ba55a974SMark Brown 			ret += len;
3512ba55a974SMark Brown 		if (ret > PAGE_SIZE) {
3513ba55a974SMark Brown 			ret = PAGE_SIZE;
3514ba55a974SMark Brown 			break;
3515ba55a974SMark Brown 		}
3516ba55a974SMark Brown 	}
3517ba55a974SMark Brown 
3518ba55a974SMark Brown 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
3519ba55a974SMark Brown 
3520ba55a974SMark Brown 	kfree(buf);
3521ba55a974SMark Brown 
3522ba55a974SMark Brown 	return ret;
3523ba55a974SMark Brown }
352424751434SStephen Boyd #endif
3525ba55a974SMark Brown 
3526ba55a974SMark Brown static const struct file_operations supply_map_fops = {
352724751434SStephen Boyd #ifdef CONFIG_DEBUG_FS
3528ba55a974SMark Brown 	.read = supply_map_read_file,
3529ba55a974SMark Brown 	.llseek = default_llseek,
3530ba55a974SMark Brown #endif
353124751434SStephen Boyd };
3532ba55a974SMark Brown 
3533414c70cbSLiam Girdwood static int __init regulator_init(void)
3534414c70cbSLiam Girdwood {
353534abbd68SMark Brown 	int ret;
353634abbd68SMark Brown 
353734abbd68SMark Brown 	ret = class_register(&regulator_class);
353834abbd68SMark Brown 
35391130e5b3SMark Brown 	debugfs_root = debugfs_create_dir("regulator", NULL);
354024751434SStephen Boyd 	if (!debugfs_root)
35411130e5b3SMark Brown 		pr_warn("regulator: Failed to create debugfs directory\n");
3542ba55a974SMark Brown 
3543f4d562c6SMark Brown 	debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
3544f4d562c6SMark Brown 			    &supply_map_fops);
35451130e5b3SMark Brown 
354634abbd68SMark Brown 	regulator_dummy_init();
354734abbd68SMark Brown 
354834abbd68SMark Brown 	return ret;
3549414c70cbSLiam Girdwood }
3550414c70cbSLiam Girdwood 
3551414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */
3552414c70cbSLiam Girdwood core_initcall(regulator_init);
3553ca725561SMark Brown 
3554ca725561SMark Brown static int __init regulator_init_complete(void)
3555ca725561SMark Brown {
3556ca725561SMark Brown 	struct regulator_dev *rdev;
3557ca725561SMark Brown 	struct regulator_ops *ops;
3558ca725561SMark Brown 	struct regulation_constraints *c;
3559ca725561SMark Brown 	int enabled, ret;
3560ca725561SMark Brown 
3561ca725561SMark Brown 	mutex_lock(&regulator_list_mutex);
3562ca725561SMark Brown 
3563ca725561SMark Brown 	/* If we have a full configuration then disable any regulators
3564ca725561SMark Brown 	 * which are not in use or always_on.  This will become the
3565ca725561SMark Brown 	 * default behaviour in the future.
3566ca725561SMark Brown 	 */
3567ca725561SMark Brown 	list_for_each_entry(rdev, &regulator_list, list) {
3568ca725561SMark Brown 		ops = rdev->desc->ops;
3569ca725561SMark Brown 		c = rdev->constraints;
3570ca725561SMark Brown 
3571f25e0b4fSMark Brown 		if (!ops->disable || (c && c->always_on))
3572ca725561SMark Brown 			continue;
3573ca725561SMark Brown 
3574ca725561SMark Brown 		mutex_lock(&rdev->mutex);
3575ca725561SMark Brown 
3576ca725561SMark Brown 		if (rdev->use_count)
3577ca725561SMark Brown 			goto unlock;
3578ca725561SMark Brown 
3579ca725561SMark Brown 		/* If we can't read the status assume it's on. */
3580ca725561SMark Brown 		if (ops->is_enabled)
3581ca725561SMark Brown 			enabled = ops->is_enabled(rdev);
3582ca725561SMark Brown 		else
3583ca725561SMark Brown 			enabled = 1;
3584ca725561SMark Brown 
3585ca725561SMark Brown 		if (!enabled)
3586ca725561SMark Brown 			goto unlock;
3587ca725561SMark Brown 
3588ca725561SMark Brown 		if (has_full_constraints) {
3589ca725561SMark Brown 			/* We log since this may kill the system if it
3590ca725561SMark Brown 			 * goes wrong. */
35915da84fd9SJoe Perches 			rdev_info(rdev, "disabling\n");
3592ca725561SMark Brown 			ret = ops->disable(rdev);
3593ca725561SMark Brown 			if (ret != 0) {
35945da84fd9SJoe Perches 				rdev_err(rdev, "couldn't disable: %d\n", ret);
3595ca725561SMark Brown 			}
3596ca725561SMark Brown 		} else {
3597ca725561SMark Brown 			/* The intention is that in future we will
3598ca725561SMark Brown 			 * assume that full constraints are provided
3599ca725561SMark Brown 			 * so warn even if we aren't going to do
3600ca725561SMark Brown 			 * anything here.
3601ca725561SMark Brown 			 */
36025da84fd9SJoe Perches 			rdev_warn(rdev, "incomplete constraints, leaving on\n");
3603ca725561SMark Brown 		}
3604ca725561SMark Brown 
3605ca725561SMark Brown unlock:
3606ca725561SMark Brown 		mutex_unlock(&rdev->mutex);
3607ca725561SMark Brown 	}
3608ca725561SMark Brown 
3609ca725561SMark Brown 	mutex_unlock(&regulator_list_mutex);
3610ca725561SMark Brown 
3611ca725561SMark Brown 	return 0;
3612ca725561SMark Brown }
3613ca725561SMark Brown late_initcall(regulator_init_complete);
3614