xref: /freebsd/sys/arm/allwinner/axp209.c (revision 094e5e7e123ab07e9ecf1daf7df7dd4ffe256d92)
12ff143afSAndrew Turner /*-
230068a1dSEmmanuel Vadot  * Copyright (c) 2015-2016 Emmanuel Vadot <manu@freebsd.org>
330068a1dSEmmanuel Vadot  * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
42ff143afSAndrew Turner  * All rights reserved.
52ff143afSAndrew Turner  *
62ff143afSAndrew Turner  * Redistribution and use in source and binary forms, with or without
72ff143afSAndrew Turner  * modification, are permitted provided that the following conditions
82ff143afSAndrew Turner  * are met:
92ff143afSAndrew Turner  * 1. Redistributions of source code must retain the above copyright
102ff143afSAndrew Turner  *    notice, this list of conditions and the following disclaimer.
112ff143afSAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright
122ff143afSAndrew Turner  *    notice, this list of conditions and the following disclaimer in the
132ff143afSAndrew Turner  *    documentation and/or other materials provided with the distribution.
142ff143afSAndrew Turner  *
152ff143afSAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162ff143afSAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172ff143afSAndrew Turner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182ff143afSAndrew Turner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192ff143afSAndrew Turner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202ff143afSAndrew Turner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212ff143afSAndrew Turner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222ff143afSAndrew Turner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232ff143afSAndrew Turner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242ff143afSAndrew Turner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252ff143afSAndrew Turner  * SUCH DAMAGE.
262ff143afSAndrew Turner  */
272ff143afSAndrew Turner 
282ff143afSAndrew Turner #include <sys/cdefs.h>
292ff143afSAndrew Turner __FBSDID("$FreeBSD$");
306988dd5eSEmmanuel Vadot 
312ff143afSAndrew Turner /*
326988dd5eSEmmanuel Vadot * X-Power AXP209/AXP211 PMU for Allwinner SoCs
332ff143afSAndrew Turner */
346988dd5eSEmmanuel Vadot 
352ff143afSAndrew Turner #include <sys/param.h>
362ff143afSAndrew Turner #include <sys/systm.h>
372ff143afSAndrew Turner #include <sys/eventhandler.h>
382ff143afSAndrew Turner #include <sys/kernel.h>
392ff143afSAndrew Turner #include <sys/module.h>
402ff143afSAndrew Turner #include <sys/clock.h>
412ff143afSAndrew Turner #include <sys/time.h>
422ff143afSAndrew Turner #include <sys/bus.h>
432ff143afSAndrew Turner #include <sys/proc.h>
4430068a1dSEmmanuel Vadot #include <sys/gpio.h>
452ff143afSAndrew Turner #include <sys/reboot.h>
462ff143afSAndrew Turner #include <sys/resource.h>
472ff143afSAndrew Turner #include <sys/rman.h>
4886914a0fSAndrew Turner #include <sys/sysctl.h>
492ff143afSAndrew Turner 
502ff143afSAndrew Turner #include <dev/iicbus/iiconf.h>
512ff143afSAndrew Turner 
5230068a1dSEmmanuel Vadot #include <dev/gpio/gpiobusvar.h>
5330068a1dSEmmanuel Vadot 
542ff143afSAndrew Turner #include <dev/ofw/ofw_bus.h>
552ff143afSAndrew Turner #include <dev/ofw/ofw_bus_subr.h>
562ff143afSAndrew Turner 
57b3d4851eSEmmanuel Vadot #include <dev/extres/regulator/regulator.h>
58b3d4851eSEmmanuel Vadot 
5930068a1dSEmmanuel Vadot #include <arm/allwinner/axp209reg.h>
6030068a1dSEmmanuel Vadot 
6130068a1dSEmmanuel Vadot #include "gpio_if.h"
62b3d4851eSEmmanuel Vadot #include "regdev_if.h"
63b3d4851eSEmmanuel Vadot 
646988dd5eSEmmanuel Vadot MALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator");
65b3d4851eSEmmanuel Vadot 
666988dd5eSEmmanuel Vadot struct axp2xx_regdef {
67b3d4851eSEmmanuel Vadot 	intptr_t		id;
68b3d4851eSEmmanuel Vadot 	char			*name;
69b3d4851eSEmmanuel Vadot 	uint8_t			enable_reg;
70b3d4851eSEmmanuel Vadot 	uint8_t			enable_mask;
71b3d4851eSEmmanuel Vadot 	uint8_t			voltage_reg;
72b3d4851eSEmmanuel Vadot 	uint8_t			voltage_mask;
73b3d4851eSEmmanuel Vadot 	uint8_t			voltage_shift;
74b3d4851eSEmmanuel Vadot 	int			voltage_min;
75b3d4851eSEmmanuel Vadot 	int			voltage_max;
76b3d4851eSEmmanuel Vadot 	int			voltage_step;
77b3d4851eSEmmanuel Vadot 	int			voltage_nstep;
78b3d4851eSEmmanuel Vadot };
79b3d4851eSEmmanuel Vadot 
806988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp209_regdefs[] = {
81b3d4851eSEmmanuel Vadot 	{
82b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC2,
83b3d4851eSEmmanuel Vadot 		.name = "dcdc2",
84b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
85b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC2,
86b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC2_VOLTAGE,
87b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x3f,
88b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
89b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
90b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
91b3d4851eSEmmanuel Vadot 		.voltage_nstep = 64,
92b3d4851eSEmmanuel Vadot 	},
93b3d4851eSEmmanuel Vadot 	{
94b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC3,
95b3d4851eSEmmanuel Vadot 		.name = "dcdc3",
96b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
97b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC3,
98b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC3_VOLTAGE,
99b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
100b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
101b3d4851eSEmmanuel Vadot 		.voltage_max = 3500,
102b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
103b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
104b3d4851eSEmmanuel Vadot 	},
105b3d4851eSEmmanuel Vadot 	{
106b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO2,
107b3d4851eSEmmanuel Vadot 		.name = "ldo2",
108b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
109b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO2,
110b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO24_VOLTAGE,
111b3d4851eSEmmanuel Vadot 		.voltage_mask = 0xf0,
112b3d4851eSEmmanuel Vadot 		.voltage_shift = 4,
113b3d4851eSEmmanuel Vadot 		.voltage_min = 1800,
114b3d4851eSEmmanuel Vadot 		.voltage_max = 3300,
115b3d4851eSEmmanuel Vadot 		.voltage_step = 100,
116b3d4851eSEmmanuel Vadot 		.voltage_nstep = 16,
117b3d4851eSEmmanuel Vadot 	},
118b3d4851eSEmmanuel Vadot 	{
119b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO3,
120b3d4851eSEmmanuel Vadot 		.name = "ldo3",
121b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
122b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO3,
123b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO3_VOLTAGE,
124b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
125b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
126b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
127b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
128b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
129b3d4851eSEmmanuel Vadot 	},
130b3d4851eSEmmanuel Vadot };
131b3d4851eSEmmanuel Vadot 
1326988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp221_regdefs[] = {
1336988dd5eSEmmanuel Vadot 	{
1346988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO1,
1356988dd5eSEmmanuel Vadot 		.name = "dldo1",
1366988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1376988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO1,
1386988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO1_VOLTAGE,
1396988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1406988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1416988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1426988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1436988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1446988dd5eSEmmanuel Vadot 	},
1456988dd5eSEmmanuel Vadot 	{
1466988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO2,
1476988dd5eSEmmanuel Vadot 		.name = "dldo2",
1486988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1496988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO2,
1506988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO2_VOLTAGE,
1516988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1526988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1536988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1546988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1556988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1566988dd5eSEmmanuel Vadot 	},
1576988dd5eSEmmanuel Vadot 	{
1586988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO3,
1596988dd5eSEmmanuel Vadot 		.name = "dldo3",
1606988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1616988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO3,
1626988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO3_VOLTAGE,
1636988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1646988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1656988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1666988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1676988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1686988dd5eSEmmanuel Vadot 	},
1696988dd5eSEmmanuel Vadot 	{
1706988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO4,
1716988dd5eSEmmanuel Vadot 		.name = "dldo4",
1726988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1736988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO4,
1746988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO4_VOLTAGE,
1756988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1766988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1776988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1786988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1796988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1806988dd5eSEmmanuel Vadot 	},
1816988dd5eSEmmanuel Vadot 	{
1826988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO1,
1836988dd5eSEmmanuel Vadot 		.name = "eldo1",
1846988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1856988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO1,
1866988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO1_VOLTAGE,
1876988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1886988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1896988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1906988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1916988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1926988dd5eSEmmanuel Vadot 	},
1936988dd5eSEmmanuel Vadot 	{
1946988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO2,
1956988dd5eSEmmanuel Vadot 		.name = "eldo2",
1966988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1976988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO2,
1986988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO2_VOLTAGE,
1996988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2006988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2016988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2026988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2036988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2046988dd5eSEmmanuel Vadot 	},
2056988dd5eSEmmanuel Vadot 	{
2066988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO3,
2076988dd5eSEmmanuel Vadot 		.name = "eldo3",
2086988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
2096988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO3,
2106988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO3_VOLTAGE,
2116988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2126988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2136988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2146988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2156988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2166988dd5eSEmmanuel Vadot 	},
2176988dd5eSEmmanuel Vadot 	{
2186988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC5LDO,
2196988dd5eSEmmanuel Vadot 		.name = "dc5ldo",
2206988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2216988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DC5LDO,
2226988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DC5LDO_VOLTAGE,
2236988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3,
2246988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2256988dd5eSEmmanuel Vadot 		.voltage_max = 1400,
2266988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2276988dd5eSEmmanuel Vadot 		.voltage_nstep = 7,
2286988dd5eSEmmanuel Vadot 	},
2296988dd5eSEmmanuel Vadot 	{
2306988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC1,
2316988dd5eSEmmanuel Vadot 		.name = "dcdc1",
2326988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2336988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC1,
2346988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC1_VOLTAGE,
2356988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2366988dd5eSEmmanuel Vadot 		.voltage_min = 1600,
2376988dd5eSEmmanuel Vadot 		.voltage_max = 3400,
2386988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2396988dd5eSEmmanuel Vadot 		.voltage_nstep = 18,
2406988dd5eSEmmanuel Vadot 	},
2416988dd5eSEmmanuel Vadot 	{
2426988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC2,
2436988dd5eSEmmanuel Vadot 		.name = "dcdc2",
2446988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2456988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC2,
2466988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC2_VOLTAGE,
2476988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2486988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2496988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2506988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2516988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2526988dd5eSEmmanuel Vadot 	},
2536988dd5eSEmmanuel Vadot 	{
2546988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC3,
2556988dd5eSEmmanuel Vadot 		.name = "dcdc3",
2566988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2576988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC3,
2586988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC3_VOLTAGE,
2596988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2606988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2616988dd5eSEmmanuel Vadot 		.voltage_max = 1860,
2626988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2636988dd5eSEmmanuel Vadot 		.voltage_nstep = 63,
2646988dd5eSEmmanuel Vadot 	},
2656988dd5eSEmmanuel Vadot 	{
2666988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC4,
2676988dd5eSEmmanuel Vadot 		.name = "dcdc4",
2686988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2696988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC4,
2706988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC4_VOLTAGE,
2716988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2726988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2736988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2746988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2756988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2766988dd5eSEmmanuel Vadot 	},
2776988dd5eSEmmanuel Vadot 	{
2786988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC5,
2796988dd5eSEmmanuel Vadot 		.name = "dcdc5",
2806988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2816988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC5,
2826988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC5_VOLTAGE,
2836988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2846988dd5eSEmmanuel Vadot 		.voltage_min = 1000,
2856988dd5eSEmmanuel Vadot 		.voltage_max = 2550,
2866988dd5eSEmmanuel Vadot 		.voltage_step = 50,
2876988dd5eSEmmanuel Vadot 		.voltage_nstep = 31,
2886988dd5eSEmmanuel Vadot 	},
2896988dd5eSEmmanuel Vadot 	{
2906988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO1,
2916988dd5eSEmmanuel Vadot 		.name = "aldo1",
2926988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2936988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO1,
2946988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO1_VOLTAGE,
2956988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2966988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2976988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2986988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2996988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3006988dd5eSEmmanuel Vadot 	},
3016988dd5eSEmmanuel Vadot 	{
3026988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO2,
3036988dd5eSEmmanuel Vadot 		.name = "aldo2",
3046988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
3056988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO2,
3066988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO2_VOLTAGE,
3076988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3086988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3096988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3106988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3116988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3126988dd5eSEmmanuel Vadot 	},
3136988dd5eSEmmanuel Vadot 	{
3146988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO3,
3156988dd5eSEmmanuel Vadot 		.name = "aldo3",
3166988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_3,
3176988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL3_ALDO3,
3186988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO3_VOLTAGE,
3196988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3206988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3216988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3226988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3236988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3246988dd5eSEmmanuel Vadot 	},
3256988dd5eSEmmanuel Vadot 	{
3266988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC1SW,
3276988dd5eSEmmanuel Vadot 		.name = "dc1sw",
3286988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
3296988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DC1SW,
3306988dd5eSEmmanuel Vadot 	},
3316988dd5eSEmmanuel Vadot };
3326988dd5eSEmmanuel Vadot 
3336988dd5eSEmmanuel Vadot struct axp2xx_reg_sc {
334b3d4851eSEmmanuel Vadot 	struct regnode		*regnode;
335b3d4851eSEmmanuel Vadot 	device_t		base_dev;
3366988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*def;
337b3d4851eSEmmanuel Vadot 	phandle_t		xref;
338b3d4851eSEmmanuel Vadot 	struct regnode_std_param *param;
339b3d4851eSEmmanuel Vadot };
34086914a0fSAndrew Turner 
3416988dd5eSEmmanuel Vadot struct axp2xx_pins {
3426988dd5eSEmmanuel Vadot 	const char	*name;
3436988dd5eSEmmanuel Vadot 	uint8_t		ctrl_reg;
3446988dd5eSEmmanuel Vadot 	uint8_t		status_reg;
3456988dd5eSEmmanuel Vadot 	uint8_t		status_mask;
3466988dd5eSEmmanuel Vadot 	uint8_t		status_shift;
3476988dd5eSEmmanuel Vadot };
3486988dd5eSEmmanuel Vadot 
3496988dd5eSEmmanuel Vadot /* GPIO3 is different, don't expose it for now */
3506988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp209_pins[] = {
3516988dd5eSEmmanuel Vadot 	{
3526988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3536988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3546988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3556988dd5eSEmmanuel Vadot 		.status_mask = 0x10,
3566988dd5eSEmmanuel Vadot 		.status_shift = 4,
3576988dd5eSEmmanuel Vadot 	},
3586988dd5eSEmmanuel Vadot 	{
3596988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3606988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO1_CTRL,
3616988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3626988dd5eSEmmanuel Vadot 		.status_mask = 0x20,
3636988dd5eSEmmanuel Vadot 		.status_shift = 5,
3646988dd5eSEmmanuel Vadot 	},
3656988dd5eSEmmanuel Vadot 	{
3666988dd5eSEmmanuel Vadot 		.name = "GPIO2",
3676988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP209_GPIO2_CTRL,
3686988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3696988dd5eSEmmanuel Vadot 		.status_mask = 0x40,
3706988dd5eSEmmanuel Vadot 		.status_shift = 6,
3716988dd5eSEmmanuel Vadot 	},
3726988dd5eSEmmanuel Vadot };
3736988dd5eSEmmanuel Vadot 
3746988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp221_pins[] = {
3756988dd5eSEmmanuel Vadot 	{
3766988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3776988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3786988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3796988dd5eSEmmanuel Vadot 		.status_mask = 0x1,
3806988dd5eSEmmanuel Vadot 		.status_shift = 0x0,
3816988dd5eSEmmanuel Vadot 	},
3826988dd5eSEmmanuel Vadot 	{
3836988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3846988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3856988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3866988dd5eSEmmanuel Vadot 		.status_mask = 0x2,
3876988dd5eSEmmanuel Vadot 		.status_shift = 0x1,
3886988dd5eSEmmanuel Vadot 	},
3896988dd5eSEmmanuel Vadot };
3906988dd5eSEmmanuel Vadot 
3916988dd5eSEmmanuel Vadot struct axp2xx_sensors {
3926988dd5eSEmmanuel Vadot 	int		id;
3936988dd5eSEmmanuel Vadot 	const char	*name;
3946988dd5eSEmmanuel Vadot 	const char	*desc;
3956988dd5eSEmmanuel Vadot 	const char	*format;
3966988dd5eSEmmanuel Vadot 	uint8_t		enable_reg;
3976988dd5eSEmmanuel Vadot 	uint8_t		enable_mask;
3986988dd5eSEmmanuel Vadot 	uint8_t		value_reg;
3996988dd5eSEmmanuel Vadot 	uint8_t		value_size;
4006988dd5eSEmmanuel Vadot 	uint8_t		h_value_mask;
4016988dd5eSEmmanuel Vadot 	uint8_t		h_value_shift;
4026988dd5eSEmmanuel Vadot 	uint8_t		l_value_mask;
4036988dd5eSEmmanuel Vadot 	uint8_t		l_value_shift;
4046988dd5eSEmmanuel Vadot 	int		value_step;
4056988dd5eSEmmanuel Vadot 	int		value_convert;
4066988dd5eSEmmanuel Vadot };
4076988dd5eSEmmanuel Vadot 
4086988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp209_sensors[] = {
4096988dd5eSEmmanuel Vadot 	{
4106988dd5eSEmmanuel Vadot 		.id = AXP209_ACVOLT,
4116988dd5eSEmmanuel Vadot 		.name = "acvolt",
4126988dd5eSEmmanuel Vadot 		.desc = "AC Voltage (microvolt)",
4136988dd5eSEmmanuel Vadot 		.format = "I",
4146988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4156988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACVOLT,
4166988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_VOLTAGE,
4176988dd5eSEmmanuel Vadot 		.value_size = 2,
4186988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4196988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4206988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4216988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4226988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4236988dd5eSEmmanuel Vadot 	},
4246988dd5eSEmmanuel Vadot 	{
4256988dd5eSEmmanuel Vadot 		.id = AXP209_ACCURRENT,
4266988dd5eSEmmanuel Vadot 		.name = "accurrent",
4276988dd5eSEmmanuel Vadot 		.desc = "AC Current (microAmpere)",
4286988dd5eSEmmanuel Vadot 		.format = "I",
4296988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4306988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACCURRENT,
4316988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_CURRENT,
4326988dd5eSEmmanuel Vadot 		.value_size = 2,
4336988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4346988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4356988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4366988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4376988dd5eSEmmanuel Vadot 		.value_step = AXP209_ACCURRENT_STEP,
4386988dd5eSEmmanuel Vadot 	},
4396988dd5eSEmmanuel Vadot 	{
4406988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSVOLT,
4416988dd5eSEmmanuel Vadot 		.name = "vbusvolt",
4426988dd5eSEmmanuel Vadot 		.desc = "VBUS Voltage (microVolt)",
4436988dd5eSEmmanuel Vadot 		.format = "I",
4446988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4456988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSVOLT,
4466988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_VOLTAGE,
4476988dd5eSEmmanuel Vadot 		.value_size = 2,
4486988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4496988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4506988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4516988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4526988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4536988dd5eSEmmanuel Vadot 	},
4546988dd5eSEmmanuel Vadot 	{
4556988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSCURRENT,
4566988dd5eSEmmanuel Vadot 		.name = "vbuscurrent",
4576988dd5eSEmmanuel Vadot 		.desc = "VBUS Current (microAmpere)",
4586988dd5eSEmmanuel Vadot 		.format = "I",
4596988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4606988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSCURRENT,
4616988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_CURRENT,
4626988dd5eSEmmanuel Vadot 		.value_size = 2,
4636988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4646988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4656988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4666988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4676988dd5eSEmmanuel Vadot 		.value_step = AXP209_VBUSCURRENT_STEP,
4686988dd5eSEmmanuel Vadot 	},
4696988dd5eSEmmanuel Vadot 	{
4706988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
4716988dd5eSEmmanuel Vadot 		.name = "batvolt",
4726988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
4736988dd5eSEmmanuel Vadot 		.format = "I",
4746988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4756988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
4766988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
4776988dd5eSEmmanuel Vadot 		.value_size = 2,
4786988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4796988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4806988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4816988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4826988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
4836988dd5eSEmmanuel Vadot 	},
4846988dd5eSEmmanuel Vadot 	{
4856988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
4866988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
4876988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
4886988dd5eSEmmanuel Vadot 		.format = "I",
4896988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4906988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
4916988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
4926988dd5eSEmmanuel Vadot 		.value_size = 2,
4936988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4946988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
4956988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
4966988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4976988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
4986988dd5eSEmmanuel Vadot 	},
4996988dd5eSEmmanuel Vadot 	{
5006988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
5016988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
5026988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5036988dd5eSEmmanuel Vadot 		.format = "I",
5046988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5056988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5066988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5076988dd5eSEmmanuel Vadot 		.value_size = 2,
5086988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5096988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5106988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5116988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5126988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5136988dd5eSEmmanuel Vadot 	},
5146988dd5eSEmmanuel Vadot 	{
5156988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5166988dd5eSEmmanuel Vadot 		.name = "temp",
5176988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5186988dd5eSEmmanuel Vadot 		.format = "IK",
5196988dd5eSEmmanuel Vadot 		.enable_reg = AXP209_ADC_ENABLE2,
5206988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC2_TEMP,
5216988dd5eSEmmanuel Vadot 		.value_reg = AXP209_TEMPMON,
5226988dd5eSEmmanuel Vadot 		.value_size = 2,
5236988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5246988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5256988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5266988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5276988dd5eSEmmanuel Vadot 		.value_step = 1,
5286988dd5eSEmmanuel Vadot 		.value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K),
5296988dd5eSEmmanuel Vadot 	},
5306988dd5eSEmmanuel Vadot };
5316988dd5eSEmmanuel Vadot 
5326988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp221_sensors[] = {
5336988dd5eSEmmanuel Vadot 	{
5346988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
5356988dd5eSEmmanuel Vadot 		.name = "batvolt",
5366988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
5376988dd5eSEmmanuel Vadot 		.format = "I",
5386988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5396988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
5406988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
5416988dd5eSEmmanuel Vadot 		.value_size = 2,
5426988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5436988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5446988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5456988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5466988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
5476988dd5eSEmmanuel Vadot 	},
5486988dd5eSEmmanuel Vadot 	{
5496988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
5506988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
5516988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
5526988dd5eSEmmanuel Vadot 		.format = "I",
5536988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5546988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5556988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
5566988dd5eSEmmanuel Vadot 		.value_size = 2,
5576988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5586988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5596988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5606988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5616988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5626988dd5eSEmmanuel Vadot 	},
5636988dd5eSEmmanuel Vadot 	{
5646988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
5656988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
5666988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5676988dd5eSEmmanuel Vadot 		.format = "I",
5686988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5696988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5706988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5716988dd5eSEmmanuel Vadot 		.value_size = 2,
5726988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5736988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5746988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5756988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5766988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5776988dd5eSEmmanuel Vadot 	},
5786988dd5eSEmmanuel Vadot 	{
5796988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5806988dd5eSEmmanuel Vadot 		.name = "temp",
5816988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5826988dd5eSEmmanuel Vadot 		.format = "IK",
5836988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5846988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_ADC1_TEMP,
5856988dd5eSEmmanuel Vadot 		.value_reg = AXP221_TEMPMON,
5866988dd5eSEmmanuel Vadot 		.value_size = 2,
5876988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5886988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5896988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5906988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5916988dd5eSEmmanuel Vadot 		.value_step = 1,
5926988dd5eSEmmanuel Vadot 		.value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K),
5936988dd5eSEmmanuel Vadot 	},
5946988dd5eSEmmanuel Vadot };
5956988dd5eSEmmanuel Vadot 
5966988dd5eSEmmanuel Vadot enum AXP2XX_TYPE {
5976988dd5eSEmmanuel Vadot 	AXP209 = 1,
5986988dd5eSEmmanuel Vadot 	AXP221,
5996988dd5eSEmmanuel Vadot };
6006988dd5eSEmmanuel Vadot 
6016988dd5eSEmmanuel Vadot struct axp2xx_softc {
60230068a1dSEmmanuel Vadot 	device_t		dev;
60330068a1dSEmmanuel Vadot 	struct resource *	res[1];
60430068a1dSEmmanuel Vadot 	void *			intrcookie;
60530068a1dSEmmanuel Vadot 	struct intr_config_hook	intr_hook;
60630068a1dSEmmanuel Vadot 	struct mtx		mtx;
6076988dd5eSEmmanuel Vadot 	uint8_t			type;
6086988dd5eSEmmanuel Vadot 
6096988dd5eSEmmanuel Vadot 	/* GPIO */
6106988dd5eSEmmanuel Vadot 	device_t		gpiodev;
6116988dd5eSEmmanuel Vadot 	int			npins;
6126988dd5eSEmmanuel Vadot 	const struct axp2xx_pins	*pins;
6136988dd5eSEmmanuel Vadot 
6146988dd5eSEmmanuel Vadot 	/* Sensors */
6156988dd5eSEmmanuel Vadot 	const struct axp2xx_sensors	*sensors;
6166988dd5eSEmmanuel Vadot 	int				nsensors;
617b3d4851eSEmmanuel Vadot 
618b3d4851eSEmmanuel Vadot 	/* Regulators */
6196988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc	**regs;
620b3d4851eSEmmanuel Vadot 	int			nregs;
6216988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*regdefs;
6222ff143afSAndrew Turner };
6232ff143afSAndrew Turner 
6246988dd5eSEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
6256988dd5eSEmmanuel Vadot 	{ "x-powers,axp209",		AXP209 },
6266988dd5eSEmmanuel Vadot 	{ "x-powers,axp221",		AXP221 },
6276988dd5eSEmmanuel Vadot 	{ NULL,				0 }
62886914a0fSAndrew Turner };
62986914a0fSAndrew Turner 
63030068a1dSEmmanuel Vadot static struct resource_spec axp_res_spec[] = {
63130068a1dSEmmanuel Vadot 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
63230068a1dSEmmanuel Vadot 	{ -1,			0,	0 }
63330068a1dSEmmanuel Vadot };
63430068a1dSEmmanuel Vadot 
63530068a1dSEmmanuel Vadot #define	AXP_LOCK(sc)	mtx_lock(&(sc)->mtx)
63630068a1dSEmmanuel Vadot #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
63730068a1dSEmmanuel Vadot 
6382ff143afSAndrew Turner static int
6396988dd5eSEmmanuel Vadot axp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
6402ff143afSAndrew Turner {
6412ff143afSAndrew Turner 
642*094e5e7eSIan Lepore 	return (iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT));
6432ff143afSAndrew Turner }
6442ff143afSAndrew Turner 
6452ff143afSAndrew Turner static int
6466988dd5eSEmmanuel Vadot axp2xx_write(device_t dev, uint8_t reg, uint8_t data)
6472ff143afSAndrew Turner {
6482ff143afSAndrew Turner 
649*094e5e7eSIan Lepore 	return (iicdev_writeto(dev, reg, &data, sizeof(data), IIC_INTRWAIT));
6502ff143afSAndrew Turner }
6512ff143afSAndrew Turner 
65286914a0fSAndrew Turner static int
6536988dd5eSEmmanuel Vadot axp2xx_regnode_init(struct regnode *regnode)
654b3d4851eSEmmanuel Vadot {
655b3d4851eSEmmanuel Vadot 	return (0);
656b3d4851eSEmmanuel Vadot }
657b3d4851eSEmmanuel Vadot 
658b3d4851eSEmmanuel Vadot static int
6596988dd5eSEmmanuel Vadot axp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
660b3d4851eSEmmanuel Vadot {
6616988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
662b3d4851eSEmmanuel Vadot 	uint8_t val;
663b3d4851eSEmmanuel Vadot 
664b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
665b3d4851eSEmmanuel Vadot 
6666988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
667b3d4851eSEmmanuel Vadot 	if (enable)
668b3d4851eSEmmanuel Vadot 		val |= sc->def->enable_mask;
669b3d4851eSEmmanuel Vadot 	else
670b3d4851eSEmmanuel Vadot 		val &= ~sc->def->enable_mask;
6716988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->enable_reg, val);
672b3d4851eSEmmanuel Vadot 
673b3d4851eSEmmanuel Vadot 	*udelay = 0;
674b3d4851eSEmmanuel Vadot 
675b3d4851eSEmmanuel Vadot 	return (0);
676b3d4851eSEmmanuel Vadot }
677b3d4851eSEmmanuel Vadot 
678b3d4851eSEmmanuel Vadot static void
6796988dd5eSEmmanuel Vadot axp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv)
680b3d4851eSEmmanuel Vadot {
681b3d4851eSEmmanuel Vadot 	if (val < sc->def->voltage_nstep)
682b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min + val * sc->def->voltage_step;
683b3d4851eSEmmanuel Vadot 	else
684b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min +
685b3d4851eSEmmanuel Vadot 		       (sc->def->voltage_nstep * sc->def->voltage_step);
686b3d4851eSEmmanuel Vadot 	*uv *= 1000;
687b3d4851eSEmmanuel Vadot }
688b3d4851eSEmmanuel Vadot 
689b3d4851eSEmmanuel Vadot static int
6906988dd5eSEmmanuel Vadot axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt,
691b3d4851eSEmmanuel Vadot     int max_uvolt, uint8_t *val)
692b3d4851eSEmmanuel Vadot {
693b3d4851eSEmmanuel Vadot 	uint8_t nval;
694b3d4851eSEmmanuel Vadot 	int nstep, uvolt;
695b3d4851eSEmmanuel Vadot 
696b3d4851eSEmmanuel Vadot 	nval = 0;
697b3d4851eSEmmanuel Vadot 	uvolt = sc->def->voltage_min * 1000;
698b3d4851eSEmmanuel Vadot 
699b3d4851eSEmmanuel Vadot 	for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
700b3d4851eSEmmanuel Vadot 	     nstep++) {
701b3d4851eSEmmanuel Vadot 		++nval;
702b3d4851eSEmmanuel Vadot 		uvolt += (sc->def->voltage_step * 1000);
703b3d4851eSEmmanuel Vadot 	}
704b3d4851eSEmmanuel Vadot 	if (uvolt > max_uvolt)
705b3d4851eSEmmanuel Vadot 		return (EINVAL);
706b3d4851eSEmmanuel Vadot 
707b3d4851eSEmmanuel Vadot 	*val = nval;
708b3d4851eSEmmanuel Vadot 	return (0);
709b3d4851eSEmmanuel Vadot }
710b3d4851eSEmmanuel Vadot 
711b3d4851eSEmmanuel Vadot static int
7126988dd5eSEmmanuel Vadot axp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
713b3d4851eSEmmanuel Vadot     int max_uvolt, int *udelay)
714b3d4851eSEmmanuel Vadot {
7156988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
716b3d4851eSEmmanuel Vadot 	uint8_t val;
717b3d4851eSEmmanuel Vadot 
718b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
719b3d4851eSEmmanuel Vadot 
720b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
721b3d4851eSEmmanuel Vadot 		return (ENXIO);
722b3d4851eSEmmanuel Vadot 
7236988dd5eSEmmanuel Vadot 	if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
724b3d4851eSEmmanuel Vadot 		return (ERANGE);
725b3d4851eSEmmanuel Vadot 
7266988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->voltage_reg, val);
727b3d4851eSEmmanuel Vadot 
728b3d4851eSEmmanuel Vadot 	*udelay = 0;
729b3d4851eSEmmanuel Vadot 
730b3d4851eSEmmanuel Vadot 	return (0);
731b3d4851eSEmmanuel Vadot }
732b3d4851eSEmmanuel Vadot 
733b3d4851eSEmmanuel Vadot static int
7346988dd5eSEmmanuel Vadot axp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
735b3d4851eSEmmanuel Vadot {
7366988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
737b3d4851eSEmmanuel Vadot 	uint8_t val;
738b3d4851eSEmmanuel Vadot 
739b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
740b3d4851eSEmmanuel Vadot 
741b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
742b3d4851eSEmmanuel Vadot 		return (ENXIO);
743b3d4851eSEmmanuel Vadot 
7446988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
7456988dd5eSEmmanuel Vadot 	axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
746b3d4851eSEmmanuel Vadot 
747b3d4851eSEmmanuel Vadot 	return (0);
748b3d4851eSEmmanuel Vadot }
749b3d4851eSEmmanuel Vadot 
7506988dd5eSEmmanuel Vadot static regnode_method_t axp2xx_regnode_methods[] = {
751b3d4851eSEmmanuel Vadot 	/* Regulator interface */
7526988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_init,		axp2xx_regnode_init),
7536988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_enable,		axp2xx_regnode_enable),
7546988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_set_voltage,	axp2xx_regnode_set_voltage),
7556988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_get_voltage,	axp2xx_regnode_get_voltage),
756b3d4851eSEmmanuel Vadot 	REGNODEMETHOD_END
757b3d4851eSEmmanuel Vadot };
7586988dd5eSEmmanuel Vadot DEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods,
7596988dd5eSEmmanuel Vadot     sizeof(struct axp2xx_reg_sc), regnode_class);
760b3d4851eSEmmanuel Vadot 
761b3d4851eSEmmanuel Vadot static int
7626988dd5eSEmmanuel Vadot axp2xx_sysctl(SYSCTL_HANDLER_ARGS)
76386914a0fSAndrew Turner {
7646988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
76586914a0fSAndrew Turner 	device_t dev = arg1;
7666988dd5eSEmmanuel Vadot 	enum axp2xx_sensor sensor = arg2;
76786914a0fSAndrew Turner 	uint8_t data[2];
7686988dd5eSEmmanuel Vadot 	int val, error, i, found;
76986914a0fSAndrew Turner 
7706988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
77186914a0fSAndrew Turner 
7726988dd5eSEmmanuel Vadot 	for (found = 0, i = 0; i < sc->nsensors; i++) {
7736988dd5eSEmmanuel Vadot 		if (sc->sensors[i].id == sensor) {
7746988dd5eSEmmanuel Vadot 			found = 1;
77530068a1dSEmmanuel Vadot 			break;
77630068a1dSEmmanuel Vadot 		}
7776988dd5eSEmmanuel Vadot 	}
7786988dd5eSEmmanuel Vadot 
7796988dd5eSEmmanuel Vadot 	if (found == 0)
7806988dd5eSEmmanuel Vadot 		return (ENOENT);
7816988dd5eSEmmanuel Vadot 
7826988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2);
7836988dd5eSEmmanuel Vadot 	if (error != 0)
7846988dd5eSEmmanuel Vadot 		return (error);
7856988dd5eSEmmanuel Vadot 
7866988dd5eSEmmanuel Vadot 	val = ((data[0] & sc->sensors[i].h_value_mask) <<
7876988dd5eSEmmanuel Vadot 	    sc->sensors[i].h_value_shift);
7886988dd5eSEmmanuel Vadot 	val |= ((data[1] & sc->sensors[i].l_value_mask) <<
7896988dd5eSEmmanuel Vadot 	    sc->sensors[i].l_value_shift);
7906988dd5eSEmmanuel Vadot 	val *= sc->sensors[i].value_step;
7916988dd5eSEmmanuel Vadot 	val += sc->sensors[i].value_convert;
79286914a0fSAndrew Turner 
79386914a0fSAndrew Turner 	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
79486914a0fSAndrew Turner }
79586914a0fSAndrew Turner 
7962ff143afSAndrew Turner static void
7976988dd5eSEmmanuel Vadot axp2xx_shutdown(void *devp, int howto)
7982ff143afSAndrew Turner {
7992ff143afSAndrew Turner 	device_t dev;
8002ff143afSAndrew Turner 
8012ff143afSAndrew Turner 	if (!(howto & RB_POWEROFF))
8022ff143afSAndrew Turner 		return;
8032ff143afSAndrew Turner 	dev = (device_t)devp;
8042ff143afSAndrew Turner 
8052ff143afSAndrew Turner 	if (bootverbose)
8066988dd5eSEmmanuel Vadot 		device_printf(dev, "Shutdown AXP2xx\n");
8072ff143afSAndrew Turner 
8086988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN);
8092ff143afSAndrew Turner }
8102ff143afSAndrew Turner 
81130068a1dSEmmanuel Vadot static void
8126988dd5eSEmmanuel Vadot axp2xx_intr(void *arg)
8132ff143afSAndrew Turner {
8146988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
81530068a1dSEmmanuel Vadot 	uint8_t reg;
8162ff143afSAndrew Turner 
81730068a1dSEmmanuel Vadot 	sc = arg;
8182ff143afSAndrew Turner 
8196988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, &reg, 1);
82030068a1dSEmmanuel Vadot 	if (reg) {
8216988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_OVERVOLT)
82230068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "overvoltage", NULL);
8236988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT)
82430068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "overvoltage", NULL);
8256988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_LOW)
82630068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "undervoltage", NULL);
8276988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_CONN)
82830068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "plugged", NULL);
8296988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_DISCONN)
83030068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "unplugged", NULL);
8316988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_CONN)
83230068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "plugged", NULL);
8336988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_DISCONN)
83430068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "unplugged", NULL);
8356988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK);
83630068a1dSEmmanuel Vadot 	}
8372ff143afSAndrew Turner 
8386988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, &reg, 1);
83930068a1dSEmmanuel Vadot 	if (reg) {
8406988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGED)
84130068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charged", NULL);
8426988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGING)
84330068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charging", NULL);
8446988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CONN)
84530068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "connected", NULL);
8466988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_DISCONN)
84730068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "disconnected", NULL);
8486988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW)
84930068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "low temp", NULL);
8506988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER)
85130068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "high temp", NULL);
8526988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK);
85330068a1dSEmmanuel Vadot 	}
8542ff143afSAndrew Turner 
8556988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, &reg, 1);
85630068a1dSEmmanuel Vadot 	if (reg) {
8576988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ3_PEK_SHORT)
85830068a1dSEmmanuel Vadot 			shutdown_nice(RB_POWEROFF);
8596988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK);
86030068a1dSEmmanuel Vadot 	}
86130068a1dSEmmanuel Vadot 
8626988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, &reg, 1);
86330068a1dSEmmanuel Vadot 	if (reg) {
8646988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK);
86530068a1dSEmmanuel Vadot 	}
86630068a1dSEmmanuel Vadot 
8676988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, &reg, 1);
86830068a1dSEmmanuel Vadot 	if (reg) {
8696988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK);
87030068a1dSEmmanuel Vadot 	}
87130068a1dSEmmanuel Vadot }
87230068a1dSEmmanuel Vadot 
87330068a1dSEmmanuel Vadot static device_t
8746988dd5eSEmmanuel Vadot axp2xx_gpio_get_bus(device_t dev)
87530068a1dSEmmanuel Vadot {
8766988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
87730068a1dSEmmanuel Vadot 
87830068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
87930068a1dSEmmanuel Vadot 
88030068a1dSEmmanuel Vadot 	return (sc->gpiodev);
8812ff143afSAndrew Turner }
8822ff143afSAndrew Turner 
8832ff143afSAndrew Turner static int
8846988dd5eSEmmanuel Vadot axp2xx_gpio_pin_max(device_t dev, int *maxpin)
8852ff143afSAndrew Turner {
8866988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
8876988dd5eSEmmanuel Vadot 
8886988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
8896988dd5eSEmmanuel Vadot 
8906988dd5eSEmmanuel Vadot 	*maxpin = sc->npins - 1;
89130068a1dSEmmanuel Vadot 
89230068a1dSEmmanuel Vadot 	return (0);
89330068a1dSEmmanuel Vadot }
89430068a1dSEmmanuel Vadot 
89530068a1dSEmmanuel Vadot static int
8966988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
89730068a1dSEmmanuel Vadot {
8986988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
8996988dd5eSEmmanuel Vadot 
9006988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9016988dd5eSEmmanuel Vadot 
9026988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
90330068a1dSEmmanuel Vadot 		return (EINVAL);
90430068a1dSEmmanuel Vadot 
90530068a1dSEmmanuel Vadot 	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
90630068a1dSEmmanuel Vadot 
90730068a1dSEmmanuel Vadot 	return (0);
90830068a1dSEmmanuel Vadot }
90930068a1dSEmmanuel Vadot 
91030068a1dSEmmanuel Vadot static int
9116988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
91230068a1dSEmmanuel Vadot {
9136988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9146988dd5eSEmmanuel Vadot 
9156988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9166988dd5eSEmmanuel Vadot 
9176988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
91830068a1dSEmmanuel Vadot 		return (EINVAL);
91930068a1dSEmmanuel Vadot 
92030068a1dSEmmanuel Vadot 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
92130068a1dSEmmanuel Vadot 
92230068a1dSEmmanuel Vadot 	return (0);
92330068a1dSEmmanuel Vadot }
92430068a1dSEmmanuel Vadot 
92530068a1dSEmmanuel Vadot static int
9266988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
92730068a1dSEmmanuel Vadot {
9286988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
92930068a1dSEmmanuel Vadot 	uint8_t data, func;
93030068a1dSEmmanuel Vadot 	int error;
93130068a1dSEmmanuel Vadot 
93230068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
93330068a1dSEmmanuel Vadot 
9346988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9356988dd5eSEmmanuel Vadot 		return (EINVAL);
9366988dd5eSEmmanuel Vadot 
93730068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9386988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
93930068a1dSEmmanuel Vadot 	if (error == 0) {
9406988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
9416988dd5eSEmmanuel Vadot 		if (func == AXP2XX_GPIO_FUNC_INPUT)
94230068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_INPUT;
9436988dd5eSEmmanuel Vadot 		else if (func == AXP2XX_GPIO_FUNC_DRVLO ||
9446988dd5eSEmmanuel Vadot 		    func == AXP2XX_GPIO_FUNC_DRVHI)
94530068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_OUTPUT;
94630068a1dSEmmanuel Vadot 		else
94730068a1dSEmmanuel Vadot 			*flags = 0;
94830068a1dSEmmanuel Vadot 	}
94930068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
95030068a1dSEmmanuel Vadot 
95130068a1dSEmmanuel Vadot 	return (error);
95230068a1dSEmmanuel Vadot }
95330068a1dSEmmanuel Vadot 
95430068a1dSEmmanuel Vadot static int
9556988dd5eSEmmanuel Vadot axp2xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
95630068a1dSEmmanuel Vadot {
9576988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
95830068a1dSEmmanuel Vadot 	uint8_t data;
95930068a1dSEmmanuel Vadot 	int error;
96030068a1dSEmmanuel Vadot 
96130068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
96230068a1dSEmmanuel Vadot 
9636988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9646988dd5eSEmmanuel Vadot 		return (EINVAL);
9656988dd5eSEmmanuel Vadot 
96630068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9676988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
96830068a1dSEmmanuel Vadot 	if (error == 0) {
9696988dd5eSEmmanuel Vadot 		data &= ~AXP2XX_GPIO_FUNC_MASK;
97030068a1dSEmmanuel Vadot 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
97130068a1dSEmmanuel Vadot 			if ((flags & GPIO_PIN_OUTPUT) == 0)
9726988dd5eSEmmanuel Vadot 				data |= AXP2XX_GPIO_FUNC_INPUT;
97330068a1dSEmmanuel Vadot 		}
9746988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
97530068a1dSEmmanuel Vadot 	}
97630068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
97730068a1dSEmmanuel Vadot 
97830068a1dSEmmanuel Vadot 	return (error);
97930068a1dSEmmanuel Vadot }
98030068a1dSEmmanuel Vadot 
98130068a1dSEmmanuel Vadot static int
9826988dd5eSEmmanuel Vadot axp2xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
98330068a1dSEmmanuel Vadot {
9846988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
98530068a1dSEmmanuel Vadot 	uint8_t data, func;
98630068a1dSEmmanuel Vadot 	int error;
98730068a1dSEmmanuel Vadot 
98830068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
98930068a1dSEmmanuel Vadot 
9906988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9916988dd5eSEmmanuel Vadot 		return (EINVAL);
9926988dd5eSEmmanuel Vadot 
99330068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9946988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
99530068a1dSEmmanuel Vadot 	if (error == 0) {
9966988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
99730068a1dSEmmanuel Vadot 		switch (func) {
9986988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
99930068a1dSEmmanuel Vadot 			*val = 0;
100030068a1dSEmmanuel Vadot 			break;
10016988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
100230068a1dSEmmanuel Vadot 			*val = 1;
100330068a1dSEmmanuel Vadot 			break;
10046988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_INPUT:
10056988dd5eSEmmanuel Vadot 			error = axp2xx_read(dev, sc->pins[pin].status_reg,
10066988dd5eSEmmanuel Vadot 			    &data, 1);
10076988dd5eSEmmanuel Vadot 			if (error == 0) {
10086988dd5eSEmmanuel Vadot 				*val = (data & sc->pins[pin].status_mask);
10096988dd5eSEmmanuel Vadot 				*val >>= sc->pins[pin].status_shift;
10106988dd5eSEmmanuel Vadot 			}
101130068a1dSEmmanuel Vadot 			break;
101230068a1dSEmmanuel Vadot 		default:
101330068a1dSEmmanuel Vadot 			error = EIO;
101430068a1dSEmmanuel Vadot 			break;
101530068a1dSEmmanuel Vadot 		}
101630068a1dSEmmanuel Vadot 	}
101730068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
101830068a1dSEmmanuel Vadot 
101930068a1dSEmmanuel Vadot 	return (error);
102030068a1dSEmmanuel Vadot }
102130068a1dSEmmanuel Vadot 
102230068a1dSEmmanuel Vadot static int
10236988dd5eSEmmanuel Vadot axp2xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
102430068a1dSEmmanuel Vadot {
10256988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
102630068a1dSEmmanuel Vadot 	uint8_t data, func;
102730068a1dSEmmanuel Vadot 	int error;
102830068a1dSEmmanuel Vadot 
102930068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
103030068a1dSEmmanuel Vadot 
10316988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10326988dd5eSEmmanuel Vadot 		return (EINVAL);
10336988dd5eSEmmanuel Vadot 
103430068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10356988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
103630068a1dSEmmanuel Vadot 	if (error == 0) {
10376988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
103830068a1dSEmmanuel Vadot 		switch (func) {
10396988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
10406988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
104130068a1dSEmmanuel Vadot 			/* GPIO2 can't be set to 1 */
104230068a1dSEmmanuel Vadot 			if (pin == 2 && val == 1) {
104330068a1dSEmmanuel Vadot 				error = EINVAL;
104430068a1dSEmmanuel Vadot 				break;
104530068a1dSEmmanuel Vadot 			}
10466988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
104730068a1dSEmmanuel Vadot 			data |= val;
104830068a1dSEmmanuel Vadot 			break;
104930068a1dSEmmanuel Vadot 		default:
105030068a1dSEmmanuel Vadot 			error = EIO;
105130068a1dSEmmanuel Vadot 			break;
105230068a1dSEmmanuel Vadot 		}
105330068a1dSEmmanuel Vadot 	}
105430068a1dSEmmanuel Vadot 	if (error == 0)
10556988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
105630068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
105730068a1dSEmmanuel Vadot 
105830068a1dSEmmanuel Vadot 	return (error);
105930068a1dSEmmanuel Vadot }
106030068a1dSEmmanuel Vadot 
106130068a1dSEmmanuel Vadot 
106230068a1dSEmmanuel Vadot static int
10636988dd5eSEmmanuel Vadot axp2xx_gpio_pin_toggle(device_t dev, uint32_t pin)
106430068a1dSEmmanuel Vadot {
10656988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
106630068a1dSEmmanuel Vadot 	uint8_t data, func;
106730068a1dSEmmanuel Vadot 	int error;
106830068a1dSEmmanuel Vadot 
106930068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
107030068a1dSEmmanuel Vadot 
10716988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10726988dd5eSEmmanuel Vadot 		return (EINVAL);
10736988dd5eSEmmanuel Vadot 
107430068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10756988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
107630068a1dSEmmanuel Vadot 	if (error == 0) {
10776988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
107830068a1dSEmmanuel Vadot 		switch (func) {
10796988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
108030068a1dSEmmanuel Vadot 			/* Pin 2 can't be set to 1*/
108130068a1dSEmmanuel Vadot 			if (pin == 2) {
108230068a1dSEmmanuel Vadot 				error = EINVAL;
108330068a1dSEmmanuel Vadot 				break;
108430068a1dSEmmanuel Vadot 			}
10856988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
10866988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVHI;
108730068a1dSEmmanuel Vadot 			break;
10886988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
10896988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
10906988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVLO;
109130068a1dSEmmanuel Vadot 			break;
109230068a1dSEmmanuel Vadot 		default:
109330068a1dSEmmanuel Vadot 			error = EIO;
109430068a1dSEmmanuel Vadot 			break;
109530068a1dSEmmanuel Vadot 		}
109630068a1dSEmmanuel Vadot 	}
109730068a1dSEmmanuel Vadot 	if (error == 0)
10986988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
109930068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
110030068a1dSEmmanuel Vadot 
110130068a1dSEmmanuel Vadot 	return (error);
110230068a1dSEmmanuel Vadot }
110330068a1dSEmmanuel Vadot 
110430068a1dSEmmanuel Vadot static int
11056988dd5eSEmmanuel Vadot axp2xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
110630068a1dSEmmanuel Vadot     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
110730068a1dSEmmanuel Vadot {
11086988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
11096988dd5eSEmmanuel Vadot 
11106988dd5eSEmmanuel Vadot 	sc = device_get_softc(bus);
11116988dd5eSEmmanuel Vadot 
11126988dd5eSEmmanuel Vadot 	if (gpios[0] >= sc->npins)
111330068a1dSEmmanuel Vadot 		return (EINVAL);
111430068a1dSEmmanuel Vadot 
111530068a1dSEmmanuel Vadot 	*pin = gpios[0];
111630068a1dSEmmanuel Vadot 	*flags = gpios[1];
111730068a1dSEmmanuel Vadot 
111830068a1dSEmmanuel Vadot 	return (0);
111930068a1dSEmmanuel Vadot }
112030068a1dSEmmanuel Vadot 
112130068a1dSEmmanuel Vadot static phandle_t
11226988dd5eSEmmanuel Vadot axp2xx_get_node(device_t dev, device_t bus)
112330068a1dSEmmanuel Vadot {
112430068a1dSEmmanuel Vadot 	return (ofw_bus_get_node(dev));
112530068a1dSEmmanuel Vadot }
112630068a1dSEmmanuel Vadot 
11276988dd5eSEmmanuel Vadot static struct axp2xx_reg_sc *
11286988dd5eSEmmanuel Vadot axp2xx_reg_attach(device_t dev, phandle_t node,
11296988dd5eSEmmanuel Vadot     struct axp2xx_regdef *def)
1130b3d4851eSEmmanuel Vadot {
11316988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg_sc;
1132b3d4851eSEmmanuel Vadot 	struct regnode_init_def initdef;
1133b3d4851eSEmmanuel Vadot 	struct regnode *regnode;
1134b3d4851eSEmmanuel Vadot 
1135b3d4851eSEmmanuel Vadot 	memset(&initdef, 0, sizeof(initdef));
1136b3d4851eSEmmanuel Vadot 	if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) {
1137b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1138b3d4851eSEmmanuel Vadot 		return (NULL);
1139b3d4851eSEmmanuel Vadot 	}
1140b3d4851eSEmmanuel Vadot 	if (initdef.std_param.min_uvolt == 0)
1141b3d4851eSEmmanuel Vadot 		initdef.std_param.min_uvolt = def->voltage_min * 1000;
1142b3d4851eSEmmanuel Vadot 	if (initdef.std_param.max_uvolt == 0)
1143b3d4851eSEmmanuel Vadot 		initdef.std_param.max_uvolt = def->voltage_max * 1000;
1144b3d4851eSEmmanuel Vadot 	initdef.id = def->id;
1145b3d4851eSEmmanuel Vadot 	initdef.ofw_node = node;
11466988dd5eSEmmanuel Vadot 	regnode = regnode_create(dev, &axp2xx_regnode_class, &initdef);
1147b3d4851eSEmmanuel Vadot 	if (regnode == NULL) {
1148b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1149b3d4851eSEmmanuel Vadot 		return (NULL);
1150b3d4851eSEmmanuel Vadot 	}
1151b3d4851eSEmmanuel Vadot 
1152b3d4851eSEmmanuel Vadot 	reg_sc = regnode_get_softc(regnode);
1153b3d4851eSEmmanuel Vadot 	reg_sc->regnode = regnode;
1154b3d4851eSEmmanuel Vadot 	reg_sc->base_dev = dev;
1155b3d4851eSEmmanuel Vadot 	reg_sc->def = def;
1156b3d4851eSEmmanuel Vadot 	reg_sc->xref = OF_xref_from_node(node);
1157b3d4851eSEmmanuel Vadot 	reg_sc->param = regnode_get_stdparam(regnode);
1158b3d4851eSEmmanuel Vadot 
1159b3d4851eSEmmanuel Vadot 	regnode_register(regnode);
1160b3d4851eSEmmanuel Vadot 
1161b3d4851eSEmmanuel Vadot 	return (reg_sc);
1162b3d4851eSEmmanuel Vadot }
1163b3d4851eSEmmanuel Vadot 
1164b3d4851eSEmmanuel Vadot static int
11656988dd5eSEmmanuel Vadot axp2xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
1166b3d4851eSEmmanuel Vadot     intptr_t *num)
1167b3d4851eSEmmanuel Vadot {
11686988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1169b3d4851eSEmmanuel Vadot 	int i;
1170b3d4851eSEmmanuel Vadot 
1171b3d4851eSEmmanuel Vadot 	sc = device_get_softc(dev);
1172b3d4851eSEmmanuel Vadot 	for (i = 0; i < sc->nregs; i++) {
1173b3d4851eSEmmanuel Vadot 		if (sc->regs[i] == NULL)
1174b3d4851eSEmmanuel Vadot 			continue;
1175b3d4851eSEmmanuel Vadot 		if (sc->regs[i]->xref == xref) {
1176b3d4851eSEmmanuel Vadot 			*num = sc->regs[i]->def->id;
1177b3d4851eSEmmanuel Vadot 			return (0);
1178b3d4851eSEmmanuel Vadot 		}
1179b3d4851eSEmmanuel Vadot 	}
1180b3d4851eSEmmanuel Vadot 
1181b3d4851eSEmmanuel Vadot 	return (ENXIO);
1182b3d4851eSEmmanuel Vadot }
1183b3d4851eSEmmanuel Vadot 
118430068a1dSEmmanuel Vadot static void
11856988dd5eSEmmanuel Vadot axp2xx_start(void *pdev)
118630068a1dSEmmanuel Vadot {
118730068a1dSEmmanuel Vadot 	device_t dev;
11886988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1189276b1ac9SAndrew Turner 	const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
11906988dd5eSEmmanuel Vadot 	int i;
11916988dd5eSEmmanuel Vadot 	uint8_t reg, data;
11922ff143afSAndrew Turner 	uint8_t pwr_src;
11932ff143afSAndrew Turner 
119430068a1dSEmmanuel Vadot 	dev = pdev;
11952ff143afSAndrew Turner 
119630068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
119730068a1dSEmmanuel Vadot 	sc->dev = dev;
11982ff143afSAndrew Turner 
1199276b1ac9SAndrew Turner 	if (bootverbose) {
12002ff143afSAndrew Turner 		/*
1201276b1ac9SAndrew Turner 		 * Read the Power State register.
1202276b1ac9SAndrew Turner 		 * Shift the AC presence into bit 0.
1203276b1ac9SAndrew Turner 		 * Shift the Battery presence into bit 1.
12042ff143afSAndrew Turner 		 */
12056988dd5eSEmmanuel Vadot 		axp2xx_read(dev, AXP2XX_PSR, &data, 1);
12066988dd5eSEmmanuel Vadot 		pwr_src = ((data & AXP2XX_PSR_ACIN) >> AXP2XX_PSR_ACIN_SHIFT) |
12076988dd5eSEmmanuel Vadot 		    ((data & AXP2XX_PSR_VBUS) >> (AXP2XX_PSR_VBUS_SHIFT - 1));
12082ff143afSAndrew Turner 
12096988dd5eSEmmanuel Vadot 		device_printf(dev, "Powered by %s\n",
12102ff143afSAndrew Turner 		    pwr_name[pwr_src]);
1211276b1ac9SAndrew Turner 	}
12122ff143afSAndrew Turner 
121330068a1dSEmmanuel Vadot 	/* Only enable interrupts that we are interested in */
12146988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ1_ENABLE,
12156988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_OVERVOLT |
12166988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_DISCONN |
12176988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_CONN |
12186988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_OVERVOLT |
12196988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_DISCONN |
12206988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_CONN);
12216988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ2_ENABLE,
12226988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CONN |
12236988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_DISCONN |
12246988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON |
12256988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF |
12266988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGING |
12276988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGED |
12286988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_OVER |
12296988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_LOW);
12306988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ3_ENABLE,
12316988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ3_PEK_SHORT | AXP2XX_IRQ3_PEK_LONG);
12326988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ4_ENABLE, AXP2XX_IRQ4_APS_LOW_2);
12336988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ5_ENABLE, 0x0);
123430068a1dSEmmanuel Vadot 
12356988dd5eSEmmanuel Vadot 	EVENTHANDLER_REGISTER(shutdown_final, axp2xx_shutdown, dev,
12362ff143afSAndrew Turner 	    SHUTDOWN_PRI_LAST);
12372ff143afSAndrew Turner 
123830068a1dSEmmanuel Vadot 	/* Enable ADC sensors */
12396988dd5eSEmmanuel Vadot 	for (i = 0; i < sc->nsensors; i++) {
12406988dd5eSEmmanuel Vadot 		if (axp2xx_read(dev, sc->sensors[i].enable_reg, &reg, 1) == -1) {
12416988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12426988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12436988dd5eSEmmanuel Vadot 			continue;
12446988dd5eSEmmanuel Vadot 		}
12456988dd5eSEmmanuel Vadot 		reg |= sc->sensors[i].enable_mask;
12466988dd5eSEmmanuel Vadot 		if (axp2xx_write(dev, sc->sensors[i].enable_reg, reg) == -1) {
12476988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12486988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12496988dd5eSEmmanuel Vadot 			continue;
12506988dd5eSEmmanuel Vadot 		}
125130068a1dSEmmanuel Vadot 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
125230068a1dSEmmanuel Vadot 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
12536988dd5eSEmmanuel Vadot 		    OID_AUTO, sc->sensors[i].name,
125430068a1dSEmmanuel Vadot 		    CTLTYPE_INT | CTLFLAG_RD,
12556988dd5eSEmmanuel Vadot 		    dev, sc->sensors[i].id, axp2xx_sysctl,
12566988dd5eSEmmanuel Vadot 		    sc->sensors[i].format,
12576988dd5eSEmmanuel Vadot 		    sc->sensors[i].desc);
125830068a1dSEmmanuel Vadot 	}
125930068a1dSEmmanuel Vadot 
126030068a1dSEmmanuel Vadot 	if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
12616988dd5eSEmmanuel Vadot 	      NULL, axp2xx_intr, sc, &sc->intrcookie)))
126230068a1dSEmmanuel Vadot 		device_printf(dev, "unable to register interrupt handler\n");
126330068a1dSEmmanuel Vadot 
126430068a1dSEmmanuel Vadot 	config_intrhook_disestablish(&sc->intr_hook);
126530068a1dSEmmanuel Vadot }
126630068a1dSEmmanuel Vadot 
126730068a1dSEmmanuel Vadot static int
12686988dd5eSEmmanuel Vadot axp2xx_probe(device_t dev)
126930068a1dSEmmanuel Vadot {
127030068a1dSEmmanuel Vadot 
127130068a1dSEmmanuel Vadot 	if (!ofw_bus_status_okay(dev))
127230068a1dSEmmanuel Vadot 		return (ENXIO);
127330068a1dSEmmanuel Vadot 
12746988dd5eSEmmanuel Vadot 	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
12756988dd5eSEmmanuel Vadot 	{
12766988dd5eSEmmanuel Vadot 	case AXP209:
127730068a1dSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
12786988dd5eSEmmanuel Vadot 		break;
12796988dd5eSEmmanuel Vadot 	case AXP221:
12806988dd5eSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP221 Power Management Unit");
12816988dd5eSEmmanuel Vadot 		break;
12826988dd5eSEmmanuel Vadot 	default:
12836988dd5eSEmmanuel Vadot 		return (ENXIO);
12846988dd5eSEmmanuel Vadot 	}
128530068a1dSEmmanuel Vadot 
128630068a1dSEmmanuel Vadot 	return (BUS_PROBE_DEFAULT);
128730068a1dSEmmanuel Vadot }
128830068a1dSEmmanuel Vadot 
128930068a1dSEmmanuel Vadot static int
12906988dd5eSEmmanuel Vadot axp2xx_attach(device_t dev)
129130068a1dSEmmanuel Vadot {
12926988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
12936988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg;
12946988dd5eSEmmanuel Vadot 	struct axp2xx_regdef *regdefs;
1295b3d4851eSEmmanuel Vadot 	phandle_t rnode, child;
1296b3d4851eSEmmanuel Vadot 	int i;
129730068a1dSEmmanuel Vadot 
129830068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
129930068a1dSEmmanuel Vadot 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
130030068a1dSEmmanuel Vadot 
130130068a1dSEmmanuel Vadot 	if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) {
130230068a1dSEmmanuel Vadot 		device_printf(dev, "can't allocate device resources\n");
130330068a1dSEmmanuel Vadot 		return (ENXIO);
130430068a1dSEmmanuel Vadot 	}
130530068a1dSEmmanuel Vadot 
13066988dd5eSEmmanuel Vadot 	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
13076988dd5eSEmmanuel Vadot 	switch (sc->type) {
13086988dd5eSEmmanuel Vadot 	case AXP209:
13096988dd5eSEmmanuel Vadot 		sc->pins = axp209_pins;
13106988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp209_pins);
13116988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13126988dd5eSEmmanuel Vadot 
13136988dd5eSEmmanuel Vadot 		sc->sensors = axp209_sensors;
13146988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp209_sensors);
13156988dd5eSEmmanuel Vadot 
13166988dd5eSEmmanuel Vadot 		regdefs = axp209_regdefs;
13176988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp209_regdefs);
13186988dd5eSEmmanuel Vadot 		break;
13196988dd5eSEmmanuel Vadot 	case AXP221:
13206988dd5eSEmmanuel Vadot 		sc->pins = axp221_pins;
13216988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp221_pins);
13226988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13236988dd5eSEmmanuel Vadot 
13246988dd5eSEmmanuel Vadot 		sc->sensors = axp221_sensors;
13256988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp221_sensors);
13266988dd5eSEmmanuel Vadot 
13276988dd5eSEmmanuel Vadot 		regdefs = axp221_regdefs;
13286988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp221_regdefs);
13296988dd5eSEmmanuel Vadot 		break;
13306988dd5eSEmmanuel Vadot 	}
13316988dd5eSEmmanuel Vadot 
13326988dd5eSEmmanuel Vadot 	sc->regs = malloc(sizeof(struct axp2xx_reg_sc *) * sc->nregs,
13336988dd5eSEmmanuel Vadot 	    M_AXP2XX_REG, M_WAITOK | M_ZERO);
13346988dd5eSEmmanuel Vadot 
13356988dd5eSEmmanuel Vadot 	sc->intr_hook.ich_func = axp2xx_start;
133630068a1dSEmmanuel Vadot 	sc->intr_hook.ich_arg = dev;
133730068a1dSEmmanuel Vadot 
133830068a1dSEmmanuel Vadot 	if (config_intrhook_establish(&sc->intr_hook) != 0)
133930068a1dSEmmanuel Vadot 		return (ENOMEM);
134030068a1dSEmmanuel Vadot 
1341b3d4851eSEmmanuel Vadot 	/* Attach known regulators that exist in the DT */
1342b3d4851eSEmmanuel Vadot 	rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
1343b3d4851eSEmmanuel Vadot 	if (rnode > 0) {
1344b3d4851eSEmmanuel Vadot 		for (i = 0; i < sc->nregs; i++) {
1345b3d4851eSEmmanuel Vadot 			child = ofw_bus_find_child(rnode,
13466988dd5eSEmmanuel Vadot 			    regdefs[i].name);
1347b3d4851eSEmmanuel Vadot 			if (child == 0)
1348b3d4851eSEmmanuel Vadot 				continue;
13496988dd5eSEmmanuel Vadot 			reg = axp2xx_reg_attach(dev, child, &regdefs[i]);
1350b3d4851eSEmmanuel Vadot 			if (reg == NULL) {
1351b3d4851eSEmmanuel Vadot 				device_printf(dev,
1352b3d4851eSEmmanuel Vadot 				    "cannot attach regulator %s\n",
13536988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1354b3d4851eSEmmanuel Vadot 				continue;
1355b3d4851eSEmmanuel Vadot 			}
1356b3d4851eSEmmanuel Vadot 			sc->regs[i] = reg;
13576988dd5eSEmmanuel Vadot 			if (bootverbose)
13586988dd5eSEmmanuel Vadot 				device_printf(dev, "Regulator %s attached\n",
13596988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1360b3d4851eSEmmanuel Vadot 		}
1361b3d4851eSEmmanuel Vadot 	}
1362b3d4851eSEmmanuel Vadot 
13632ff143afSAndrew Turner 	return (0);
13642ff143afSAndrew Turner }
13652ff143afSAndrew Turner 
13666988dd5eSEmmanuel Vadot static device_method_t axp2xx_methods[] = {
13676988dd5eSEmmanuel Vadot 	DEVMETHOD(device_probe,		axp2xx_probe),
13686988dd5eSEmmanuel Vadot 	DEVMETHOD(device_attach,	axp2xx_attach),
136930068a1dSEmmanuel Vadot 
137030068a1dSEmmanuel Vadot 	/* GPIO interface */
13716988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_get_bus,		axp2xx_gpio_get_bus),
13726988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_max,		axp2xx_gpio_pin_max),
13736988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getname,	axp2xx_gpio_pin_getname),
13746988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getcaps,	axp2xx_gpio_pin_getcaps),
13756988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getflags,	axp2xx_gpio_pin_getflags),
13766988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_setflags,	axp2xx_gpio_pin_setflags),
13776988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_get,		axp2xx_gpio_pin_get),
13786988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_set,		axp2xx_gpio_pin_set),
13796988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_toggle,	axp2xx_gpio_pin_toggle),
13806988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_map_gpios,	axp2xx_gpio_map_gpios),
138130068a1dSEmmanuel Vadot 
1382b3d4851eSEmmanuel Vadot 	/* Regdev interface */
13836988dd5eSEmmanuel Vadot 	DEVMETHOD(regdev_map,		axp2xx_regdev_map),
1384b3d4851eSEmmanuel Vadot 
138530068a1dSEmmanuel Vadot 	/* OFW bus interface */
13866988dd5eSEmmanuel Vadot 	DEVMETHOD(ofw_bus_get_node,	axp2xx_get_node),
138730068a1dSEmmanuel Vadot 
138830068a1dSEmmanuel Vadot 	DEVMETHOD_END
13892ff143afSAndrew Turner };
13902ff143afSAndrew Turner 
13916988dd5eSEmmanuel Vadot static driver_t axp2xx_driver = {
13926988dd5eSEmmanuel Vadot 	"axp2xx_pmu",
13936988dd5eSEmmanuel Vadot 	axp2xx_methods,
13946988dd5eSEmmanuel Vadot 	sizeof(struct axp2xx_softc),
13952ff143afSAndrew Turner };
13962ff143afSAndrew Turner 
13976988dd5eSEmmanuel Vadot static devclass_t axp2xx_devclass;
139830068a1dSEmmanuel Vadot extern devclass_t ofwgpiobus_devclass, gpioc_devclass;
139930068a1dSEmmanuel Vadot extern driver_t ofw_gpiobus_driver, gpioc_driver;
14002ff143afSAndrew Turner 
14016988dd5eSEmmanuel Vadot EARLY_DRIVER_MODULE(axp2xx, iicbus, axp2xx_driver, axp2xx_devclass,
140280ab358eSEmmanuel Vadot   0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
14036988dd5eSEmmanuel Vadot EARLY_DRIVER_MODULE(ofw_gpiobus, axp2xx_pmu, ofw_gpiobus_driver,
140480ab358eSEmmanuel Vadot     ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
14056988dd5eSEmmanuel Vadot DRIVER_MODULE(gpioc, axp2xx_pmu, gpioc_driver, gpioc_devclass,
140680ab358eSEmmanuel Vadot     0, 0);
14076988dd5eSEmmanuel Vadot MODULE_VERSION(axp2xx, 1);
1408*094e5e7eSIan Lepore MODULE_DEPEND(axp2xx, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
1409