xref: /freebsd/sys/arm/allwinner/axp81x.c (revision 8ef24a0d4b28fe230e20637f56869cc4148cd2ca)
1 /*-
2  * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 /*
30  * X-Powers AXP813/818 PMU for Allwinner SoCs
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/eventhandler.h>
39 #include <sys/bus.h>
40 #include <sys/rman.h>
41 #include <sys/kernel.h>
42 #include <sys/reboot.h>
43 #include <sys/gpio.h>
44 #include <sys/module.h>
45 #include <machine/bus.h>
46 
47 #include <dev/iicbus/iicbus.h>
48 #include <dev/iicbus/iiconf.h>
49 
50 #include <dev/gpio/gpiobusvar.h>
51 
52 #include <dev/ofw/ofw_bus.h>
53 #include <dev/ofw/ofw_bus_subr.h>
54 
55 #include "iicbus_if.h"
56 #include "gpio_if.h"
57 
58 #define	AXP_ICTYPE		0x03
59 #define	AXP_POWERBAT		0x32
60 #define	 AXP_POWERBAT_SHUTDOWN	(1 << 7)
61 #define	AXP_IRQEN1		0x40
62 #define	AXP_IRQEN2		0x41
63 #define	AXP_IRQEN3		0x42
64 #define	AXP_IRQEN4		0x43
65 #define	AXP_IRQEN5		0x44
66 #define	 AXP_IRQEN5_POKSIRQ	(1 << 4)
67 #define	AXP_IRQEN6		0x45
68 #define	AXP_IRQSTAT5		0x4c
69 #define	 AXP_IRQSTAT5_POKSIRQ	(1 << 4)
70 #define	AXP_GPIO0_CTRL		0x90
71 #define	AXP_GPIO1_CTRL		0x92
72 #define	 AXP_GPIO_FUNC		(0x7 << 0)
73 #define	 AXP_GPIO_FUNC_SHIFT	0
74 #define	 AXP_GPIO_FUNC_DRVLO	0
75 #define	 AXP_GPIO_FUNC_DRVHI	1
76 #define	 AXP_GPIO_FUNC_INPUT	2
77 #define	AXP_GPIO_SIGBIT		0x94
78 #define	AXP_GPIO_PD		0x97
79 
80 static const struct {
81 	const char *name;
82 	uint8_t	ctrl_reg;
83 } axp81x_pins[] = {
84 	{ "GPIO0", AXP_GPIO0_CTRL },
85 	{ "GPIO1", AXP_GPIO1_CTRL },
86 };
87 
88 static struct ofw_compat_data compat_data[] = {
89 	{ "x-powers,axp813",			1 },
90 	{ "x-powers,axp818",			1 },
91 	{ NULL,					0 }
92 };
93 
94 static struct resource_spec axp81x_spec[] = {
95 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
96 	{ -1, 0 }
97 };
98 
99 struct axp81x_softc {
100 	struct resource		*res;
101 	uint16_t		addr;
102 	void			*ih;
103 	device_t		gpiodev;
104 	struct mtx		mtx;
105 	int			busy;
106 };
107 
108 #define	AXP_LOCK(sc)	mtx_lock(&(sc)->mtx)
109 #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
110 
111 static int
112 axp81x_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
113 {
114 	struct axp81x_softc *sc;
115 	struct iic_msg msg[2];
116 
117 	sc = device_get_softc(dev);
118 
119 	msg[0].slave = sc->addr;
120 	msg[0].flags = IIC_M_WR;
121 	msg[0].len = 1;
122 	msg[0].buf = &reg;
123 
124 	msg[1].slave = sc->addr;
125 	msg[1].flags = IIC_M_RD;
126 	msg[1].len = size;
127 	msg[1].buf = data;
128 
129 	return (iicbus_transfer(dev, msg, 2));
130 }
131 
132 static int
133 axp81x_write(device_t dev, uint8_t reg, uint8_t val)
134 {
135 	struct axp81x_softc *sc;
136 	struct iic_msg msg[2];
137 
138 	sc = device_get_softc(dev);
139 
140 	msg[0].slave = sc->addr;
141 	msg[0].flags = IIC_M_WR;
142 	msg[0].len = 1;
143 	msg[0].buf = &reg;
144 
145 	msg[1].slave = sc->addr;
146 	msg[1].flags = IIC_M_WR;
147 	msg[1].len = 1;
148 	msg[1].buf = &val;
149 
150 	return (iicbus_transfer(dev, msg, 2));
151 }
152 
153 static void
154 axp81x_shutdown(void *devp, int howto)
155 {
156 	device_t dev;
157 
158 	if ((howto & RB_POWEROFF) == 0)
159 		return;
160 
161 	dev = devp;
162 
163 	if (bootverbose)
164 		device_printf(dev, "Shutdown AXP81x\n");
165 
166 	axp81x_write(dev, AXP_POWERBAT, AXP_POWERBAT_SHUTDOWN);
167 }
168 
169 static void
170 axp81x_intr(void *arg)
171 {
172 	struct axp81x_softc *sc;
173 	device_t dev;
174 	uint8_t val;
175 	int error;
176 
177 	dev = arg;
178 	sc = device_get_softc(dev);
179 
180 	error = axp81x_read(dev, AXP_IRQSTAT5, &val, 1);
181 	if (error != 0)
182 		return;
183 
184 	if (val != 0) {
185 		if ((val & AXP_IRQSTAT5_POKSIRQ) != 0) {
186 			if (bootverbose)
187 				device_printf(dev, "Power button pressed\n");
188 			shutdown_nice(RB_POWEROFF);
189 		}
190 		/* Acknowledge */
191 		axp81x_write(dev, AXP_IRQSTAT5, val);
192 	}
193 }
194 
195 static device_t
196 axp81x_gpio_get_bus(device_t dev)
197 {
198 	struct axp81x_softc *sc;
199 
200 	sc = device_get_softc(dev);
201 
202 	return (sc->gpiodev);
203 }
204 
205 static int
206 axp81x_gpio_pin_max(device_t dev, int *maxpin)
207 {
208 	*maxpin = nitems(axp81x_pins) - 1;
209 
210 	return (0);
211 }
212 
213 static int
214 axp81x_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
215 {
216 	if (pin >= nitems(axp81x_pins))
217 		return (EINVAL);
218 
219 	snprintf(name, GPIOMAXNAME, "%s", axp81x_pins[pin].name);
220 
221 	return (0);
222 }
223 
224 static int
225 axp81x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
226 {
227 	if (pin >= nitems(axp81x_pins))
228 		return (EINVAL);
229 
230 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
231 
232 	return (0);
233 }
234 
235 static int
236 axp81x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
237 {
238 	struct axp81x_softc *sc;
239 	uint8_t data, func;
240 	int error;
241 
242 	if (pin >= nitems(axp81x_pins))
243 		return (EINVAL);
244 
245 	sc = device_get_softc(dev);
246 
247 	AXP_LOCK(sc);
248 	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
249 	if (error == 0) {
250 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
251 		if (func == AXP_GPIO_FUNC_INPUT)
252 			*flags = GPIO_PIN_INPUT;
253 		else if (func == AXP_GPIO_FUNC_DRVLO ||
254 		    func == AXP_GPIO_FUNC_DRVHI)
255 			*flags = GPIO_PIN_OUTPUT;
256 		else
257 			*flags = 0;
258 	}
259 	AXP_UNLOCK(sc);
260 
261 	return (error);
262 }
263 
264 static int
265 axp81x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
266 {
267 	struct axp81x_softc *sc;
268 	uint8_t data;
269 	int error;
270 
271 	if (pin >= nitems(axp81x_pins))
272 		return (EINVAL);
273 
274 	sc = device_get_softc(dev);
275 
276 	AXP_LOCK(sc);
277 	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
278 	if (error == 0) {
279 		data &= ~AXP_GPIO_FUNC;
280 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
281 			if ((flags & GPIO_PIN_OUTPUT) == 0)
282 				data |= AXP_GPIO_FUNC_INPUT;
283 		}
284 		error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
285 	}
286 	AXP_UNLOCK(sc);
287 
288 	return (error);
289 }
290 
291 static int
292 axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
293 {
294 	struct axp81x_softc *sc;
295 	uint8_t data, func;
296 	int error;
297 
298 	if (pin >= nitems(axp81x_pins))
299 		return (EINVAL);
300 
301 	sc = device_get_softc(dev);
302 
303 	AXP_LOCK(sc);
304 	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
305 	if (error == 0) {
306 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
307 		switch (func) {
308 		case AXP_GPIO_FUNC_DRVLO:
309 			*val = 0;
310 			break;
311 		case AXP_GPIO_FUNC_DRVHI:
312 			*val = 1;
313 			break;
314 		case AXP_GPIO_FUNC_INPUT:
315 			error = axp81x_read(dev, AXP_GPIO_SIGBIT, &data, 1);
316 			if (error == 0)
317 				*val = (data & (1 << pin)) ? 1 : 0;
318 			break;
319 		default:
320 			error = EIO;
321 			break;
322 		}
323 	}
324 	AXP_UNLOCK(sc);
325 
326 	return (error);
327 }
328 
329 static int
330 axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
331 {
332 	struct axp81x_softc *sc;
333 	uint8_t data, func;
334 	int error;
335 
336 	if (pin >= nitems(axp81x_pins))
337 		return (EINVAL);
338 
339 	sc = device_get_softc(dev);
340 
341 	AXP_LOCK(sc);
342 	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
343 	if (error == 0) {
344 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
345 		switch (func) {
346 		case AXP_GPIO_FUNC_DRVLO:
347 		case AXP_GPIO_FUNC_DRVHI:
348 			data &= ~AXP_GPIO_FUNC;
349 			data |= (val << AXP_GPIO_FUNC_SHIFT);
350 			break;
351 		default:
352 			error = EIO;
353 			break;
354 		}
355 	}
356 	if (error == 0)
357 		error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
358 	AXP_UNLOCK(sc);
359 
360 	return (error);
361 }
362 
363 
364 static int
365 axp81x_gpio_pin_toggle(device_t dev, uint32_t pin)
366 {
367 	struct axp81x_softc *sc;
368 	uint8_t data, func;
369 	int error;
370 
371 	if (pin >= nitems(axp81x_pins))
372 		return (EINVAL);
373 
374 	sc = device_get_softc(dev);
375 
376 	AXP_LOCK(sc);
377 	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
378 	if (error == 0) {
379 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
380 		switch (func) {
381 		case AXP_GPIO_FUNC_DRVLO:
382 			data &= ~AXP_GPIO_FUNC;
383 			data |= (AXP_GPIO_FUNC_DRVHI << AXP_GPIO_FUNC_SHIFT);
384 			break;
385 		case AXP_GPIO_FUNC_DRVHI:
386 			data &= ~AXP_GPIO_FUNC;
387 			data |= (AXP_GPIO_FUNC_DRVLO << AXP_GPIO_FUNC_SHIFT);
388 			break;
389 		default:
390 			error = EIO;
391 			break;
392 		}
393 	}
394 	if (error == 0)
395 		error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
396 	AXP_UNLOCK(sc);
397 
398 	return (error);
399 }
400 
401 static int
402 axp81x_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
403     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
404 {
405 	if (gpios[0] >= nitems(axp81x_pins))
406 		return (EINVAL);
407 
408 	*pin = gpios[0];
409 	*flags = gpios[1];
410 
411 	return (0);
412 }
413 
414 static phandle_t
415 axp81x_get_node(device_t dev, device_t bus)
416 {
417 	return (ofw_bus_get_node(dev));
418 }
419 
420 static int
421 axp81x_probe(device_t dev)
422 {
423 	if (!ofw_bus_status_okay(dev))
424 		return (ENXIO);
425 
426 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
427 		return (ENXIO);
428 
429 	device_set_desc(dev, "X-Powers AXP81x Power Management Unit");
430 
431 	return (BUS_PROBE_DEFAULT);
432 }
433 
434 static int
435 axp81x_attach(device_t dev)
436 {
437 	struct axp81x_softc *sc;
438 	uint8_t chip_id;
439 	int error;
440 
441 	sc = device_get_softc(dev);
442 
443 	sc->addr = iicbus_get_addr(dev);
444 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
445 
446 	error = bus_alloc_resources(dev, axp81x_spec, &sc->res);
447 	if (error != 0) {
448 		device_printf(dev, "cannot allocate resources for device\n");
449 		return (error);
450 	}
451 
452 	if (bootverbose) {
453 		axp81x_read(dev, AXP_ICTYPE, &chip_id, 1);
454 		device_printf(dev, "chip ID 0x%02x\n", chip_id);
455 	}
456 
457 	/* Enable IRQ on short power key press */
458 	axp81x_write(dev, AXP_IRQEN1, 0);
459 	axp81x_write(dev, AXP_IRQEN2, 0);
460 	axp81x_write(dev, AXP_IRQEN3, 0);
461 	axp81x_write(dev, AXP_IRQEN4, 0);
462 	axp81x_write(dev, AXP_IRQEN5, AXP_IRQEN5_POKSIRQ);
463 	axp81x_write(dev, AXP_IRQEN6, 0);
464 
465 	/* Install interrupt handler */
466 	error = bus_setup_intr(dev, sc->res, INTR_TYPE_MISC | INTR_MPSAFE,
467 	    NULL, axp81x_intr, dev, &sc->ih);
468 	if (error != 0) {
469 		device_printf(dev, "cannot setup interrupt handler\n");
470 		return (error);
471 	}
472 
473 	EVENTHANDLER_REGISTER(shutdown_final, axp81x_shutdown, dev,
474 	    SHUTDOWN_PRI_LAST);
475 
476 	sc->gpiodev = gpiobus_attach_bus(dev);
477 
478 	return (0);
479 }
480 
481 static device_method_t axp81x_methods[] = {
482 	/* Device interface */
483 	DEVMETHOD(device_probe,		axp81x_probe),
484 	DEVMETHOD(device_attach,	axp81x_attach),
485 
486 	/* GPIO interface */
487 	DEVMETHOD(gpio_get_bus,		axp81x_gpio_get_bus),
488 	DEVMETHOD(gpio_pin_max,		axp81x_gpio_pin_max),
489 	DEVMETHOD(gpio_pin_getname,	axp81x_gpio_pin_getname),
490 	DEVMETHOD(gpio_pin_getcaps,	axp81x_gpio_pin_getcaps),
491 	DEVMETHOD(gpio_pin_getflags,	axp81x_gpio_pin_getflags),
492 	DEVMETHOD(gpio_pin_setflags,	axp81x_gpio_pin_setflags),
493 	DEVMETHOD(gpio_pin_get,		axp81x_gpio_pin_get),
494 	DEVMETHOD(gpio_pin_set,		axp81x_gpio_pin_set),
495 	DEVMETHOD(gpio_pin_toggle,	axp81x_gpio_pin_toggle),
496 	DEVMETHOD(gpio_map_gpios,	axp81x_gpio_map_gpios),
497 
498 	/* OFW bus interface */
499 	DEVMETHOD(ofw_bus_get_node,	axp81x_get_node),
500 
501 	DEVMETHOD_END
502 };
503 
504 static driver_t axp81x_driver = {
505 	"axp81x_pmu",
506 	axp81x_methods,
507 	sizeof(struct axp81x_softc),
508 };
509 
510 static devclass_t axp81x_devclass;
511 extern devclass_t ofwgpiobus_devclass, gpioc_devclass;
512 extern driver_t ofw_gpiobus_driver, gpioc_driver;
513 
514 DRIVER_MODULE(axp81x, iicbus, axp81x_driver, axp81x_devclass, 0, 0);
515 DRIVER_MODULE(ofw_gpiobus, axp81x_pmu, ofw_gpiobus_driver,
516     ofwgpiobus_devclass, 0, 0);
517 DRIVER_MODULE(gpioc, axp81x_pmu, gpioc_driver, gpioc_devclass, 0, 0);
518 MODULE_VERSION(axp81x, 1);
519 MODULE_DEPEND(axp81x, iicbus, 1, 1, 1);
520