xref: /freebsd/sys/arm/allwinner/axp209.c (revision 3fc36ee018bb836bd1796067cf4ef8683f166ebc)
1 /*-
2  * Copyright (c) 2015-2016 Emmanuel Vadot <manu@freebsd.org>
3  * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 /*
31 * X-Power AXP209 PMU for Allwinner SoCs
32 */
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/eventhandler.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/clock.h>
39 #include <sys/time.h>
40 #include <sys/bus.h>
41 #include <sys/proc.h>
42 #include <sys/gpio.h>
43 #include <sys/reboot.h>
44 #include <sys/resource.h>
45 #include <sys/rman.h>
46 #include <sys/sysctl.h>
47 
48 #include <dev/iicbus/iicbus.h>
49 #include <dev/iicbus/iiconf.h>
50 
51 #include <dev/gpio/gpiobusvar.h>
52 
53 #include <dev/ofw/openfirm.h>
54 #include <dev/ofw/ofw_bus.h>
55 #include <dev/ofw/ofw_bus_subr.h>
56 
57 #include <arm/allwinner/axp209reg.h>
58 
59 #include "iicbus_if.h"
60 #include "gpio_if.h"
61 
62 struct axp209_softc {
63 	device_t		dev;
64 	uint32_t		addr;
65 	struct resource *	res[1];
66 	void *			intrcookie;
67 	struct intr_config_hook	intr_hook;
68 	device_t		gpiodev;
69 	struct mtx		mtx;
70 };
71 
72 /* GPIO3 is different, don't expose it for now */
73 static const struct {
74 	const char *name;
75 	uint8_t	ctrl_reg;
76 } axp209_pins[] = {
77 	{ "GPIO0", AXP209_GPIO0_CTRL },
78 	{ "GPIO1", AXP209_GPIO1_CTRL },
79 	{ "GPIO2", AXP209_GPIO2_CTRL },
80 };
81 
82 static struct resource_spec axp_res_spec[] = {
83 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
84 	{ -1,			0,	0 }
85 };
86 
87 #define	AXP_LOCK(sc)	mtx_lock(&(sc)->mtx)
88 #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
89 
90 static int
91 axp209_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
92 {
93 	struct axp209_softc *sc = device_get_softc(dev);
94 	struct iic_msg msg[2];
95 
96 	msg[0].slave = sc->addr;
97 	msg[0].flags = IIC_M_WR;
98 	msg[0].len = 1;
99 	msg[0].buf = &reg;
100 
101 	msg[1].slave = sc->addr;
102 	msg[1].flags = IIC_M_RD;
103 	msg[1].len = size;
104 	msg[1].buf = data;
105 
106 	return (iicbus_transfer(dev, msg, 2));
107 }
108 
109 static int
110 axp209_write(device_t dev, uint8_t reg, uint8_t data)
111 {
112 	uint8_t buffer[2];
113 	struct axp209_softc *sc = device_get_softc(dev);
114 	struct iic_msg msg;
115 
116 	buffer[0] = reg;
117 	buffer[1] = data;
118 
119 	msg.slave = sc->addr;
120 	msg.flags = IIC_M_WR;
121 	msg.len = 2;
122 	msg.buf = buffer;
123 
124 	return (iicbus_transfer(dev, &msg, 1));
125 }
126 
127 static int
128 axp209_sysctl(SYSCTL_HANDLER_ARGS)
129 {
130 	device_t dev = arg1;
131 	enum axp209_sensor sensor = arg2;
132 	uint8_t data[2];
133 	int val, error;
134 
135 	switch (sensor) {
136 	case AXP209_TEMP:
137 		error = axp209_read(dev, AXP209_TEMPMON, data, 2);
138 		if (error != 0)
139 			return (error);
140 
141 		/* Temperature is between -144.7C and 264.8C, step +0.1C */
142 		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) -
143 		    AXP209_TEMPMON_MIN + AXP209_0C_TO_K;
144 		break;
145 	case AXP209_ACVOLT:
146 		error = axp209_read(dev, AXP209_ACIN_VOLTAGE, data, 2);
147 		if (error != 0)
148 			return (error);
149 
150 		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
151 		    AXP209_VOLT_STEP;
152 		break;
153 	case AXP209_ACCURRENT:
154 		error = axp209_read(dev, AXP209_ACIN_CURRENT, data, 2);
155 		if (error != 0)
156 			return (error);
157 
158 		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
159 		    AXP209_ACCURRENT_STEP;
160 		break;
161 	case AXP209_VBUSVOLT:
162 		error = axp209_read(dev, AXP209_VBUS_VOLTAGE, data, 2);
163 		if (error != 0)
164 			return (error);
165 
166 		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
167 		    AXP209_VOLT_STEP;
168 		break;
169 	case AXP209_VBUSCURRENT:
170 		error = axp209_read(dev, AXP209_VBUS_CURRENT, data, 2);
171 		if (error != 0)
172 			return (error);
173 
174 		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
175 		    AXP209_VBUSCURRENT_STEP;
176 		break;
177 	case AXP209_BATVOLT:
178 		error = axp209_read(dev, AXP209_BAT_VOLTAGE, data, 2);
179 		if (error != 0)
180 			return (error);
181 
182 		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
183 		    AXP209_BATVOLT_STEP;
184 		break;
185 	case AXP209_BATCHARGECURRENT:
186 		error = axp209_read(dev, AXP209_BAT_CHARGE_CURRENT, data, 2);
187 		if (error != 0)
188 			return (error);
189 
190 		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
191 		    AXP209_BATCURRENT_STEP;
192 		break;
193 	case AXP209_BATDISCHARGECURRENT:
194 		error = axp209_read(dev, AXP209_BAT_DISCHARGE_CURRENT, data, 2);
195 		if (error != 0)
196 			return (error);
197 
198 		val = (AXP209_SENSOR_BAT_H(data[0]) |
199 		    AXP209_SENSOR_BAT_L(data[1])) * AXP209_BATCURRENT_STEP;
200 		break;
201 	default:
202 		return (ENOENT);
203 	}
204 
205 	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
206 }
207 
208 static void
209 axp209_shutdown(void *devp, int howto)
210 {
211 	device_t dev;
212 
213 	if (!(howto & RB_POWEROFF))
214 		return;
215 	dev = (device_t)devp;
216 
217 	if (bootverbose)
218 		device_printf(dev, "Shutdown AXP209\n");
219 
220 	axp209_write(dev, AXP209_SHUTBAT, AXP209_SHUTBAT_SHUTDOWN);
221 }
222 
223 static void
224 axp_intr(void *arg)
225 {
226 	struct axp209_softc *sc;
227 	uint8_t reg;
228 
229 	sc = arg;
230 
231 	axp209_read(sc->dev, AXP209_IRQ1_STATUS, &reg, 1);
232 	if (reg) {
233 		if (reg & AXP209_IRQ1_AC_OVERVOLT)
234 			devctl_notify("PMU", "AC", "overvoltage", NULL);
235 		if (reg & AXP209_IRQ1_VBUS_OVERVOLT)
236 			devctl_notify("PMU", "USB", "overvoltage", NULL);
237 		if (reg & AXP209_IRQ1_VBUS_LOW)
238 			devctl_notify("PMU", "USB", "undervoltage", NULL);
239 		if (reg & AXP209_IRQ1_AC_CONN)
240 			devctl_notify("PMU", "AC", "plugged", NULL);
241 		if (reg & AXP209_IRQ1_AC_DISCONN)
242 			devctl_notify("PMU", "AC", "unplugged", NULL);
243 		if (reg & AXP209_IRQ1_VBUS_CONN)
244 			devctl_notify("PMU", "USB", "plugged", NULL);
245 		if (reg & AXP209_IRQ1_VBUS_DISCONN)
246 			devctl_notify("PMU", "USB", "unplugged", NULL);
247 		axp209_write(sc->dev, AXP209_IRQ1_STATUS, AXP209_IRQ_ACK);
248 	}
249 
250 	axp209_read(sc->dev, AXP209_IRQ2_STATUS, &reg, 1);
251 	if (reg) {
252 		if (reg & AXP209_IRQ2_BATT_CHARGED)
253 			devctl_notify("PMU", "Battery", "charged", NULL);
254 		if (reg & AXP209_IRQ2_BATT_CHARGING)
255 			devctl_notify("PMU", "Battery", "charging", NULL);
256 		if (reg & AXP209_IRQ2_BATT_CONN)
257 			devctl_notify("PMU", "Battery", "connected", NULL);
258 		if (reg & AXP209_IRQ2_BATT_DISCONN)
259 			devctl_notify("PMU", "Battery", "disconnected", NULL);
260 		if (reg & AXP209_IRQ2_BATT_TEMP_LOW)
261 			devctl_notify("PMU", "Battery", "low temp", NULL);
262 		if (reg & AXP209_IRQ2_BATT_TEMP_OVER)
263 			devctl_notify("PMU", "Battery", "high temp", NULL);
264 		axp209_write(sc->dev, AXP209_IRQ2_STATUS, AXP209_IRQ_ACK);
265 	}
266 
267 	axp209_read(sc->dev, AXP209_IRQ3_STATUS, &reg, 1);
268 	if (reg) {
269 		if (reg & AXP209_IRQ3_PEK_SHORT)
270 			shutdown_nice(RB_POWEROFF);
271 		axp209_write(sc->dev, AXP209_IRQ3_STATUS, AXP209_IRQ_ACK);
272 	}
273 
274 	axp209_read(sc->dev, AXP209_IRQ4_STATUS, &reg, 1);
275 	if (reg) {
276 		axp209_write(sc->dev, AXP209_IRQ4_STATUS, AXP209_IRQ_ACK);
277 	}
278 
279 	axp209_read(sc->dev, AXP209_IRQ5_STATUS, &reg, 1);
280 	if (reg) {
281 		axp209_write(sc->dev, AXP209_IRQ5_STATUS, AXP209_IRQ_ACK);
282 	}
283 }
284 
285 static device_t
286 axp209_gpio_get_bus(device_t dev)
287 {
288 	struct axp209_softc *sc;
289 
290 	sc = device_get_softc(dev);
291 
292 	return (sc->gpiodev);
293 }
294 
295 static int
296 axp209_gpio_pin_max(device_t dev, int *maxpin)
297 {
298 	*maxpin = nitems(axp209_pins) - 1;
299 
300 	return (0);
301 }
302 
303 static int
304 axp209_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
305 {
306 	if (pin >= nitems(axp209_pins))
307 		return (EINVAL);
308 
309 	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
310 
311 	return (0);
312 }
313 
314 static int
315 axp209_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
316 {
317 	if (pin >= nitems(axp209_pins))
318 		return (EINVAL);
319 
320 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
321 
322 	return (0);
323 }
324 
325 static int
326 axp209_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
327 {
328 	struct axp209_softc *sc;
329 	uint8_t data, func;
330 	int error;
331 
332 	if (pin >= nitems(axp209_pins))
333 		return (EINVAL);
334 
335 	sc = device_get_softc(dev);
336 
337 	AXP_LOCK(sc);
338 	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
339 	if (error == 0) {
340 		func = data & AXP209_GPIO_FUNC_MASK;
341 		if (func == AXP209_GPIO_FUNC_INPUT)
342 			*flags = GPIO_PIN_INPUT;
343 		else if (func == AXP209_GPIO_FUNC_DRVLO ||
344 		    func == AXP209_GPIO_FUNC_DRVHI)
345 			*flags = GPIO_PIN_OUTPUT;
346 		else
347 			*flags = 0;
348 	}
349 	AXP_UNLOCK(sc);
350 
351 	return (error);
352 }
353 
354 static int
355 axp209_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
356 {
357 	struct axp209_softc *sc;
358 	uint8_t data;
359 	int error;
360 
361 	if (pin >= nitems(axp209_pins))
362 		return (EINVAL);
363 
364 	sc = device_get_softc(dev);
365 
366 	AXP_LOCK(sc);
367 	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
368 	if (error == 0) {
369 		data &= ~AXP209_GPIO_FUNC_MASK;
370 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
371 			if ((flags & GPIO_PIN_OUTPUT) == 0)
372 				data |= AXP209_GPIO_FUNC_INPUT;
373 		}
374 		error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data);
375 	}
376 	AXP_UNLOCK(sc);
377 
378 	return (error);
379 }
380 
381 static int
382 axp209_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
383 {
384 	struct axp209_softc *sc;
385 	uint8_t data, func;
386 	int error;
387 
388 	if (pin >= nitems(axp209_pins))
389 		return (EINVAL);
390 
391 	sc = device_get_softc(dev);
392 
393 	AXP_LOCK(sc);
394 	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
395 	if (error == 0) {
396 		func = data & AXP209_GPIO_FUNC_MASK;
397 		switch (func) {
398 		case AXP209_GPIO_FUNC_DRVLO:
399 			*val = 0;
400 			break;
401 		case AXP209_GPIO_FUNC_DRVHI:
402 			*val = 1;
403 			break;
404 		case AXP209_GPIO_FUNC_INPUT:
405 			error = axp209_read(dev, AXP209_GPIO_STATUS, &data, 1);
406 			if (error == 0)
407 				*val = (data & AXP209_GPIO_DATA(pin)) ? 1 : 0;
408 			break;
409 		default:
410 			error = EIO;
411 			break;
412 		}
413 	}
414 	AXP_UNLOCK(sc);
415 
416 	return (error);
417 }
418 
419 static int
420 axp209_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
421 {
422 	struct axp209_softc *sc;
423 	uint8_t data, func;
424 	int error;
425 
426 	if (pin >= nitems(axp209_pins))
427 		return (EINVAL);
428 
429 	sc = device_get_softc(dev);
430 
431 	AXP_LOCK(sc);
432 	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
433 	if (error == 0) {
434 		func = data & AXP209_GPIO_FUNC_MASK;
435 		switch (func) {
436 		case AXP209_GPIO_FUNC_DRVLO:
437 		case AXP209_GPIO_FUNC_DRVHI:
438 			/* GPIO2 can't be set to 1 */
439 			if (pin == 2 && val == 1) {
440 				error = EINVAL;
441 				break;
442 			}
443 			data &= ~AXP209_GPIO_FUNC_MASK;
444 			data |= val;
445 			break;
446 		default:
447 			error = EIO;
448 			break;
449 		}
450 	}
451 	if (error == 0)
452 		error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data);
453 	AXP_UNLOCK(sc);
454 
455 	return (error);
456 }
457 
458 
459 static int
460 axp209_gpio_pin_toggle(device_t dev, uint32_t pin)
461 {
462 	struct axp209_softc *sc;
463 	uint8_t data, func;
464 	int error;
465 
466 	if (pin >= nitems(axp209_pins))
467 		return (EINVAL);
468 
469 	sc = device_get_softc(dev);
470 
471 	AXP_LOCK(sc);
472 	error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1);
473 	if (error == 0) {
474 		func = data & AXP209_GPIO_FUNC_MASK;
475 		switch (func) {
476 		case AXP209_GPIO_FUNC_DRVLO:
477 			/* Pin 2 can't be set to 1*/
478 			if (pin == 2) {
479 				error = EINVAL;
480 				break;
481 			}
482 			data &= ~AXP209_GPIO_FUNC_MASK;
483 			data |= AXP209_GPIO_FUNC_DRVHI;
484 			break;
485 		case AXP209_GPIO_FUNC_DRVHI:
486 			data &= ~AXP209_GPIO_FUNC_MASK;
487 			data |= AXP209_GPIO_FUNC_DRVLO;
488 			break;
489 		default:
490 			error = EIO;
491 			break;
492 		}
493 	}
494 	if (error == 0)
495 		error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data);
496 	AXP_UNLOCK(sc);
497 
498 	return (error);
499 }
500 
501 static int
502 axp209_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
503     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
504 {
505 	if (gpios[0] >= nitems(axp209_pins))
506 		return (EINVAL);
507 
508 	*pin = gpios[0];
509 	*flags = gpios[1];
510 
511 	return (0);
512 }
513 
514 static phandle_t
515 axp209_get_node(device_t dev, device_t bus)
516 {
517 	return (ofw_bus_get_node(dev));
518 }
519 
520 static void
521 axp209_start(void *pdev)
522 {
523 	device_t dev;
524 	struct axp209_softc *sc;
525 	const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
526 	uint8_t data;
527 	uint8_t pwr_src;
528 
529 	dev = pdev;
530 
531 	sc = device_get_softc(dev);
532 	sc->addr = iicbus_get_addr(dev);
533 	sc->dev = dev;
534 
535 	if (bootverbose) {
536 		/*
537 		 * Read the Power State register.
538 		 * Shift the AC presence into bit 0.
539 		 * Shift the Battery presence into bit 1.
540 		 */
541 		axp209_read(dev, AXP209_PSR, &data, 1);
542 		pwr_src = ((data & AXP209_PSR_ACIN) >> AXP209_PSR_ACIN_SHIFT) |
543 		    ((data & AXP209_PSR_VBUS) >> (AXP209_PSR_VBUS_SHIFT - 1));
544 
545 		device_printf(dev, "AXP209 Powered by %s\n",
546 		    pwr_name[pwr_src]);
547 	}
548 
549 	/* Only enable interrupts that we are interested in */
550 	axp209_write(dev, AXP209_IRQ1_ENABLE,
551 	    AXP209_IRQ1_AC_OVERVOLT |
552 	    AXP209_IRQ1_AC_DISCONN |
553 	    AXP209_IRQ1_AC_CONN |
554 	    AXP209_IRQ1_VBUS_OVERVOLT |
555 	    AXP209_IRQ1_VBUS_DISCONN |
556 	    AXP209_IRQ1_VBUS_CONN);
557 	axp209_write(dev, AXP209_IRQ2_ENABLE,
558 	    AXP209_IRQ2_BATT_CONN |
559 	    AXP209_IRQ2_BATT_DISCONN |
560 	    AXP209_IRQ2_BATT_CHARGE_ACCT_ON |
561 	    AXP209_IRQ2_BATT_CHARGE_ACCT_OFF |
562 	    AXP209_IRQ2_BATT_CHARGING |
563 	    AXP209_IRQ2_BATT_CHARGED |
564 	    AXP209_IRQ2_BATT_TEMP_OVER |
565 	    AXP209_IRQ2_BATT_TEMP_LOW);
566 	axp209_write(dev, AXP209_IRQ3_ENABLE,
567 	    AXP209_IRQ3_PEK_SHORT | AXP209_IRQ3_PEK_LONG);
568 	axp209_write(dev, AXP209_IRQ4_ENABLE, AXP209_IRQ4_APS_LOW_2);
569 	axp209_write(dev, AXP209_IRQ5_ENABLE, 0x0);
570 
571 	EVENTHANDLER_REGISTER(shutdown_final, axp209_shutdown, dev,
572 	    SHUTDOWN_PRI_LAST);
573 
574 	/* Enable ADC sensors */
575 	if (axp209_write(dev, AXP209_ADC_ENABLE1,
576 	    AXP209_ADC1_BATVOLT | AXP209_ADC1_BATCURRENT |
577 	    AXP209_ADC1_ACVOLT | AXP209_ADC1_ACCURRENT |
578 	    AXP209_ADC1_VBUSVOLT | AXP209_ADC1_VBUSCURRENT) != -1) {
579 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
580 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
581 		    OID_AUTO, "acvolt",
582 		    CTLTYPE_INT | CTLFLAG_RD,
583 		    dev, AXP209_ACVOLT, axp209_sysctl, "I",
584 		    "AC Voltage (microVolt)");
585 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
586 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
587 		    OID_AUTO, "accurrent",
588 		    CTLTYPE_INT | CTLFLAG_RD,
589 		    dev, AXP209_ACCURRENT, axp209_sysctl, "I",
590 		    "AC Current (microAmpere)");
591 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
592 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
593 		    OID_AUTO, "vbusvolt",
594 		    CTLTYPE_INT | CTLFLAG_RD,
595 		    dev, AXP209_VBUSVOLT, axp209_sysctl, "I",
596 		    "VBUS Voltage (microVolt)");
597 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
598 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
599 		    OID_AUTO, "vbuscurrent",
600 		    CTLTYPE_INT | CTLFLAG_RD,
601 		    dev, AXP209_VBUSCURRENT, axp209_sysctl, "I",
602 		    "VBUS Current (microAmpere)");
603 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
604 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
605 		    OID_AUTO, "batvolt",
606 		    CTLTYPE_INT | CTLFLAG_RD,
607 		    dev, AXP209_BATVOLT, axp209_sysctl, "I",
608 		    "Battery Voltage (microVolt)");
609 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
610 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
611 		    OID_AUTO, "batchargecurrent",
612 		    CTLTYPE_INT | CTLFLAG_RD,
613 		    dev, AXP209_BATCHARGECURRENT, axp209_sysctl, "I",
614 		    "Battery Charging Current (microAmpere)");
615 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
616 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
617 		    OID_AUTO, "batdischargecurrent",
618 		    CTLTYPE_INT | CTLFLAG_RD,
619 		    dev, AXP209_BATDISCHARGECURRENT, axp209_sysctl, "I",
620 		    "Battery Discharging Current (microAmpere)");
621 	} else {
622 		device_printf(dev, "Couldn't enable ADC sensors\n");
623 	}
624 
625 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
626 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
627 	    OID_AUTO, "temp",
628 	    CTLTYPE_INT | CTLFLAG_RD,
629 	    dev, AXP209_TEMP, axp209_sysctl, "IK", "Internal temperature");
630 
631 	if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
632 	      NULL, axp_intr, sc, &sc->intrcookie)))
633 		device_printf(dev, "unable to register interrupt handler\n");
634 
635 	config_intrhook_disestablish(&sc->intr_hook);
636 }
637 
638 static int
639 axp209_probe(device_t dev)
640 {
641 
642 	if (!ofw_bus_status_okay(dev))
643 		return (ENXIO);
644 
645 	if (!ofw_bus_is_compatible(dev, "x-powers,axp209"))
646 		return (ENXIO);
647 
648 	device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
649 
650 	return (BUS_PROBE_DEFAULT);
651 }
652 
653 static int
654 axp209_attach(device_t dev)
655 {
656 	struct axp209_softc *sc;
657 
658 	sc = device_get_softc(dev);
659 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
660 
661 	if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) {
662 		device_printf(dev, "can't allocate device resources\n");
663 		return (ENXIO);
664 	}
665 
666 	sc->intr_hook.ich_func = axp209_start;
667 	sc->intr_hook.ich_arg = dev;
668 
669 	if (config_intrhook_establish(&sc->intr_hook) != 0)
670 		return (ENOMEM);
671 
672 	sc->gpiodev = gpiobus_attach_bus(dev);
673 
674 	return (0);
675 }
676 
677 static device_method_t axp209_methods[] = {
678 	DEVMETHOD(device_probe,		axp209_probe),
679 	DEVMETHOD(device_attach,	axp209_attach),
680 
681 	/* GPIO interface */
682 	DEVMETHOD(gpio_get_bus,		axp209_gpio_get_bus),
683 	DEVMETHOD(gpio_pin_max,		axp209_gpio_pin_max),
684 	DEVMETHOD(gpio_pin_getname,	axp209_gpio_pin_getname),
685 	DEVMETHOD(gpio_pin_getcaps,	axp209_gpio_pin_getcaps),
686 	DEVMETHOD(gpio_pin_getflags,	axp209_gpio_pin_getflags),
687 	DEVMETHOD(gpio_pin_setflags,	axp209_gpio_pin_setflags),
688 	DEVMETHOD(gpio_pin_get,		axp209_gpio_pin_get),
689 	DEVMETHOD(gpio_pin_set,		axp209_gpio_pin_set),
690 	DEVMETHOD(gpio_pin_toggle,	axp209_gpio_pin_toggle),
691 	DEVMETHOD(gpio_map_gpios,	axp209_gpio_map_gpios),
692 
693 	/* OFW bus interface */
694 	DEVMETHOD(ofw_bus_get_node,	axp209_get_node),
695 
696 	DEVMETHOD_END
697 };
698 
699 static driver_t axp209_driver = {
700 	"axp209_pmu",
701 	axp209_methods,
702 	sizeof(struct axp209_softc),
703 };
704 
705 static devclass_t axp209_devclass;
706 extern devclass_t ofwgpiobus_devclass, gpioc_devclass;
707 extern driver_t ofw_gpiobus_driver, gpioc_driver;
708 
709 EARLY_DRIVER_MODULE(axp209, iicbus, axp209_driver, axp209_devclass,
710   0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
711 EARLY_DRIVER_MODULE(ofw_gpiobus, axp209_pmu, ofw_gpiobus_driver,
712     ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
713 DRIVER_MODULE(gpioc, axp209_pmu, gpioc_driver, gpioc_devclass,
714     0, 0);
715 MODULE_VERSION(axp209, 1);
716 MODULE_DEPEND(axp209, iicbus, 1, 1, 1);
717