xref: /freebsd/sys/arm/allwinner/axp209.c (revision 7e1e2ba1)
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  *
52ff143afSAndrew Turner  * Redistribution and use in source and binary forms, with or without
62ff143afSAndrew Turner  * modification, are permitted provided that the following conditions
72ff143afSAndrew Turner  * are met:
82ff143afSAndrew Turner  * 1. Redistributions of source code must retain the above copyright
92ff143afSAndrew Turner  *    notice, this list of conditions and the following disclaimer.
102ff143afSAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright
112ff143afSAndrew Turner  *    notice, this list of conditions and the following disclaimer in the
122ff143afSAndrew Turner  *    documentation and/or other materials provided with the distribution.
132ff143afSAndrew Turner  *
142ff143afSAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152ff143afSAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162ff143afSAndrew Turner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172ff143afSAndrew Turner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182ff143afSAndrew Turner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192ff143afSAndrew Turner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202ff143afSAndrew Turner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212ff143afSAndrew Turner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222ff143afSAndrew Turner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232ff143afSAndrew Turner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242ff143afSAndrew Turner  * SUCH DAMAGE.
252ff143afSAndrew Turner  */
262ff143afSAndrew Turner 
272ff143afSAndrew Turner #include <sys/cdefs.h>
282ff143afSAndrew Turner __FBSDID("$FreeBSD$");
296988dd5eSEmmanuel Vadot 
302ff143afSAndrew Turner /*
316988dd5eSEmmanuel Vadot * X-Power AXP209/AXP211 PMU for Allwinner SoCs
322ff143afSAndrew Turner */
336988dd5eSEmmanuel Vadot 
342ff143afSAndrew Turner #include <sys/param.h>
352ff143afSAndrew Turner #include <sys/systm.h>
362ff143afSAndrew Turner #include <sys/eventhandler.h>
372ff143afSAndrew Turner #include <sys/kernel.h>
382ff143afSAndrew Turner #include <sys/module.h>
392ff143afSAndrew Turner #include <sys/clock.h>
402ff143afSAndrew Turner #include <sys/time.h>
412ff143afSAndrew Turner #include <sys/bus.h>
422ff143afSAndrew Turner #include <sys/proc.h>
4330068a1dSEmmanuel Vadot #include <sys/gpio.h>
442ff143afSAndrew Turner #include <sys/reboot.h>
452ff143afSAndrew Turner #include <sys/resource.h>
462ff143afSAndrew Turner #include <sys/rman.h>
4786914a0fSAndrew Turner #include <sys/sysctl.h>
482ff143afSAndrew Turner 
492ff143afSAndrew Turner #include <dev/iicbus/iiconf.h>
502ff143afSAndrew Turner 
5130068a1dSEmmanuel Vadot #include <dev/gpio/gpiobusvar.h>
5230068a1dSEmmanuel Vadot 
532ff143afSAndrew Turner #include <dev/ofw/ofw_bus.h>
542ff143afSAndrew Turner #include <dev/ofw/ofw_bus_subr.h>
552ff143afSAndrew Turner 
56b3d4851eSEmmanuel Vadot #include <dev/extres/regulator/regulator.h>
57b3d4851eSEmmanuel Vadot 
5830068a1dSEmmanuel Vadot #include <arm/allwinner/axp209reg.h>
5930068a1dSEmmanuel Vadot 
6030068a1dSEmmanuel Vadot #include "gpio_if.h"
61b3d4851eSEmmanuel Vadot #include "regdev_if.h"
62b3d4851eSEmmanuel Vadot 
636988dd5eSEmmanuel Vadot MALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator");
64b3d4851eSEmmanuel Vadot 
656988dd5eSEmmanuel Vadot struct axp2xx_regdef {
66b3d4851eSEmmanuel Vadot 	intptr_t		id;
67b3d4851eSEmmanuel Vadot 	char			*name;
68b3d4851eSEmmanuel Vadot 	uint8_t			enable_reg;
69b3d4851eSEmmanuel Vadot 	uint8_t			enable_mask;
70b3d4851eSEmmanuel Vadot 	uint8_t			voltage_reg;
71b3d4851eSEmmanuel Vadot 	uint8_t			voltage_mask;
72b3d4851eSEmmanuel Vadot 	uint8_t			voltage_shift;
73b3d4851eSEmmanuel Vadot 	int			voltage_min;
74b3d4851eSEmmanuel Vadot 	int			voltage_max;
75b3d4851eSEmmanuel Vadot 	int			voltage_step;
76b3d4851eSEmmanuel Vadot 	int			voltage_nstep;
77b3d4851eSEmmanuel Vadot };
78b3d4851eSEmmanuel Vadot 
796988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp209_regdefs[] = {
80b3d4851eSEmmanuel Vadot 	{
81b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC2,
82b3d4851eSEmmanuel Vadot 		.name = "dcdc2",
83b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
84b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC2,
85b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC2_VOLTAGE,
86b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x3f,
87b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
88b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
89b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
90b3d4851eSEmmanuel Vadot 		.voltage_nstep = 64,
91b3d4851eSEmmanuel Vadot 	},
92b3d4851eSEmmanuel Vadot 	{
93b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC3,
94b3d4851eSEmmanuel Vadot 		.name = "dcdc3",
95b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
96b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC3,
97b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC3_VOLTAGE,
98b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
99b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
100b3d4851eSEmmanuel Vadot 		.voltage_max = 3500,
101b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
102b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
103b3d4851eSEmmanuel Vadot 	},
104b3d4851eSEmmanuel Vadot 	{
105b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO2,
106b3d4851eSEmmanuel Vadot 		.name = "ldo2",
107b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
108b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO2,
109b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO24_VOLTAGE,
110b3d4851eSEmmanuel Vadot 		.voltage_mask = 0xf0,
111b3d4851eSEmmanuel Vadot 		.voltage_shift = 4,
112b3d4851eSEmmanuel Vadot 		.voltage_min = 1800,
113b3d4851eSEmmanuel Vadot 		.voltage_max = 3300,
114b3d4851eSEmmanuel Vadot 		.voltage_step = 100,
115b3d4851eSEmmanuel Vadot 		.voltage_nstep = 16,
116b3d4851eSEmmanuel Vadot 	},
117b3d4851eSEmmanuel Vadot 	{
118b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO3,
119b3d4851eSEmmanuel Vadot 		.name = "ldo3",
120b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
121b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO3,
122b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO3_VOLTAGE,
123b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
124b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
125b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
126b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
127b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
128b3d4851eSEmmanuel Vadot 	},
129b3d4851eSEmmanuel Vadot };
130b3d4851eSEmmanuel Vadot 
1316988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp221_regdefs[] = {
1326988dd5eSEmmanuel Vadot 	{
1336988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO1,
1346988dd5eSEmmanuel Vadot 		.name = "dldo1",
1356988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1366988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO1,
1376988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO1_VOLTAGE,
1386988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1396988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1406988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1416988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1426988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1436988dd5eSEmmanuel Vadot 	},
1446988dd5eSEmmanuel Vadot 	{
1456988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO2,
1466988dd5eSEmmanuel Vadot 		.name = "dldo2",
1476988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1486988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO2,
1496988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO2_VOLTAGE,
1506988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1516988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1526988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1536988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1546988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1556988dd5eSEmmanuel Vadot 	},
1566988dd5eSEmmanuel Vadot 	{
1576988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO3,
1586988dd5eSEmmanuel Vadot 		.name = "dldo3",
1596988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1606988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO3,
1616988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO3_VOLTAGE,
1626988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1636988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1646988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1656988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1666988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1676988dd5eSEmmanuel Vadot 	},
1686988dd5eSEmmanuel Vadot 	{
1696988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO4,
1706988dd5eSEmmanuel Vadot 		.name = "dldo4",
1716988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1726988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO4,
1736988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO4_VOLTAGE,
1746988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1756988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1766988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1776988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1786988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1796988dd5eSEmmanuel Vadot 	},
1806988dd5eSEmmanuel Vadot 	{
1816988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO1,
1826988dd5eSEmmanuel Vadot 		.name = "eldo1",
1836988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1846988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO1,
1856988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO1_VOLTAGE,
1866988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1876988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1886988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1896988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1906988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1916988dd5eSEmmanuel Vadot 	},
1926988dd5eSEmmanuel Vadot 	{
1936988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO2,
1946988dd5eSEmmanuel Vadot 		.name = "eldo2",
1956988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1966988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO2,
1976988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO2_VOLTAGE,
1986988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1996988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2006988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2016988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2026988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2036988dd5eSEmmanuel Vadot 	},
2046988dd5eSEmmanuel Vadot 	{
2056988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO3,
2066988dd5eSEmmanuel Vadot 		.name = "eldo3",
2076988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
2086988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO3,
2096988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO3_VOLTAGE,
2106988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2116988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2126988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2136988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2146988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2156988dd5eSEmmanuel Vadot 	},
2166988dd5eSEmmanuel Vadot 	{
2176988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC5LDO,
2186988dd5eSEmmanuel Vadot 		.name = "dc5ldo",
2196988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2206988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DC5LDO,
2216988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DC5LDO_VOLTAGE,
2226988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3,
2236988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2246988dd5eSEmmanuel Vadot 		.voltage_max = 1400,
2256988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2266988dd5eSEmmanuel Vadot 		.voltage_nstep = 7,
2276988dd5eSEmmanuel Vadot 	},
2286988dd5eSEmmanuel Vadot 	{
2296988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC1,
2306988dd5eSEmmanuel Vadot 		.name = "dcdc1",
2316988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2326988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC1,
2336988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC1_VOLTAGE,
2346988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2356988dd5eSEmmanuel Vadot 		.voltage_min = 1600,
2366988dd5eSEmmanuel Vadot 		.voltage_max = 3400,
2376988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2386988dd5eSEmmanuel Vadot 		.voltage_nstep = 18,
2396988dd5eSEmmanuel Vadot 	},
2406988dd5eSEmmanuel Vadot 	{
2416988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC2,
2426988dd5eSEmmanuel Vadot 		.name = "dcdc2",
2436988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2446988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC2,
2456988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC2_VOLTAGE,
2466988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2476988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2486988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2496988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2506988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2516988dd5eSEmmanuel Vadot 	},
2526988dd5eSEmmanuel Vadot 	{
2536988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC3,
2546988dd5eSEmmanuel Vadot 		.name = "dcdc3",
2556988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2566988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC3,
2576988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC3_VOLTAGE,
2586988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2596988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2606988dd5eSEmmanuel Vadot 		.voltage_max = 1860,
2616988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2626988dd5eSEmmanuel Vadot 		.voltage_nstep = 63,
2636988dd5eSEmmanuel Vadot 	},
2646988dd5eSEmmanuel Vadot 	{
2656988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC4,
2666988dd5eSEmmanuel Vadot 		.name = "dcdc4",
2676988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2686988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC4,
2696988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC4_VOLTAGE,
2706988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2716988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2726988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2736988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2746988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2756988dd5eSEmmanuel Vadot 	},
2766988dd5eSEmmanuel Vadot 	{
2776988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC5,
2786988dd5eSEmmanuel Vadot 		.name = "dcdc5",
2796988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2806988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC5,
2816988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC5_VOLTAGE,
2826988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2836988dd5eSEmmanuel Vadot 		.voltage_min = 1000,
2846988dd5eSEmmanuel Vadot 		.voltage_max = 2550,
2856988dd5eSEmmanuel Vadot 		.voltage_step = 50,
2866988dd5eSEmmanuel Vadot 		.voltage_nstep = 31,
2876988dd5eSEmmanuel Vadot 	},
2886988dd5eSEmmanuel Vadot 	{
2896988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO1,
2906988dd5eSEmmanuel Vadot 		.name = "aldo1",
2916988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2926988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO1,
2936988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO1_VOLTAGE,
2946988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2956988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2966988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2976988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2986988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2996988dd5eSEmmanuel Vadot 	},
3006988dd5eSEmmanuel Vadot 	{
3016988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO2,
3026988dd5eSEmmanuel Vadot 		.name = "aldo2",
3036988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
3046988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO2,
3056988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO2_VOLTAGE,
3066988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3076988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3086988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3096988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3106988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3116988dd5eSEmmanuel Vadot 	},
3126988dd5eSEmmanuel Vadot 	{
3136988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO3,
3146988dd5eSEmmanuel Vadot 		.name = "aldo3",
3156988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_3,
3166988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL3_ALDO3,
3176988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO3_VOLTAGE,
3186988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3196988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3206988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3216988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3226988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3236988dd5eSEmmanuel Vadot 	},
3246988dd5eSEmmanuel Vadot 	{
3256988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC1SW,
3266988dd5eSEmmanuel Vadot 		.name = "dc1sw",
3276988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
3286988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DC1SW,
3296988dd5eSEmmanuel Vadot 	},
3306988dd5eSEmmanuel Vadot };
3316988dd5eSEmmanuel Vadot 
3326988dd5eSEmmanuel Vadot struct axp2xx_reg_sc {
333b3d4851eSEmmanuel Vadot 	struct regnode		*regnode;
334b3d4851eSEmmanuel Vadot 	device_t		base_dev;
3356988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*def;
336b3d4851eSEmmanuel Vadot 	phandle_t		xref;
337b3d4851eSEmmanuel Vadot 	struct regnode_std_param *param;
338b3d4851eSEmmanuel Vadot };
33986914a0fSAndrew Turner 
3406988dd5eSEmmanuel Vadot struct axp2xx_pins {
3416988dd5eSEmmanuel Vadot 	const char	*name;
3426988dd5eSEmmanuel Vadot 	uint8_t		ctrl_reg;
3436988dd5eSEmmanuel Vadot 	uint8_t		status_reg;
3446988dd5eSEmmanuel Vadot 	uint8_t		status_mask;
3456988dd5eSEmmanuel Vadot 	uint8_t		status_shift;
3466988dd5eSEmmanuel Vadot };
3476988dd5eSEmmanuel Vadot 
3486988dd5eSEmmanuel Vadot /* GPIO3 is different, don't expose it for now */
3496988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp209_pins[] = {
3506988dd5eSEmmanuel Vadot 	{
3516988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3526988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3536988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3546988dd5eSEmmanuel Vadot 		.status_mask = 0x10,
3556988dd5eSEmmanuel Vadot 		.status_shift = 4,
3566988dd5eSEmmanuel Vadot 	},
3576988dd5eSEmmanuel Vadot 	{
3586988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3596988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO1_CTRL,
3606988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3616988dd5eSEmmanuel Vadot 		.status_mask = 0x20,
3626988dd5eSEmmanuel Vadot 		.status_shift = 5,
3636988dd5eSEmmanuel Vadot 	},
3646988dd5eSEmmanuel Vadot 	{
3656988dd5eSEmmanuel Vadot 		.name = "GPIO2",
3666988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP209_GPIO2_CTRL,
3676988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3686988dd5eSEmmanuel Vadot 		.status_mask = 0x40,
3696988dd5eSEmmanuel Vadot 		.status_shift = 6,
3706988dd5eSEmmanuel Vadot 	},
3716988dd5eSEmmanuel Vadot };
3726988dd5eSEmmanuel Vadot 
3736988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp221_pins[] = {
3746988dd5eSEmmanuel Vadot 	{
3756988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3766988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3776988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3786988dd5eSEmmanuel Vadot 		.status_mask = 0x1,
3796988dd5eSEmmanuel Vadot 		.status_shift = 0x0,
3806988dd5eSEmmanuel Vadot 	},
3816988dd5eSEmmanuel Vadot 	{
3826988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3836988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3846988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3856988dd5eSEmmanuel Vadot 		.status_mask = 0x2,
3866988dd5eSEmmanuel Vadot 		.status_shift = 0x1,
3876988dd5eSEmmanuel Vadot 	},
3886988dd5eSEmmanuel Vadot };
3896988dd5eSEmmanuel Vadot 
3906988dd5eSEmmanuel Vadot struct axp2xx_sensors {
3916988dd5eSEmmanuel Vadot 	int		id;
3926988dd5eSEmmanuel Vadot 	const char	*name;
3936988dd5eSEmmanuel Vadot 	const char	*desc;
3946988dd5eSEmmanuel Vadot 	const char	*format;
3956988dd5eSEmmanuel Vadot 	uint8_t		enable_reg;
3966988dd5eSEmmanuel Vadot 	uint8_t		enable_mask;
3976988dd5eSEmmanuel Vadot 	uint8_t		value_reg;
3986988dd5eSEmmanuel Vadot 	uint8_t		value_size;
3996988dd5eSEmmanuel Vadot 	uint8_t		h_value_mask;
4006988dd5eSEmmanuel Vadot 	uint8_t		h_value_shift;
4016988dd5eSEmmanuel Vadot 	uint8_t		l_value_mask;
4026988dd5eSEmmanuel Vadot 	uint8_t		l_value_shift;
4036988dd5eSEmmanuel Vadot 	int		value_step;
4046988dd5eSEmmanuel Vadot 	int		value_convert;
4056988dd5eSEmmanuel Vadot };
4066988dd5eSEmmanuel Vadot 
4076988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp209_sensors[] = {
4086988dd5eSEmmanuel Vadot 	{
4096988dd5eSEmmanuel Vadot 		.id = AXP209_ACVOLT,
4106988dd5eSEmmanuel Vadot 		.name = "acvolt",
4116988dd5eSEmmanuel Vadot 		.desc = "AC Voltage (microvolt)",
4126988dd5eSEmmanuel Vadot 		.format = "I",
4136988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4146988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACVOLT,
4156988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_VOLTAGE,
4166988dd5eSEmmanuel Vadot 		.value_size = 2,
4176988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4186988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4196988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4206988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4216988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4226988dd5eSEmmanuel Vadot 	},
4236988dd5eSEmmanuel Vadot 	{
4246988dd5eSEmmanuel Vadot 		.id = AXP209_ACCURRENT,
4256988dd5eSEmmanuel Vadot 		.name = "accurrent",
4266988dd5eSEmmanuel Vadot 		.desc = "AC Current (microAmpere)",
4276988dd5eSEmmanuel Vadot 		.format = "I",
4286988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4296988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACCURRENT,
4306988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_CURRENT,
4316988dd5eSEmmanuel Vadot 		.value_size = 2,
4326988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4336988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4346988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4356988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4366988dd5eSEmmanuel Vadot 		.value_step = AXP209_ACCURRENT_STEP,
4376988dd5eSEmmanuel Vadot 	},
4386988dd5eSEmmanuel Vadot 	{
4396988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSVOLT,
4406988dd5eSEmmanuel Vadot 		.name = "vbusvolt",
4416988dd5eSEmmanuel Vadot 		.desc = "VBUS Voltage (microVolt)",
4426988dd5eSEmmanuel Vadot 		.format = "I",
4436988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4446988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSVOLT,
4456988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_VOLTAGE,
4466988dd5eSEmmanuel Vadot 		.value_size = 2,
4476988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4486988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4496988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4506988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4516988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4526988dd5eSEmmanuel Vadot 	},
4536988dd5eSEmmanuel Vadot 	{
4546988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSCURRENT,
4556988dd5eSEmmanuel Vadot 		.name = "vbuscurrent",
4566988dd5eSEmmanuel Vadot 		.desc = "VBUS Current (microAmpere)",
4576988dd5eSEmmanuel Vadot 		.format = "I",
4586988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4596988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSCURRENT,
4606988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_CURRENT,
4616988dd5eSEmmanuel Vadot 		.value_size = 2,
4626988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4636988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4646988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4656988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4666988dd5eSEmmanuel Vadot 		.value_step = AXP209_VBUSCURRENT_STEP,
4676988dd5eSEmmanuel Vadot 	},
4686988dd5eSEmmanuel Vadot 	{
4696988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
4706988dd5eSEmmanuel Vadot 		.name = "batvolt",
4716988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
4726988dd5eSEmmanuel Vadot 		.format = "I",
4736988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4746988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
4756988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
4766988dd5eSEmmanuel Vadot 		.value_size = 2,
4776988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4786988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4796988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4806988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4816988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
4826988dd5eSEmmanuel Vadot 	},
4836988dd5eSEmmanuel Vadot 	{
4846988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
4856988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
4866988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
4876988dd5eSEmmanuel Vadot 		.format = "I",
4886988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4896988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
4906988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
4916988dd5eSEmmanuel Vadot 		.value_size = 2,
4926988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4936988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
4946988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
4956988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4966988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
4976988dd5eSEmmanuel Vadot 	},
4986988dd5eSEmmanuel Vadot 	{
4996988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
5006988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
5016988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5026988dd5eSEmmanuel Vadot 		.format = "I",
5036988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5046988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5056988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5066988dd5eSEmmanuel Vadot 		.value_size = 2,
5076988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5086988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5096988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5106988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5116988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5126988dd5eSEmmanuel Vadot 	},
5136988dd5eSEmmanuel Vadot 	{
5146988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5156988dd5eSEmmanuel Vadot 		.name = "temp",
5166988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5176988dd5eSEmmanuel Vadot 		.format = "IK",
5186988dd5eSEmmanuel Vadot 		.enable_reg = AXP209_ADC_ENABLE2,
5196988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC2_TEMP,
5206988dd5eSEmmanuel Vadot 		.value_reg = AXP209_TEMPMON,
5216988dd5eSEmmanuel Vadot 		.value_size = 2,
5226988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5236988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5246988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5256988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5266988dd5eSEmmanuel Vadot 		.value_step = 1,
5276988dd5eSEmmanuel Vadot 		.value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K),
5286988dd5eSEmmanuel Vadot 	},
5296988dd5eSEmmanuel Vadot };
5306988dd5eSEmmanuel Vadot 
5316988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp221_sensors[] = {
5326988dd5eSEmmanuel Vadot 	{
5336988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
5346988dd5eSEmmanuel Vadot 		.name = "batvolt",
5356988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
5366988dd5eSEmmanuel Vadot 		.format = "I",
5376988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5386988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
5396988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
5406988dd5eSEmmanuel Vadot 		.value_size = 2,
5416988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5426988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5436988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5446988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5456988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
5466988dd5eSEmmanuel Vadot 	},
5476988dd5eSEmmanuel Vadot 	{
5486988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
5496988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
5506988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
5516988dd5eSEmmanuel Vadot 		.format = "I",
5526988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5536988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5546988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
5556988dd5eSEmmanuel Vadot 		.value_size = 2,
5566988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5576988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5586988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5596988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5606988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5616988dd5eSEmmanuel Vadot 	},
5626988dd5eSEmmanuel Vadot 	{
5636988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
5646988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
5656988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5666988dd5eSEmmanuel Vadot 		.format = "I",
5676988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5686988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5696988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5706988dd5eSEmmanuel Vadot 		.value_size = 2,
5716988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5726988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5736988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5746988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5756988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5766988dd5eSEmmanuel Vadot 	},
5776988dd5eSEmmanuel Vadot 	{
5786988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5796988dd5eSEmmanuel Vadot 		.name = "temp",
5806988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5816988dd5eSEmmanuel Vadot 		.format = "IK",
5826988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5836988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_ADC1_TEMP,
5846988dd5eSEmmanuel Vadot 		.value_reg = AXP221_TEMPMON,
5856988dd5eSEmmanuel Vadot 		.value_size = 2,
5866988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5876988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5886988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5896988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5906988dd5eSEmmanuel Vadot 		.value_step = 1,
5916988dd5eSEmmanuel Vadot 		.value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K),
5926988dd5eSEmmanuel Vadot 	},
5936988dd5eSEmmanuel Vadot };
5946988dd5eSEmmanuel Vadot 
5956988dd5eSEmmanuel Vadot enum AXP2XX_TYPE {
5966988dd5eSEmmanuel Vadot 	AXP209 = 1,
5976988dd5eSEmmanuel Vadot 	AXP221,
5986988dd5eSEmmanuel Vadot };
5996988dd5eSEmmanuel Vadot 
6006988dd5eSEmmanuel Vadot struct axp2xx_softc {
60130068a1dSEmmanuel Vadot 	device_t		dev;
60230068a1dSEmmanuel Vadot 	struct resource *	res[1];
60330068a1dSEmmanuel Vadot 	void *			intrcookie;
60430068a1dSEmmanuel Vadot 	struct intr_config_hook	intr_hook;
60530068a1dSEmmanuel Vadot 	struct mtx		mtx;
6066988dd5eSEmmanuel Vadot 	uint8_t			type;
6076988dd5eSEmmanuel Vadot 
6086988dd5eSEmmanuel Vadot 	/* GPIO */
6096988dd5eSEmmanuel Vadot 	device_t		gpiodev;
6106988dd5eSEmmanuel Vadot 	int			npins;
6116988dd5eSEmmanuel Vadot 	const struct axp2xx_pins	*pins;
6126988dd5eSEmmanuel Vadot 
6136988dd5eSEmmanuel Vadot 	/* Sensors */
6146988dd5eSEmmanuel Vadot 	const struct axp2xx_sensors	*sensors;
6156988dd5eSEmmanuel Vadot 	int				nsensors;
616b3d4851eSEmmanuel Vadot 
617b3d4851eSEmmanuel Vadot 	/* Regulators */
6186988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc	**regs;
619b3d4851eSEmmanuel Vadot 	int			nregs;
6206988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*regdefs;
6212ff143afSAndrew Turner };
6222ff143afSAndrew Turner 
6236988dd5eSEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
6246988dd5eSEmmanuel Vadot 	{ "x-powers,axp209",		AXP209 },
6256988dd5eSEmmanuel Vadot 	{ "x-powers,axp221",		AXP221 },
6266988dd5eSEmmanuel Vadot 	{ NULL,				0 }
62786914a0fSAndrew Turner };
62886914a0fSAndrew Turner 
62930068a1dSEmmanuel Vadot static struct resource_spec axp_res_spec[] = {
63030068a1dSEmmanuel Vadot 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
63130068a1dSEmmanuel Vadot 	{ -1,			0,	0 }
63230068a1dSEmmanuel Vadot };
63330068a1dSEmmanuel Vadot 
63430068a1dSEmmanuel Vadot #define	AXP_LOCK(sc)	mtx_lock(&(sc)->mtx)
63530068a1dSEmmanuel Vadot #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
63630068a1dSEmmanuel Vadot 
6372ff143afSAndrew Turner static int
6386988dd5eSEmmanuel Vadot axp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
6392ff143afSAndrew Turner {
6402ff143afSAndrew Turner 
641094e5e7eSIan Lepore 	return (iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT));
6422ff143afSAndrew Turner }
6432ff143afSAndrew Turner 
6442ff143afSAndrew Turner static int
6456988dd5eSEmmanuel Vadot axp2xx_write(device_t dev, uint8_t reg, uint8_t data)
6462ff143afSAndrew Turner {
6472ff143afSAndrew Turner 
648094e5e7eSIan Lepore 	return (iicdev_writeto(dev, reg, &data, sizeof(data), IIC_INTRWAIT));
6492ff143afSAndrew Turner }
6502ff143afSAndrew Turner 
65186914a0fSAndrew Turner static int
6526988dd5eSEmmanuel Vadot axp2xx_regnode_init(struct regnode *regnode)
653b3d4851eSEmmanuel Vadot {
654b3d4851eSEmmanuel Vadot 	return (0);
655b3d4851eSEmmanuel Vadot }
656b3d4851eSEmmanuel Vadot 
657b3d4851eSEmmanuel Vadot static int
6586988dd5eSEmmanuel Vadot axp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
659b3d4851eSEmmanuel Vadot {
6606988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
661b3d4851eSEmmanuel Vadot 	uint8_t val;
662b3d4851eSEmmanuel Vadot 
663b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
664b3d4851eSEmmanuel Vadot 
6656988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
666b3d4851eSEmmanuel Vadot 	if (enable)
667b3d4851eSEmmanuel Vadot 		val |= sc->def->enable_mask;
668b3d4851eSEmmanuel Vadot 	else
669b3d4851eSEmmanuel Vadot 		val &= ~sc->def->enable_mask;
6706988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->enable_reg, val);
671b3d4851eSEmmanuel Vadot 
672b3d4851eSEmmanuel Vadot 	*udelay = 0;
673b3d4851eSEmmanuel Vadot 
674b3d4851eSEmmanuel Vadot 	return (0);
675b3d4851eSEmmanuel Vadot }
676b3d4851eSEmmanuel Vadot 
677b3d4851eSEmmanuel Vadot static void
6786988dd5eSEmmanuel Vadot axp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv)
679b3d4851eSEmmanuel Vadot {
680b3d4851eSEmmanuel Vadot 	if (val < sc->def->voltage_nstep)
681b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min + val * sc->def->voltage_step;
682b3d4851eSEmmanuel Vadot 	else
683b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min +
684b3d4851eSEmmanuel Vadot 		       (sc->def->voltage_nstep * sc->def->voltage_step);
685b3d4851eSEmmanuel Vadot 	*uv *= 1000;
686b3d4851eSEmmanuel Vadot }
687b3d4851eSEmmanuel Vadot 
688b3d4851eSEmmanuel Vadot static int
6896988dd5eSEmmanuel Vadot axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt,
690b3d4851eSEmmanuel Vadot     int max_uvolt, uint8_t *val)
691b3d4851eSEmmanuel Vadot {
692b3d4851eSEmmanuel Vadot 	uint8_t nval;
693b3d4851eSEmmanuel Vadot 	int nstep, uvolt;
694b3d4851eSEmmanuel Vadot 
695b3d4851eSEmmanuel Vadot 	nval = 0;
696b3d4851eSEmmanuel Vadot 	uvolt = sc->def->voltage_min * 1000;
697b3d4851eSEmmanuel Vadot 
698b3d4851eSEmmanuel Vadot 	for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
699b3d4851eSEmmanuel Vadot 	     nstep++) {
700b3d4851eSEmmanuel Vadot 		++nval;
701b3d4851eSEmmanuel Vadot 		uvolt += (sc->def->voltage_step * 1000);
702b3d4851eSEmmanuel Vadot 	}
703b3d4851eSEmmanuel Vadot 	if (uvolt > max_uvolt)
704b3d4851eSEmmanuel Vadot 		return (EINVAL);
705b3d4851eSEmmanuel Vadot 
706b3d4851eSEmmanuel Vadot 	*val = nval;
707b3d4851eSEmmanuel Vadot 	return (0);
708b3d4851eSEmmanuel Vadot }
709b3d4851eSEmmanuel Vadot 
710b3d4851eSEmmanuel Vadot static int
711ca438784SEmmanuel Vadot axp2xx_regnode_status(struct regnode *regnode, int *status)
712ca438784SEmmanuel Vadot {
713ca438784SEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
714ca438784SEmmanuel Vadot 	uint8_t val;
715ca438784SEmmanuel Vadot 
716ca438784SEmmanuel Vadot 	sc = regnode_get_softc(regnode);
717ca438784SEmmanuel Vadot 
718ca438784SEmmanuel Vadot 	*status = 0;
719ca438784SEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
720ca438784SEmmanuel Vadot 	if (val & sc->def->enable_mask)
721ca438784SEmmanuel Vadot 		*status = REGULATOR_STATUS_ENABLED;
722ca438784SEmmanuel Vadot 
723ca438784SEmmanuel Vadot 	return (0);
724ca438784SEmmanuel Vadot }
725ca438784SEmmanuel Vadot 
726ca438784SEmmanuel Vadot static int
7276988dd5eSEmmanuel Vadot axp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
728b3d4851eSEmmanuel Vadot     int max_uvolt, int *udelay)
729b3d4851eSEmmanuel Vadot {
7306988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
731b3d4851eSEmmanuel Vadot 	uint8_t val;
732b3d4851eSEmmanuel Vadot 
733b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
734b3d4851eSEmmanuel Vadot 
735b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
736b3d4851eSEmmanuel Vadot 		return (ENXIO);
737b3d4851eSEmmanuel Vadot 
7386988dd5eSEmmanuel Vadot 	if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
739b3d4851eSEmmanuel Vadot 		return (ERANGE);
740b3d4851eSEmmanuel Vadot 
7416988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->voltage_reg, val);
742b3d4851eSEmmanuel Vadot 
743b3d4851eSEmmanuel Vadot 	*udelay = 0;
744b3d4851eSEmmanuel Vadot 
745b3d4851eSEmmanuel Vadot 	return (0);
746b3d4851eSEmmanuel Vadot }
747b3d4851eSEmmanuel Vadot 
748b3d4851eSEmmanuel Vadot static int
7496988dd5eSEmmanuel Vadot axp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
750b3d4851eSEmmanuel Vadot {
7516988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
752b3d4851eSEmmanuel Vadot 	uint8_t val;
753b3d4851eSEmmanuel Vadot 
754b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
755b3d4851eSEmmanuel Vadot 
756b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
757b3d4851eSEmmanuel Vadot 		return (ENXIO);
758b3d4851eSEmmanuel Vadot 
7596988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
7606988dd5eSEmmanuel Vadot 	axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
761b3d4851eSEmmanuel Vadot 
762b3d4851eSEmmanuel Vadot 	return (0);
763b3d4851eSEmmanuel Vadot }
764b3d4851eSEmmanuel Vadot 
7656988dd5eSEmmanuel Vadot static regnode_method_t axp2xx_regnode_methods[] = {
766b3d4851eSEmmanuel Vadot 	/* Regulator interface */
7676988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_init,		axp2xx_regnode_init),
7686988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_enable,		axp2xx_regnode_enable),
769ca438784SEmmanuel Vadot 	REGNODEMETHOD(regnode_status,		axp2xx_regnode_status),
7706988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_set_voltage,	axp2xx_regnode_set_voltage),
7716988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_get_voltage,	axp2xx_regnode_get_voltage),
7729c3a56d0SEmmanuel Vadot 	REGNODEMETHOD(regnode_check_voltage,	regnode_method_check_voltage),
773b3d4851eSEmmanuel Vadot 	REGNODEMETHOD_END
774b3d4851eSEmmanuel Vadot };
7756988dd5eSEmmanuel Vadot DEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods,
7766988dd5eSEmmanuel Vadot     sizeof(struct axp2xx_reg_sc), regnode_class);
777b3d4851eSEmmanuel Vadot 
778b3d4851eSEmmanuel Vadot static int
7796988dd5eSEmmanuel Vadot axp2xx_sysctl(SYSCTL_HANDLER_ARGS)
78086914a0fSAndrew Turner {
7816988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
78286914a0fSAndrew Turner 	device_t dev = arg1;
7836988dd5eSEmmanuel Vadot 	enum axp2xx_sensor sensor = arg2;
78486914a0fSAndrew Turner 	uint8_t data[2];
7856988dd5eSEmmanuel Vadot 	int val, error, i, found;
78686914a0fSAndrew Turner 
7876988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
78886914a0fSAndrew Turner 
7896988dd5eSEmmanuel Vadot 	for (found = 0, i = 0; i < sc->nsensors; i++) {
7906988dd5eSEmmanuel Vadot 		if (sc->sensors[i].id == sensor) {
7916988dd5eSEmmanuel Vadot 			found = 1;
79230068a1dSEmmanuel Vadot 			break;
79330068a1dSEmmanuel Vadot 		}
7946988dd5eSEmmanuel Vadot 	}
7956988dd5eSEmmanuel Vadot 
7966988dd5eSEmmanuel Vadot 	if (found == 0)
7976988dd5eSEmmanuel Vadot 		return (ENOENT);
7986988dd5eSEmmanuel Vadot 
7996988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2);
8006988dd5eSEmmanuel Vadot 	if (error != 0)
8016988dd5eSEmmanuel Vadot 		return (error);
8026988dd5eSEmmanuel Vadot 
8036988dd5eSEmmanuel Vadot 	val = ((data[0] & sc->sensors[i].h_value_mask) <<
8046988dd5eSEmmanuel Vadot 	    sc->sensors[i].h_value_shift);
8056988dd5eSEmmanuel Vadot 	val |= ((data[1] & sc->sensors[i].l_value_mask) <<
8066988dd5eSEmmanuel Vadot 	    sc->sensors[i].l_value_shift);
8076988dd5eSEmmanuel Vadot 	val *= sc->sensors[i].value_step;
8086988dd5eSEmmanuel Vadot 	val += sc->sensors[i].value_convert;
80986914a0fSAndrew Turner 
81086914a0fSAndrew Turner 	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
81186914a0fSAndrew Turner }
81286914a0fSAndrew Turner 
8132ff143afSAndrew Turner static void
8146988dd5eSEmmanuel Vadot axp2xx_shutdown(void *devp, int howto)
8152ff143afSAndrew Turner {
8162ff143afSAndrew Turner 	device_t dev;
8172ff143afSAndrew Turner 
8182ff143afSAndrew Turner 	if (!(howto & RB_POWEROFF))
8192ff143afSAndrew Turner 		return;
8202ff143afSAndrew Turner 	dev = (device_t)devp;
8212ff143afSAndrew Turner 
8222ff143afSAndrew Turner 	if (bootverbose)
8236988dd5eSEmmanuel Vadot 		device_printf(dev, "Shutdown AXP2xx\n");
8242ff143afSAndrew Turner 
8256988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN);
8262ff143afSAndrew Turner }
8272ff143afSAndrew Turner 
82830068a1dSEmmanuel Vadot static void
8296988dd5eSEmmanuel Vadot axp2xx_intr(void *arg)
8302ff143afSAndrew Turner {
8316988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
83230068a1dSEmmanuel Vadot 	uint8_t reg;
8332ff143afSAndrew Turner 
83430068a1dSEmmanuel Vadot 	sc = arg;
8352ff143afSAndrew Turner 
8366988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, &reg, 1);
83730068a1dSEmmanuel Vadot 	if (reg) {
8386988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_OVERVOLT)
83930068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "overvoltage", NULL);
8406988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT)
84130068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "overvoltage", NULL);
8426988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_LOW)
84330068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "undervoltage", NULL);
8446988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_CONN)
84530068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "plugged", NULL);
8466988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_DISCONN)
84730068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "unplugged", NULL);
8486988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_CONN)
84930068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "plugged", NULL);
8506988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_DISCONN)
85130068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "unplugged", NULL);
8526988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK);
85330068a1dSEmmanuel Vadot 	}
8542ff143afSAndrew Turner 
8556988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, &reg, 1);
85630068a1dSEmmanuel Vadot 	if (reg) {
8576988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGED)
85830068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charged", NULL);
8596988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGING)
86030068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charging", NULL);
8616988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CONN)
86230068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "connected", NULL);
8636988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_DISCONN)
86430068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "disconnected", NULL);
8656988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW)
86680bd2aadSWarner Losh 			devctl_notify("PMU", "Battery", "low-temp", NULL);
8676988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER)
86880bd2aadSWarner Losh 			devctl_notify("PMU", "Battery", "high-temp", NULL);
8696988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK);
87030068a1dSEmmanuel Vadot 	}
8712ff143afSAndrew Turner 
8726988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, &reg, 1);
87330068a1dSEmmanuel Vadot 	if (reg) {
8746988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ3_PEK_SHORT)
87530068a1dSEmmanuel Vadot 			shutdown_nice(RB_POWEROFF);
8766988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK);
87730068a1dSEmmanuel Vadot 	}
87830068a1dSEmmanuel Vadot 
8796988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, &reg, 1);
88030068a1dSEmmanuel Vadot 	if (reg) {
8816988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK);
88230068a1dSEmmanuel Vadot 	}
88330068a1dSEmmanuel Vadot 
8846988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, &reg, 1);
88530068a1dSEmmanuel Vadot 	if (reg) {
8866988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK);
88730068a1dSEmmanuel Vadot 	}
88830068a1dSEmmanuel Vadot }
88930068a1dSEmmanuel Vadot 
89030068a1dSEmmanuel Vadot static device_t
8916988dd5eSEmmanuel Vadot axp2xx_gpio_get_bus(device_t dev)
89230068a1dSEmmanuel Vadot {
8936988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
89430068a1dSEmmanuel Vadot 
89530068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
89630068a1dSEmmanuel Vadot 
89730068a1dSEmmanuel Vadot 	return (sc->gpiodev);
8982ff143afSAndrew Turner }
8992ff143afSAndrew Turner 
9002ff143afSAndrew Turner static int
9016988dd5eSEmmanuel Vadot axp2xx_gpio_pin_max(device_t dev, int *maxpin)
9022ff143afSAndrew Turner {
9036988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9046988dd5eSEmmanuel Vadot 
9056988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9066988dd5eSEmmanuel Vadot 
9076988dd5eSEmmanuel Vadot 	*maxpin = sc->npins - 1;
90830068a1dSEmmanuel Vadot 
90930068a1dSEmmanuel Vadot 	return (0);
91030068a1dSEmmanuel Vadot }
91130068a1dSEmmanuel Vadot 
91230068a1dSEmmanuel Vadot static int
9136988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
91430068a1dSEmmanuel Vadot {
9156988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9166988dd5eSEmmanuel Vadot 
9176988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9186988dd5eSEmmanuel Vadot 
9196988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
92030068a1dSEmmanuel Vadot 		return (EINVAL);
92130068a1dSEmmanuel Vadot 
92230068a1dSEmmanuel Vadot 	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
92330068a1dSEmmanuel Vadot 
92430068a1dSEmmanuel Vadot 	return (0);
92530068a1dSEmmanuel Vadot }
92630068a1dSEmmanuel Vadot 
92730068a1dSEmmanuel Vadot static int
9286988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
92930068a1dSEmmanuel Vadot {
9306988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9316988dd5eSEmmanuel Vadot 
9326988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9336988dd5eSEmmanuel Vadot 
9346988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
93530068a1dSEmmanuel Vadot 		return (EINVAL);
93630068a1dSEmmanuel Vadot 
93730068a1dSEmmanuel Vadot 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
93830068a1dSEmmanuel Vadot 
93930068a1dSEmmanuel Vadot 	return (0);
94030068a1dSEmmanuel Vadot }
94130068a1dSEmmanuel Vadot 
94230068a1dSEmmanuel Vadot static int
9436988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
94430068a1dSEmmanuel Vadot {
9456988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
94630068a1dSEmmanuel Vadot 	uint8_t data, func;
94730068a1dSEmmanuel Vadot 	int error;
94830068a1dSEmmanuel Vadot 
94930068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
95030068a1dSEmmanuel Vadot 
9516988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9526988dd5eSEmmanuel Vadot 		return (EINVAL);
9536988dd5eSEmmanuel Vadot 
95430068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9556988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
95630068a1dSEmmanuel Vadot 	if (error == 0) {
9576988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
9586988dd5eSEmmanuel Vadot 		if (func == AXP2XX_GPIO_FUNC_INPUT)
95930068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_INPUT;
9606988dd5eSEmmanuel Vadot 		else if (func == AXP2XX_GPIO_FUNC_DRVLO ||
9616988dd5eSEmmanuel Vadot 		    func == AXP2XX_GPIO_FUNC_DRVHI)
96230068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_OUTPUT;
96330068a1dSEmmanuel Vadot 		else
96430068a1dSEmmanuel Vadot 			*flags = 0;
96530068a1dSEmmanuel Vadot 	}
96630068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
96730068a1dSEmmanuel Vadot 
96830068a1dSEmmanuel Vadot 	return (error);
96930068a1dSEmmanuel Vadot }
97030068a1dSEmmanuel Vadot 
97130068a1dSEmmanuel Vadot static int
9726988dd5eSEmmanuel Vadot axp2xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
97330068a1dSEmmanuel Vadot {
9746988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
97530068a1dSEmmanuel Vadot 	uint8_t data;
97630068a1dSEmmanuel Vadot 	int error;
97730068a1dSEmmanuel Vadot 
97830068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
97930068a1dSEmmanuel Vadot 
9806988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9816988dd5eSEmmanuel Vadot 		return (EINVAL);
9826988dd5eSEmmanuel Vadot 
98330068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9846988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
98530068a1dSEmmanuel Vadot 	if (error == 0) {
9866988dd5eSEmmanuel Vadot 		data &= ~AXP2XX_GPIO_FUNC_MASK;
98730068a1dSEmmanuel Vadot 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
98830068a1dSEmmanuel Vadot 			if ((flags & GPIO_PIN_OUTPUT) == 0)
9896988dd5eSEmmanuel Vadot 				data |= AXP2XX_GPIO_FUNC_INPUT;
99030068a1dSEmmanuel Vadot 		}
9916988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
99230068a1dSEmmanuel Vadot 	}
99330068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
99430068a1dSEmmanuel Vadot 
99530068a1dSEmmanuel Vadot 	return (error);
99630068a1dSEmmanuel Vadot }
99730068a1dSEmmanuel Vadot 
99830068a1dSEmmanuel Vadot static int
9996988dd5eSEmmanuel Vadot axp2xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
100030068a1dSEmmanuel Vadot {
10016988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
100230068a1dSEmmanuel Vadot 	uint8_t data, func;
100330068a1dSEmmanuel Vadot 	int error;
100430068a1dSEmmanuel Vadot 
100530068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
100630068a1dSEmmanuel Vadot 
10076988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10086988dd5eSEmmanuel Vadot 		return (EINVAL);
10096988dd5eSEmmanuel Vadot 
101030068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10116988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
101230068a1dSEmmanuel Vadot 	if (error == 0) {
10136988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
101430068a1dSEmmanuel Vadot 		switch (func) {
10156988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
101630068a1dSEmmanuel Vadot 			*val = 0;
101730068a1dSEmmanuel Vadot 			break;
10186988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
101930068a1dSEmmanuel Vadot 			*val = 1;
102030068a1dSEmmanuel Vadot 			break;
10216988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_INPUT:
10226988dd5eSEmmanuel Vadot 			error = axp2xx_read(dev, sc->pins[pin].status_reg,
10236988dd5eSEmmanuel Vadot 			    &data, 1);
10246988dd5eSEmmanuel Vadot 			if (error == 0) {
10256988dd5eSEmmanuel Vadot 				*val = (data & sc->pins[pin].status_mask);
10266988dd5eSEmmanuel Vadot 				*val >>= sc->pins[pin].status_shift;
10276988dd5eSEmmanuel Vadot 			}
102830068a1dSEmmanuel Vadot 			break;
102930068a1dSEmmanuel Vadot 		default:
103030068a1dSEmmanuel Vadot 			error = EIO;
103130068a1dSEmmanuel Vadot 			break;
103230068a1dSEmmanuel Vadot 		}
103330068a1dSEmmanuel Vadot 	}
103430068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
103530068a1dSEmmanuel Vadot 
103630068a1dSEmmanuel Vadot 	return (error);
103730068a1dSEmmanuel Vadot }
103830068a1dSEmmanuel Vadot 
103930068a1dSEmmanuel Vadot static int
10406988dd5eSEmmanuel Vadot axp2xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
104130068a1dSEmmanuel Vadot {
10426988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
104330068a1dSEmmanuel Vadot 	uint8_t data, func;
104430068a1dSEmmanuel Vadot 	int error;
104530068a1dSEmmanuel Vadot 
104630068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
104730068a1dSEmmanuel Vadot 
10486988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10496988dd5eSEmmanuel Vadot 		return (EINVAL);
10506988dd5eSEmmanuel Vadot 
105130068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10526988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
105330068a1dSEmmanuel Vadot 	if (error == 0) {
10546988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
105530068a1dSEmmanuel Vadot 		switch (func) {
10566988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
10576988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
105830068a1dSEmmanuel Vadot 			/* GPIO2 can't be set to 1 */
105930068a1dSEmmanuel Vadot 			if (pin == 2 && val == 1) {
106030068a1dSEmmanuel Vadot 				error = EINVAL;
106130068a1dSEmmanuel Vadot 				break;
106230068a1dSEmmanuel Vadot 			}
10636988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
106430068a1dSEmmanuel Vadot 			data |= val;
106530068a1dSEmmanuel Vadot 			break;
106630068a1dSEmmanuel Vadot 		default:
106730068a1dSEmmanuel Vadot 			error = EIO;
106830068a1dSEmmanuel Vadot 			break;
106930068a1dSEmmanuel Vadot 		}
107030068a1dSEmmanuel Vadot 	}
107130068a1dSEmmanuel Vadot 	if (error == 0)
10726988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
107330068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
107430068a1dSEmmanuel Vadot 
107530068a1dSEmmanuel Vadot 	return (error);
107630068a1dSEmmanuel Vadot }
107730068a1dSEmmanuel Vadot 
107830068a1dSEmmanuel Vadot static int
10796988dd5eSEmmanuel Vadot axp2xx_gpio_pin_toggle(device_t dev, uint32_t pin)
108030068a1dSEmmanuel Vadot {
10816988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
108230068a1dSEmmanuel Vadot 	uint8_t data, func;
108330068a1dSEmmanuel Vadot 	int error;
108430068a1dSEmmanuel Vadot 
108530068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
108630068a1dSEmmanuel Vadot 
10876988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10886988dd5eSEmmanuel Vadot 		return (EINVAL);
10896988dd5eSEmmanuel Vadot 
109030068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10916988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
109230068a1dSEmmanuel Vadot 	if (error == 0) {
10936988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
109430068a1dSEmmanuel Vadot 		switch (func) {
10956988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
109630068a1dSEmmanuel Vadot 			/* Pin 2 can't be set to 1*/
109730068a1dSEmmanuel Vadot 			if (pin == 2) {
109830068a1dSEmmanuel Vadot 				error = EINVAL;
109930068a1dSEmmanuel Vadot 				break;
110030068a1dSEmmanuel Vadot 			}
11016988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
11026988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVHI;
110330068a1dSEmmanuel Vadot 			break;
11046988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
11056988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
11066988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVLO;
110730068a1dSEmmanuel Vadot 			break;
110830068a1dSEmmanuel Vadot 		default:
110930068a1dSEmmanuel Vadot 			error = EIO;
111030068a1dSEmmanuel Vadot 			break;
111130068a1dSEmmanuel Vadot 		}
111230068a1dSEmmanuel Vadot 	}
111330068a1dSEmmanuel Vadot 	if (error == 0)
11146988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
111530068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
111630068a1dSEmmanuel Vadot 
111730068a1dSEmmanuel Vadot 	return (error);
111830068a1dSEmmanuel Vadot }
111930068a1dSEmmanuel Vadot 
112030068a1dSEmmanuel Vadot static int
11216988dd5eSEmmanuel Vadot axp2xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
112230068a1dSEmmanuel Vadot     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
112330068a1dSEmmanuel Vadot {
11246988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
11256988dd5eSEmmanuel Vadot 
11266988dd5eSEmmanuel Vadot 	sc = device_get_softc(bus);
11276988dd5eSEmmanuel Vadot 
11286988dd5eSEmmanuel Vadot 	if (gpios[0] >= sc->npins)
112930068a1dSEmmanuel Vadot 		return (EINVAL);
113030068a1dSEmmanuel Vadot 
113130068a1dSEmmanuel Vadot 	*pin = gpios[0];
113230068a1dSEmmanuel Vadot 	*flags = gpios[1];
113330068a1dSEmmanuel Vadot 
113430068a1dSEmmanuel Vadot 	return (0);
113530068a1dSEmmanuel Vadot }
113630068a1dSEmmanuel Vadot 
113730068a1dSEmmanuel Vadot static phandle_t
11386988dd5eSEmmanuel Vadot axp2xx_get_node(device_t dev, device_t bus)
113930068a1dSEmmanuel Vadot {
114030068a1dSEmmanuel Vadot 	return (ofw_bus_get_node(dev));
114130068a1dSEmmanuel Vadot }
114230068a1dSEmmanuel Vadot 
11436988dd5eSEmmanuel Vadot static struct axp2xx_reg_sc *
11446988dd5eSEmmanuel Vadot axp2xx_reg_attach(device_t dev, phandle_t node,
11456988dd5eSEmmanuel Vadot     struct axp2xx_regdef *def)
1146b3d4851eSEmmanuel Vadot {
11476988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg_sc;
1148b3d4851eSEmmanuel Vadot 	struct regnode_init_def initdef;
1149b3d4851eSEmmanuel Vadot 	struct regnode *regnode;
1150b3d4851eSEmmanuel Vadot 
1151b3d4851eSEmmanuel Vadot 	memset(&initdef, 0, sizeof(initdef));
1152b3d4851eSEmmanuel Vadot 	if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) {
1153b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1154b3d4851eSEmmanuel Vadot 		return (NULL);
1155b3d4851eSEmmanuel Vadot 	}
1156b3d4851eSEmmanuel Vadot 	if (initdef.std_param.min_uvolt == 0)
1157b3d4851eSEmmanuel Vadot 		initdef.std_param.min_uvolt = def->voltage_min * 1000;
1158b3d4851eSEmmanuel Vadot 	if (initdef.std_param.max_uvolt == 0)
1159b3d4851eSEmmanuel Vadot 		initdef.std_param.max_uvolt = def->voltage_max * 1000;
1160b3d4851eSEmmanuel Vadot 	initdef.id = def->id;
1161b3d4851eSEmmanuel Vadot 	initdef.ofw_node = node;
11626988dd5eSEmmanuel Vadot 	regnode = regnode_create(dev, &axp2xx_regnode_class, &initdef);
1163b3d4851eSEmmanuel Vadot 	if (regnode == NULL) {
1164b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1165b3d4851eSEmmanuel Vadot 		return (NULL);
1166b3d4851eSEmmanuel Vadot 	}
1167b3d4851eSEmmanuel Vadot 
1168b3d4851eSEmmanuel Vadot 	reg_sc = regnode_get_softc(regnode);
1169b3d4851eSEmmanuel Vadot 	reg_sc->regnode = regnode;
1170b3d4851eSEmmanuel Vadot 	reg_sc->base_dev = dev;
1171b3d4851eSEmmanuel Vadot 	reg_sc->def = def;
1172b3d4851eSEmmanuel Vadot 	reg_sc->xref = OF_xref_from_node(node);
1173b3d4851eSEmmanuel Vadot 	reg_sc->param = regnode_get_stdparam(regnode);
1174b3d4851eSEmmanuel Vadot 
1175b3d4851eSEmmanuel Vadot 	regnode_register(regnode);
1176b3d4851eSEmmanuel Vadot 
1177b3d4851eSEmmanuel Vadot 	return (reg_sc);
1178b3d4851eSEmmanuel Vadot }
1179b3d4851eSEmmanuel Vadot 
1180b3d4851eSEmmanuel Vadot static int
11816988dd5eSEmmanuel Vadot axp2xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
1182b3d4851eSEmmanuel Vadot     intptr_t *num)
1183b3d4851eSEmmanuel Vadot {
11846988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1185b3d4851eSEmmanuel Vadot 	int i;
1186b3d4851eSEmmanuel Vadot 
1187b3d4851eSEmmanuel Vadot 	sc = device_get_softc(dev);
1188b3d4851eSEmmanuel Vadot 	for (i = 0; i < sc->nregs; i++) {
1189b3d4851eSEmmanuel Vadot 		if (sc->regs[i] == NULL)
1190b3d4851eSEmmanuel Vadot 			continue;
1191b3d4851eSEmmanuel Vadot 		if (sc->regs[i]->xref == xref) {
1192b3d4851eSEmmanuel Vadot 			*num = sc->regs[i]->def->id;
1193b3d4851eSEmmanuel Vadot 			return (0);
1194b3d4851eSEmmanuel Vadot 		}
1195b3d4851eSEmmanuel Vadot 	}
1196b3d4851eSEmmanuel Vadot 
1197b3d4851eSEmmanuel Vadot 	return (ENXIO);
1198b3d4851eSEmmanuel Vadot }
1199b3d4851eSEmmanuel Vadot 
120030068a1dSEmmanuel Vadot static void
12016988dd5eSEmmanuel Vadot axp2xx_start(void *pdev)
120230068a1dSEmmanuel Vadot {
120330068a1dSEmmanuel Vadot 	device_t dev;
12046988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1205276b1ac9SAndrew Turner 	const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
12066988dd5eSEmmanuel Vadot 	int i;
12076988dd5eSEmmanuel Vadot 	uint8_t reg, data;
12082ff143afSAndrew Turner 	uint8_t pwr_src;
12092ff143afSAndrew Turner 
121030068a1dSEmmanuel Vadot 	dev = pdev;
12112ff143afSAndrew Turner 
121230068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
121330068a1dSEmmanuel Vadot 	sc->dev = dev;
12142ff143afSAndrew Turner 
1215276b1ac9SAndrew Turner 	if (bootverbose) {
12162ff143afSAndrew Turner 		/*
1217276b1ac9SAndrew Turner 		 * Read the Power State register.
1218276b1ac9SAndrew Turner 		 * Shift the AC presence into bit 0.
1219276b1ac9SAndrew Turner 		 * Shift the Battery presence into bit 1.
12202ff143afSAndrew Turner 		 */
12216988dd5eSEmmanuel Vadot 		axp2xx_read(dev, AXP2XX_PSR, &data, 1);
12226988dd5eSEmmanuel Vadot 		pwr_src = ((data & AXP2XX_PSR_ACIN) >> AXP2XX_PSR_ACIN_SHIFT) |
12236988dd5eSEmmanuel Vadot 		    ((data & AXP2XX_PSR_VBUS) >> (AXP2XX_PSR_VBUS_SHIFT - 1));
12242ff143afSAndrew Turner 
12256988dd5eSEmmanuel Vadot 		device_printf(dev, "Powered by %s\n",
12262ff143afSAndrew Turner 		    pwr_name[pwr_src]);
1227276b1ac9SAndrew Turner 	}
12282ff143afSAndrew Turner 
122930068a1dSEmmanuel Vadot 	/* Only enable interrupts that we are interested in */
12306988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ1_ENABLE,
12316988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_OVERVOLT |
12326988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_DISCONN |
12336988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_CONN |
12346988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_OVERVOLT |
12356988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_DISCONN |
12366988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_CONN);
12376988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ2_ENABLE,
12386988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CONN |
12396988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_DISCONN |
12406988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON |
12416988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF |
12426988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGING |
12436988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGED |
12446988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_OVER |
12456988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_LOW);
12466988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ3_ENABLE,
12476988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ3_PEK_SHORT | AXP2XX_IRQ3_PEK_LONG);
12486988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ4_ENABLE, AXP2XX_IRQ4_APS_LOW_2);
12496988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ5_ENABLE, 0x0);
125030068a1dSEmmanuel Vadot 
12516988dd5eSEmmanuel Vadot 	EVENTHANDLER_REGISTER(shutdown_final, axp2xx_shutdown, dev,
12522ff143afSAndrew Turner 	    SHUTDOWN_PRI_LAST);
12532ff143afSAndrew Turner 
125430068a1dSEmmanuel Vadot 	/* Enable ADC sensors */
12556988dd5eSEmmanuel Vadot 	for (i = 0; i < sc->nsensors; i++) {
12566988dd5eSEmmanuel Vadot 		if (axp2xx_read(dev, sc->sensors[i].enable_reg, &reg, 1) == -1) {
12576988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12586988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12596988dd5eSEmmanuel Vadot 			continue;
12606988dd5eSEmmanuel Vadot 		}
12616988dd5eSEmmanuel Vadot 		reg |= sc->sensors[i].enable_mask;
12626988dd5eSEmmanuel Vadot 		if (axp2xx_write(dev, sc->sensors[i].enable_reg, reg) == -1) {
12636988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12646988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12656988dd5eSEmmanuel Vadot 			continue;
12666988dd5eSEmmanuel Vadot 		}
126730068a1dSEmmanuel Vadot 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
126830068a1dSEmmanuel Vadot 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
12696988dd5eSEmmanuel Vadot 		    OID_AUTO, sc->sensors[i].name,
12708eea36aeSPawel Biernacki 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
12716988dd5eSEmmanuel Vadot 		    dev, sc->sensors[i].id, axp2xx_sysctl,
12726988dd5eSEmmanuel Vadot 		    sc->sensors[i].format,
12736988dd5eSEmmanuel Vadot 		    sc->sensors[i].desc);
127430068a1dSEmmanuel Vadot 	}
127530068a1dSEmmanuel Vadot 
127630068a1dSEmmanuel Vadot 	if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
12776988dd5eSEmmanuel Vadot 	      NULL, axp2xx_intr, sc, &sc->intrcookie)))
127830068a1dSEmmanuel Vadot 		device_printf(dev, "unable to register interrupt handler\n");
127930068a1dSEmmanuel Vadot 
128030068a1dSEmmanuel Vadot 	config_intrhook_disestablish(&sc->intr_hook);
128130068a1dSEmmanuel Vadot }
128230068a1dSEmmanuel Vadot 
128330068a1dSEmmanuel Vadot static int
12846988dd5eSEmmanuel Vadot axp2xx_probe(device_t dev)
128530068a1dSEmmanuel Vadot {
128630068a1dSEmmanuel Vadot 
128730068a1dSEmmanuel Vadot 	if (!ofw_bus_status_okay(dev))
128830068a1dSEmmanuel Vadot 		return (ENXIO);
128930068a1dSEmmanuel Vadot 
12906988dd5eSEmmanuel Vadot 	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
12916988dd5eSEmmanuel Vadot 	{
12926988dd5eSEmmanuel Vadot 	case AXP209:
129330068a1dSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
12946988dd5eSEmmanuel Vadot 		break;
12956988dd5eSEmmanuel Vadot 	case AXP221:
12966988dd5eSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP221 Power Management Unit");
12976988dd5eSEmmanuel Vadot 		break;
12986988dd5eSEmmanuel Vadot 	default:
12996988dd5eSEmmanuel Vadot 		return (ENXIO);
13006988dd5eSEmmanuel Vadot 	}
130130068a1dSEmmanuel Vadot 
130230068a1dSEmmanuel Vadot 	return (BUS_PROBE_DEFAULT);
130330068a1dSEmmanuel Vadot }
130430068a1dSEmmanuel Vadot 
130530068a1dSEmmanuel Vadot static int
13066988dd5eSEmmanuel Vadot axp2xx_attach(device_t dev)
130730068a1dSEmmanuel Vadot {
13086988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
13096988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg;
13106988dd5eSEmmanuel Vadot 	struct axp2xx_regdef *regdefs;
1311b3d4851eSEmmanuel Vadot 	phandle_t rnode, child;
1312b3d4851eSEmmanuel Vadot 	int i;
131330068a1dSEmmanuel Vadot 
131430068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
131530068a1dSEmmanuel Vadot 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
131630068a1dSEmmanuel Vadot 
131730068a1dSEmmanuel Vadot 	if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) {
131830068a1dSEmmanuel Vadot 		device_printf(dev, "can't allocate device resources\n");
131930068a1dSEmmanuel Vadot 		return (ENXIO);
132030068a1dSEmmanuel Vadot 	}
132130068a1dSEmmanuel Vadot 
13226988dd5eSEmmanuel Vadot 	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
13236988dd5eSEmmanuel Vadot 	switch (sc->type) {
13246988dd5eSEmmanuel Vadot 	case AXP209:
13256988dd5eSEmmanuel Vadot 		sc->pins = axp209_pins;
13266988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp209_pins);
13276988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13286988dd5eSEmmanuel Vadot 
13296988dd5eSEmmanuel Vadot 		sc->sensors = axp209_sensors;
13306988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp209_sensors);
13316988dd5eSEmmanuel Vadot 
13326988dd5eSEmmanuel Vadot 		regdefs = axp209_regdefs;
13336988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp209_regdefs);
13346988dd5eSEmmanuel Vadot 		break;
13356988dd5eSEmmanuel Vadot 	case AXP221:
13366988dd5eSEmmanuel Vadot 		sc->pins = axp221_pins;
13376988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp221_pins);
13386988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13396988dd5eSEmmanuel Vadot 
13406988dd5eSEmmanuel Vadot 		sc->sensors = axp221_sensors;
13416988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp221_sensors);
13426988dd5eSEmmanuel Vadot 
13436988dd5eSEmmanuel Vadot 		regdefs = axp221_regdefs;
13446988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp221_regdefs);
13456988dd5eSEmmanuel Vadot 		break;
13466988dd5eSEmmanuel Vadot 	}
13476988dd5eSEmmanuel Vadot 
13486988dd5eSEmmanuel Vadot 	sc->regs = malloc(sizeof(struct axp2xx_reg_sc *) * sc->nregs,
13496988dd5eSEmmanuel Vadot 	    M_AXP2XX_REG, M_WAITOK | M_ZERO);
13506988dd5eSEmmanuel Vadot 
13516988dd5eSEmmanuel Vadot 	sc->intr_hook.ich_func = axp2xx_start;
135230068a1dSEmmanuel Vadot 	sc->intr_hook.ich_arg = dev;
135330068a1dSEmmanuel Vadot 
135430068a1dSEmmanuel Vadot 	if (config_intrhook_establish(&sc->intr_hook) != 0)
135530068a1dSEmmanuel Vadot 		return (ENOMEM);
135630068a1dSEmmanuel Vadot 
1357b3d4851eSEmmanuel Vadot 	/* Attach known regulators that exist in the DT */
1358b3d4851eSEmmanuel Vadot 	rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
1359b3d4851eSEmmanuel Vadot 	if (rnode > 0) {
1360b3d4851eSEmmanuel Vadot 		for (i = 0; i < sc->nregs; i++) {
1361b3d4851eSEmmanuel Vadot 			child = ofw_bus_find_child(rnode,
13626988dd5eSEmmanuel Vadot 			    regdefs[i].name);
1363b3d4851eSEmmanuel Vadot 			if (child == 0)
1364b3d4851eSEmmanuel Vadot 				continue;
13656988dd5eSEmmanuel Vadot 			reg = axp2xx_reg_attach(dev, child, &regdefs[i]);
1366b3d4851eSEmmanuel Vadot 			if (reg == NULL) {
1367b3d4851eSEmmanuel Vadot 				device_printf(dev,
1368b3d4851eSEmmanuel Vadot 				    "cannot attach regulator %s\n",
13696988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1370b3d4851eSEmmanuel Vadot 				continue;
1371b3d4851eSEmmanuel Vadot 			}
1372b3d4851eSEmmanuel Vadot 			sc->regs[i] = reg;
13736988dd5eSEmmanuel Vadot 			if (bootverbose)
13746988dd5eSEmmanuel Vadot 				device_printf(dev, "Regulator %s attached\n",
13756988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1376b3d4851eSEmmanuel Vadot 		}
1377b3d4851eSEmmanuel Vadot 	}
1378b3d4851eSEmmanuel Vadot 
13792ff143afSAndrew Turner 	return (0);
13802ff143afSAndrew Turner }
13812ff143afSAndrew Turner 
13826988dd5eSEmmanuel Vadot static device_method_t axp2xx_methods[] = {
13836988dd5eSEmmanuel Vadot 	DEVMETHOD(device_probe,		axp2xx_probe),
13846988dd5eSEmmanuel Vadot 	DEVMETHOD(device_attach,	axp2xx_attach),
138530068a1dSEmmanuel Vadot 
138630068a1dSEmmanuel Vadot 	/* GPIO interface */
13876988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_get_bus,		axp2xx_gpio_get_bus),
13886988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_max,		axp2xx_gpio_pin_max),
13896988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getname,	axp2xx_gpio_pin_getname),
13906988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getcaps,	axp2xx_gpio_pin_getcaps),
13916988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getflags,	axp2xx_gpio_pin_getflags),
13926988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_setflags,	axp2xx_gpio_pin_setflags),
13936988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_get,		axp2xx_gpio_pin_get),
13946988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_set,		axp2xx_gpio_pin_set),
13956988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_toggle,	axp2xx_gpio_pin_toggle),
13966988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_map_gpios,	axp2xx_gpio_map_gpios),
139730068a1dSEmmanuel Vadot 
1398b3d4851eSEmmanuel Vadot 	/* Regdev interface */
13996988dd5eSEmmanuel Vadot 	DEVMETHOD(regdev_map,		axp2xx_regdev_map),
1400b3d4851eSEmmanuel Vadot 
140130068a1dSEmmanuel Vadot 	/* OFW bus interface */
14026988dd5eSEmmanuel Vadot 	DEVMETHOD(ofw_bus_get_node,	axp2xx_get_node),
140330068a1dSEmmanuel Vadot 
140430068a1dSEmmanuel Vadot 	DEVMETHOD_END
14052ff143afSAndrew Turner };
14062ff143afSAndrew Turner 
14076988dd5eSEmmanuel Vadot static driver_t axp2xx_driver = {
14086988dd5eSEmmanuel Vadot 	"axp2xx_pmu",
14096988dd5eSEmmanuel Vadot 	axp2xx_methods,
14106988dd5eSEmmanuel Vadot 	sizeof(struct axp2xx_softc),
14112ff143afSAndrew Turner };
14122ff143afSAndrew Turner 
141330068a1dSEmmanuel Vadot extern driver_t ofw_gpiobus_driver, gpioc_driver;
14142ff143afSAndrew Turner 
14157e1e2ba1SJohn Baldwin EARLY_DRIVER_MODULE(axp2xx, iicbus, axp2xx_driver, 0, 0,
14167e1e2ba1SJohn Baldwin     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
1417e8590c97SJohn Baldwin EARLY_DRIVER_MODULE(ofw_gpiobus, axp2xx_pmu, ofw_gpiobus_driver, 0, 0,
1418e8590c97SJohn Baldwin     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
1419d885615aSJohn Baldwin DRIVER_MODULE(gpioc, axp2xx_pmu, gpioc_driver, 0, 0);
14206988dd5eSEmmanuel Vadot MODULE_VERSION(axp2xx, 1);
1421094e5e7eSIan Lepore MODULE_DEPEND(axp2xx, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
1422