xref: /freebsd/sys/dev/regulator/regulator.c (revision b2f0caf1)
1*b2f0caf1SEmmanuel Vadot /*-
2*b2f0caf1SEmmanuel Vadot  * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
3*b2f0caf1SEmmanuel Vadot  * All rights reserved.
4*b2f0caf1SEmmanuel Vadot  *
5*b2f0caf1SEmmanuel Vadot  * Redistribution and use in source and binary forms, with or without
6*b2f0caf1SEmmanuel Vadot  * modification, are permitted provided that the following conditions
7*b2f0caf1SEmmanuel Vadot  * are met:
8*b2f0caf1SEmmanuel Vadot  * 1. Redistributions of source code must retain the above copyright
9*b2f0caf1SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer.
10*b2f0caf1SEmmanuel Vadot  * 2. Redistributions in binary form must reproduce the above copyright
11*b2f0caf1SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer in the
12*b2f0caf1SEmmanuel Vadot  *    documentation and/or other materials provided with the distribution.
13*b2f0caf1SEmmanuel Vadot  *
14*b2f0caf1SEmmanuel Vadot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*b2f0caf1SEmmanuel Vadot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*b2f0caf1SEmmanuel Vadot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*b2f0caf1SEmmanuel Vadot  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*b2f0caf1SEmmanuel Vadot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*b2f0caf1SEmmanuel Vadot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*b2f0caf1SEmmanuel Vadot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*b2f0caf1SEmmanuel Vadot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*b2f0caf1SEmmanuel Vadot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*b2f0caf1SEmmanuel Vadot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*b2f0caf1SEmmanuel Vadot  * SUCH DAMAGE.
25*b2f0caf1SEmmanuel Vadot  */
26*b2f0caf1SEmmanuel Vadot 
27*b2f0caf1SEmmanuel Vadot #include <sys/cdefs.h>
28*b2f0caf1SEmmanuel Vadot #include "opt_platform.h"
29*b2f0caf1SEmmanuel Vadot #include <sys/param.h>
30*b2f0caf1SEmmanuel Vadot #include <sys/conf.h>
31*b2f0caf1SEmmanuel Vadot #include <sys/bus.h>
32*b2f0caf1SEmmanuel Vadot #include <sys/kernel.h>
33*b2f0caf1SEmmanuel Vadot #include <sys/queue.h>
34*b2f0caf1SEmmanuel Vadot #include <sys/kobj.h>
35*b2f0caf1SEmmanuel Vadot #include <sys/malloc.h>
36*b2f0caf1SEmmanuel Vadot #include <sys/mutex.h>
37*b2f0caf1SEmmanuel Vadot #include <sys/limits.h>
38*b2f0caf1SEmmanuel Vadot #include <sys/lock.h>
39*b2f0caf1SEmmanuel Vadot #include <sys/sysctl.h>
40*b2f0caf1SEmmanuel Vadot #include <sys/systm.h>
41*b2f0caf1SEmmanuel Vadot #include <sys/sx.h>
42*b2f0caf1SEmmanuel Vadot 
43*b2f0caf1SEmmanuel Vadot #ifdef FDT
44*b2f0caf1SEmmanuel Vadot #include <dev/fdt/fdt_common.h>
45*b2f0caf1SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
46*b2f0caf1SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
47*b2f0caf1SEmmanuel Vadot #endif
48*b2f0caf1SEmmanuel Vadot #include <dev/regulator/regulator.h>
49*b2f0caf1SEmmanuel Vadot 
50*b2f0caf1SEmmanuel Vadot #ifdef FDT
51*b2f0caf1SEmmanuel Vadot #include "regdev_if.h"
52*b2f0caf1SEmmanuel Vadot #endif
53*b2f0caf1SEmmanuel Vadot 
54*b2f0caf1SEmmanuel Vadot SYSCTL_NODE(_hw, OID_AUTO, regulator, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
55*b2f0caf1SEmmanuel Vadot     "Regulators");
56*b2f0caf1SEmmanuel Vadot 
57*b2f0caf1SEmmanuel Vadot MALLOC_DEFINE(M_REGULATOR, "regulator", "Regulator framework");
58*b2f0caf1SEmmanuel Vadot 
59*b2f0caf1SEmmanuel Vadot #define	DIV_ROUND_UP(n,d) howmany(n, d)
60*b2f0caf1SEmmanuel Vadot 
61*b2f0caf1SEmmanuel Vadot /* Forward declarations. */
62*b2f0caf1SEmmanuel Vadot struct regulator;
63*b2f0caf1SEmmanuel Vadot struct regnode;
64*b2f0caf1SEmmanuel Vadot 
65*b2f0caf1SEmmanuel Vadot typedef TAILQ_HEAD(regnode_list, regnode) regnode_list_t;
66*b2f0caf1SEmmanuel Vadot typedef TAILQ_HEAD(regulator_list, regulator) regulator_list_t;
67*b2f0caf1SEmmanuel Vadot 
68*b2f0caf1SEmmanuel Vadot /* Default regulator methods. */
69*b2f0caf1SEmmanuel Vadot static int regnode_method_init(struct regnode *regnode);
70*b2f0caf1SEmmanuel Vadot static int regnode_method_enable(struct regnode *regnode, bool enable,
71*b2f0caf1SEmmanuel Vadot     int *udelay);
72*b2f0caf1SEmmanuel Vadot static int regnode_method_status(struct regnode *regnode, int *status);
73*b2f0caf1SEmmanuel Vadot static int regnode_method_set_voltage(struct regnode *regnode, int min_uvolt,
74*b2f0caf1SEmmanuel Vadot     int max_uvolt, int *udelay);
75*b2f0caf1SEmmanuel Vadot static int regnode_method_get_voltage(struct regnode *regnode, int *uvolt);
76*b2f0caf1SEmmanuel Vadot static void regulator_constraint(void *dummy);
77*b2f0caf1SEmmanuel Vadot static void regulator_shutdown(void *dummy);
78*b2f0caf1SEmmanuel Vadot 
79*b2f0caf1SEmmanuel Vadot /*
80*b2f0caf1SEmmanuel Vadot  * Regulator controller methods.
81*b2f0caf1SEmmanuel Vadot  */
82*b2f0caf1SEmmanuel Vadot static regnode_method_t regnode_methods[] = {
83*b2f0caf1SEmmanuel Vadot 	REGNODEMETHOD(regnode_init,		regnode_method_init),
84*b2f0caf1SEmmanuel Vadot 	REGNODEMETHOD(regnode_enable,		regnode_method_enable),
85*b2f0caf1SEmmanuel Vadot 	REGNODEMETHOD(regnode_status,		regnode_method_status),
86*b2f0caf1SEmmanuel Vadot 	REGNODEMETHOD(regnode_set_voltage,	regnode_method_set_voltage),
87*b2f0caf1SEmmanuel Vadot 	REGNODEMETHOD(regnode_get_voltage,	regnode_method_get_voltage),
88*b2f0caf1SEmmanuel Vadot 	REGNODEMETHOD(regnode_check_voltage,	regnode_method_check_voltage),
89*b2f0caf1SEmmanuel Vadot 
90*b2f0caf1SEmmanuel Vadot 	REGNODEMETHOD_END
91*b2f0caf1SEmmanuel Vadot };
92*b2f0caf1SEmmanuel Vadot DEFINE_CLASS_0(regnode, regnode_class, regnode_methods, 0);
93*b2f0caf1SEmmanuel Vadot 
94*b2f0caf1SEmmanuel Vadot /*
95*b2f0caf1SEmmanuel Vadot  * Regulator node - basic element for modelling SOC and bard power supply
96*b2f0caf1SEmmanuel Vadot  * chains. Its contains producer data.
97*b2f0caf1SEmmanuel Vadot  */
98*b2f0caf1SEmmanuel Vadot struct regnode {
99*b2f0caf1SEmmanuel Vadot 	KOBJ_FIELDS;
100*b2f0caf1SEmmanuel Vadot 
101*b2f0caf1SEmmanuel Vadot 	TAILQ_ENTRY(regnode)	reglist_link;	/* Global list entry */
102*b2f0caf1SEmmanuel Vadot 	regulator_list_t	consumers_list;	/* Consumers list */
103*b2f0caf1SEmmanuel Vadot 
104*b2f0caf1SEmmanuel Vadot 	/* Cache for already resolved names */
105*b2f0caf1SEmmanuel Vadot 	struct regnode		*parent;	/* Resolved parent */
106*b2f0caf1SEmmanuel Vadot 
107*b2f0caf1SEmmanuel Vadot 	/* Details of this device. */
108*b2f0caf1SEmmanuel Vadot 	const char		*name;		/* Globally unique name */
109*b2f0caf1SEmmanuel Vadot 	const char		*parent_name;	/* Parent name */
110*b2f0caf1SEmmanuel Vadot 
111*b2f0caf1SEmmanuel Vadot 	device_t		pdev;		/* Producer device_t */
112*b2f0caf1SEmmanuel Vadot 	void			*softc;		/* Producer softc */
113*b2f0caf1SEmmanuel Vadot 	intptr_t		id;		/* Per producer unique id */
114*b2f0caf1SEmmanuel Vadot #ifdef FDT
115*b2f0caf1SEmmanuel Vadot 	 phandle_t 		ofw_node;	/* OFW node of regulator */
116*b2f0caf1SEmmanuel Vadot #endif
117*b2f0caf1SEmmanuel Vadot 	int			flags;		/* REGULATOR_FLAGS_ */
118*b2f0caf1SEmmanuel Vadot 	struct sx		lock;		/* Lock for this regulator */
119*b2f0caf1SEmmanuel Vadot 	int			ref_cnt;	/* Reference counter */
120*b2f0caf1SEmmanuel Vadot 	int			enable_cnt;	/* Enabled counter */
121*b2f0caf1SEmmanuel Vadot 
122*b2f0caf1SEmmanuel Vadot 	struct regnode_std_param std_param;	/* Standard parameters */
123*b2f0caf1SEmmanuel Vadot 
124*b2f0caf1SEmmanuel Vadot 	struct sysctl_ctx_list	sysctl_ctx;
125*b2f0caf1SEmmanuel Vadot };
126*b2f0caf1SEmmanuel Vadot 
127*b2f0caf1SEmmanuel Vadot /*
128*b2f0caf1SEmmanuel Vadot  * Per consumer data, information about how a consumer is using a regulator
129*b2f0caf1SEmmanuel Vadot  * node.
130*b2f0caf1SEmmanuel Vadot  * A pointer to this structure is used as a handle in the consumer interface.
131*b2f0caf1SEmmanuel Vadot  */
132*b2f0caf1SEmmanuel Vadot struct regulator {
133*b2f0caf1SEmmanuel Vadot 	device_t		cdev;		/* Consumer device */
134*b2f0caf1SEmmanuel Vadot 	struct regnode		*regnode;
135*b2f0caf1SEmmanuel Vadot 	TAILQ_ENTRY(regulator)	link;		/* Consumers list entry */
136*b2f0caf1SEmmanuel Vadot 
137*b2f0caf1SEmmanuel Vadot 	int			enable_cnt;
138*b2f0caf1SEmmanuel Vadot 	int 			min_uvolt;	/* Requested uvolt range */
139*b2f0caf1SEmmanuel Vadot 	int 			max_uvolt;
140*b2f0caf1SEmmanuel Vadot };
141*b2f0caf1SEmmanuel Vadot 
142*b2f0caf1SEmmanuel Vadot /*
143*b2f0caf1SEmmanuel Vadot  * Regulator names must be system wide unique.
144*b2f0caf1SEmmanuel Vadot  */
145*b2f0caf1SEmmanuel Vadot static regnode_list_t regnode_list = TAILQ_HEAD_INITIALIZER(regnode_list);
146*b2f0caf1SEmmanuel Vadot 
147*b2f0caf1SEmmanuel Vadot static struct sx		regnode_topo_lock;
148*b2f0caf1SEmmanuel Vadot SX_SYSINIT(regulator_topology, &regnode_topo_lock, "Regulator topology lock");
149*b2f0caf1SEmmanuel Vadot 
150*b2f0caf1SEmmanuel Vadot #define REG_TOPO_SLOCK()	sx_slock(&regnode_topo_lock)
151*b2f0caf1SEmmanuel Vadot #define REG_TOPO_XLOCK()	sx_xlock(&regnode_topo_lock)
152*b2f0caf1SEmmanuel Vadot #define REG_TOPO_UNLOCK()	sx_unlock(&regnode_topo_lock)
153*b2f0caf1SEmmanuel Vadot #define REG_TOPO_ASSERT()	sx_assert(&regnode_topo_lock, SA_LOCKED)
154*b2f0caf1SEmmanuel Vadot #define REG_TOPO_XASSERT() 	sx_assert(&regnode_topo_lock, SA_XLOCKED)
155*b2f0caf1SEmmanuel Vadot 
156*b2f0caf1SEmmanuel Vadot #define REGNODE_SLOCK(_sc)	sx_slock(&((_sc)->lock))
157*b2f0caf1SEmmanuel Vadot #define REGNODE_XLOCK(_sc)	sx_xlock(&((_sc)->lock))
158*b2f0caf1SEmmanuel Vadot #define REGNODE_UNLOCK(_sc)	sx_unlock(&((_sc)->lock))
159*b2f0caf1SEmmanuel Vadot 
160*b2f0caf1SEmmanuel Vadot SYSINIT(regulator_constraint, SI_SUB_LAST, SI_ORDER_ANY, regulator_constraint,
161*b2f0caf1SEmmanuel Vadot     NULL);
162*b2f0caf1SEmmanuel Vadot SYSINIT(regulator_shutdown, SI_SUB_LAST, SI_ORDER_ANY, regulator_shutdown,
163*b2f0caf1SEmmanuel Vadot     NULL);
164*b2f0caf1SEmmanuel Vadot 
165*b2f0caf1SEmmanuel Vadot static void
regulator_constraint(void * dummy)166*b2f0caf1SEmmanuel Vadot regulator_constraint(void *dummy)
167*b2f0caf1SEmmanuel Vadot {
168*b2f0caf1SEmmanuel Vadot 	struct regnode *entry;
169*b2f0caf1SEmmanuel Vadot 	int rv;
170*b2f0caf1SEmmanuel Vadot 
171*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
172*b2f0caf1SEmmanuel Vadot 	TAILQ_FOREACH(entry, &regnode_list, reglist_link) {
173*b2f0caf1SEmmanuel Vadot 		rv = regnode_set_constraint(entry);
174*b2f0caf1SEmmanuel Vadot 		if (rv != 0 && bootverbose)
175*b2f0caf1SEmmanuel Vadot 			printf("regulator: setting constraint on %s failed (%d)\n",
176*b2f0caf1SEmmanuel Vadot 			    entry->name, rv);
177*b2f0caf1SEmmanuel Vadot 	}
178*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
179*b2f0caf1SEmmanuel Vadot }
180*b2f0caf1SEmmanuel Vadot 
181*b2f0caf1SEmmanuel Vadot /*
182*b2f0caf1SEmmanuel Vadot  * Disable unused regulator
183*b2f0caf1SEmmanuel Vadot  * We run this function at SI_SUB_LAST which mean that every driver that needs
184*b2f0caf1SEmmanuel Vadot  * regulator should have already enable them.
185*b2f0caf1SEmmanuel Vadot  * All the remaining regulators should be those left enabled by the bootloader
186*b2f0caf1SEmmanuel Vadot  * or enable by default by the PMIC.
187*b2f0caf1SEmmanuel Vadot  */
188*b2f0caf1SEmmanuel Vadot static void
regulator_shutdown(void * dummy)189*b2f0caf1SEmmanuel Vadot regulator_shutdown(void *dummy)
190*b2f0caf1SEmmanuel Vadot {
191*b2f0caf1SEmmanuel Vadot 	struct regnode *entry;
192*b2f0caf1SEmmanuel Vadot 	int status, ret;
193*b2f0caf1SEmmanuel Vadot 	int disable = 1;
194*b2f0caf1SEmmanuel Vadot 
195*b2f0caf1SEmmanuel Vadot 	TUNABLE_INT_FETCH("hw.regulator.disable_unused", &disable);
196*b2f0caf1SEmmanuel Vadot 	if (!disable)
197*b2f0caf1SEmmanuel Vadot 		return;
198*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
199*b2f0caf1SEmmanuel Vadot 
200*b2f0caf1SEmmanuel Vadot 	if (bootverbose)
201*b2f0caf1SEmmanuel Vadot 		printf("regulator: shutting down unused regulators\n");
202*b2f0caf1SEmmanuel Vadot 	TAILQ_FOREACH(entry, &regnode_list, reglist_link) {
203*b2f0caf1SEmmanuel Vadot 		if (!entry->std_param.always_on) {
204*b2f0caf1SEmmanuel Vadot 			ret = regnode_status(entry, &status);
205*b2f0caf1SEmmanuel Vadot 			if (ret == 0 && status == REGULATOR_STATUS_ENABLED) {
206*b2f0caf1SEmmanuel Vadot 				if (bootverbose)
207*b2f0caf1SEmmanuel Vadot 					printf("regulator: shutting down %s... ",
208*b2f0caf1SEmmanuel Vadot 					    entry->name);
209*b2f0caf1SEmmanuel Vadot 				ret = regnode_stop(entry, 0);
210*b2f0caf1SEmmanuel Vadot 				if (bootverbose) {
211*b2f0caf1SEmmanuel Vadot 					/*
212*b2f0caf1SEmmanuel Vadot 					 * Call out busy in particular, here,
213*b2f0caf1SEmmanuel Vadot 					 * because it's not unexpected to fail
214*b2f0caf1SEmmanuel Vadot 					 * shutdown if the regulator is simply
215*b2f0caf1SEmmanuel Vadot 					 * in-use.
216*b2f0caf1SEmmanuel Vadot 					 */
217*b2f0caf1SEmmanuel Vadot 					if (ret == EBUSY)
218*b2f0caf1SEmmanuel Vadot 						printf("busy\n");
219*b2f0caf1SEmmanuel Vadot 					else if (ret != 0)
220*b2f0caf1SEmmanuel Vadot 						printf("error (%d)\n", ret);
221*b2f0caf1SEmmanuel Vadot 					else
222*b2f0caf1SEmmanuel Vadot 						printf("ok\n");
223*b2f0caf1SEmmanuel Vadot 				}
224*b2f0caf1SEmmanuel Vadot 			}
225*b2f0caf1SEmmanuel Vadot 		}
226*b2f0caf1SEmmanuel Vadot 	}
227*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
228*b2f0caf1SEmmanuel Vadot }
229*b2f0caf1SEmmanuel Vadot 
230*b2f0caf1SEmmanuel Vadot /*
231*b2f0caf1SEmmanuel Vadot  * sysctl handler
232*b2f0caf1SEmmanuel Vadot  */
233*b2f0caf1SEmmanuel Vadot static int
regnode_uvolt_sysctl(SYSCTL_HANDLER_ARGS)234*b2f0caf1SEmmanuel Vadot regnode_uvolt_sysctl(SYSCTL_HANDLER_ARGS)
235*b2f0caf1SEmmanuel Vadot {
236*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode = arg1;
237*b2f0caf1SEmmanuel Vadot 	int rv, uvolt;
238*b2f0caf1SEmmanuel Vadot 
239*b2f0caf1SEmmanuel Vadot 	if (regnode->std_param.min_uvolt == regnode->std_param.max_uvolt) {
240*b2f0caf1SEmmanuel Vadot 		uvolt = regnode->std_param.min_uvolt;
241*b2f0caf1SEmmanuel Vadot 	} else {
242*b2f0caf1SEmmanuel Vadot 		REG_TOPO_SLOCK();
243*b2f0caf1SEmmanuel Vadot 		if ((rv = regnode_get_voltage(regnode, &uvolt)) != 0) {
244*b2f0caf1SEmmanuel Vadot 			REG_TOPO_UNLOCK();
245*b2f0caf1SEmmanuel Vadot 			return (rv);
246*b2f0caf1SEmmanuel Vadot 		}
247*b2f0caf1SEmmanuel Vadot 		REG_TOPO_UNLOCK();
248*b2f0caf1SEmmanuel Vadot 	}
249*b2f0caf1SEmmanuel Vadot 
250*b2f0caf1SEmmanuel Vadot 	return sysctl_handle_int(oidp, &uvolt, sizeof(uvolt), req);
251*b2f0caf1SEmmanuel Vadot }
252*b2f0caf1SEmmanuel Vadot 
253*b2f0caf1SEmmanuel Vadot /* ----------------------------------------------------------------------------
254*b2f0caf1SEmmanuel Vadot  *
255*b2f0caf1SEmmanuel Vadot  * Default regulator methods for base class.
256*b2f0caf1SEmmanuel Vadot  *
257*b2f0caf1SEmmanuel Vadot  */
258*b2f0caf1SEmmanuel Vadot static int
regnode_method_init(struct regnode * regnode)259*b2f0caf1SEmmanuel Vadot regnode_method_init(struct regnode *regnode)
260*b2f0caf1SEmmanuel Vadot {
261*b2f0caf1SEmmanuel Vadot 
262*b2f0caf1SEmmanuel Vadot 	return (0);
263*b2f0caf1SEmmanuel Vadot }
264*b2f0caf1SEmmanuel Vadot 
265*b2f0caf1SEmmanuel Vadot static int
regnode_method_enable(struct regnode * regnode,bool enable,int * udelay)266*b2f0caf1SEmmanuel Vadot regnode_method_enable(struct regnode *regnode, bool enable, int *udelay)
267*b2f0caf1SEmmanuel Vadot {
268*b2f0caf1SEmmanuel Vadot 
269*b2f0caf1SEmmanuel Vadot 	if (!enable)
270*b2f0caf1SEmmanuel Vadot 		return (ENXIO);
271*b2f0caf1SEmmanuel Vadot 
272*b2f0caf1SEmmanuel Vadot 	*udelay = 0;
273*b2f0caf1SEmmanuel Vadot 	return (0);
274*b2f0caf1SEmmanuel Vadot }
275*b2f0caf1SEmmanuel Vadot 
276*b2f0caf1SEmmanuel Vadot static int
regnode_method_status(struct regnode * regnode,int * status)277*b2f0caf1SEmmanuel Vadot regnode_method_status(struct regnode *regnode, int *status)
278*b2f0caf1SEmmanuel Vadot {
279*b2f0caf1SEmmanuel Vadot 	*status = REGULATOR_STATUS_ENABLED;
280*b2f0caf1SEmmanuel Vadot 	return (0);
281*b2f0caf1SEmmanuel Vadot }
282*b2f0caf1SEmmanuel Vadot 
283*b2f0caf1SEmmanuel Vadot static int
regnode_method_set_voltage(struct regnode * regnode,int min_uvolt,int max_uvolt,int * udelay)284*b2f0caf1SEmmanuel Vadot regnode_method_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt,
285*b2f0caf1SEmmanuel Vadot     int *udelay)
286*b2f0caf1SEmmanuel Vadot {
287*b2f0caf1SEmmanuel Vadot 
288*b2f0caf1SEmmanuel Vadot 	if ((min_uvolt > regnode->std_param.max_uvolt) ||
289*b2f0caf1SEmmanuel Vadot 	    (max_uvolt < regnode->std_param.min_uvolt))
290*b2f0caf1SEmmanuel Vadot 		return (ERANGE);
291*b2f0caf1SEmmanuel Vadot 	*udelay = 0;
292*b2f0caf1SEmmanuel Vadot 	return (0);
293*b2f0caf1SEmmanuel Vadot }
294*b2f0caf1SEmmanuel Vadot 
295*b2f0caf1SEmmanuel Vadot static int
regnode_method_get_voltage(struct regnode * regnode,int * uvolt)296*b2f0caf1SEmmanuel Vadot regnode_method_get_voltage(struct regnode *regnode, int *uvolt)
297*b2f0caf1SEmmanuel Vadot {
298*b2f0caf1SEmmanuel Vadot 
299*b2f0caf1SEmmanuel Vadot 	*uvolt = regnode->std_param.min_uvolt +
300*b2f0caf1SEmmanuel Vadot 	    (regnode->std_param.max_uvolt - regnode->std_param.min_uvolt) / 2;
301*b2f0caf1SEmmanuel Vadot 	return (0);
302*b2f0caf1SEmmanuel Vadot }
303*b2f0caf1SEmmanuel Vadot 
304*b2f0caf1SEmmanuel Vadot int
regnode_method_check_voltage(struct regnode * regnode,int uvolt)305*b2f0caf1SEmmanuel Vadot regnode_method_check_voltage(struct regnode *regnode, int uvolt)
306*b2f0caf1SEmmanuel Vadot {
307*b2f0caf1SEmmanuel Vadot 
308*b2f0caf1SEmmanuel Vadot 	if ((uvolt > regnode->std_param.max_uvolt) ||
309*b2f0caf1SEmmanuel Vadot 	    (uvolt < regnode->std_param.min_uvolt))
310*b2f0caf1SEmmanuel Vadot 		return (ERANGE);
311*b2f0caf1SEmmanuel Vadot 	return (0);
312*b2f0caf1SEmmanuel Vadot }
313*b2f0caf1SEmmanuel Vadot 
314*b2f0caf1SEmmanuel Vadot /* ----------------------------------------------------------------------------
315*b2f0caf1SEmmanuel Vadot  *
316*b2f0caf1SEmmanuel Vadot  * Internal functions.
317*b2f0caf1SEmmanuel Vadot  *
318*b2f0caf1SEmmanuel Vadot  */
319*b2f0caf1SEmmanuel Vadot 
320*b2f0caf1SEmmanuel Vadot static struct regnode *
regnode_find_by_name(const char * name)321*b2f0caf1SEmmanuel Vadot regnode_find_by_name(const char *name)
322*b2f0caf1SEmmanuel Vadot {
323*b2f0caf1SEmmanuel Vadot 	struct regnode *entry;
324*b2f0caf1SEmmanuel Vadot 
325*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
326*b2f0caf1SEmmanuel Vadot 
327*b2f0caf1SEmmanuel Vadot 	TAILQ_FOREACH(entry, &regnode_list, reglist_link) {
328*b2f0caf1SEmmanuel Vadot 		if (strcmp(entry->name, name) == 0)
329*b2f0caf1SEmmanuel Vadot 			return (entry);
330*b2f0caf1SEmmanuel Vadot 	}
331*b2f0caf1SEmmanuel Vadot 	return (NULL);
332*b2f0caf1SEmmanuel Vadot }
333*b2f0caf1SEmmanuel Vadot 
334*b2f0caf1SEmmanuel Vadot static struct regnode *
regnode_find_by_id(device_t dev,intptr_t id)335*b2f0caf1SEmmanuel Vadot regnode_find_by_id(device_t dev, intptr_t id)
336*b2f0caf1SEmmanuel Vadot {
337*b2f0caf1SEmmanuel Vadot 	struct regnode *entry;
338*b2f0caf1SEmmanuel Vadot 
339*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
340*b2f0caf1SEmmanuel Vadot 
341*b2f0caf1SEmmanuel Vadot 	TAILQ_FOREACH(entry, &regnode_list, reglist_link) {
342*b2f0caf1SEmmanuel Vadot 		if ((entry->pdev == dev) && (entry->id ==  id))
343*b2f0caf1SEmmanuel Vadot 			return (entry);
344*b2f0caf1SEmmanuel Vadot 	}
345*b2f0caf1SEmmanuel Vadot 
346*b2f0caf1SEmmanuel Vadot 	return (NULL);
347*b2f0caf1SEmmanuel Vadot }
348*b2f0caf1SEmmanuel Vadot 
349*b2f0caf1SEmmanuel Vadot /*
350*b2f0caf1SEmmanuel Vadot  * Create and initialize regulator object, but do not register it.
351*b2f0caf1SEmmanuel Vadot  */
352*b2f0caf1SEmmanuel Vadot struct regnode *
regnode_create(device_t pdev,regnode_class_t regnode_class,struct regnode_init_def * def)353*b2f0caf1SEmmanuel Vadot regnode_create(device_t pdev, regnode_class_t regnode_class,
354*b2f0caf1SEmmanuel Vadot     struct regnode_init_def *def)
355*b2f0caf1SEmmanuel Vadot {
356*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
357*b2f0caf1SEmmanuel Vadot 	struct sysctl_oid *regnode_oid;
358*b2f0caf1SEmmanuel Vadot 
359*b2f0caf1SEmmanuel Vadot 	KASSERT(def->name != NULL, ("regulator name is NULL"));
360*b2f0caf1SEmmanuel Vadot 	KASSERT(def->name[0] != '\0', ("regulator name is empty"));
361*b2f0caf1SEmmanuel Vadot 
362*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
363*b2f0caf1SEmmanuel Vadot 	if (regnode_find_by_name(def->name) != NULL)
364*b2f0caf1SEmmanuel Vadot 		panic("Duplicated regulator registration: %s\n", def->name);
365*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
366*b2f0caf1SEmmanuel Vadot 
367*b2f0caf1SEmmanuel Vadot 	/* Create object and initialize it. */
368*b2f0caf1SEmmanuel Vadot 	regnode = malloc(sizeof(struct regnode), M_REGULATOR,
369*b2f0caf1SEmmanuel Vadot 	    M_WAITOK | M_ZERO);
370*b2f0caf1SEmmanuel Vadot 	kobj_init((kobj_t)regnode, (kobj_class_t)regnode_class);
371*b2f0caf1SEmmanuel Vadot 	sx_init(&regnode->lock, "Regulator node lock");
372*b2f0caf1SEmmanuel Vadot 
373*b2f0caf1SEmmanuel Vadot 	/* Allocate softc if required. */
374*b2f0caf1SEmmanuel Vadot 	if (regnode_class->size > 0) {
375*b2f0caf1SEmmanuel Vadot 		regnode->softc = malloc(regnode_class->size, M_REGULATOR,
376*b2f0caf1SEmmanuel Vadot 		    M_WAITOK | M_ZERO);
377*b2f0caf1SEmmanuel Vadot 	}
378*b2f0caf1SEmmanuel Vadot 
379*b2f0caf1SEmmanuel Vadot 
380*b2f0caf1SEmmanuel Vadot 	/* Copy all strings unless they're flagged as static. */
381*b2f0caf1SEmmanuel Vadot 	if (def->flags & REGULATOR_FLAGS_STATIC) {
382*b2f0caf1SEmmanuel Vadot 		regnode->name = def->name;
383*b2f0caf1SEmmanuel Vadot 		regnode->parent_name = def->parent_name;
384*b2f0caf1SEmmanuel Vadot 	} else {
385*b2f0caf1SEmmanuel Vadot 		regnode->name = strdup(def->name, M_REGULATOR);
386*b2f0caf1SEmmanuel Vadot 		if (def->parent_name != NULL)
387*b2f0caf1SEmmanuel Vadot 			regnode->parent_name = strdup(def->parent_name,
388*b2f0caf1SEmmanuel Vadot 			    M_REGULATOR);
389*b2f0caf1SEmmanuel Vadot 	}
390*b2f0caf1SEmmanuel Vadot 
391*b2f0caf1SEmmanuel Vadot 	/* Rest of init. */
392*b2f0caf1SEmmanuel Vadot 	TAILQ_INIT(&regnode->consumers_list);
393*b2f0caf1SEmmanuel Vadot 	regnode->id = def->id;
394*b2f0caf1SEmmanuel Vadot 	regnode->pdev = pdev;
395*b2f0caf1SEmmanuel Vadot 	regnode->flags = def->flags;
396*b2f0caf1SEmmanuel Vadot 	regnode->parent = NULL;
397*b2f0caf1SEmmanuel Vadot 	regnode->std_param = def->std_param;
398*b2f0caf1SEmmanuel Vadot #ifdef FDT
399*b2f0caf1SEmmanuel Vadot 	regnode->ofw_node = def->ofw_node;
400*b2f0caf1SEmmanuel Vadot #endif
401*b2f0caf1SEmmanuel Vadot 
402*b2f0caf1SEmmanuel Vadot 	sysctl_ctx_init(&regnode->sysctl_ctx);
403*b2f0caf1SEmmanuel Vadot 	regnode_oid = SYSCTL_ADD_NODE(&regnode->sysctl_ctx,
404*b2f0caf1SEmmanuel Vadot 	    SYSCTL_STATIC_CHILDREN(_hw_regulator),
405*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, regnode->name,
406*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "A regulator node");
407*b2f0caf1SEmmanuel Vadot 
408*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_INT(&regnode->sysctl_ctx,
409*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
410*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "min_uvolt",
411*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, &regnode->std_param.min_uvolt, 0,
412*b2f0caf1SEmmanuel Vadot 	    "Minimal voltage (in uV)");
413*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_INT(&regnode->sysctl_ctx,
414*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
415*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "max_uvolt",
416*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, &regnode->std_param.max_uvolt, 0,
417*b2f0caf1SEmmanuel Vadot 	    "Maximal voltage (in uV)");
418*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_INT(&regnode->sysctl_ctx,
419*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
420*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "min_uamp",
421*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, &regnode->std_param.min_uamp, 0,
422*b2f0caf1SEmmanuel Vadot 	    "Minimal amperage (in uA)");
423*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_INT(&regnode->sysctl_ctx,
424*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
425*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "max_uamp",
426*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, &regnode->std_param.max_uamp, 0,
427*b2f0caf1SEmmanuel Vadot 	    "Maximal amperage (in uA)");
428*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_INT(&regnode->sysctl_ctx,
429*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
430*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "ramp_delay",
431*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, &regnode->std_param.ramp_delay, 0,
432*b2f0caf1SEmmanuel Vadot 	    "Ramp delay (in uV/us)");
433*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_INT(&regnode->sysctl_ctx,
434*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
435*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "enable_delay",
436*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, &regnode->std_param.enable_delay, 0,
437*b2f0caf1SEmmanuel Vadot 	    "Enable delay (in us)");
438*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_INT(&regnode->sysctl_ctx,
439*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
440*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "enable_cnt",
441*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, &regnode->enable_cnt, 0,
442*b2f0caf1SEmmanuel Vadot 	    "The regulator enable counter");
443*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_U8(&regnode->sysctl_ctx,
444*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
445*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "boot_on",
446*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, (uint8_t *) &regnode->std_param.boot_on, 0,
447*b2f0caf1SEmmanuel Vadot 	    "Is enabled on boot");
448*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_U8(&regnode->sysctl_ctx,
449*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
450*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "always_on",
451*b2f0caf1SEmmanuel Vadot 	    CTLFLAG_RD, (uint8_t *)&regnode->std_param.always_on, 0,
452*b2f0caf1SEmmanuel Vadot 	    "Is always enabled");
453*b2f0caf1SEmmanuel Vadot 
454*b2f0caf1SEmmanuel Vadot 	SYSCTL_ADD_PROC(&regnode->sysctl_ctx,
455*b2f0caf1SEmmanuel Vadot 	    SYSCTL_CHILDREN(regnode_oid),
456*b2f0caf1SEmmanuel Vadot 	    OID_AUTO, "uvolt",
457*b2f0caf1SEmmanuel Vadot 	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
458*b2f0caf1SEmmanuel Vadot 	    regnode, 0, regnode_uvolt_sysctl,
459*b2f0caf1SEmmanuel Vadot 	    "I",
460*b2f0caf1SEmmanuel Vadot 	    "Current voltage (in uV)");
461*b2f0caf1SEmmanuel Vadot 
462*b2f0caf1SEmmanuel Vadot 	return (regnode);
463*b2f0caf1SEmmanuel Vadot }
464*b2f0caf1SEmmanuel Vadot 
465*b2f0caf1SEmmanuel Vadot /* Register regulator object. */
466*b2f0caf1SEmmanuel Vadot struct regnode *
regnode_register(struct regnode * regnode)467*b2f0caf1SEmmanuel Vadot regnode_register(struct regnode *regnode)
468*b2f0caf1SEmmanuel Vadot {
469*b2f0caf1SEmmanuel Vadot 	int rv;
470*b2f0caf1SEmmanuel Vadot 
471*b2f0caf1SEmmanuel Vadot #ifdef FDT
472*b2f0caf1SEmmanuel Vadot 	if (regnode->ofw_node <= 0)
473*b2f0caf1SEmmanuel Vadot 		regnode->ofw_node = ofw_bus_get_node(regnode->pdev);
474*b2f0caf1SEmmanuel Vadot 	if (regnode->ofw_node <= 0)
475*b2f0caf1SEmmanuel Vadot 		return (NULL);
476*b2f0caf1SEmmanuel Vadot #endif
477*b2f0caf1SEmmanuel Vadot 
478*b2f0caf1SEmmanuel Vadot 	rv = REGNODE_INIT(regnode);
479*b2f0caf1SEmmanuel Vadot 	if (rv != 0) {
480*b2f0caf1SEmmanuel Vadot 		printf("REGNODE_INIT failed: %d\n", rv);
481*b2f0caf1SEmmanuel Vadot 		return (NULL);
482*b2f0caf1SEmmanuel Vadot 	}
483*b2f0caf1SEmmanuel Vadot 
484*b2f0caf1SEmmanuel Vadot 	REG_TOPO_XLOCK();
485*b2f0caf1SEmmanuel Vadot 	TAILQ_INSERT_TAIL(&regnode_list, regnode, reglist_link);
486*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
487*b2f0caf1SEmmanuel Vadot #ifdef FDT
488*b2f0caf1SEmmanuel Vadot 	OF_device_register_xref(OF_xref_from_node(regnode->ofw_node),
489*b2f0caf1SEmmanuel Vadot 	    regnode->pdev);
490*b2f0caf1SEmmanuel Vadot #endif
491*b2f0caf1SEmmanuel Vadot 	return (regnode);
492*b2f0caf1SEmmanuel Vadot }
493*b2f0caf1SEmmanuel Vadot 
494*b2f0caf1SEmmanuel Vadot static int
regnode_resolve_parent(struct regnode * regnode)495*b2f0caf1SEmmanuel Vadot regnode_resolve_parent(struct regnode *regnode)
496*b2f0caf1SEmmanuel Vadot {
497*b2f0caf1SEmmanuel Vadot 
498*b2f0caf1SEmmanuel Vadot 	/* All ready resolved or no parent? */
499*b2f0caf1SEmmanuel Vadot 	if ((regnode->parent != NULL) ||
500*b2f0caf1SEmmanuel Vadot 	    (regnode->parent_name == NULL))
501*b2f0caf1SEmmanuel Vadot 		return (0);
502*b2f0caf1SEmmanuel Vadot 
503*b2f0caf1SEmmanuel Vadot 	regnode->parent = regnode_find_by_name(regnode->parent_name);
504*b2f0caf1SEmmanuel Vadot 	if (regnode->parent == NULL)
505*b2f0caf1SEmmanuel Vadot 		return (ENODEV);
506*b2f0caf1SEmmanuel Vadot 	return (0);
507*b2f0caf1SEmmanuel Vadot }
508*b2f0caf1SEmmanuel Vadot 
509*b2f0caf1SEmmanuel Vadot static void
regnode_delay(int usec)510*b2f0caf1SEmmanuel Vadot regnode_delay(int usec)
511*b2f0caf1SEmmanuel Vadot {
512*b2f0caf1SEmmanuel Vadot 	int ticks;
513*b2f0caf1SEmmanuel Vadot 
514*b2f0caf1SEmmanuel Vadot 	if (usec == 0)
515*b2f0caf1SEmmanuel Vadot 		return;
516*b2f0caf1SEmmanuel Vadot 	ticks = (usec * hz + 999999) / 1000000;
517*b2f0caf1SEmmanuel Vadot 
518*b2f0caf1SEmmanuel Vadot 	if (cold || ticks < 2)
519*b2f0caf1SEmmanuel Vadot 		DELAY(usec);
520*b2f0caf1SEmmanuel Vadot 	else
521*b2f0caf1SEmmanuel Vadot 		pause("REGULATOR", ticks);
522*b2f0caf1SEmmanuel Vadot }
523*b2f0caf1SEmmanuel Vadot 
524*b2f0caf1SEmmanuel Vadot /* --------------------------------------------------------------------------
525*b2f0caf1SEmmanuel Vadot  *
526*b2f0caf1SEmmanuel Vadot  * Regulator providers interface
527*b2f0caf1SEmmanuel Vadot  *
528*b2f0caf1SEmmanuel Vadot  */
529*b2f0caf1SEmmanuel Vadot 
530*b2f0caf1SEmmanuel Vadot const char *
regnode_get_name(struct regnode * regnode)531*b2f0caf1SEmmanuel Vadot regnode_get_name(struct regnode *regnode)
532*b2f0caf1SEmmanuel Vadot {
533*b2f0caf1SEmmanuel Vadot 
534*b2f0caf1SEmmanuel Vadot 	return (regnode->name);
535*b2f0caf1SEmmanuel Vadot }
536*b2f0caf1SEmmanuel Vadot 
537*b2f0caf1SEmmanuel Vadot const char *
regnode_get_parent_name(struct regnode * regnode)538*b2f0caf1SEmmanuel Vadot regnode_get_parent_name(struct regnode *regnode)
539*b2f0caf1SEmmanuel Vadot {
540*b2f0caf1SEmmanuel Vadot 
541*b2f0caf1SEmmanuel Vadot 	return (regnode->parent_name);
542*b2f0caf1SEmmanuel Vadot }
543*b2f0caf1SEmmanuel Vadot 
544*b2f0caf1SEmmanuel Vadot int
regnode_get_flags(struct regnode * regnode)545*b2f0caf1SEmmanuel Vadot regnode_get_flags(struct regnode *regnode)
546*b2f0caf1SEmmanuel Vadot {
547*b2f0caf1SEmmanuel Vadot 
548*b2f0caf1SEmmanuel Vadot 	return (regnode->flags);
549*b2f0caf1SEmmanuel Vadot }
550*b2f0caf1SEmmanuel Vadot 
551*b2f0caf1SEmmanuel Vadot void *
regnode_get_softc(struct regnode * regnode)552*b2f0caf1SEmmanuel Vadot regnode_get_softc(struct regnode *regnode)
553*b2f0caf1SEmmanuel Vadot {
554*b2f0caf1SEmmanuel Vadot 
555*b2f0caf1SEmmanuel Vadot 	return (regnode->softc);
556*b2f0caf1SEmmanuel Vadot }
557*b2f0caf1SEmmanuel Vadot 
558*b2f0caf1SEmmanuel Vadot device_t
regnode_get_device(struct regnode * regnode)559*b2f0caf1SEmmanuel Vadot regnode_get_device(struct regnode *regnode)
560*b2f0caf1SEmmanuel Vadot {
561*b2f0caf1SEmmanuel Vadot 
562*b2f0caf1SEmmanuel Vadot 	return (regnode->pdev);
563*b2f0caf1SEmmanuel Vadot }
564*b2f0caf1SEmmanuel Vadot 
regnode_get_stdparam(struct regnode * regnode)565*b2f0caf1SEmmanuel Vadot struct regnode_std_param *regnode_get_stdparam(struct regnode *regnode)
566*b2f0caf1SEmmanuel Vadot {
567*b2f0caf1SEmmanuel Vadot 
568*b2f0caf1SEmmanuel Vadot 	return (&regnode->std_param);
569*b2f0caf1SEmmanuel Vadot }
570*b2f0caf1SEmmanuel Vadot 
regnode_topo_unlock(void)571*b2f0caf1SEmmanuel Vadot void regnode_topo_unlock(void)
572*b2f0caf1SEmmanuel Vadot {
573*b2f0caf1SEmmanuel Vadot 
574*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
575*b2f0caf1SEmmanuel Vadot }
576*b2f0caf1SEmmanuel Vadot 
regnode_topo_xlock(void)577*b2f0caf1SEmmanuel Vadot void regnode_topo_xlock(void)
578*b2f0caf1SEmmanuel Vadot {
579*b2f0caf1SEmmanuel Vadot 
580*b2f0caf1SEmmanuel Vadot 	REG_TOPO_XLOCK();
581*b2f0caf1SEmmanuel Vadot }
582*b2f0caf1SEmmanuel Vadot 
regnode_topo_slock(void)583*b2f0caf1SEmmanuel Vadot void regnode_topo_slock(void)
584*b2f0caf1SEmmanuel Vadot {
585*b2f0caf1SEmmanuel Vadot 
586*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
587*b2f0caf1SEmmanuel Vadot }
588*b2f0caf1SEmmanuel Vadot 
589*b2f0caf1SEmmanuel Vadot 
590*b2f0caf1SEmmanuel Vadot /* --------------------------------------------------------------------------
591*b2f0caf1SEmmanuel Vadot  *
592*b2f0caf1SEmmanuel Vadot  * Real consumers executive
593*b2f0caf1SEmmanuel Vadot  *
594*b2f0caf1SEmmanuel Vadot  */
595*b2f0caf1SEmmanuel Vadot struct regnode *
regnode_get_parent(struct regnode * regnode)596*b2f0caf1SEmmanuel Vadot regnode_get_parent(struct regnode *regnode)
597*b2f0caf1SEmmanuel Vadot {
598*b2f0caf1SEmmanuel Vadot 	int rv;
599*b2f0caf1SEmmanuel Vadot 
600*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
601*b2f0caf1SEmmanuel Vadot 
602*b2f0caf1SEmmanuel Vadot 	rv = regnode_resolve_parent(regnode);
603*b2f0caf1SEmmanuel Vadot 	if (rv != 0)
604*b2f0caf1SEmmanuel Vadot 		return (NULL);
605*b2f0caf1SEmmanuel Vadot 
606*b2f0caf1SEmmanuel Vadot 	return (regnode->parent);
607*b2f0caf1SEmmanuel Vadot }
608*b2f0caf1SEmmanuel Vadot 
609*b2f0caf1SEmmanuel Vadot /*
610*b2f0caf1SEmmanuel Vadot  * Enable regulator.
611*b2f0caf1SEmmanuel Vadot  */
612*b2f0caf1SEmmanuel Vadot int
regnode_enable(struct regnode * regnode)613*b2f0caf1SEmmanuel Vadot regnode_enable(struct regnode *regnode)
614*b2f0caf1SEmmanuel Vadot {
615*b2f0caf1SEmmanuel Vadot 	int udelay;
616*b2f0caf1SEmmanuel Vadot 	int rv;
617*b2f0caf1SEmmanuel Vadot 
618*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
619*b2f0caf1SEmmanuel Vadot 
620*b2f0caf1SEmmanuel Vadot 	/* Enable regulator for each node in chain, starting from source. */
621*b2f0caf1SEmmanuel Vadot 	rv = regnode_resolve_parent(regnode);
622*b2f0caf1SEmmanuel Vadot 	if (rv != 0)
623*b2f0caf1SEmmanuel Vadot 		return (rv);
624*b2f0caf1SEmmanuel Vadot 	if (regnode->parent != NULL) {
625*b2f0caf1SEmmanuel Vadot 		rv = regnode_enable(regnode->parent);
626*b2f0caf1SEmmanuel Vadot 		if (rv != 0)
627*b2f0caf1SEmmanuel Vadot 			return (rv);
628*b2f0caf1SEmmanuel Vadot 	}
629*b2f0caf1SEmmanuel Vadot 
630*b2f0caf1SEmmanuel Vadot 	/* Handle this node. */
631*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
632*b2f0caf1SEmmanuel Vadot 	if (regnode->enable_cnt == 0) {
633*b2f0caf1SEmmanuel Vadot 		rv = REGNODE_ENABLE(regnode, true, &udelay);
634*b2f0caf1SEmmanuel Vadot 		if (rv != 0) {
635*b2f0caf1SEmmanuel Vadot 			REGNODE_UNLOCK(regnode);
636*b2f0caf1SEmmanuel Vadot 			return (rv);
637*b2f0caf1SEmmanuel Vadot 		}
638*b2f0caf1SEmmanuel Vadot 		regnode_delay(udelay);
639*b2f0caf1SEmmanuel Vadot 	}
640*b2f0caf1SEmmanuel Vadot 	regnode->enable_cnt++;
641*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
642*b2f0caf1SEmmanuel Vadot 	return (0);
643*b2f0caf1SEmmanuel Vadot }
644*b2f0caf1SEmmanuel Vadot 
645*b2f0caf1SEmmanuel Vadot /*
646*b2f0caf1SEmmanuel Vadot  * Disable regulator.
647*b2f0caf1SEmmanuel Vadot  */
648*b2f0caf1SEmmanuel Vadot int
regnode_disable(struct regnode * regnode)649*b2f0caf1SEmmanuel Vadot regnode_disable(struct regnode *regnode)
650*b2f0caf1SEmmanuel Vadot {
651*b2f0caf1SEmmanuel Vadot 	int udelay;
652*b2f0caf1SEmmanuel Vadot 	int rv;
653*b2f0caf1SEmmanuel Vadot 
654*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
655*b2f0caf1SEmmanuel Vadot 	rv = 0;
656*b2f0caf1SEmmanuel Vadot 
657*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
658*b2f0caf1SEmmanuel Vadot 	/* Disable regulator for each node in chain, starting from consumer. */
659*b2f0caf1SEmmanuel Vadot 	if (regnode->enable_cnt == 1 &&
660*b2f0caf1SEmmanuel Vadot 	    (regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0 &&
661*b2f0caf1SEmmanuel Vadot 	    !regnode->std_param.always_on) {
662*b2f0caf1SEmmanuel Vadot 		rv = REGNODE_ENABLE(regnode, false, &udelay);
663*b2f0caf1SEmmanuel Vadot 		if (rv != 0) {
664*b2f0caf1SEmmanuel Vadot 			REGNODE_UNLOCK(regnode);
665*b2f0caf1SEmmanuel Vadot 			return (rv);
666*b2f0caf1SEmmanuel Vadot 		}
667*b2f0caf1SEmmanuel Vadot 		regnode_delay(udelay);
668*b2f0caf1SEmmanuel Vadot 	}
669*b2f0caf1SEmmanuel Vadot 	regnode->enable_cnt--;
670*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
671*b2f0caf1SEmmanuel Vadot 
672*b2f0caf1SEmmanuel Vadot 	rv = regnode_resolve_parent(regnode);
673*b2f0caf1SEmmanuel Vadot 	if (rv != 0)
674*b2f0caf1SEmmanuel Vadot 		return (rv);
675*b2f0caf1SEmmanuel Vadot 	if (regnode->parent != NULL)
676*b2f0caf1SEmmanuel Vadot 		rv = regnode_disable(regnode->parent);
677*b2f0caf1SEmmanuel Vadot 	return (rv);
678*b2f0caf1SEmmanuel Vadot }
679*b2f0caf1SEmmanuel Vadot 
680*b2f0caf1SEmmanuel Vadot /*
681*b2f0caf1SEmmanuel Vadot  * Stop regulator.
682*b2f0caf1SEmmanuel Vadot  */
683*b2f0caf1SEmmanuel Vadot int
regnode_stop(struct regnode * regnode,int depth)684*b2f0caf1SEmmanuel Vadot regnode_stop(struct regnode *regnode, int depth)
685*b2f0caf1SEmmanuel Vadot {
686*b2f0caf1SEmmanuel Vadot 	int udelay;
687*b2f0caf1SEmmanuel Vadot 	int rv;
688*b2f0caf1SEmmanuel Vadot 
689*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
690*b2f0caf1SEmmanuel Vadot 	rv = 0;
691*b2f0caf1SEmmanuel Vadot 
692*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
693*b2f0caf1SEmmanuel Vadot 	/* The first node must not be enabled. */
694*b2f0caf1SEmmanuel Vadot 	if ((regnode->enable_cnt != 0) && (depth == 0)) {
695*b2f0caf1SEmmanuel Vadot 		REGNODE_UNLOCK(regnode);
696*b2f0caf1SEmmanuel Vadot 		return (EBUSY);
697*b2f0caf1SEmmanuel Vadot 	}
698*b2f0caf1SEmmanuel Vadot 	/* Disable regulator for each node in chain, starting from consumer */
699*b2f0caf1SEmmanuel Vadot 	if ((regnode->enable_cnt == 0) &&
700*b2f0caf1SEmmanuel Vadot 	    ((regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0)) {
701*b2f0caf1SEmmanuel Vadot 		rv = REGNODE_STOP(regnode, &udelay);
702*b2f0caf1SEmmanuel Vadot 		if (rv != 0) {
703*b2f0caf1SEmmanuel Vadot 			REGNODE_UNLOCK(regnode);
704*b2f0caf1SEmmanuel Vadot 			return (rv);
705*b2f0caf1SEmmanuel Vadot 		}
706*b2f0caf1SEmmanuel Vadot 		regnode_delay(udelay);
707*b2f0caf1SEmmanuel Vadot 	}
708*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
709*b2f0caf1SEmmanuel Vadot 
710*b2f0caf1SEmmanuel Vadot 	rv = regnode_resolve_parent(regnode);
711*b2f0caf1SEmmanuel Vadot 	if (rv != 0)
712*b2f0caf1SEmmanuel Vadot 		return (rv);
713*b2f0caf1SEmmanuel Vadot 	if (regnode->parent != NULL && regnode->parent->enable_cnt == 0)
714*b2f0caf1SEmmanuel Vadot 		rv = regnode_stop(regnode->parent, depth + 1);
715*b2f0caf1SEmmanuel Vadot 	return (rv);
716*b2f0caf1SEmmanuel Vadot }
717*b2f0caf1SEmmanuel Vadot 
718*b2f0caf1SEmmanuel Vadot /*
719*b2f0caf1SEmmanuel Vadot  * Get regulator status. (REGULATOR_STATUS_*)
720*b2f0caf1SEmmanuel Vadot  */
721*b2f0caf1SEmmanuel Vadot int
regnode_status(struct regnode * regnode,int * status)722*b2f0caf1SEmmanuel Vadot regnode_status(struct regnode *regnode, int *status)
723*b2f0caf1SEmmanuel Vadot {
724*b2f0caf1SEmmanuel Vadot 	int rv;
725*b2f0caf1SEmmanuel Vadot 
726*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
727*b2f0caf1SEmmanuel Vadot 
728*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
729*b2f0caf1SEmmanuel Vadot 	rv = REGNODE_STATUS(regnode, status);
730*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
731*b2f0caf1SEmmanuel Vadot 	return (rv);
732*b2f0caf1SEmmanuel Vadot }
733*b2f0caf1SEmmanuel Vadot 
734*b2f0caf1SEmmanuel Vadot /*
735*b2f0caf1SEmmanuel Vadot  * Get actual regulator voltage.
736*b2f0caf1SEmmanuel Vadot  */
737*b2f0caf1SEmmanuel Vadot int
regnode_get_voltage(struct regnode * regnode,int * uvolt)738*b2f0caf1SEmmanuel Vadot regnode_get_voltage(struct regnode *regnode, int *uvolt)
739*b2f0caf1SEmmanuel Vadot {
740*b2f0caf1SEmmanuel Vadot 	int rv;
741*b2f0caf1SEmmanuel Vadot 
742*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
743*b2f0caf1SEmmanuel Vadot 
744*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
745*b2f0caf1SEmmanuel Vadot 	rv = REGNODE_GET_VOLTAGE(regnode, uvolt);
746*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
747*b2f0caf1SEmmanuel Vadot 
748*b2f0caf1SEmmanuel Vadot 	/* Pass call into parent, if regulator is in bypass mode. */
749*b2f0caf1SEmmanuel Vadot 	if (rv == ENOENT) {
750*b2f0caf1SEmmanuel Vadot 		rv = regnode_resolve_parent(regnode);
751*b2f0caf1SEmmanuel Vadot 		if (rv != 0)
752*b2f0caf1SEmmanuel Vadot 			return (rv);
753*b2f0caf1SEmmanuel Vadot 		if (regnode->parent != NULL)
754*b2f0caf1SEmmanuel Vadot 			rv = regnode_get_voltage(regnode->parent, uvolt);
755*b2f0caf1SEmmanuel Vadot 
756*b2f0caf1SEmmanuel Vadot 	}
757*b2f0caf1SEmmanuel Vadot 	return (rv);
758*b2f0caf1SEmmanuel Vadot }
759*b2f0caf1SEmmanuel Vadot 
760*b2f0caf1SEmmanuel Vadot /*
761*b2f0caf1SEmmanuel Vadot  * Set regulator voltage.
762*b2f0caf1SEmmanuel Vadot  */
763*b2f0caf1SEmmanuel Vadot int
regnode_set_voltage(struct regnode * regnode,int min_uvolt,int max_uvolt)764*b2f0caf1SEmmanuel Vadot regnode_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt)
765*b2f0caf1SEmmanuel Vadot {
766*b2f0caf1SEmmanuel Vadot 	int udelay;
767*b2f0caf1SEmmanuel Vadot 	int rv;
768*b2f0caf1SEmmanuel Vadot 
769*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
770*b2f0caf1SEmmanuel Vadot 
771*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
772*b2f0caf1SEmmanuel Vadot 
773*b2f0caf1SEmmanuel Vadot 	rv = REGNODE_SET_VOLTAGE(regnode, min_uvolt, max_uvolt, &udelay);
774*b2f0caf1SEmmanuel Vadot 	if (rv == 0)
775*b2f0caf1SEmmanuel Vadot 		regnode_delay(udelay);
776*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
777*b2f0caf1SEmmanuel Vadot 	return (rv);
778*b2f0caf1SEmmanuel Vadot }
779*b2f0caf1SEmmanuel Vadot 
780*b2f0caf1SEmmanuel Vadot /*
781*b2f0caf1SEmmanuel Vadot  * Consumer variant of regnode_set_voltage().
782*b2f0caf1SEmmanuel Vadot  */
783*b2f0caf1SEmmanuel Vadot static int
regnode_set_voltage_checked(struct regnode * regnode,struct regulator * reg,int min_uvolt,int max_uvolt)784*b2f0caf1SEmmanuel Vadot regnode_set_voltage_checked(struct regnode *regnode, struct regulator *reg,
785*b2f0caf1SEmmanuel Vadot     int min_uvolt, int max_uvolt)
786*b2f0caf1SEmmanuel Vadot {
787*b2f0caf1SEmmanuel Vadot 	int udelay;
788*b2f0caf1SEmmanuel Vadot 	int all_max_uvolt;
789*b2f0caf1SEmmanuel Vadot 	int all_min_uvolt;
790*b2f0caf1SEmmanuel Vadot 	struct regulator *tmp;
791*b2f0caf1SEmmanuel Vadot 	int rv;
792*b2f0caf1SEmmanuel Vadot 
793*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
794*b2f0caf1SEmmanuel Vadot 
795*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
796*b2f0caf1SEmmanuel Vadot 	/* Return error if requested range is outside of regulator range. */
797*b2f0caf1SEmmanuel Vadot 	if ((min_uvolt > regnode->std_param.max_uvolt) ||
798*b2f0caf1SEmmanuel Vadot 	    (max_uvolt < regnode->std_param.min_uvolt)) {
799*b2f0caf1SEmmanuel Vadot 		REGNODE_UNLOCK(regnode);
800*b2f0caf1SEmmanuel Vadot 		return (ERANGE);
801*b2f0caf1SEmmanuel Vadot 	}
802*b2f0caf1SEmmanuel Vadot 
803*b2f0caf1SEmmanuel Vadot 	/* Get actual voltage range for all consumers. */
804*b2f0caf1SEmmanuel Vadot 	all_min_uvolt = regnode->std_param.min_uvolt;
805*b2f0caf1SEmmanuel Vadot 	all_max_uvolt = regnode->std_param.max_uvolt;
806*b2f0caf1SEmmanuel Vadot 	TAILQ_FOREACH(tmp, &regnode->consumers_list, link) {
807*b2f0caf1SEmmanuel Vadot 		/* Don't take requestor in account. */
808*b2f0caf1SEmmanuel Vadot 		if (tmp == reg)
809*b2f0caf1SEmmanuel Vadot 			continue;
810*b2f0caf1SEmmanuel Vadot 		if (all_min_uvolt < tmp->min_uvolt)
811*b2f0caf1SEmmanuel Vadot 			all_min_uvolt = tmp->min_uvolt;
812*b2f0caf1SEmmanuel Vadot 		if (all_max_uvolt > tmp->max_uvolt)
813*b2f0caf1SEmmanuel Vadot 			all_max_uvolt = tmp->max_uvolt;
814*b2f0caf1SEmmanuel Vadot 	}
815*b2f0caf1SEmmanuel Vadot 
816*b2f0caf1SEmmanuel Vadot 	/* Test if request fits to actual contract. */
817*b2f0caf1SEmmanuel Vadot 	if ((min_uvolt > all_max_uvolt) ||
818*b2f0caf1SEmmanuel Vadot 	    (max_uvolt < all_min_uvolt)) {
819*b2f0caf1SEmmanuel Vadot 		REGNODE_UNLOCK(regnode);
820*b2f0caf1SEmmanuel Vadot 		return (ERANGE);
821*b2f0caf1SEmmanuel Vadot 	}
822*b2f0caf1SEmmanuel Vadot 
823*b2f0caf1SEmmanuel Vadot 	/* Adjust new range.*/
824*b2f0caf1SEmmanuel Vadot 	if (min_uvolt < all_min_uvolt)
825*b2f0caf1SEmmanuel Vadot 		min_uvolt = all_min_uvolt;
826*b2f0caf1SEmmanuel Vadot 	if (max_uvolt > all_max_uvolt)
827*b2f0caf1SEmmanuel Vadot 		max_uvolt = all_max_uvolt;
828*b2f0caf1SEmmanuel Vadot 
829*b2f0caf1SEmmanuel Vadot 	rv = REGNODE_SET_VOLTAGE(regnode, min_uvolt, max_uvolt, &udelay);
830*b2f0caf1SEmmanuel Vadot 	regnode_delay(udelay);
831*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
832*b2f0caf1SEmmanuel Vadot 	return (rv);
833*b2f0caf1SEmmanuel Vadot }
834*b2f0caf1SEmmanuel Vadot 
835*b2f0caf1SEmmanuel Vadot int
regnode_set_constraint(struct regnode * regnode)836*b2f0caf1SEmmanuel Vadot regnode_set_constraint(struct regnode *regnode)
837*b2f0caf1SEmmanuel Vadot {
838*b2f0caf1SEmmanuel Vadot 	int status, rv, uvolt;
839*b2f0caf1SEmmanuel Vadot 
840*b2f0caf1SEmmanuel Vadot 	if (regnode->std_param.boot_on != true &&
841*b2f0caf1SEmmanuel Vadot 	    regnode->std_param.always_on != true)
842*b2f0caf1SEmmanuel Vadot 		return (0);
843*b2f0caf1SEmmanuel Vadot 
844*b2f0caf1SEmmanuel Vadot 	rv = regnode_status(regnode, &status);
845*b2f0caf1SEmmanuel Vadot 	if (rv != 0) {
846*b2f0caf1SEmmanuel Vadot 		if (bootverbose)
847*b2f0caf1SEmmanuel Vadot 			printf("Cannot get regulator status for %s\n",
848*b2f0caf1SEmmanuel Vadot 			    regnode_get_name(regnode));
849*b2f0caf1SEmmanuel Vadot 		return (rv);
850*b2f0caf1SEmmanuel Vadot 	}
851*b2f0caf1SEmmanuel Vadot 
852*b2f0caf1SEmmanuel Vadot 	if (status == REGULATOR_STATUS_ENABLED)
853*b2f0caf1SEmmanuel Vadot 		return (0);
854*b2f0caf1SEmmanuel Vadot 
855*b2f0caf1SEmmanuel Vadot 	rv = regnode_get_voltage(regnode, &uvolt);
856*b2f0caf1SEmmanuel Vadot 	if (rv != 0) {
857*b2f0caf1SEmmanuel Vadot 		if (bootverbose)
858*b2f0caf1SEmmanuel Vadot 			printf("Cannot get regulator voltage for %s\n",
859*b2f0caf1SEmmanuel Vadot 			    regnode_get_name(regnode));
860*b2f0caf1SEmmanuel Vadot 		return (rv);
861*b2f0caf1SEmmanuel Vadot 	}
862*b2f0caf1SEmmanuel Vadot 
863*b2f0caf1SEmmanuel Vadot 	if (uvolt < regnode->std_param.min_uvolt ||
864*b2f0caf1SEmmanuel Vadot 	  uvolt > regnode->std_param.max_uvolt) {
865*b2f0caf1SEmmanuel Vadot 		if (bootverbose)
866*b2f0caf1SEmmanuel Vadot 			printf("Regulator %s current voltage %d is not in the"
867*b2f0caf1SEmmanuel Vadot 			    " acceptable range : %d<->%d\n",
868*b2f0caf1SEmmanuel Vadot 			    regnode_get_name(regnode),
869*b2f0caf1SEmmanuel Vadot 			    uvolt, regnode->std_param.min_uvolt,
870*b2f0caf1SEmmanuel Vadot 			    regnode->std_param.max_uvolt);
871*b2f0caf1SEmmanuel Vadot 		return (ERANGE);
872*b2f0caf1SEmmanuel Vadot 	}
873*b2f0caf1SEmmanuel Vadot 
874*b2f0caf1SEmmanuel Vadot 	rv = regnode_enable(regnode);
875*b2f0caf1SEmmanuel Vadot 	if (rv != 0) {
876*b2f0caf1SEmmanuel Vadot 		if (bootverbose)
877*b2f0caf1SEmmanuel Vadot 			printf("Cannot enable regulator %s\n",
878*b2f0caf1SEmmanuel Vadot 			    regnode_get_name(regnode));
879*b2f0caf1SEmmanuel Vadot 		return (rv);
880*b2f0caf1SEmmanuel Vadot 	}
881*b2f0caf1SEmmanuel Vadot 
882*b2f0caf1SEmmanuel Vadot 	return (0);
883*b2f0caf1SEmmanuel Vadot }
884*b2f0caf1SEmmanuel Vadot 
885*b2f0caf1SEmmanuel Vadot #ifdef FDT
886*b2f0caf1SEmmanuel Vadot phandle_t
regnode_get_ofw_node(struct regnode * regnode)887*b2f0caf1SEmmanuel Vadot regnode_get_ofw_node(struct regnode *regnode)
888*b2f0caf1SEmmanuel Vadot {
889*b2f0caf1SEmmanuel Vadot 
890*b2f0caf1SEmmanuel Vadot 	return (regnode->ofw_node);
891*b2f0caf1SEmmanuel Vadot }
892*b2f0caf1SEmmanuel Vadot #endif
893*b2f0caf1SEmmanuel Vadot 
894*b2f0caf1SEmmanuel Vadot /* --------------------------------------------------------------------------
895*b2f0caf1SEmmanuel Vadot  *
896*b2f0caf1SEmmanuel Vadot  * Regulator consumers interface.
897*b2f0caf1SEmmanuel Vadot  *
898*b2f0caf1SEmmanuel Vadot  */
899*b2f0caf1SEmmanuel Vadot /* Helper function for regulator_get*() */
900*b2f0caf1SEmmanuel Vadot static regulator_t
regulator_create(struct regnode * regnode,device_t cdev)901*b2f0caf1SEmmanuel Vadot regulator_create(struct regnode *regnode, device_t cdev)
902*b2f0caf1SEmmanuel Vadot {
903*b2f0caf1SEmmanuel Vadot 	struct regulator *reg;
904*b2f0caf1SEmmanuel Vadot 
905*b2f0caf1SEmmanuel Vadot 	REG_TOPO_ASSERT();
906*b2f0caf1SEmmanuel Vadot 
907*b2f0caf1SEmmanuel Vadot 	reg =  malloc(sizeof(struct regulator), M_REGULATOR,
908*b2f0caf1SEmmanuel Vadot 	    M_WAITOK | M_ZERO);
909*b2f0caf1SEmmanuel Vadot 	reg->cdev = cdev;
910*b2f0caf1SEmmanuel Vadot 	reg->regnode = regnode;
911*b2f0caf1SEmmanuel Vadot 	reg->enable_cnt = 0;
912*b2f0caf1SEmmanuel Vadot 
913*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
914*b2f0caf1SEmmanuel Vadot 	regnode->ref_cnt++;
915*b2f0caf1SEmmanuel Vadot 	TAILQ_INSERT_TAIL(&regnode->consumers_list, reg, link);
916*b2f0caf1SEmmanuel Vadot 	reg ->min_uvolt = regnode->std_param.min_uvolt;
917*b2f0caf1SEmmanuel Vadot 	reg ->max_uvolt = regnode->std_param.max_uvolt;
918*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
919*b2f0caf1SEmmanuel Vadot 
920*b2f0caf1SEmmanuel Vadot 	return (reg);
921*b2f0caf1SEmmanuel Vadot }
922*b2f0caf1SEmmanuel Vadot 
923*b2f0caf1SEmmanuel Vadot int
regulator_enable(regulator_t reg)924*b2f0caf1SEmmanuel Vadot regulator_enable(regulator_t reg)
925*b2f0caf1SEmmanuel Vadot {
926*b2f0caf1SEmmanuel Vadot 	int rv;
927*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
928*b2f0caf1SEmmanuel Vadot 
929*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
930*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
931*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
932*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
933*b2f0caf1SEmmanuel Vadot 	rv = regnode_enable(regnode);
934*b2f0caf1SEmmanuel Vadot 	if (rv == 0)
935*b2f0caf1SEmmanuel Vadot 		reg->enable_cnt++;
936*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
937*b2f0caf1SEmmanuel Vadot 	return (rv);
938*b2f0caf1SEmmanuel Vadot }
939*b2f0caf1SEmmanuel Vadot 
940*b2f0caf1SEmmanuel Vadot int
regulator_disable(regulator_t reg)941*b2f0caf1SEmmanuel Vadot regulator_disable(regulator_t reg)
942*b2f0caf1SEmmanuel Vadot {
943*b2f0caf1SEmmanuel Vadot 	int rv;
944*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
945*b2f0caf1SEmmanuel Vadot 
946*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
947*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
948*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
949*b2f0caf1SEmmanuel Vadot 	KASSERT(reg->enable_cnt > 0,
950*b2f0caf1SEmmanuel Vadot 	   ("Attempt to disable already disabled regulator: %s\n",
951*b2f0caf1SEmmanuel Vadot 	   regnode->name));
952*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
953*b2f0caf1SEmmanuel Vadot 	rv = regnode_disable(regnode);
954*b2f0caf1SEmmanuel Vadot 	if (rv == 0)
955*b2f0caf1SEmmanuel Vadot 		reg->enable_cnt--;
956*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
957*b2f0caf1SEmmanuel Vadot 	return (rv);
958*b2f0caf1SEmmanuel Vadot }
959*b2f0caf1SEmmanuel Vadot 
960*b2f0caf1SEmmanuel Vadot int
regulator_stop(regulator_t reg)961*b2f0caf1SEmmanuel Vadot regulator_stop(regulator_t reg)
962*b2f0caf1SEmmanuel Vadot {
963*b2f0caf1SEmmanuel Vadot 	int rv;
964*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
965*b2f0caf1SEmmanuel Vadot 
966*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
967*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
968*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
969*b2f0caf1SEmmanuel Vadot 	KASSERT(reg->enable_cnt == 0,
970*b2f0caf1SEmmanuel Vadot 	   ("Attempt to stop already enabled regulator: %s\n", regnode->name));
971*b2f0caf1SEmmanuel Vadot 
972*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
973*b2f0caf1SEmmanuel Vadot 	rv = regnode_stop(regnode, 0);
974*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
975*b2f0caf1SEmmanuel Vadot 	return (rv);
976*b2f0caf1SEmmanuel Vadot }
977*b2f0caf1SEmmanuel Vadot 
978*b2f0caf1SEmmanuel Vadot int
regulator_status(regulator_t reg,int * status)979*b2f0caf1SEmmanuel Vadot regulator_status(regulator_t reg, int *status)
980*b2f0caf1SEmmanuel Vadot {
981*b2f0caf1SEmmanuel Vadot 	int rv;
982*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
983*b2f0caf1SEmmanuel Vadot 
984*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
985*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
986*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
987*b2f0caf1SEmmanuel Vadot 
988*b2f0caf1SEmmanuel Vadot 	if (reg->enable_cnt == 0) {
989*b2f0caf1SEmmanuel Vadot 		*status = 0;
990*b2f0caf1SEmmanuel Vadot 		return (0);
991*b2f0caf1SEmmanuel Vadot 	}
992*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
993*b2f0caf1SEmmanuel Vadot 	rv = regnode_status(regnode, status);
994*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
995*b2f0caf1SEmmanuel Vadot 	return (rv);
996*b2f0caf1SEmmanuel Vadot }
997*b2f0caf1SEmmanuel Vadot 
998*b2f0caf1SEmmanuel Vadot int
regulator_get_voltage(regulator_t reg,int * uvolt)999*b2f0caf1SEmmanuel Vadot regulator_get_voltage(regulator_t reg, int *uvolt)
1000*b2f0caf1SEmmanuel Vadot {
1001*b2f0caf1SEmmanuel Vadot 	int rv;
1002*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
1003*b2f0caf1SEmmanuel Vadot 
1004*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
1005*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
1006*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
1007*b2f0caf1SEmmanuel Vadot 
1008*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
1009*b2f0caf1SEmmanuel Vadot 	rv = regnode_get_voltage(regnode, uvolt);
1010*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
1011*b2f0caf1SEmmanuel Vadot 	return (rv);
1012*b2f0caf1SEmmanuel Vadot }
1013*b2f0caf1SEmmanuel Vadot 
1014*b2f0caf1SEmmanuel Vadot int
regulator_set_voltage(regulator_t reg,int min_uvolt,int max_uvolt)1015*b2f0caf1SEmmanuel Vadot regulator_set_voltage(regulator_t reg, int min_uvolt, int max_uvolt)
1016*b2f0caf1SEmmanuel Vadot {
1017*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
1018*b2f0caf1SEmmanuel Vadot 	int rv;
1019*b2f0caf1SEmmanuel Vadot 
1020*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
1021*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
1022*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
1023*b2f0caf1SEmmanuel Vadot 
1024*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
1025*b2f0caf1SEmmanuel Vadot 
1026*b2f0caf1SEmmanuel Vadot 	rv = regnode_set_voltage_checked(regnode, reg, min_uvolt, max_uvolt);
1027*b2f0caf1SEmmanuel Vadot 	if (rv == 0) {
1028*b2f0caf1SEmmanuel Vadot 		reg->min_uvolt = min_uvolt;
1029*b2f0caf1SEmmanuel Vadot 		reg->max_uvolt = max_uvolt;
1030*b2f0caf1SEmmanuel Vadot 	}
1031*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
1032*b2f0caf1SEmmanuel Vadot 	return (rv);
1033*b2f0caf1SEmmanuel Vadot }
1034*b2f0caf1SEmmanuel Vadot 
1035*b2f0caf1SEmmanuel Vadot int
regulator_check_voltage(regulator_t reg,int uvolt)1036*b2f0caf1SEmmanuel Vadot regulator_check_voltage(regulator_t reg, int uvolt)
1037*b2f0caf1SEmmanuel Vadot {
1038*b2f0caf1SEmmanuel Vadot 	int rv;
1039*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
1040*b2f0caf1SEmmanuel Vadot 
1041*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
1042*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
1043*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
1044*b2f0caf1SEmmanuel Vadot 
1045*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
1046*b2f0caf1SEmmanuel Vadot 	rv = REGNODE_CHECK_VOLTAGE(regnode, uvolt);
1047*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
1048*b2f0caf1SEmmanuel Vadot 	return (rv);
1049*b2f0caf1SEmmanuel Vadot }
1050*b2f0caf1SEmmanuel Vadot 
1051*b2f0caf1SEmmanuel Vadot const char *
regulator_get_name(regulator_t reg)1052*b2f0caf1SEmmanuel Vadot regulator_get_name(regulator_t reg)
1053*b2f0caf1SEmmanuel Vadot {
1054*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
1055*b2f0caf1SEmmanuel Vadot 
1056*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
1057*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
1058*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
1059*b2f0caf1SEmmanuel Vadot 	return (regnode->name);
1060*b2f0caf1SEmmanuel Vadot }
1061*b2f0caf1SEmmanuel Vadot 
1062*b2f0caf1SEmmanuel Vadot int
regulator_get_by_name(device_t cdev,const char * name,regulator_t * reg)1063*b2f0caf1SEmmanuel Vadot regulator_get_by_name(device_t cdev, const char *name, regulator_t *reg)
1064*b2f0caf1SEmmanuel Vadot {
1065*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
1066*b2f0caf1SEmmanuel Vadot 
1067*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
1068*b2f0caf1SEmmanuel Vadot 	regnode = regnode_find_by_name(name);
1069*b2f0caf1SEmmanuel Vadot 	if (regnode == NULL) {
1070*b2f0caf1SEmmanuel Vadot 		REG_TOPO_UNLOCK();
1071*b2f0caf1SEmmanuel Vadot 		return (ENODEV);
1072*b2f0caf1SEmmanuel Vadot 	}
1073*b2f0caf1SEmmanuel Vadot 	*reg = regulator_create(regnode, cdev);
1074*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
1075*b2f0caf1SEmmanuel Vadot 	return (0);
1076*b2f0caf1SEmmanuel Vadot }
1077*b2f0caf1SEmmanuel Vadot 
1078*b2f0caf1SEmmanuel Vadot int
regulator_get_by_id(device_t cdev,device_t pdev,intptr_t id,regulator_t * reg)1079*b2f0caf1SEmmanuel Vadot regulator_get_by_id(device_t cdev, device_t pdev, intptr_t id, regulator_t *reg)
1080*b2f0caf1SEmmanuel Vadot {
1081*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
1082*b2f0caf1SEmmanuel Vadot 
1083*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
1084*b2f0caf1SEmmanuel Vadot 
1085*b2f0caf1SEmmanuel Vadot 	regnode = regnode_find_by_id(pdev, id);
1086*b2f0caf1SEmmanuel Vadot 	if (regnode == NULL) {
1087*b2f0caf1SEmmanuel Vadot 		REG_TOPO_UNLOCK();
1088*b2f0caf1SEmmanuel Vadot 		return (ENODEV);
1089*b2f0caf1SEmmanuel Vadot 	}
1090*b2f0caf1SEmmanuel Vadot 	*reg = regulator_create(regnode, cdev);
1091*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
1092*b2f0caf1SEmmanuel Vadot 
1093*b2f0caf1SEmmanuel Vadot 	return (0);
1094*b2f0caf1SEmmanuel Vadot }
1095*b2f0caf1SEmmanuel Vadot 
1096*b2f0caf1SEmmanuel Vadot int
regulator_release(regulator_t reg)1097*b2f0caf1SEmmanuel Vadot regulator_release(regulator_t reg)
1098*b2f0caf1SEmmanuel Vadot {
1099*b2f0caf1SEmmanuel Vadot 	struct regnode *regnode;
1100*b2f0caf1SEmmanuel Vadot 
1101*b2f0caf1SEmmanuel Vadot 	regnode = reg->regnode;
1102*b2f0caf1SEmmanuel Vadot 	KASSERT(regnode->ref_cnt > 0,
1103*b2f0caf1SEmmanuel Vadot 	   ("Attempt to access unreferenced regulator: %s\n", regnode->name));
1104*b2f0caf1SEmmanuel Vadot 	REG_TOPO_SLOCK();
1105*b2f0caf1SEmmanuel Vadot 	while (reg->enable_cnt > 0) {
1106*b2f0caf1SEmmanuel Vadot 		regnode_disable(regnode);
1107*b2f0caf1SEmmanuel Vadot 		reg->enable_cnt--;
1108*b2f0caf1SEmmanuel Vadot 	}
1109*b2f0caf1SEmmanuel Vadot 	REGNODE_XLOCK(regnode);
1110*b2f0caf1SEmmanuel Vadot 	TAILQ_REMOVE(&regnode->consumers_list, reg, link);
1111*b2f0caf1SEmmanuel Vadot 	regnode->ref_cnt--;
1112*b2f0caf1SEmmanuel Vadot 	REGNODE_UNLOCK(regnode);
1113*b2f0caf1SEmmanuel Vadot 	REG_TOPO_UNLOCK();
1114*b2f0caf1SEmmanuel Vadot 
1115*b2f0caf1SEmmanuel Vadot 	free(reg, M_REGULATOR);
1116*b2f0caf1SEmmanuel Vadot 	return (0);
1117*b2f0caf1SEmmanuel Vadot }
1118*b2f0caf1SEmmanuel Vadot 
1119*b2f0caf1SEmmanuel Vadot #ifdef FDT
1120*b2f0caf1SEmmanuel Vadot /* Default DT mapper. */
1121*b2f0caf1SEmmanuel Vadot int
regdev_default_ofw_map(device_t dev,phandle_t xref,int ncells,pcell_t * cells,intptr_t * id)1122*b2f0caf1SEmmanuel Vadot regdev_default_ofw_map(device_t dev, phandle_t 	xref, int ncells,
1123*b2f0caf1SEmmanuel Vadot     pcell_t *cells, intptr_t *id)
1124*b2f0caf1SEmmanuel Vadot {
1125*b2f0caf1SEmmanuel Vadot 	if (ncells == 0)
1126*b2f0caf1SEmmanuel Vadot 		*id = 1;
1127*b2f0caf1SEmmanuel Vadot 	else if (ncells == 1)
1128*b2f0caf1SEmmanuel Vadot 		*id = cells[0];
1129*b2f0caf1SEmmanuel Vadot 	else
1130*b2f0caf1SEmmanuel Vadot 		return  (ERANGE);
1131*b2f0caf1SEmmanuel Vadot 
1132*b2f0caf1SEmmanuel Vadot 	return (0);
1133*b2f0caf1SEmmanuel Vadot }
1134*b2f0caf1SEmmanuel Vadot 
1135*b2f0caf1SEmmanuel Vadot int
regulator_parse_ofw_stdparam(device_t pdev,phandle_t node,struct regnode_init_def * def)1136*b2f0caf1SEmmanuel Vadot regulator_parse_ofw_stdparam(device_t pdev, phandle_t node,
1137*b2f0caf1SEmmanuel Vadot     struct regnode_init_def *def)
1138*b2f0caf1SEmmanuel Vadot {
1139*b2f0caf1SEmmanuel Vadot 	phandle_t supply_xref;
1140*b2f0caf1SEmmanuel Vadot 	struct regnode_std_param *par;
1141*b2f0caf1SEmmanuel Vadot 	int rv;
1142*b2f0caf1SEmmanuel Vadot 
1143*b2f0caf1SEmmanuel Vadot 	par = &def->std_param;
1144*b2f0caf1SEmmanuel Vadot 	rv = OF_getprop_alloc(node, "regulator-name",
1145*b2f0caf1SEmmanuel Vadot 	    (void **)&def->name);
1146*b2f0caf1SEmmanuel Vadot 	if (rv <= 0) {
1147*b2f0caf1SEmmanuel Vadot 		device_printf(pdev, "%s: Missing regulator name\n",
1148*b2f0caf1SEmmanuel Vadot 		 __func__);
1149*b2f0caf1SEmmanuel Vadot 		return (ENXIO);
1150*b2f0caf1SEmmanuel Vadot 	}
1151*b2f0caf1SEmmanuel Vadot 
1152*b2f0caf1SEmmanuel Vadot 	rv = OF_getencprop(node, "regulator-min-microvolt", &par->min_uvolt,
1153*b2f0caf1SEmmanuel Vadot 	    sizeof(par->min_uvolt));
1154*b2f0caf1SEmmanuel Vadot 	if (rv <= 0)
1155*b2f0caf1SEmmanuel Vadot 		par->min_uvolt = 0;
1156*b2f0caf1SEmmanuel Vadot 
1157*b2f0caf1SEmmanuel Vadot 	rv = OF_getencprop(node, "regulator-max-microvolt", &par->max_uvolt,
1158*b2f0caf1SEmmanuel Vadot 	    sizeof(par->max_uvolt));
1159*b2f0caf1SEmmanuel Vadot 	if (rv <= 0)
1160*b2f0caf1SEmmanuel Vadot 		par->max_uvolt = 0;
1161*b2f0caf1SEmmanuel Vadot 
1162*b2f0caf1SEmmanuel Vadot 	rv = OF_getencprop(node, "regulator-min-microamp", &par->min_uamp,
1163*b2f0caf1SEmmanuel Vadot 	    sizeof(par->min_uamp));
1164*b2f0caf1SEmmanuel Vadot 	if (rv <= 0)
1165*b2f0caf1SEmmanuel Vadot 		par->min_uamp = 0;
1166*b2f0caf1SEmmanuel Vadot 
1167*b2f0caf1SEmmanuel Vadot 	rv = OF_getencprop(node, "regulator-max-microamp", &par->max_uamp,
1168*b2f0caf1SEmmanuel Vadot 	    sizeof(par->max_uamp));
1169*b2f0caf1SEmmanuel Vadot 	if (rv <= 0)
1170*b2f0caf1SEmmanuel Vadot 		par->max_uamp = 0;
1171*b2f0caf1SEmmanuel Vadot 
1172*b2f0caf1SEmmanuel Vadot 	rv = OF_getencprop(node, "regulator-ramp-delay", &par->ramp_delay,
1173*b2f0caf1SEmmanuel Vadot 	    sizeof(par->ramp_delay));
1174*b2f0caf1SEmmanuel Vadot 	if (rv <= 0)
1175*b2f0caf1SEmmanuel Vadot 		par->ramp_delay = 0;
1176*b2f0caf1SEmmanuel Vadot 
1177*b2f0caf1SEmmanuel Vadot 	rv = OF_getencprop(node, "regulator-enable-ramp-delay",
1178*b2f0caf1SEmmanuel Vadot 	    &par->enable_delay, sizeof(par->enable_delay));
1179*b2f0caf1SEmmanuel Vadot 	if (rv <= 0)
1180*b2f0caf1SEmmanuel Vadot 		par->enable_delay = 0;
1181*b2f0caf1SEmmanuel Vadot 
1182*b2f0caf1SEmmanuel Vadot 	if (OF_hasprop(node, "regulator-boot-on"))
1183*b2f0caf1SEmmanuel Vadot 		par->boot_on = true;
1184*b2f0caf1SEmmanuel Vadot 
1185*b2f0caf1SEmmanuel Vadot 	if (OF_hasprop(node, "regulator-always-on"))
1186*b2f0caf1SEmmanuel Vadot 		par->always_on = true;
1187*b2f0caf1SEmmanuel Vadot 
1188*b2f0caf1SEmmanuel Vadot 	if (OF_hasprop(node, "enable-active-high"))
1189*b2f0caf1SEmmanuel Vadot 		par->enable_active_high = 1;
1190*b2f0caf1SEmmanuel Vadot 
1191*b2f0caf1SEmmanuel Vadot 	rv = OF_getencprop(node, "vin-supply", &supply_xref,
1192*b2f0caf1SEmmanuel Vadot 	    sizeof(supply_xref));
1193*b2f0caf1SEmmanuel Vadot 	if (rv >=  0) {
1194*b2f0caf1SEmmanuel Vadot 		rv = OF_getprop_alloc(supply_xref, "regulator-name",
1195*b2f0caf1SEmmanuel Vadot 		    (void **)&def->parent_name);
1196*b2f0caf1SEmmanuel Vadot 		if (rv <= 0)
1197*b2f0caf1SEmmanuel Vadot 			def->parent_name = NULL;
1198*b2f0caf1SEmmanuel Vadot 	}
1199*b2f0caf1SEmmanuel Vadot 	return (0);
1200*b2f0caf1SEmmanuel Vadot }
1201*b2f0caf1SEmmanuel Vadot 
1202*b2f0caf1SEmmanuel Vadot int
regulator_get_by_ofw_property(device_t cdev,phandle_t cnode,char * name,regulator_t * reg)1203*b2f0caf1SEmmanuel Vadot regulator_get_by_ofw_property(device_t cdev, phandle_t cnode, char *name,
1204*b2f0caf1SEmmanuel Vadot     regulator_t *reg)
1205*b2f0caf1SEmmanuel Vadot {
1206*b2f0caf1SEmmanuel Vadot 	phandle_t *cells;
1207*b2f0caf1SEmmanuel Vadot 	device_t regdev;
1208*b2f0caf1SEmmanuel Vadot 	int ncells, rv;
1209*b2f0caf1SEmmanuel Vadot 	intptr_t id;
1210*b2f0caf1SEmmanuel Vadot 
1211*b2f0caf1SEmmanuel Vadot 	*reg = NULL;
1212*b2f0caf1SEmmanuel Vadot 
1213*b2f0caf1SEmmanuel Vadot 	if (cnode <= 0)
1214*b2f0caf1SEmmanuel Vadot 		cnode = ofw_bus_get_node(cdev);
1215*b2f0caf1SEmmanuel Vadot 	if (cnode <= 0) {
1216*b2f0caf1SEmmanuel Vadot 		device_printf(cdev, "%s called on not ofw based device\n",
1217*b2f0caf1SEmmanuel Vadot 		 __func__);
1218*b2f0caf1SEmmanuel Vadot 		return (ENXIO);
1219*b2f0caf1SEmmanuel Vadot 	}
1220*b2f0caf1SEmmanuel Vadot 
1221*b2f0caf1SEmmanuel Vadot 	cells = NULL;
1222*b2f0caf1SEmmanuel Vadot 	ncells = OF_getencprop_alloc_multi(cnode, name, sizeof(*cells),
1223*b2f0caf1SEmmanuel Vadot 	    (void **)&cells);
1224*b2f0caf1SEmmanuel Vadot 	if (ncells <= 0)
1225*b2f0caf1SEmmanuel Vadot 		return (ENOENT);
1226*b2f0caf1SEmmanuel Vadot 
1227*b2f0caf1SEmmanuel Vadot 	/* Translate xref to device */
1228*b2f0caf1SEmmanuel Vadot 	regdev = OF_device_from_xref(cells[0]);
1229*b2f0caf1SEmmanuel Vadot 	if (regdev == NULL) {
1230*b2f0caf1SEmmanuel Vadot 		OF_prop_free(cells);
1231*b2f0caf1SEmmanuel Vadot 		return (ENODEV);
1232*b2f0caf1SEmmanuel Vadot 	}
1233*b2f0caf1SEmmanuel Vadot 
1234*b2f0caf1SEmmanuel Vadot 	/* Map regulator to number */
1235*b2f0caf1SEmmanuel Vadot 	rv = REGDEV_MAP(regdev, cells[0], ncells - 1, cells + 1, &id);
1236*b2f0caf1SEmmanuel Vadot 	OF_prop_free(cells);
1237*b2f0caf1SEmmanuel Vadot 	if (rv != 0)
1238*b2f0caf1SEmmanuel Vadot 		return (rv);
1239*b2f0caf1SEmmanuel Vadot 	return (regulator_get_by_id(cdev, regdev, id, reg));
1240*b2f0caf1SEmmanuel Vadot }
1241*b2f0caf1SEmmanuel Vadot #endif
1242*b2f0caf1SEmmanuel Vadot 
1243*b2f0caf1SEmmanuel Vadot /* --------------------------------------------------------------------------
1244*b2f0caf1SEmmanuel Vadot  *
1245*b2f0caf1SEmmanuel Vadot  * Regulator utility functions.
1246*b2f0caf1SEmmanuel Vadot  *
1247*b2f0caf1SEmmanuel Vadot  */
1248*b2f0caf1SEmmanuel Vadot 
1249*b2f0caf1SEmmanuel Vadot /* Convert raw selector value to real voltage */
1250*b2f0caf1SEmmanuel Vadot int
regulator_range_sel8_to_volt(struct regulator_range * ranges,int nranges,uint8_t sel,int * volt)1251*b2f0caf1SEmmanuel Vadot regulator_range_sel8_to_volt(struct regulator_range *ranges, int nranges,
1252*b2f0caf1SEmmanuel Vadot    uint8_t sel, int *volt)
1253*b2f0caf1SEmmanuel Vadot {
1254*b2f0caf1SEmmanuel Vadot 	struct regulator_range *range;
1255*b2f0caf1SEmmanuel Vadot 	int i;
1256*b2f0caf1SEmmanuel Vadot 
1257*b2f0caf1SEmmanuel Vadot 	if (nranges == 0)
1258*b2f0caf1SEmmanuel Vadot 		panic("Voltage regulator have zero ranges\n");
1259*b2f0caf1SEmmanuel Vadot 
1260*b2f0caf1SEmmanuel Vadot 	for (i = 0; i < nranges ; i++) {
1261*b2f0caf1SEmmanuel Vadot 		range = ranges  + i;
1262*b2f0caf1SEmmanuel Vadot 
1263*b2f0caf1SEmmanuel Vadot 		if (!(sel >= range->min_sel &&
1264*b2f0caf1SEmmanuel Vadot 		      sel <= range->max_sel))
1265*b2f0caf1SEmmanuel Vadot 			continue;
1266*b2f0caf1SEmmanuel Vadot 
1267*b2f0caf1SEmmanuel Vadot 		sel -= range->min_sel;
1268*b2f0caf1SEmmanuel Vadot 
1269*b2f0caf1SEmmanuel Vadot 		*volt = range->min_uvolt + sel * range->step_uvolt;
1270*b2f0caf1SEmmanuel Vadot 		return (0);
1271*b2f0caf1SEmmanuel Vadot 	}
1272*b2f0caf1SEmmanuel Vadot 
1273*b2f0caf1SEmmanuel Vadot 	return (ERANGE);
1274*b2f0caf1SEmmanuel Vadot }
1275*b2f0caf1SEmmanuel Vadot 
1276*b2f0caf1SEmmanuel Vadot int
regulator_range_volt_to_sel8(struct regulator_range * ranges,int nranges,int min_uvolt,int max_uvolt,uint8_t * out_sel)1277*b2f0caf1SEmmanuel Vadot regulator_range_volt_to_sel8(struct regulator_range *ranges, int nranges,
1278*b2f0caf1SEmmanuel Vadot     int min_uvolt, int max_uvolt, uint8_t *out_sel)
1279*b2f0caf1SEmmanuel Vadot {
1280*b2f0caf1SEmmanuel Vadot 	struct regulator_range *range;
1281*b2f0caf1SEmmanuel Vadot 	uint8_t sel;
1282*b2f0caf1SEmmanuel Vadot 	int uvolt;
1283*b2f0caf1SEmmanuel Vadot 	int rv, i;
1284*b2f0caf1SEmmanuel Vadot 
1285*b2f0caf1SEmmanuel Vadot 	if (nranges == 0)
1286*b2f0caf1SEmmanuel Vadot 		panic("Voltage regulator have zero ranges\n");
1287*b2f0caf1SEmmanuel Vadot 
1288*b2f0caf1SEmmanuel Vadot 	for (i = 0; i < nranges; i++) {
1289*b2f0caf1SEmmanuel Vadot 		range = ranges  + i;
1290*b2f0caf1SEmmanuel Vadot 		uvolt = range->min_uvolt +
1291*b2f0caf1SEmmanuel Vadot 		    (range->max_sel - range->min_sel) * range->step_uvolt;
1292*b2f0caf1SEmmanuel Vadot 
1293*b2f0caf1SEmmanuel Vadot 		if ((min_uvolt > uvolt) ||
1294*b2f0caf1SEmmanuel Vadot 		    (max_uvolt < range->min_uvolt))
1295*b2f0caf1SEmmanuel Vadot 			continue;
1296*b2f0caf1SEmmanuel Vadot 
1297*b2f0caf1SEmmanuel Vadot 		if (min_uvolt <= range->min_uvolt)
1298*b2f0caf1SEmmanuel Vadot 			min_uvolt = range->min_uvolt;
1299*b2f0caf1SEmmanuel Vadot 
1300*b2f0caf1SEmmanuel Vadot 		/* if step == 0 -> fixed voltage range. */
1301*b2f0caf1SEmmanuel Vadot 		if (range->step_uvolt == 0)
1302*b2f0caf1SEmmanuel Vadot 			sel = 0;
1303*b2f0caf1SEmmanuel Vadot 		else
1304*b2f0caf1SEmmanuel Vadot 			sel = DIV_ROUND_UP(min_uvolt - range->min_uvolt,
1305*b2f0caf1SEmmanuel Vadot 			   range->step_uvolt);
1306*b2f0caf1SEmmanuel Vadot 
1307*b2f0caf1SEmmanuel Vadot 
1308*b2f0caf1SEmmanuel Vadot 		sel += range->min_sel;
1309*b2f0caf1SEmmanuel Vadot 
1310*b2f0caf1SEmmanuel Vadot 		break;
1311*b2f0caf1SEmmanuel Vadot 	}
1312*b2f0caf1SEmmanuel Vadot 
1313*b2f0caf1SEmmanuel Vadot 	if (i >= nranges)
1314*b2f0caf1SEmmanuel Vadot 		return (ERANGE);
1315*b2f0caf1SEmmanuel Vadot 
1316*b2f0caf1SEmmanuel Vadot 	/* Verify new settings. */
1317*b2f0caf1SEmmanuel Vadot 	rv = regulator_range_sel8_to_volt(ranges, nranges, sel, &uvolt);
1318*b2f0caf1SEmmanuel Vadot 	if (rv != 0)
1319*b2f0caf1SEmmanuel Vadot 		return (rv);
1320*b2f0caf1SEmmanuel Vadot 	if ((uvolt < min_uvolt) || (uvolt > max_uvolt))
1321*b2f0caf1SEmmanuel Vadot 		return (ERANGE);
1322*b2f0caf1SEmmanuel Vadot 
1323*b2f0caf1SEmmanuel Vadot 	*out_sel = sel;
1324*b2f0caf1SEmmanuel Vadot 	return (0);
1325*b2f0caf1SEmmanuel Vadot }
1326