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
axp81x_read(device_t dev,uint8_t reg,uint8_t * data,uint8_t size)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 = ®
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
axp81x_write(device_t dev,uint8_t reg,uint8_t val)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 = ®
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
axp81x_shutdown(void * devp,int howto)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
axp81x_intr(void * arg)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
axp81x_gpio_get_bus(device_t dev)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
axp81x_gpio_pin_max(device_t dev,int * maxpin)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
axp81x_gpio_pin_getname(device_t dev,uint32_t pin,char * name)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
axp81x_gpio_pin_getcaps(device_t dev,uint32_t pin,uint32_t * caps)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
axp81x_gpio_pin_getflags(device_t dev,uint32_t pin,uint32_t * flags)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
axp81x_gpio_pin_setflags(device_t dev,uint32_t pin,uint32_t flags)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
axp81x_gpio_pin_get(device_t dev,uint32_t pin,unsigned int * val)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
axp81x_gpio_pin_set(device_t dev,uint32_t pin,unsigned int val)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
axp81x_gpio_pin_toggle(device_t dev,uint32_t pin)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
axp81x_gpio_map_gpios(device_t bus,phandle_t dev,phandle_t gparent,int gcells,pcell_t * gpios,uint32_t * pin,uint32_t * flags)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
axp81x_get_node(device_t dev,device_t bus)415 axp81x_get_node(device_t dev, device_t bus)
416 {
417 return (ofw_bus_get_node(dev));
418 }
419
420 static int
axp81x_probe(device_t dev)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
axp81x_attach(device_t dev)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