1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2011
5 *	Ben Gray <ben.r.gray@gmail.com>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31/*
32 * Texas Instruments TWL4030/TWL5030/TWL60x0/TPS659x0 Power Management.
33 *
34 * This driver covers the voltages regulators (LDO), allows for enabling &
35 * disabling the voltage output and adjusting the voltage level.
36 *
37 * Voltage regulators can belong to different power groups, in this driver we
38 * put the regulators under our control in the "Application power group".
39 *
40 *
41 * FLATTENED DEVICE TREE (FDT)
42 * Startup override settings can be specified in the FDT, if they are they
43 * should be under the twl parent device and take the following form:
44 *
45 *    voltage-regulators = "name1", "millivolts1",
46 *                         "name2", "millivolts2";
47 *
48 * Each override should be a pair, the first entry is the name of the regulator
49 * the second is the voltage (in millivolts) to set for the given regulator.
50 *
51 */
52
53#include <sys/param.h>
54#include <sys/systm.h>
55#include <sys/kernel.h>
56#include <sys/lock.h>
57#include <sys/module.h>
58#include <sys/bus.h>
59#include <sys/resource.h>
60#include <sys/rman.h>
61#include <sys/sysctl.h>
62#include <sys/sx.h>
63#include <sys/malloc.h>
64
65#include <machine/bus.h>
66#include <machine/resource.h>
67#include <machine/intr.h>
68
69#include <dev/ofw/openfirm.h>
70#include <dev/ofw/ofw_bus.h>
71
72#include "twl.h"
73#include "twl_vreg.h"
74
75static int twl_vreg_debug = 1;
76
77/*
78 * Power Groups bits for the 4030 and 6030 devices
79 */
80#define TWL4030_P3_GRP		0x80	/* Peripherals, power group */
81#define TWL4030_P2_GRP		0x40	/* Modem power group */
82#define TWL4030_P1_GRP		0x20	/* Application power group (FreeBSD control) */
83
84#define TWL6030_P3_GRP		0x04	/* Modem power group */
85#define TWL6030_P2_GRP		0x02	/* Connectivity power group */
86#define TWL6030_P1_GRP		0x01	/* Application power group (FreeBSD control) */
87
88/*
89 * Register offsets within a LDO regulator register set
90 */
91#define TWL_VREG_GRP		0x00	/* Regulator GRP register */
92#define TWL_VREG_STATE		0x02
93#define TWL_VREG_VSEL		0x03	/* Voltage select register */
94
95#define UNDF  0xFFFF
96
97static const uint16_t twl6030_voltages[] = {
98	0000, 1000, 1100, 1200, 1300, 1400, 1500, 1600,
99	1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400,
100	2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200,
101	3300, UNDF, UNDF, UNDF, UNDF, UNDF, UNDF, 2750
102};
103
104static const uint16_t twl4030_vaux1_voltages[] = {
105	1500, 1800, 2500, 2800, 3000, 3000, 3000, 3000
106};
107static const uint16_t twl4030_vaux2_voltages[] = {
108	1700, 1700, 1900, 1300, 1500, 1800, 2000, 2500,
109	2100, 2800, 2200, 2300, 2400, 2400, 2400, 2400
110};
111static const uint16_t twl4030_vaux3_voltages[] = {
112	1500, 1800, 2500, 2800, 3000, 3000, 3000, 3000
113};
114static const uint16_t twl4030_vaux4_voltages[] = {
115	700,  1000, 1200, 1300, 1500, 1800, 1850, 2500,
116	2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150
117};
118static const uint16_t twl4030_vmmc1_voltages[] = {
119	1850, 2850, 3000, 3150
120};
121static const uint16_t twl4030_vmmc2_voltages[] = {
122	1000, 1000, 1200, 1300, 1500, 1800, 1850, 2500,
123	2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150
124};
125static const uint16_t twl4030_vpll1_voltages[] = {
126	1000, 1200, 1300, 1800, 2800, 3000, 3000, 3000
127};
128static const uint16_t twl4030_vpll2_voltages[] = {
129	700,  1000, 1200, 1300, 1500, 1800, 1850, 2500,
130	2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150
131};
132static const uint16_t twl4030_vsim_voltages[] = {
133	1000, 1200, 1300, 1800, 2800, 3000, 3000, 3000
134};
135static const uint16_t twl4030_vdac_voltages[] = {
136	1200, 1300, 1800, 1800
137};
138#if 0 /* vdd1, vdd2, vdio, not currently used. */
139static const uint16_t twl4030_vdd1_voltages[] = {
140	800, 1450
141};
142static const uint16_t twl4030_vdd2_voltages[] = {
143	800, 1450, 1500
144};
145static const uint16_t twl4030_vio_voltages[] = {
146	1800, 1850
147};
148#endif
149static const uint16_t twl4030_vintana2_voltages[] = {
150	2500, 2750
151};
152
153/**
154 *  Support voltage regulators for the different IC's
155 */
156struct twl_regulator {
157	const char	*name;
158	uint8_t		subdev;
159	uint8_t		regbase;
160
161	uint16_t	fixedvoltage;
162
163	const uint16_t	*voltages;
164	uint32_t	num_voltages;
165};
166
167#define TWL_REGULATOR_ADJUSTABLE(name, subdev, reg, voltages) \
168	{ name, subdev, reg, 0, voltages, (sizeof(voltages)/sizeof(voltages[0])) }
169#define TWL_REGULATOR_FIXED(name, subdev, reg, voltage) \
170	{ name, subdev, reg, voltage, NULL, 0 }
171
172static const struct twl_regulator twl4030_regulators[] = {
173	TWL_REGULATOR_ADJUSTABLE("vaux1",    0, 0x17, twl4030_vaux1_voltages),
174	TWL_REGULATOR_ADJUSTABLE("vaux2",    0, 0x1B, twl4030_vaux2_voltages),
175	TWL_REGULATOR_ADJUSTABLE("vaux3",    0, 0x1F, twl4030_vaux3_voltages),
176	TWL_REGULATOR_ADJUSTABLE("vaux4",    0, 0x23, twl4030_vaux4_voltages),
177	TWL_REGULATOR_ADJUSTABLE("vmmc1",    0, 0x27, twl4030_vmmc1_voltages),
178	TWL_REGULATOR_ADJUSTABLE("vmmc2",    0, 0x2B, twl4030_vmmc2_voltages),
179	TWL_REGULATOR_ADJUSTABLE("vpll1",    0, 0x2F, twl4030_vpll1_voltages),
180	TWL_REGULATOR_ADJUSTABLE("vpll2",    0, 0x33, twl4030_vpll2_voltages),
181	TWL_REGULATOR_ADJUSTABLE("vsim",     0, 0x37, twl4030_vsim_voltages),
182	TWL_REGULATOR_ADJUSTABLE("vdac",     0, 0x3B, twl4030_vdac_voltages),
183	TWL_REGULATOR_ADJUSTABLE("vintana2", 0, 0x43, twl4030_vintana2_voltages),
184	TWL_REGULATOR_FIXED("vintana1", 0, 0x3F, 1500),
185	TWL_REGULATOR_FIXED("vintdig",  0, 0x47, 1500),
186	TWL_REGULATOR_FIXED("vusb1v5",  0, 0x71, 1500),
187	TWL_REGULATOR_FIXED("vusb1v8",  0, 0x74, 1800),
188	TWL_REGULATOR_FIXED("vusb3v1",  0, 0x77, 3100),
189	{ NULL, 0, 0x00, 0, NULL, 0 }
190};
191
192static const struct twl_regulator twl6030_regulators[] = {
193	TWL_REGULATOR_ADJUSTABLE("vaux1", 0, 0x84, twl6030_voltages),
194	TWL_REGULATOR_ADJUSTABLE("vaux2", 0, 0x89, twl6030_voltages),
195	TWL_REGULATOR_ADJUSTABLE("vaux3", 0, 0x8C, twl6030_voltages),
196	TWL_REGULATOR_ADJUSTABLE("vmmc",  0, 0x98, twl6030_voltages),
197	TWL_REGULATOR_ADJUSTABLE("vpp",   0, 0x9C, twl6030_voltages),
198	TWL_REGULATOR_ADJUSTABLE("vusim", 0, 0xA4, twl6030_voltages),
199	TWL_REGULATOR_FIXED("vmem",  0, 0x64, 1800),
200	TWL_REGULATOR_FIXED("vusb",  0, 0xA0, 3300),
201	TWL_REGULATOR_FIXED("v1v8",  0, 0x46, 1800),
202	TWL_REGULATOR_FIXED("v2v1",  0, 0x4C, 2100),
203	TWL_REGULATOR_FIXED("v1v29", 0, 0x40, 1290),
204	TWL_REGULATOR_FIXED("vcxio", 0, 0x90, 1800),
205	TWL_REGULATOR_FIXED("vdac",  0, 0x94, 1800),
206	TWL_REGULATOR_FIXED("vana",  0, 0x80, 2100),
207	{ NULL, 0, 0x00, 0, NULL, 0 }
208};
209
210#define TWL_VREG_MAX_NAMELEN  32
211
212struct twl_regulator_entry {
213	LIST_ENTRY(twl_regulator_entry) entries;
214	char                 name[TWL_VREG_MAX_NAMELEN];
215	struct sysctl_oid   *oid;
216	uint8_t          sub_dev;           /* TWL sub-device group */
217	uint8_t          reg_off;           /* base register offset for the LDO */
218	uint16_t         fixed_voltage;	    /* the (milli)voltage if LDO is fixed */
219	const uint16_t  *supp_voltages;     /* pointer to an array of possible voltages */
220	uint32_t         num_supp_voltages; /* the number of supplied voltages */
221};
222
223struct twl_vreg_softc {
224	device_t        sc_dev;
225	device_t        sc_pdev;
226	struct sx       sc_sx;
227
228	struct intr_config_hook sc_init_hook;
229	LIST_HEAD(twl_regulator_list, twl_regulator_entry) sc_vreg_list;
230};
231
232#define TWL_VREG_XLOCK(_sc)			sx_xlock(&(_sc)->sc_sx)
233#define	TWL_VREG_XUNLOCK(_sc)		sx_xunlock(&(_sc)->sc_sx)
234#define TWL_VREG_SLOCK(_sc)			sx_slock(&(_sc)->sc_sx)
235#define	TWL_VREG_SUNLOCK(_sc)		sx_sunlock(&(_sc)->sc_sx)
236#define TWL_VREG_LOCK_INIT(_sc)		sx_init(&(_sc)->sc_sx, "twl_vreg")
237#define TWL_VREG_LOCK_DESTROY(_sc)	sx_destroy(&(_sc)->sc_sx);
238
239#define TWL_VREG_ASSERT_LOCKED(_sc)	sx_assert(&(_sc)->sc_sx, SA_LOCKED);
240
241#define TWL_VREG_LOCK_UPGRADE(_sc)               \
242	do {                                         \
243		while (!sx_try_upgrade(&(_sc)->sc_sx))   \
244			pause("twl_vreg_ex", (hz / 100));    \
245	} while(0)
246#define TWL_VREG_LOCK_DOWNGRADE(_sc)	sx_downgrade(&(_sc)->sc_sx);
247
248/**
249 *	twl_vreg_read_1 - read single register from the TWL device
250 *	twl_vreg_write_1 - write a single register in the TWL device
251 *	@sc: device context
252 *	@clk: the clock device we're reading from / writing to
253 *	@off: offset within the clock's register set
254 *	@val: the value to write or a pointer to a variable to store the result
255 *
256 *	RETURNS:
257 *	Zero on success or an error code on failure.
258 */
259static inline int
260twl_vreg_read_1(struct twl_vreg_softc *sc, struct twl_regulator_entry *regulator,
261	uint8_t off, uint8_t *val)
262{
263	return (twl_read(sc->sc_pdev, regulator->sub_dev,
264	    regulator->reg_off + off, val, 1));
265}
266
267static inline int
268twl_vreg_write_1(struct twl_vreg_softc *sc, struct twl_regulator_entry *regulator,
269	uint8_t off, uint8_t val)
270{
271	return (twl_write(sc->sc_pdev, regulator->sub_dev,
272	    regulator->reg_off + off, &val, 1));
273}
274
275/**
276 *	twl_millivolt_to_vsel - gets the vsel bit value to write into the register
277 *	                        for a desired voltage and regulator
278 *	@sc: the device soft context
279 *	@regulator: pointer to the regulator device
280 *	@millivolts: the millivolts to find the bit value for
281 *	@vsel: upon return will contain the corresponding register value
282 *
283 *	Accepts a (milli)voltage value and tries to find the closest match to the
284 *	actual supported voltages for the given regulator.  If a match is found
285 *	within 100mv of the target, @vsel is written with the match and 0 is
286 *	returned. If no voltage match is found the function returns an non-zero
287 *	value.
288 *
289 *	RETURNS:
290 *	Zero on success or an error code on failure.
291 */
292static int
293twl_vreg_millivolt_to_vsel(struct twl_vreg_softc *sc,
294	struct twl_regulator_entry *regulator, int millivolts, uint8_t *vsel)
295{
296	int delta, smallest_delta;
297	unsigned i, closest_idx;
298
299	TWL_VREG_ASSERT_LOCKED(sc);
300
301	if (regulator->supp_voltages == NULL)
302		return (EINVAL);
303
304	/* Loop over the support voltages and try and find the closest match */
305	closest_idx = 0;
306	smallest_delta = 0x7fffffff;
307	for (i = 0; i < regulator->num_supp_voltages; i++) {
308		/* Ignore undefined values */
309		if (regulator->supp_voltages[i] == UNDF)
310			continue;
311
312		/* Calculate the difference */
313		delta = millivolts - (int)regulator->supp_voltages[i];
314		if (abs(delta) < smallest_delta) {
315			smallest_delta = abs(delta);
316			closest_idx = i;
317		}
318	}
319
320	/* Check we got a voltage that was within 100mv of the actual target, this
321	 * is just a value I picked out of thin air.
322	 */
323	if ((smallest_delta > 100) && (closest_idx < 0x100))
324		return (EINVAL);
325
326	*vsel = closest_idx;
327	return (0);
328}
329
330/**
331 *	twl_vreg_is_regulator_enabled - returns the enabled status of the regulator
332 *	@sc: the device soft context
333 *	@regulator: pointer to the regulator device
334 *	@enabled: stores the enabled status, zero disabled, non-zero enabled
335 *
336 *	LOCKING:
337 *	On entry expects the TWL VREG lock to be held. Will upgrade the lock to
338 *	exclusive if not already but, if so, it will be downgraded again before
339 *	returning.
340 *
341 *	RETURNS:
342 *	Zero on success or an error code on failure.
343 */
344static int
345twl_vreg_is_regulator_enabled(struct twl_vreg_softc *sc,
346	struct twl_regulator_entry *regulator, int *enabled)
347{
348	int err;
349	uint8_t grp;
350	uint8_t state;
351	int xlocked;
352
353	if (enabled == NULL)
354		return (EINVAL);
355
356	TWL_VREG_ASSERT_LOCKED(sc);
357
358	xlocked = sx_xlocked(&sc->sc_sx);
359	if (!xlocked)
360		TWL_VREG_LOCK_UPGRADE(sc);
361
362	/* The status reading is different for the different devices */
363	if (twl_is_4030(sc->sc_pdev)) {
364		err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &state);
365		if (err)
366			goto done;
367
368		*enabled = (state & TWL4030_P1_GRP);
369
370	} else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
371		/* Check the regulator is in the application group */
372		if (twl_is_6030(sc->sc_pdev)) {
373			err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp);
374			if (err)
375				goto done;
376
377			if (!(grp & TWL6030_P1_GRP)) {
378				*enabled = 0; /* disabled */
379				goto done;
380			}
381		}
382
383		/* Read the application mode state and verify it's ON */
384		err = twl_vreg_read_1(sc, regulator, TWL_VREG_STATE, &state);
385		if (err)
386			goto done;
387
388		*enabled = ((state & 0x0C) == 0x04);
389
390	} else {
391		err = EINVAL;
392	}
393
394done:
395	if (!xlocked)
396		TWL_VREG_LOCK_DOWNGRADE(sc);
397
398	return (err);
399}
400
401/**
402 *	twl_vreg_disable_regulator - disables a voltage regulator
403 *	@sc: the device soft context
404 *	@regulator: pointer to the regulator device
405 *
406 *	Disables the regulator which will stop the output drivers.
407 *
408 *	LOCKING:
409 *	On entry expects the TWL VREG lock to be held. Will upgrade the lock to
410 *	exclusive if not already but, if so, it will be downgraded again before
411 *	returning.
412 *
413 *	RETURNS:
414 *	Zero on success or a positive error code on failure.
415 */
416static int
417twl_vreg_disable_regulator(struct twl_vreg_softc *sc,
418	struct twl_regulator_entry *regulator)
419{
420	int err = 0;
421	uint8_t grp;
422	int xlocked;
423
424	TWL_VREG_ASSERT_LOCKED(sc);
425
426	xlocked = sx_xlocked(&sc->sc_sx);
427	if (!xlocked)
428		TWL_VREG_LOCK_UPGRADE(sc);
429
430	if (twl_is_4030(sc->sc_pdev)) {
431		/* Read the regulator CFG_GRP register */
432		err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp);
433		if (err)
434			goto done;
435
436		/* On the TWL4030 we just need to remove the regulator from all the
437		 * power groups.
438		 */
439		grp &= ~(TWL4030_P1_GRP | TWL4030_P2_GRP | TWL4030_P3_GRP);
440		err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp);
441
442	} else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
443		/* On TWL6030 we need to make sure we disable power for all groups */
444		if (twl_is_6030(sc->sc_pdev))
445			grp = TWL6030_P1_GRP | TWL6030_P2_GRP | TWL6030_P3_GRP;
446		else
447			grp = 0x00;
448
449		/* Write the resource state to "OFF" */
450		err = twl_vreg_write_1(sc, regulator, TWL_VREG_STATE, (grp << 5));
451	}
452
453done:
454	if (!xlocked)
455		TWL_VREG_LOCK_DOWNGRADE(sc);
456
457	return (err);
458}
459
460/**
461 *	twl_vreg_enable_regulator - enables the voltage regulator
462 *	@sc: the device soft context
463 *	@regulator: pointer to the regulator device
464 *
465 *	Enables the regulator which will enable the voltage out at the currently
466 *	set voltage.  Set the voltage before calling this function to avoid
467 *	driving the voltage too high/low by mistake.
468 *
469 *	LOCKING:
470 *	On entry expects the TWL VREG lock to be held. Will upgrade the lock to
471 *	exclusive if not already but, if so, it will be downgraded again before
472 *	returning.
473 *
474 *	RETURNS:
475 *	Zero on success or a positive error code on failure.
476 */
477static int
478twl_vreg_enable_regulator(struct twl_vreg_softc *sc,
479    struct twl_regulator_entry *regulator)
480{
481	int err;
482	uint8_t grp;
483	int xlocked;
484
485	TWL_VREG_ASSERT_LOCKED(sc);
486
487	xlocked = sx_xlocked(&sc->sc_sx);
488	if (!xlocked)
489		TWL_VREG_LOCK_UPGRADE(sc);
490
491	err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp);
492	if (err)
493		goto done;
494
495	/* Enable the regulator by ensuring it's in the application power group
496	 * and is in the "on" state.
497	 */
498	if (twl_is_4030(sc->sc_pdev)) {
499		/* On the TWL4030 we just need to ensure the regulator is in the right
500		 * power domain, don't need to turn on explicitly like TWL6030.
501		 */
502		grp |= TWL4030_P1_GRP;
503		err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp);
504
505	} else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) {
506		if (twl_is_6030(sc->sc_pdev) && !(grp & TWL6030_P1_GRP)) {
507			grp |= TWL6030_P1_GRP;
508			err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp);
509			if (err)
510				goto done;
511		}
512
513		/* Write the resource state to "ON" */
514		err = twl_vreg_write_1(sc, regulator, TWL_VREG_STATE, (grp << 5) | 0x01);
515	}
516
517done:
518	if (!xlocked)
519		TWL_VREG_LOCK_DOWNGRADE(sc);
520
521	return (err);
522}
523
524/**
525 *	twl_vreg_write_regulator_voltage - sets the voltage level on a regulator
526 *	@sc: the device soft context
527 *	@regulator: pointer to the regulator structure
528 *	@millivolts: the voltage to set
529 *
530 *	Sets the voltage output on a given regulator, if the regulator is not
531 *	enabled, it will be enabled.
532 *
533 *	LOCKING:
534 *	On entry expects the TWL VREG lock to be held, may upgrade the lock to
535 *	exclusive but if so it will be downgraded once again before returning.
536 *
537 *	RETURNS:
538 *	Zero on success or an error code on failure.
539 */
540static int
541twl_vreg_write_regulator_voltage(struct twl_vreg_softc *sc,
542    struct twl_regulator_entry *regulator, int millivolts)
543{
544	int err;
545	uint8_t vsel;
546	int xlocked;
547
548	TWL_VREG_ASSERT_LOCKED(sc);
549
550	/* If millivolts is zero then we simply disable the output */
551	if (millivolts == 0)
552		return (twl_vreg_disable_regulator(sc, regulator));
553
554	/* If the regulator has a fixed voltage then check the setting matches
555	 * and simply enable.
556	 */
557	if (regulator->supp_voltages == NULL || regulator->num_supp_voltages == 0) {
558		if (millivolts != regulator->fixed_voltage)
559			return (EINVAL);
560
561		return (twl_vreg_enable_regulator(sc, regulator));
562	}
563
564	/* Get the VSEL value for the given voltage */
565	err = twl_vreg_millivolt_to_vsel(sc, regulator, millivolts, &vsel);
566	if (err)
567		return (err);
568
569	/* Need to upgrade because writing the voltage and enabling should be atomic */
570	xlocked = sx_xlocked(&sc->sc_sx);
571	if (!xlocked)
572		TWL_VREG_LOCK_UPGRADE(sc);
573
574	/* Set voltage and enable (atomically) */
575	err = twl_vreg_write_1(sc, regulator, TWL_VREG_VSEL, (vsel & 0x1f));
576	if (!err) {
577		err = twl_vreg_enable_regulator(sc, regulator);
578	}
579
580	if (!xlocked)
581		TWL_VREG_LOCK_DOWNGRADE(sc);
582
583	if ((twl_vreg_debug > 1) && !err)
584		device_printf(sc->sc_dev, "%s : setting voltage to %dmV (vsel: 0x%x)\n",
585		    regulator->name, millivolts, vsel);
586
587	return (err);
588}
589
590/**
591 *	twl_vreg_read_regulator_voltage - reads the voltage on a given regulator
592 *	@sc: the device soft context
593 *	@regulator: pointer to the regulator structure
594 *	@millivolts: upon return will contain the voltage on the regulator
595 *
596 *	LOCKING:
597 *	On entry expects the TWL VREG lock to be held. It will upgrade the lock to
598 *	exclusive if not already, but if so, it will be downgraded again before
599 *	returning.
600 *
601 *	RETURNS:
602 *	Zero on success, or otherwise an error code.
603 */
604static int
605twl_vreg_read_regulator_voltage(struct twl_vreg_softc *sc,
606    struct twl_regulator_entry *regulator, int *millivolts)
607{
608	int err;
609	int en = 0;
610	int xlocked;
611	uint8_t vsel;
612
613	TWL_VREG_ASSERT_LOCKED(sc);
614
615	/* Need to upgrade the lock because checking enabled state and voltage
616	 * should be atomic.
617	 */
618	xlocked = sx_xlocked(&sc->sc_sx);
619	if (!xlocked)
620		TWL_VREG_LOCK_UPGRADE(sc);
621
622	/* Check if the regulator is currently enabled */
623	err = twl_vreg_is_regulator_enabled(sc, regulator, &en);
624	if (err)
625		goto done;
626
627	*millivolts = 0;
628	if (!en)
629		goto done;
630
631	/* Not all voltages are adjustable */
632	if (regulator->supp_voltages == NULL || !regulator->num_supp_voltages) {
633		*millivolts = regulator->fixed_voltage;
634		goto done;
635	}
636
637	/* For variable voltages read the voltage register */
638	err = twl_vreg_read_1(sc, regulator, TWL_VREG_VSEL, &vsel);
639	if (err)
640		goto done;
641
642	vsel &= (regulator->num_supp_voltages - 1);
643	if (regulator->supp_voltages[vsel] == UNDF) {
644		err = EINVAL;
645		goto done;
646	}
647
648	*millivolts = regulator->supp_voltages[vsel];
649
650done:
651	if (!xlocked)
652		TWL_VREG_LOCK_DOWNGRADE(sc);
653
654	if ((twl_vreg_debug > 1) && !err)
655		device_printf(sc->sc_dev, "%s : reading voltage is %dmV (vsel: 0x%x)\n",
656		    regulator->name, *millivolts, vsel);
657
658	return (err);
659}
660
661/**
662 *	twl_vreg_get_voltage - public interface to read the voltage on a regulator
663 *	@dev: TWL VREG device
664 *	@name: the name of the regulator to read the voltage of
665 *	@millivolts: pointer to an integer that upon return will contain the mV
666 *
667 *	If the regulator is disabled the function will set the @millivolts to zero.
668 *
669 *	LOCKING:
670 *	Internally the function takes and releases the TWL VREG lock.
671 *
672 *	RETURNS:
673 *	Zero on success or a negative error code on failure.
674 */
675int
676twl_vreg_get_voltage(device_t dev, const char *name, int *millivolts)
677{
678	struct twl_vreg_softc *sc;
679	struct twl_regulator_entry *regulator;
680	int err = EINVAL;
681
682	if (millivolts == NULL)
683		return (EINVAL);
684
685	sc = device_get_softc(dev);
686
687	TWL_VREG_SLOCK(sc);
688
689	LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) {
690		if (strcmp(regulator->name, name) == 0) {
691			err = twl_vreg_read_regulator_voltage(sc, regulator, millivolts);
692			break;
693		}
694	}
695
696	TWL_VREG_SUNLOCK(sc);
697
698	return (err);
699}
700
701/**
702 *	twl_vreg_set_voltage - public interface to write the voltage on a regulator
703 *	@dev: TWL VREG device
704 *	@name: the name of the regulator to read the voltage of
705 *	@millivolts: the voltage to set in millivolts
706 *
707 *	Sets the output voltage on a given regulator. If the regulator is a fixed
708 *	voltage reg then the @millivolts value should match the fixed voltage. If
709 *	a variable regulator then the @millivolt value must fit within the max/min
710 *	range of the given regulator.
711 *
712 *	LOCKING:
713 *	Internally the function takes and releases the TWL VREG lock.
714 *
715 *	RETURNS:
716 *	Zero on success or a negative error code on failure.
717 */
718int
719twl_vreg_set_voltage(device_t dev, const char *name, int millivolts)
720{
721	struct twl_vreg_softc *sc;
722	struct twl_regulator_entry *regulator;
723	int err = EINVAL;
724
725	sc = device_get_softc(dev);
726
727	TWL_VREG_SLOCK(sc);
728
729	LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) {
730		if (strcmp(regulator->name, name) == 0) {
731			err = twl_vreg_write_regulator_voltage(sc, regulator, millivolts);
732			break;
733		}
734	}
735
736	TWL_VREG_SUNLOCK(sc);
737
738	return (err);
739}
740
741/**
742 *	twl_sysctl_voltage - reads or writes the voltage for a regulator
743 *	@SYSCTL_HANDLER_ARGS: arguments for the callback
744 *
745 *	Callback for the sysctl entry for the regulator, simply used to return
746 *	the voltage on a particular regulator.
747 *
748 *	LOCKING:
749 *	Takes the TWL_VREG shared lock internally.
750 *
751 *	RETURNS:
752 *	Zero on success or an error code on failure.
753 */
754static int
755twl_vreg_sysctl_voltage(SYSCTL_HANDLER_ARGS)
756{
757	struct twl_vreg_softc *sc = (struct twl_vreg_softc*)arg1;
758	struct twl_regulator_entry *regulator;
759	int voltage;
760	int found = 0;
761
762	TWL_VREG_SLOCK(sc);
763
764	/* Find the regulator with the matching name */
765	LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) {
766		if (strcmp(regulator->name, oidp->oid_name) == 0) {
767			found = 1;
768			break;
769		}
770	}
771
772	/* Sanity check that we found the regulator */
773	if (!found) {
774		TWL_VREG_SUNLOCK(sc);
775		return (EINVAL);
776	}
777
778	twl_vreg_read_regulator_voltage(sc, regulator, &voltage);
779
780	TWL_VREG_SUNLOCK(sc);
781
782	return sysctl_handle_int(oidp, &voltage, 0, req);
783}
784
785/**
786 *	twl_add_regulator - adds single voltage regulator sysctls for the device
787 *	@sc: device soft context
788 *	@name: the name of the regulator
789 *	@nsub: the number of the subdevice
790 *	@regbase: the base address of the voltage regulator registers
791 *	@fixed_voltage: if a fixed voltage regulator this defines it's voltage
792 *	@voltages: if a variable voltage regulator, an array of possible voltages
793 *	@num_voltages: the number of entries @voltages
794 *
795 *	Adds a voltage regulator to the device and also a sysctl interface for the
796 *	regulator.
797 *
798 *	LOCKING:
799 *	The TWL_VEG exclusive lock must be held while this function is called.
800 *
801 *	RETURNS:
802 *	Pointer to the new regulator entry on success, otherwise on failure NULL.
803 */
804static struct twl_regulator_entry*
805twl_vreg_add_regulator(struct twl_vreg_softc *sc, const char *name,
806	uint8_t nsub, uint8_t regbase, uint16_t fixed_voltage,
807	const uint16_t *voltages, uint32_t num_voltages)
808{
809	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
810	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
811	struct twl_regulator_entry *new;
812
813	new = malloc(sizeof(struct twl_regulator_entry), M_DEVBUF, M_NOWAIT | M_ZERO);
814	if (new == NULL)
815		return (NULL);
816
817	strncpy(new->name, name, TWL_VREG_MAX_NAMELEN);
818	new->name[TWL_VREG_MAX_NAMELEN - 1] = '\0';
819
820	new->sub_dev = nsub;
821	new->reg_off = regbase;
822
823	new->fixed_voltage = fixed_voltage;
824
825	new->supp_voltages = voltages;
826	new->num_supp_voltages = num_voltages;
827
828	/* Add a sysctl entry for the voltage */
829	new->oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, name,
830	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0,
831	    twl_vreg_sysctl_voltage, "I", "voltage regulator");
832
833	/* Finally add the regulator to list of supported regulators */
834	LIST_INSERT_HEAD(&sc->sc_vreg_list, new, entries);
835
836	return (new);
837}
838
839/**
840 *	twl_vreg_add_regulators - adds any voltage regulators to the device
841 *	@sc: device soft context
842 *	@chip: the name of the chip used in the hints
843 *	@regulators: the list of possible voltage regulators
844 *
845 *	Loops over the list of regulators and matches up with the FDT values,
846 *	adjusting the actual voltage based on the supplied values.
847 *
848 *	LOCKING:
849 *	The TWL_VEG exclusive lock must be held while this function is called.
850 *
851 *	RETURNS:
852 *	Always returns 0.
853 */
854static int
855twl_vreg_add_regulators(struct twl_vreg_softc *sc,
856	const struct twl_regulator *regulators)
857{
858	int err;
859	int millivolts;
860	const struct twl_regulator *walker;
861	struct twl_regulator_entry *entry;
862	phandle_t child;
863	char rnames[256];
864	char *name, *voltage;
865	int len = 0, prop_len;
866
867	/* Add the regulators from the list */
868	walker = &regulators[0];
869	while (walker->name != NULL) {
870		/* Add the regulator to the list */
871		entry = twl_vreg_add_regulator(sc, walker->name, walker->subdev,
872		    walker->regbase, walker->fixedvoltage,
873		    walker->voltages, walker->num_voltages);
874		if (entry == NULL)
875			continue;
876
877		walker++;
878	}
879
880	/* Check if the FDT is telling us to set any voltages */
881	child = ofw_bus_get_node(sc->sc_pdev);
882	if (child) {
883		prop_len = OF_getprop(child, "voltage-regulators", rnames, sizeof(rnames));
884		while (len < prop_len) {
885			name = rnames + len;
886			len += strlen(name) + 1;
887			if ((len >= prop_len) || (name[0] == '\0'))
888				break;
889
890			voltage = rnames + len;
891			len += strlen(voltage) + 1;
892			if (voltage[0] == '\0')
893				break;
894
895			millivolts = strtoul(voltage, NULL, 0);
896
897			LIST_FOREACH(entry, &sc->sc_vreg_list, entries) {
898				if (strcmp(entry->name, name) == 0) {
899					twl_vreg_write_regulator_voltage(sc, entry, millivolts);
900					break;
901				}
902			}
903		}
904	}
905
906	if (twl_vreg_debug) {
907		LIST_FOREACH(entry, &sc->sc_vreg_list, entries) {
908			err = twl_vreg_read_regulator_voltage(sc, entry, &millivolts);
909			if (!err)
910				device_printf(sc->sc_dev, "%s : %d mV\n", entry->name, millivolts);
911		}
912	}
913
914	return (0);
915}
916
917/**
918 *	twl_vreg_init - initialises the list of regulators
919 *	@dev: the twl_vreg device
920 *
921 *	This function is called as an intrhook once interrupts have been enabled,
922 *	this is done so that the driver has the option to enable/disable or set
923 *	the voltage level based on settings providied in the FDT.
924 *
925 *	LOCKING:
926 *	Takes the exclusive lock in the function.
927 */
928static void
929twl_vreg_init(void *dev)
930{
931	struct twl_vreg_softc *sc;
932
933	sc = device_get_softc((device_t)dev);
934
935	TWL_VREG_XLOCK(sc);
936
937	if (twl_is_4030(sc->sc_pdev))
938		twl_vreg_add_regulators(sc, twl4030_regulators);
939	else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev))
940		twl_vreg_add_regulators(sc, twl6030_regulators);
941
942	TWL_VREG_XUNLOCK(sc);
943
944	config_intrhook_disestablish(&sc->sc_init_hook);
945}
946
947static int
948twl_vreg_probe(device_t dev)
949{
950	if (twl_is_4030(device_get_parent(dev)))
951		device_set_desc(dev, "TI TWL4030 PMIC Voltage Regulators");
952	else if (twl_is_6025(device_get_parent(dev)) ||
953	         twl_is_6030(device_get_parent(dev)))
954		device_set_desc(dev, "TI TWL6025/TWL6030 PMIC Voltage Regulators");
955	else
956		return (ENXIO);
957
958	return (0);
959}
960
961static int
962twl_vreg_attach(device_t dev)
963{
964	struct twl_vreg_softc *sc;
965
966	sc = device_get_softc(dev);
967	sc->sc_dev = dev;
968	sc->sc_pdev = device_get_parent(dev);
969
970	TWL_VREG_LOCK_INIT(sc);
971
972	LIST_INIT(&sc->sc_vreg_list);
973
974	/* We have to wait until interrupts are enabled. I2C read and write
975	 * only works if the interrupts are available.
976	 */
977	sc->sc_init_hook.ich_func = twl_vreg_init;
978	sc->sc_init_hook.ich_arg = dev;
979
980	if (config_intrhook_establish(&sc->sc_init_hook) != 0)
981		return (ENOMEM);
982
983	return (0);
984}
985
986static int
987twl_vreg_detach(device_t dev)
988{
989	struct twl_vreg_softc *sc;
990	struct twl_regulator_entry *regulator;
991	struct twl_regulator_entry *tmp;
992
993	sc = device_get_softc(dev);
994
995	/* Take the lock and free all the added regulators */
996	TWL_VREG_XLOCK(sc);
997
998	LIST_FOREACH_SAFE(regulator, &sc->sc_vreg_list, entries, tmp) {
999		LIST_REMOVE(regulator, entries);
1000		sysctl_remove_oid(regulator->oid, 1, 0);
1001		free(regulator, M_DEVBUF);
1002	}
1003
1004	TWL_VREG_XUNLOCK(sc);
1005
1006	TWL_VREG_LOCK_DESTROY(sc);
1007
1008	return (0);
1009}
1010
1011static device_method_t twl_vreg_methods[] = {
1012	DEVMETHOD(device_probe,		twl_vreg_probe),
1013	DEVMETHOD(device_attach,	twl_vreg_attach),
1014	DEVMETHOD(device_detach,	twl_vreg_detach),
1015
1016	{0, 0},
1017};
1018
1019static driver_t twl_vreg_driver = {
1020	"twl_vreg",
1021	twl_vreg_methods,
1022	sizeof(struct twl_vreg_softc),
1023};
1024
1025DRIVER_MODULE(twl_vreg, twl, twl_vreg_driver, 0, 0);
1026MODULE_VERSION(twl_vreg, 1);
1027