xref: /freebsd/sys/arm/allwinner/axp209.c (revision 6988dd5e)
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/iicbus.h>
512ff143afSAndrew Turner #include <dev/iicbus/iiconf.h>
522ff143afSAndrew Turner 
5330068a1dSEmmanuel Vadot #include <dev/gpio/gpiobusvar.h>
5430068a1dSEmmanuel Vadot 
552ff143afSAndrew Turner #include <dev/ofw/ofw_bus.h>
562ff143afSAndrew Turner #include <dev/ofw/ofw_bus_subr.h>
572ff143afSAndrew Turner 
58b3d4851eSEmmanuel Vadot #include <dev/extres/regulator/regulator.h>
59b3d4851eSEmmanuel Vadot 
6030068a1dSEmmanuel Vadot #include <arm/allwinner/axp209reg.h>
6130068a1dSEmmanuel Vadot 
622ff143afSAndrew Turner #include "iicbus_if.h"
6330068a1dSEmmanuel Vadot #include "gpio_if.h"
64b3d4851eSEmmanuel Vadot #include "regdev_if.h"
65b3d4851eSEmmanuel Vadot 
666988dd5eSEmmanuel Vadot MALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator");
67b3d4851eSEmmanuel Vadot 
686988dd5eSEmmanuel Vadot struct axp2xx_regdef {
69b3d4851eSEmmanuel Vadot 	intptr_t		id;
70b3d4851eSEmmanuel Vadot 	char			*name;
71b3d4851eSEmmanuel Vadot 	uint8_t			enable_reg;
72b3d4851eSEmmanuel Vadot 	uint8_t			enable_mask;
73b3d4851eSEmmanuel Vadot 	uint8_t			voltage_reg;
74b3d4851eSEmmanuel Vadot 	uint8_t			voltage_mask;
75b3d4851eSEmmanuel Vadot 	uint8_t			voltage_shift;
76b3d4851eSEmmanuel Vadot 	int			voltage_min;
77b3d4851eSEmmanuel Vadot 	int			voltage_max;
78b3d4851eSEmmanuel Vadot 	int			voltage_step;
79b3d4851eSEmmanuel Vadot 	int			voltage_nstep;
80b3d4851eSEmmanuel Vadot };
81b3d4851eSEmmanuel Vadot 
826988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp209_regdefs[] = {
83b3d4851eSEmmanuel Vadot 	{
84b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC2,
85b3d4851eSEmmanuel Vadot 		.name = "dcdc2",
86b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
87b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC2,
88b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC2_VOLTAGE,
89b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x3f,
90b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
91b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
92b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
93b3d4851eSEmmanuel Vadot 		.voltage_nstep = 64,
94b3d4851eSEmmanuel Vadot 	},
95b3d4851eSEmmanuel Vadot 	{
96b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC3,
97b3d4851eSEmmanuel Vadot 		.name = "dcdc3",
98b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
99b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC3,
100b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC3_VOLTAGE,
101b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
102b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
103b3d4851eSEmmanuel Vadot 		.voltage_max = 3500,
104b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
105b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
106b3d4851eSEmmanuel Vadot 	},
107b3d4851eSEmmanuel Vadot 	{
108b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO2,
109b3d4851eSEmmanuel Vadot 		.name = "ldo2",
110b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
111b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO2,
112b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO24_VOLTAGE,
113b3d4851eSEmmanuel Vadot 		.voltage_mask = 0xf0,
114b3d4851eSEmmanuel Vadot 		.voltage_shift = 4,
115b3d4851eSEmmanuel Vadot 		.voltage_min = 1800,
116b3d4851eSEmmanuel Vadot 		.voltage_max = 3300,
117b3d4851eSEmmanuel Vadot 		.voltage_step = 100,
118b3d4851eSEmmanuel Vadot 		.voltage_nstep = 16,
119b3d4851eSEmmanuel Vadot 	},
120b3d4851eSEmmanuel Vadot 	{
121b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO3,
122b3d4851eSEmmanuel Vadot 		.name = "ldo3",
123b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
124b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO3,
125b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO3_VOLTAGE,
126b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
127b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
128b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
129b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
130b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
131b3d4851eSEmmanuel Vadot 	},
132b3d4851eSEmmanuel Vadot };
133b3d4851eSEmmanuel Vadot 
1346988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp221_regdefs[] = {
1356988dd5eSEmmanuel Vadot 	{
1366988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO1,
1376988dd5eSEmmanuel Vadot 		.name = "dldo1",
1386988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1396988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO1,
1406988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO1_VOLTAGE,
1416988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1426988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1436988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1446988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1456988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1466988dd5eSEmmanuel Vadot 	},
1476988dd5eSEmmanuel Vadot 	{
1486988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO2,
1496988dd5eSEmmanuel Vadot 		.name = "dldo2",
1506988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1516988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO2,
1526988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO2_VOLTAGE,
1536988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1546988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1556988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1566988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1576988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1586988dd5eSEmmanuel Vadot 	},
1596988dd5eSEmmanuel Vadot 	{
1606988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO3,
1616988dd5eSEmmanuel Vadot 		.name = "dldo3",
1626988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1636988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO3,
1646988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO3_VOLTAGE,
1656988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1666988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1676988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1686988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1696988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1706988dd5eSEmmanuel Vadot 	},
1716988dd5eSEmmanuel Vadot 	{
1726988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO4,
1736988dd5eSEmmanuel Vadot 		.name = "dldo4",
1746988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1756988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO4,
1766988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO4_VOLTAGE,
1776988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1786988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1796988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1806988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1816988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1826988dd5eSEmmanuel Vadot 	},
1836988dd5eSEmmanuel Vadot 	{
1846988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO1,
1856988dd5eSEmmanuel Vadot 		.name = "eldo1",
1866988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1876988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO1,
1886988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO1_VOLTAGE,
1896988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1906988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1916988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1926988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1936988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1946988dd5eSEmmanuel Vadot 	},
1956988dd5eSEmmanuel Vadot 	{
1966988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO2,
1976988dd5eSEmmanuel Vadot 		.name = "eldo2",
1986988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1996988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO2,
2006988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO2_VOLTAGE,
2016988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2026988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2036988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2046988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2056988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2066988dd5eSEmmanuel Vadot 	},
2076988dd5eSEmmanuel Vadot 	{
2086988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO3,
2096988dd5eSEmmanuel Vadot 		.name = "eldo3",
2106988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
2116988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO3,
2126988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO3_VOLTAGE,
2136988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2146988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2156988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2166988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2176988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2186988dd5eSEmmanuel Vadot 	},
2196988dd5eSEmmanuel Vadot 	{
2206988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC5LDO,
2216988dd5eSEmmanuel Vadot 		.name = "dc5ldo",
2226988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2236988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DC5LDO,
2246988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DC5LDO_VOLTAGE,
2256988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3,
2266988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2276988dd5eSEmmanuel Vadot 		.voltage_max = 1400,
2286988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2296988dd5eSEmmanuel Vadot 		.voltage_nstep = 7,
2306988dd5eSEmmanuel Vadot 	},
2316988dd5eSEmmanuel Vadot 	{
2326988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC1,
2336988dd5eSEmmanuel Vadot 		.name = "dcdc1",
2346988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2356988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC1,
2366988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC1_VOLTAGE,
2376988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2386988dd5eSEmmanuel Vadot 		.voltage_min = 1600,
2396988dd5eSEmmanuel Vadot 		.voltage_max = 3400,
2406988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2416988dd5eSEmmanuel Vadot 		.voltage_nstep = 18,
2426988dd5eSEmmanuel Vadot 	},
2436988dd5eSEmmanuel Vadot 	{
2446988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC2,
2456988dd5eSEmmanuel Vadot 		.name = "dcdc2",
2466988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2476988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC2,
2486988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC2_VOLTAGE,
2496988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2506988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2516988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2526988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2536988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2546988dd5eSEmmanuel Vadot 	},
2556988dd5eSEmmanuel Vadot 	{
2566988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC3,
2576988dd5eSEmmanuel Vadot 		.name = "dcdc3",
2586988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2596988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC3,
2606988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC3_VOLTAGE,
2616988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2626988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2636988dd5eSEmmanuel Vadot 		.voltage_max = 1860,
2646988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2656988dd5eSEmmanuel Vadot 		.voltage_nstep = 63,
2666988dd5eSEmmanuel Vadot 	},
2676988dd5eSEmmanuel Vadot 	{
2686988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC4,
2696988dd5eSEmmanuel Vadot 		.name = "dcdc4",
2706988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2716988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC4,
2726988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC4_VOLTAGE,
2736988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2746988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2756988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2766988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2776988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2786988dd5eSEmmanuel Vadot 	},
2796988dd5eSEmmanuel Vadot 	{
2806988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC5,
2816988dd5eSEmmanuel Vadot 		.name = "dcdc5",
2826988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2836988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC5,
2846988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC5_VOLTAGE,
2856988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2866988dd5eSEmmanuel Vadot 		.voltage_min = 1000,
2876988dd5eSEmmanuel Vadot 		.voltage_max = 2550,
2886988dd5eSEmmanuel Vadot 		.voltage_step = 50,
2896988dd5eSEmmanuel Vadot 		.voltage_nstep = 31,
2906988dd5eSEmmanuel Vadot 	},
2916988dd5eSEmmanuel Vadot 	{
2926988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO1,
2936988dd5eSEmmanuel Vadot 		.name = "aldo1",
2946988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2956988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO1,
2966988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO1_VOLTAGE,
2976988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2986988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2996988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3006988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3016988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3026988dd5eSEmmanuel Vadot 	},
3036988dd5eSEmmanuel Vadot 	{
3046988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO2,
3056988dd5eSEmmanuel Vadot 		.name = "aldo2",
3066988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
3076988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO2,
3086988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO2_VOLTAGE,
3096988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3106988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3116988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3126988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3136988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3146988dd5eSEmmanuel Vadot 	},
3156988dd5eSEmmanuel Vadot 	{
3166988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO3,
3176988dd5eSEmmanuel Vadot 		.name = "aldo3",
3186988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_3,
3196988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL3_ALDO3,
3206988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO3_VOLTAGE,
3216988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3226988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3236988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3246988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3256988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3266988dd5eSEmmanuel Vadot 	},
3276988dd5eSEmmanuel Vadot 	{
3286988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC1SW,
3296988dd5eSEmmanuel Vadot 		.name = "dc1sw",
3306988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
3316988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DC1SW,
3326988dd5eSEmmanuel Vadot 	},
3336988dd5eSEmmanuel Vadot };
3346988dd5eSEmmanuel Vadot 
3356988dd5eSEmmanuel Vadot struct axp2xx_reg_sc {
336b3d4851eSEmmanuel Vadot 	struct regnode		*regnode;
337b3d4851eSEmmanuel Vadot 	device_t		base_dev;
3386988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*def;
339b3d4851eSEmmanuel Vadot 	phandle_t		xref;
340b3d4851eSEmmanuel Vadot 	struct regnode_std_param *param;
341b3d4851eSEmmanuel Vadot };
34286914a0fSAndrew Turner 
3436988dd5eSEmmanuel Vadot struct axp2xx_pins {
3446988dd5eSEmmanuel Vadot 	const char	*name;
3456988dd5eSEmmanuel Vadot 	uint8_t		ctrl_reg;
3466988dd5eSEmmanuel Vadot 	uint8_t		status_reg;
3476988dd5eSEmmanuel Vadot 	uint8_t		status_mask;
3486988dd5eSEmmanuel Vadot 	uint8_t		status_shift;
3496988dd5eSEmmanuel Vadot };
3506988dd5eSEmmanuel Vadot 
3516988dd5eSEmmanuel Vadot /* GPIO3 is different, don't expose it for now */
3526988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp209_pins[] = {
3536988dd5eSEmmanuel Vadot 	{
3546988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3556988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3566988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3576988dd5eSEmmanuel Vadot 		.status_mask = 0x10,
3586988dd5eSEmmanuel Vadot 		.status_shift = 4,
3596988dd5eSEmmanuel Vadot 	},
3606988dd5eSEmmanuel Vadot 	{
3616988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3626988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO1_CTRL,
3636988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3646988dd5eSEmmanuel Vadot 		.status_mask = 0x20,
3656988dd5eSEmmanuel Vadot 		.status_shift = 5,
3666988dd5eSEmmanuel Vadot 	},
3676988dd5eSEmmanuel Vadot 	{
3686988dd5eSEmmanuel Vadot 		.name = "GPIO2",
3696988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP209_GPIO2_CTRL,
3706988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3716988dd5eSEmmanuel Vadot 		.status_mask = 0x40,
3726988dd5eSEmmanuel Vadot 		.status_shift = 6,
3736988dd5eSEmmanuel Vadot 	},
3746988dd5eSEmmanuel Vadot };
3756988dd5eSEmmanuel Vadot 
3766988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp221_pins[] = {
3776988dd5eSEmmanuel Vadot 	{
3786988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3796988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3806988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3816988dd5eSEmmanuel Vadot 		.status_mask = 0x1,
3826988dd5eSEmmanuel Vadot 		.status_shift = 0x0,
3836988dd5eSEmmanuel Vadot 	},
3846988dd5eSEmmanuel Vadot 	{
3856988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3866988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3876988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3886988dd5eSEmmanuel Vadot 		.status_mask = 0x2,
3896988dd5eSEmmanuel Vadot 		.status_shift = 0x1,
3906988dd5eSEmmanuel Vadot 	},
3916988dd5eSEmmanuel Vadot };
3926988dd5eSEmmanuel Vadot 
3936988dd5eSEmmanuel Vadot struct axp2xx_sensors {
3946988dd5eSEmmanuel Vadot 	int		id;
3956988dd5eSEmmanuel Vadot 	const char	*name;
3966988dd5eSEmmanuel Vadot 	const char	*desc;
3976988dd5eSEmmanuel Vadot 	const char	*format;
3986988dd5eSEmmanuel Vadot 	uint8_t		enable_reg;
3996988dd5eSEmmanuel Vadot 	uint8_t		enable_mask;
4006988dd5eSEmmanuel Vadot 	uint8_t		value_reg;
4016988dd5eSEmmanuel Vadot 	uint8_t		value_size;
4026988dd5eSEmmanuel Vadot 	uint8_t		h_value_mask;
4036988dd5eSEmmanuel Vadot 	uint8_t		h_value_shift;
4046988dd5eSEmmanuel Vadot 	uint8_t		l_value_mask;
4056988dd5eSEmmanuel Vadot 	uint8_t		l_value_shift;
4066988dd5eSEmmanuel Vadot 	int		value_step;
4076988dd5eSEmmanuel Vadot 	int		value_convert;
4086988dd5eSEmmanuel Vadot };
4096988dd5eSEmmanuel Vadot 
4106988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp209_sensors[] = {
4116988dd5eSEmmanuel Vadot 	{
4126988dd5eSEmmanuel Vadot 		.id = AXP209_ACVOLT,
4136988dd5eSEmmanuel Vadot 		.name = "acvolt",
4146988dd5eSEmmanuel Vadot 		.desc = "AC Voltage (microvolt)",
4156988dd5eSEmmanuel Vadot 		.format = "I",
4166988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4176988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACVOLT,
4186988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_VOLTAGE,
4196988dd5eSEmmanuel Vadot 		.value_size = 2,
4206988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4216988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4226988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4236988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4246988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4256988dd5eSEmmanuel Vadot 	},
4266988dd5eSEmmanuel Vadot 	{
4276988dd5eSEmmanuel Vadot 		.id = AXP209_ACCURRENT,
4286988dd5eSEmmanuel Vadot 		.name = "accurrent",
4296988dd5eSEmmanuel Vadot 		.desc = "AC Current (microAmpere)",
4306988dd5eSEmmanuel Vadot 		.format = "I",
4316988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4326988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACCURRENT,
4336988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_CURRENT,
4346988dd5eSEmmanuel Vadot 		.value_size = 2,
4356988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4366988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4376988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4386988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4396988dd5eSEmmanuel Vadot 		.value_step = AXP209_ACCURRENT_STEP,
4406988dd5eSEmmanuel Vadot 	},
4416988dd5eSEmmanuel Vadot 	{
4426988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSVOLT,
4436988dd5eSEmmanuel Vadot 		.name = "vbusvolt",
4446988dd5eSEmmanuel Vadot 		.desc = "VBUS Voltage (microVolt)",
4456988dd5eSEmmanuel Vadot 		.format = "I",
4466988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4476988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSVOLT,
4486988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_VOLTAGE,
4496988dd5eSEmmanuel Vadot 		.value_size = 2,
4506988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4516988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4526988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4536988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4546988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4556988dd5eSEmmanuel Vadot 	},
4566988dd5eSEmmanuel Vadot 	{
4576988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSCURRENT,
4586988dd5eSEmmanuel Vadot 		.name = "vbuscurrent",
4596988dd5eSEmmanuel Vadot 		.desc = "VBUS Current (microAmpere)",
4606988dd5eSEmmanuel Vadot 		.format = "I",
4616988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4626988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSCURRENT,
4636988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_CURRENT,
4646988dd5eSEmmanuel Vadot 		.value_size = 2,
4656988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4666988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4676988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4686988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4696988dd5eSEmmanuel Vadot 		.value_step = AXP209_VBUSCURRENT_STEP,
4706988dd5eSEmmanuel Vadot 	},
4716988dd5eSEmmanuel Vadot 	{
4726988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
4736988dd5eSEmmanuel Vadot 		.name = "batvolt",
4746988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
4756988dd5eSEmmanuel Vadot 		.format = "I",
4766988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4776988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
4786988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
4796988dd5eSEmmanuel Vadot 		.value_size = 2,
4806988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4816988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4826988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4836988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4846988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
4856988dd5eSEmmanuel Vadot 	},
4866988dd5eSEmmanuel Vadot 	{
4876988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
4886988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
4896988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
4906988dd5eSEmmanuel Vadot 		.format = "I",
4916988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4926988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
4936988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
4946988dd5eSEmmanuel Vadot 		.value_size = 2,
4956988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4966988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
4976988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
4986988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4996988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5006988dd5eSEmmanuel Vadot 	},
5016988dd5eSEmmanuel Vadot 	{
5026988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
5036988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
5046988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5056988dd5eSEmmanuel Vadot 		.format = "I",
5066988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5076988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5086988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5096988dd5eSEmmanuel Vadot 		.value_size = 2,
5106988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5116988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5126988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5136988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5146988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5156988dd5eSEmmanuel Vadot 	},
5166988dd5eSEmmanuel Vadot 	{
5176988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5186988dd5eSEmmanuel Vadot 		.name = "temp",
5196988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5206988dd5eSEmmanuel Vadot 		.format = "IK",
5216988dd5eSEmmanuel Vadot 		.enable_reg = AXP209_ADC_ENABLE2,
5226988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC2_TEMP,
5236988dd5eSEmmanuel Vadot 		.value_reg = AXP209_TEMPMON,
5246988dd5eSEmmanuel Vadot 		.value_size = 2,
5256988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5266988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5276988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5286988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5296988dd5eSEmmanuel Vadot 		.value_step = 1,
5306988dd5eSEmmanuel Vadot 		.value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K),
5316988dd5eSEmmanuel Vadot 	},
5326988dd5eSEmmanuel Vadot };
5336988dd5eSEmmanuel Vadot 
5346988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp221_sensors[] = {
5356988dd5eSEmmanuel Vadot 	{
5366988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
5376988dd5eSEmmanuel Vadot 		.name = "batvolt",
5386988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
5396988dd5eSEmmanuel Vadot 		.format = "I",
5406988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5416988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
5426988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
5436988dd5eSEmmanuel Vadot 		.value_size = 2,
5446988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5456988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5466988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5476988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5486988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
5496988dd5eSEmmanuel Vadot 	},
5506988dd5eSEmmanuel Vadot 	{
5516988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
5526988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
5536988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
5546988dd5eSEmmanuel Vadot 		.format = "I",
5556988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5566988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5576988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
5586988dd5eSEmmanuel Vadot 		.value_size = 2,
5596988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5606988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5616988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5626988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5636988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5646988dd5eSEmmanuel Vadot 	},
5656988dd5eSEmmanuel Vadot 	{
5666988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
5676988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
5686988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5696988dd5eSEmmanuel Vadot 		.format = "I",
5706988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5716988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5726988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5736988dd5eSEmmanuel Vadot 		.value_size = 2,
5746988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5756988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5766988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5776988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5786988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5796988dd5eSEmmanuel Vadot 	},
5806988dd5eSEmmanuel Vadot 	{
5816988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5826988dd5eSEmmanuel Vadot 		.name = "temp",
5836988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5846988dd5eSEmmanuel Vadot 		.format = "IK",
5856988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5866988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_ADC1_TEMP,
5876988dd5eSEmmanuel Vadot 		.value_reg = AXP221_TEMPMON,
5886988dd5eSEmmanuel Vadot 		.value_size = 2,
5896988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5906988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5916988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5926988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5936988dd5eSEmmanuel Vadot 		.value_step = 1,
5946988dd5eSEmmanuel Vadot 		.value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K),
5956988dd5eSEmmanuel Vadot 	},
5966988dd5eSEmmanuel Vadot };
5976988dd5eSEmmanuel Vadot 
5986988dd5eSEmmanuel Vadot enum AXP2XX_TYPE {
5996988dd5eSEmmanuel Vadot 	AXP209 = 1,
6006988dd5eSEmmanuel Vadot 	AXP221,
6016988dd5eSEmmanuel Vadot };
6026988dd5eSEmmanuel Vadot 
6036988dd5eSEmmanuel Vadot struct axp2xx_softc {
60430068a1dSEmmanuel Vadot 	device_t		dev;
6052ff143afSAndrew Turner 	uint32_t		addr;
60630068a1dSEmmanuel Vadot 	struct resource *	res[1];
60730068a1dSEmmanuel Vadot 	void *			intrcookie;
60830068a1dSEmmanuel Vadot 	struct intr_config_hook	intr_hook;
60930068a1dSEmmanuel Vadot 	struct mtx		mtx;
6106988dd5eSEmmanuel Vadot 	uint8_t			type;
6116988dd5eSEmmanuel Vadot 
6126988dd5eSEmmanuel Vadot 	/* GPIO */
6136988dd5eSEmmanuel Vadot 	device_t		gpiodev;
6146988dd5eSEmmanuel Vadot 	int			npins;
6156988dd5eSEmmanuel Vadot 	const struct axp2xx_pins	*pins;
6166988dd5eSEmmanuel Vadot 
6176988dd5eSEmmanuel Vadot 	/* Sensors */
6186988dd5eSEmmanuel Vadot 	const struct axp2xx_sensors	*sensors;
6196988dd5eSEmmanuel Vadot 	int				nsensors;
620b3d4851eSEmmanuel Vadot 
621b3d4851eSEmmanuel Vadot 	/* Regulators */
6226988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc	**regs;
623b3d4851eSEmmanuel Vadot 	int			nregs;
6246988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*regdefs;
6252ff143afSAndrew Turner };
6262ff143afSAndrew Turner 
6276988dd5eSEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
6286988dd5eSEmmanuel Vadot 	{ "x-powers,axp209",		AXP209 },
6296988dd5eSEmmanuel Vadot 	{ "x-powers,axp221",		AXP221 },
6306988dd5eSEmmanuel Vadot 	{ NULL,				0 }
63186914a0fSAndrew Turner };
63286914a0fSAndrew Turner 
63330068a1dSEmmanuel Vadot static struct resource_spec axp_res_spec[] = {
63430068a1dSEmmanuel Vadot 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
63530068a1dSEmmanuel Vadot 	{ -1,			0,	0 }
63630068a1dSEmmanuel Vadot };
63730068a1dSEmmanuel Vadot 
63830068a1dSEmmanuel Vadot #define	AXP_LOCK(sc)	mtx_lock(&(sc)->mtx)
63930068a1dSEmmanuel Vadot #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
64030068a1dSEmmanuel Vadot 
6412ff143afSAndrew Turner static int
6426988dd5eSEmmanuel Vadot axp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
6432ff143afSAndrew Turner {
6446988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc = device_get_softc(dev);
6452ff143afSAndrew Turner 	struct iic_msg msg[2];
6462ff143afSAndrew Turner 
6472ff143afSAndrew Turner 	msg[0].slave = sc->addr;
6482ff143afSAndrew Turner 	msg[0].flags = IIC_M_WR;
6492ff143afSAndrew Turner 	msg[0].len = 1;
6502ff143afSAndrew Turner 	msg[0].buf = &reg;
6512ff143afSAndrew Turner 
6522ff143afSAndrew Turner 	msg[1].slave = sc->addr;
6532ff143afSAndrew Turner 	msg[1].flags = IIC_M_RD;
6542ff143afSAndrew Turner 	msg[1].len = size;
6552ff143afSAndrew Turner 	msg[1].buf = data;
6562ff143afSAndrew Turner 
6572ff143afSAndrew Turner 	return (iicbus_transfer(dev, msg, 2));
6582ff143afSAndrew Turner }
6592ff143afSAndrew Turner 
6602ff143afSAndrew Turner static int
6616988dd5eSEmmanuel Vadot axp2xx_write(device_t dev, uint8_t reg, uint8_t data)
6622ff143afSAndrew Turner {
6632ff143afSAndrew Turner 	uint8_t buffer[2];
6646988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc = device_get_softc(dev);
6656988dd5eSEmmanuel Vadot 	struct iic_msg msg[2];
6666988dd5eSEmmanuel Vadot 	int nmsgs = 0;
6672ff143afSAndrew Turner 
6686988dd5eSEmmanuel Vadot 	if (sc->type == AXP209) {
6692ff143afSAndrew Turner 		buffer[0] = reg;
6702ff143afSAndrew Turner 		buffer[1] = data;
6712ff143afSAndrew Turner 
6726988dd5eSEmmanuel Vadot 		msg[0].slave = sc->addr;
6736988dd5eSEmmanuel Vadot 		msg[0].flags = IIC_M_WR;
6746988dd5eSEmmanuel Vadot 		msg[0].len = 2;
6756988dd5eSEmmanuel Vadot 		msg[0].buf = buffer;
6762ff143afSAndrew Turner 
6776988dd5eSEmmanuel Vadot 		nmsgs = 1;
6786988dd5eSEmmanuel Vadot 	}
6796988dd5eSEmmanuel Vadot 	else if (sc->type == AXP221) {
6806988dd5eSEmmanuel Vadot 		msg[0].slave = sc->addr;
6816988dd5eSEmmanuel Vadot 		msg[0].flags = IIC_M_WR;
6826988dd5eSEmmanuel Vadot 		msg[0].len = 1;
6836988dd5eSEmmanuel Vadot 		msg[0].buf = &reg;
6846988dd5eSEmmanuel Vadot 
6856988dd5eSEmmanuel Vadot 		msg[1].slave = sc->addr;
6866988dd5eSEmmanuel Vadot 		msg[1].flags = IIC_M_WR;
6876988dd5eSEmmanuel Vadot 		msg[1].len = 1;
6886988dd5eSEmmanuel Vadot 		msg[1].buf = &data;
6896988dd5eSEmmanuel Vadot 		nmsgs = 2;
6906988dd5eSEmmanuel Vadot 	}
6916988dd5eSEmmanuel Vadot 	else
6926988dd5eSEmmanuel Vadot 		return (EINVAL);
6936988dd5eSEmmanuel Vadot 
6946988dd5eSEmmanuel Vadot 	return (iicbus_transfer(dev, msg, nmsgs));
6952ff143afSAndrew Turner }
6962ff143afSAndrew Turner 
69786914a0fSAndrew Turner static int
6986988dd5eSEmmanuel Vadot axp2xx_regnode_init(struct regnode *regnode)
699b3d4851eSEmmanuel Vadot {
700b3d4851eSEmmanuel Vadot 	return (0);
701b3d4851eSEmmanuel Vadot }
702b3d4851eSEmmanuel Vadot 
703b3d4851eSEmmanuel Vadot static int
7046988dd5eSEmmanuel Vadot axp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
705b3d4851eSEmmanuel Vadot {
7066988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
707b3d4851eSEmmanuel Vadot 	uint8_t val;
708b3d4851eSEmmanuel Vadot 
709b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
710b3d4851eSEmmanuel Vadot 
7116988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
712b3d4851eSEmmanuel Vadot 	if (enable)
713b3d4851eSEmmanuel Vadot 		val |= sc->def->enable_mask;
714b3d4851eSEmmanuel Vadot 	else
715b3d4851eSEmmanuel Vadot 		val &= ~sc->def->enable_mask;
7166988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->enable_reg, val);
717b3d4851eSEmmanuel Vadot 
718b3d4851eSEmmanuel Vadot 	*udelay = 0;
719b3d4851eSEmmanuel Vadot 
720b3d4851eSEmmanuel Vadot 	return (0);
721b3d4851eSEmmanuel Vadot }
722b3d4851eSEmmanuel Vadot 
723b3d4851eSEmmanuel Vadot static void
7246988dd5eSEmmanuel Vadot axp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv)
725b3d4851eSEmmanuel Vadot {
726b3d4851eSEmmanuel Vadot 	if (val < sc->def->voltage_nstep)
727b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min + val * sc->def->voltage_step;
728b3d4851eSEmmanuel Vadot 	else
729b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min +
730b3d4851eSEmmanuel Vadot 		       (sc->def->voltage_nstep * sc->def->voltage_step);
731b3d4851eSEmmanuel Vadot 	*uv *= 1000;
732b3d4851eSEmmanuel Vadot }
733b3d4851eSEmmanuel Vadot 
734b3d4851eSEmmanuel Vadot static int
7356988dd5eSEmmanuel Vadot axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt,
736b3d4851eSEmmanuel Vadot     int max_uvolt, uint8_t *val)
737b3d4851eSEmmanuel Vadot {
738b3d4851eSEmmanuel Vadot 	uint8_t nval;
739b3d4851eSEmmanuel Vadot 	int nstep, uvolt;
740b3d4851eSEmmanuel Vadot 
741b3d4851eSEmmanuel Vadot 	nval = 0;
742b3d4851eSEmmanuel Vadot 	uvolt = sc->def->voltage_min * 1000;
743b3d4851eSEmmanuel Vadot 
744b3d4851eSEmmanuel Vadot 	for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
745b3d4851eSEmmanuel Vadot 	     nstep++) {
746b3d4851eSEmmanuel Vadot 		++nval;
747b3d4851eSEmmanuel Vadot 		uvolt += (sc->def->voltage_step * 1000);
748b3d4851eSEmmanuel Vadot 	}
749b3d4851eSEmmanuel Vadot 	if (uvolt > max_uvolt)
750b3d4851eSEmmanuel Vadot 		return (EINVAL);
751b3d4851eSEmmanuel Vadot 
752b3d4851eSEmmanuel Vadot 	*val = nval;
753b3d4851eSEmmanuel Vadot 	return (0);
754b3d4851eSEmmanuel Vadot }
755b3d4851eSEmmanuel Vadot 
756b3d4851eSEmmanuel Vadot static int
7576988dd5eSEmmanuel Vadot axp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
758b3d4851eSEmmanuel Vadot     int max_uvolt, int *udelay)
759b3d4851eSEmmanuel Vadot {
7606988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
761b3d4851eSEmmanuel Vadot 	uint8_t val;
762b3d4851eSEmmanuel Vadot 
763b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
764b3d4851eSEmmanuel Vadot 
765b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
766b3d4851eSEmmanuel Vadot 		return (ENXIO);
767b3d4851eSEmmanuel Vadot 
7686988dd5eSEmmanuel Vadot 	if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
769b3d4851eSEmmanuel Vadot 		return (ERANGE);
770b3d4851eSEmmanuel Vadot 
7716988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->voltage_reg, val);
772b3d4851eSEmmanuel Vadot 
773b3d4851eSEmmanuel Vadot 	*udelay = 0;
774b3d4851eSEmmanuel Vadot 
775b3d4851eSEmmanuel Vadot 	return (0);
776b3d4851eSEmmanuel Vadot }
777b3d4851eSEmmanuel Vadot 
778b3d4851eSEmmanuel Vadot static int
7796988dd5eSEmmanuel Vadot axp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
780b3d4851eSEmmanuel Vadot {
7816988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
782b3d4851eSEmmanuel Vadot 	uint8_t val;
783b3d4851eSEmmanuel Vadot 
784b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
785b3d4851eSEmmanuel Vadot 
786b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
787b3d4851eSEmmanuel Vadot 		return (ENXIO);
788b3d4851eSEmmanuel Vadot 
7896988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
7906988dd5eSEmmanuel Vadot 	axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
791b3d4851eSEmmanuel Vadot 
792b3d4851eSEmmanuel Vadot 	return (0);
793b3d4851eSEmmanuel Vadot }
794b3d4851eSEmmanuel Vadot 
7956988dd5eSEmmanuel Vadot static regnode_method_t axp2xx_regnode_methods[] = {
796b3d4851eSEmmanuel Vadot 	/* Regulator interface */
7976988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_init,		axp2xx_regnode_init),
7986988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_enable,		axp2xx_regnode_enable),
7996988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_set_voltage,	axp2xx_regnode_set_voltage),
8006988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_get_voltage,	axp2xx_regnode_get_voltage),
801b3d4851eSEmmanuel Vadot 	REGNODEMETHOD_END
802b3d4851eSEmmanuel Vadot };
8036988dd5eSEmmanuel Vadot DEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods,
8046988dd5eSEmmanuel Vadot     sizeof(struct axp2xx_reg_sc), regnode_class);
805b3d4851eSEmmanuel Vadot 
806b3d4851eSEmmanuel Vadot static int
8076988dd5eSEmmanuel Vadot axp2xx_sysctl(SYSCTL_HANDLER_ARGS)
80886914a0fSAndrew Turner {
8096988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
81086914a0fSAndrew Turner 	device_t dev = arg1;
8116988dd5eSEmmanuel Vadot 	enum axp2xx_sensor sensor = arg2;
81286914a0fSAndrew Turner 	uint8_t data[2];
8136988dd5eSEmmanuel Vadot 	int val, error, i, found;
81486914a0fSAndrew Turner 
8156988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
81686914a0fSAndrew Turner 
8176988dd5eSEmmanuel Vadot 	for (found = 0, i = 0; i < sc->nsensors; i++) {
8186988dd5eSEmmanuel Vadot 		if (sc->sensors[i].id == sensor) {
8196988dd5eSEmmanuel Vadot 			found = 1;
82030068a1dSEmmanuel Vadot 			break;
82130068a1dSEmmanuel Vadot 		}
8226988dd5eSEmmanuel Vadot 	}
8236988dd5eSEmmanuel Vadot 
8246988dd5eSEmmanuel Vadot 	if (found == 0)
8256988dd5eSEmmanuel Vadot 		return (ENOENT);
8266988dd5eSEmmanuel Vadot 
8276988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2);
8286988dd5eSEmmanuel Vadot 	if (error != 0)
8296988dd5eSEmmanuel Vadot 		return (error);
8306988dd5eSEmmanuel Vadot 
8316988dd5eSEmmanuel Vadot 	val = ((data[0] & sc->sensors[i].h_value_mask) <<
8326988dd5eSEmmanuel Vadot 	    sc->sensors[i].h_value_shift);
8336988dd5eSEmmanuel Vadot 	val |= ((data[1] & sc->sensors[i].l_value_mask) <<
8346988dd5eSEmmanuel Vadot 	    sc->sensors[i].l_value_shift);
8356988dd5eSEmmanuel Vadot 	val *= sc->sensors[i].value_step;
8366988dd5eSEmmanuel Vadot 	val += sc->sensors[i].value_convert;
83786914a0fSAndrew Turner 
83886914a0fSAndrew Turner 	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
83986914a0fSAndrew Turner }
84086914a0fSAndrew Turner 
8412ff143afSAndrew Turner static void
8426988dd5eSEmmanuel Vadot axp2xx_shutdown(void *devp, int howto)
8432ff143afSAndrew Turner {
8442ff143afSAndrew Turner 	device_t dev;
8452ff143afSAndrew Turner 
8462ff143afSAndrew Turner 	if (!(howto & RB_POWEROFF))
8472ff143afSAndrew Turner 		return;
8482ff143afSAndrew Turner 	dev = (device_t)devp;
8492ff143afSAndrew Turner 
8502ff143afSAndrew Turner 	if (bootverbose)
8516988dd5eSEmmanuel Vadot 		device_printf(dev, "Shutdown AXP2xx\n");
8522ff143afSAndrew Turner 
8536988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN);
8542ff143afSAndrew Turner }
8552ff143afSAndrew Turner 
85630068a1dSEmmanuel Vadot static void
8576988dd5eSEmmanuel Vadot axp2xx_intr(void *arg)
8582ff143afSAndrew Turner {
8596988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
86030068a1dSEmmanuel Vadot 	uint8_t reg;
8612ff143afSAndrew Turner 
86230068a1dSEmmanuel Vadot 	sc = arg;
8632ff143afSAndrew Turner 
8646988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, &reg, 1);
86530068a1dSEmmanuel Vadot 	if (reg) {
8666988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_OVERVOLT)
86730068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "overvoltage", NULL);
8686988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT)
86930068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "overvoltage", NULL);
8706988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_LOW)
87130068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "undervoltage", NULL);
8726988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_CONN)
87330068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "plugged", NULL);
8746988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_DISCONN)
87530068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "unplugged", NULL);
8766988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_CONN)
87730068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "plugged", NULL);
8786988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_DISCONN)
87930068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "unplugged", NULL);
8806988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK);
88130068a1dSEmmanuel Vadot 	}
8822ff143afSAndrew Turner 
8836988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, &reg, 1);
88430068a1dSEmmanuel Vadot 	if (reg) {
8856988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGED)
88630068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charged", NULL);
8876988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGING)
88830068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charging", NULL);
8896988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CONN)
89030068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "connected", NULL);
8916988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_DISCONN)
89230068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "disconnected", NULL);
8936988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW)
89430068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "low temp", NULL);
8956988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER)
89630068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "high temp", NULL);
8976988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK);
89830068a1dSEmmanuel Vadot 	}
8992ff143afSAndrew Turner 
9006988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, &reg, 1);
90130068a1dSEmmanuel Vadot 	if (reg) {
9026988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ3_PEK_SHORT)
90330068a1dSEmmanuel Vadot 			shutdown_nice(RB_POWEROFF);
9046988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK);
90530068a1dSEmmanuel Vadot 	}
90630068a1dSEmmanuel Vadot 
9076988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, &reg, 1);
90830068a1dSEmmanuel Vadot 	if (reg) {
9096988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK);
91030068a1dSEmmanuel Vadot 	}
91130068a1dSEmmanuel Vadot 
9126988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, &reg, 1);
91330068a1dSEmmanuel Vadot 	if (reg) {
9146988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK);
91530068a1dSEmmanuel Vadot 	}
91630068a1dSEmmanuel Vadot }
91730068a1dSEmmanuel Vadot 
91830068a1dSEmmanuel Vadot static device_t
9196988dd5eSEmmanuel Vadot axp2xx_gpio_get_bus(device_t dev)
92030068a1dSEmmanuel Vadot {
9216988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
92230068a1dSEmmanuel Vadot 
92330068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
92430068a1dSEmmanuel Vadot 
92530068a1dSEmmanuel Vadot 	return (sc->gpiodev);
9262ff143afSAndrew Turner }
9272ff143afSAndrew Turner 
9282ff143afSAndrew Turner static int
9296988dd5eSEmmanuel Vadot axp2xx_gpio_pin_max(device_t dev, int *maxpin)
9302ff143afSAndrew Turner {
9316988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9326988dd5eSEmmanuel Vadot 
9336988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9346988dd5eSEmmanuel Vadot 
9356988dd5eSEmmanuel Vadot 	*maxpin = sc->npins - 1;
93630068a1dSEmmanuel Vadot 
93730068a1dSEmmanuel Vadot 	return (0);
93830068a1dSEmmanuel Vadot }
93930068a1dSEmmanuel Vadot 
94030068a1dSEmmanuel Vadot static int
9416988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
94230068a1dSEmmanuel Vadot {
9436988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9446988dd5eSEmmanuel Vadot 
9456988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9466988dd5eSEmmanuel Vadot 
9476988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
94830068a1dSEmmanuel Vadot 		return (EINVAL);
94930068a1dSEmmanuel Vadot 
95030068a1dSEmmanuel Vadot 	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
95130068a1dSEmmanuel Vadot 
95230068a1dSEmmanuel Vadot 	return (0);
95330068a1dSEmmanuel Vadot }
95430068a1dSEmmanuel Vadot 
95530068a1dSEmmanuel Vadot static int
9566988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
95730068a1dSEmmanuel Vadot {
9586988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9596988dd5eSEmmanuel Vadot 
9606988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9616988dd5eSEmmanuel Vadot 
9626988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
96330068a1dSEmmanuel Vadot 		return (EINVAL);
96430068a1dSEmmanuel Vadot 
96530068a1dSEmmanuel Vadot 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
96630068a1dSEmmanuel Vadot 
96730068a1dSEmmanuel Vadot 	return (0);
96830068a1dSEmmanuel Vadot }
96930068a1dSEmmanuel Vadot 
97030068a1dSEmmanuel Vadot static int
9716988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
97230068a1dSEmmanuel Vadot {
9736988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
97430068a1dSEmmanuel Vadot 	uint8_t data, func;
97530068a1dSEmmanuel Vadot 	int error;
97630068a1dSEmmanuel Vadot 
97730068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
97830068a1dSEmmanuel Vadot 
9796988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9806988dd5eSEmmanuel Vadot 		return (EINVAL);
9816988dd5eSEmmanuel Vadot 
98230068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9836988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
98430068a1dSEmmanuel Vadot 	if (error == 0) {
9856988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
9866988dd5eSEmmanuel Vadot 		if (func == AXP2XX_GPIO_FUNC_INPUT)
98730068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_INPUT;
9886988dd5eSEmmanuel Vadot 		else if (func == AXP2XX_GPIO_FUNC_DRVLO ||
9896988dd5eSEmmanuel Vadot 		    func == AXP2XX_GPIO_FUNC_DRVHI)
99030068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_OUTPUT;
99130068a1dSEmmanuel Vadot 		else
99230068a1dSEmmanuel Vadot 			*flags = 0;
99330068a1dSEmmanuel Vadot 	}
99430068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
99530068a1dSEmmanuel Vadot 
99630068a1dSEmmanuel Vadot 	return (error);
99730068a1dSEmmanuel Vadot }
99830068a1dSEmmanuel Vadot 
99930068a1dSEmmanuel Vadot static int
10006988dd5eSEmmanuel Vadot axp2xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
100130068a1dSEmmanuel Vadot {
10026988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
100330068a1dSEmmanuel Vadot 	uint8_t data;
100430068a1dSEmmanuel Vadot 	int error;
100530068a1dSEmmanuel Vadot 
100630068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
100730068a1dSEmmanuel Vadot 
10086988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10096988dd5eSEmmanuel Vadot 		return (EINVAL);
10106988dd5eSEmmanuel Vadot 
101130068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10126988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
101330068a1dSEmmanuel Vadot 	if (error == 0) {
10146988dd5eSEmmanuel Vadot 		data &= ~AXP2XX_GPIO_FUNC_MASK;
101530068a1dSEmmanuel Vadot 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
101630068a1dSEmmanuel Vadot 			if ((flags & GPIO_PIN_OUTPUT) == 0)
10176988dd5eSEmmanuel Vadot 				data |= AXP2XX_GPIO_FUNC_INPUT;
101830068a1dSEmmanuel Vadot 		}
10196988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
102030068a1dSEmmanuel Vadot 	}
102130068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
102230068a1dSEmmanuel Vadot 
102330068a1dSEmmanuel Vadot 	return (error);
102430068a1dSEmmanuel Vadot }
102530068a1dSEmmanuel Vadot 
102630068a1dSEmmanuel Vadot static int
10276988dd5eSEmmanuel Vadot axp2xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
102830068a1dSEmmanuel Vadot {
10296988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
103030068a1dSEmmanuel Vadot 	uint8_t data, func;
103130068a1dSEmmanuel Vadot 	int error;
103230068a1dSEmmanuel Vadot 
103330068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
103430068a1dSEmmanuel Vadot 
10356988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10366988dd5eSEmmanuel Vadot 		return (EINVAL);
10376988dd5eSEmmanuel Vadot 
103830068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10396988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
104030068a1dSEmmanuel Vadot 	if (error == 0) {
10416988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
104230068a1dSEmmanuel Vadot 		switch (func) {
10436988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
104430068a1dSEmmanuel Vadot 			*val = 0;
104530068a1dSEmmanuel Vadot 			break;
10466988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
104730068a1dSEmmanuel Vadot 			*val = 1;
104830068a1dSEmmanuel Vadot 			break;
10496988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_INPUT:
10506988dd5eSEmmanuel Vadot 			error = axp2xx_read(dev, sc->pins[pin].status_reg,
10516988dd5eSEmmanuel Vadot 			    &data, 1);
10526988dd5eSEmmanuel Vadot 			if (error == 0) {
10536988dd5eSEmmanuel Vadot 				*val = (data & sc->pins[pin].status_mask);
10546988dd5eSEmmanuel Vadot 				*val >>= sc->pins[pin].status_shift;
10556988dd5eSEmmanuel Vadot 			}
105630068a1dSEmmanuel Vadot 			break;
105730068a1dSEmmanuel Vadot 		default:
105830068a1dSEmmanuel Vadot 			error = EIO;
105930068a1dSEmmanuel Vadot 			break;
106030068a1dSEmmanuel Vadot 		}
106130068a1dSEmmanuel Vadot 	}
106230068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
106330068a1dSEmmanuel Vadot 
106430068a1dSEmmanuel Vadot 	return (error);
106530068a1dSEmmanuel Vadot }
106630068a1dSEmmanuel Vadot 
106730068a1dSEmmanuel Vadot static int
10686988dd5eSEmmanuel Vadot axp2xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
106930068a1dSEmmanuel Vadot {
10706988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
107130068a1dSEmmanuel Vadot 	uint8_t data, func;
107230068a1dSEmmanuel Vadot 	int error;
107330068a1dSEmmanuel Vadot 
107430068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
107530068a1dSEmmanuel Vadot 
10766988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10776988dd5eSEmmanuel Vadot 		return (EINVAL);
10786988dd5eSEmmanuel Vadot 
107930068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10806988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
108130068a1dSEmmanuel Vadot 	if (error == 0) {
10826988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
108330068a1dSEmmanuel Vadot 		switch (func) {
10846988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
10856988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
108630068a1dSEmmanuel Vadot 			/* GPIO2 can't be set to 1 */
108730068a1dSEmmanuel Vadot 			if (pin == 2 && val == 1) {
108830068a1dSEmmanuel Vadot 				error = EINVAL;
108930068a1dSEmmanuel Vadot 				break;
109030068a1dSEmmanuel Vadot 			}
10916988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
109230068a1dSEmmanuel Vadot 			data |= val;
109330068a1dSEmmanuel Vadot 			break;
109430068a1dSEmmanuel Vadot 		default:
109530068a1dSEmmanuel Vadot 			error = EIO;
109630068a1dSEmmanuel Vadot 			break;
109730068a1dSEmmanuel Vadot 		}
109830068a1dSEmmanuel Vadot 	}
109930068a1dSEmmanuel Vadot 	if (error == 0)
11006988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
110130068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
110230068a1dSEmmanuel Vadot 
110330068a1dSEmmanuel Vadot 	return (error);
110430068a1dSEmmanuel Vadot }
110530068a1dSEmmanuel Vadot 
110630068a1dSEmmanuel Vadot 
110730068a1dSEmmanuel Vadot static int
11086988dd5eSEmmanuel Vadot axp2xx_gpio_pin_toggle(device_t dev, uint32_t pin)
110930068a1dSEmmanuel Vadot {
11106988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
111130068a1dSEmmanuel Vadot 	uint8_t data, func;
111230068a1dSEmmanuel Vadot 	int error;
111330068a1dSEmmanuel Vadot 
111430068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
111530068a1dSEmmanuel Vadot 
11166988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
11176988dd5eSEmmanuel Vadot 		return (EINVAL);
11186988dd5eSEmmanuel Vadot 
111930068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
11206988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
112130068a1dSEmmanuel Vadot 	if (error == 0) {
11226988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
112330068a1dSEmmanuel Vadot 		switch (func) {
11246988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
112530068a1dSEmmanuel Vadot 			/* Pin 2 can't be set to 1*/
112630068a1dSEmmanuel Vadot 			if (pin == 2) {
112730068a1dSEmmanuel Vadot 				error = EINVAL;
112830068a1dSEmmanuel Vadot 				break;
112930068a1dSEmmanuel Vadot 			}
11306988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
11316988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVHI;
113230068a1dSEmmanuel Vadot 			break;
11336988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
11346988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
11356988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVLO;
113630068a1dSEmmanuel Vadot 			break;
113730068a1dSEmmanuel Vadot 		default:
113830068a1dSEmmanuel Vadot 			error = EIO;
113930068a1dSEmmanuel Vadot 			break;
114030068a1dSEmmanuel Vadot 		}
114130068a1dSEmmanuel Vadot 	}
114230068a1dSEmmanuel Vadot 	if (error == 0)
11436988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
114430068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
114530068a1dSEmmanuel Vadot 
114630068a1dSEmmanuel Vadot 	return (error);
114730068a1dSEmmanuel Vadot }
114830068a1dSEmmanuel Vadot 
114930068a1dSEmmanuel Vadot static int
11506988dd5eSEmmanuel Vadot axp2xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
115130068a1dSEmmanuel Vadot     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
115230068a1dSEmmanuel Vadot {
11536988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
11546988dd5eSEmmanuel Vadot 
11556988dd5eSEmmanuel Vadot 	sc = device_get_softc(bus);
11566988dd5eSEmmanuel Vadot 
11576988dd5eSEmmanuel Vadot 	if (gpios[0] >= sc->npins)
115830068a1dSEmmanuel Vadot 		return (EINVAL);
115930068a1dSEmmanuel Vadot 
116030068a1dSEmmanuel Vadot 	*pin = gpios[0];
116130068a1dSEmmanuel Vadot 	*flags = gpios[1];
116230068a1dSEmmanuel Vadot 
116330068a1dSEmmanuel Vadot 	return (0);
116430068a1dSEmmanuel Vadot }
116530068a1dSEmmanuel Vadot 
116630068a1dSEmmanuel Vadot static phandle_t
11676988dd5eSEmmanuel Vadot axp2xx_get_node(device_t dev, device_t bus)
116830068a1dSEmmanuel Vadot {
116930068a1dSEmmanuel Vadot 	return (ofw_bus_get_node(dev));
117030068a1dSEmmanuel Vadot }
117130068a1dSEmmanuel Vadot 
11726988dd5eSEmmanuel Vadot static struct axp2xx_reg_sc *
11736988dd5eSEmmanuel Vadot axp2xx_reg_attach(device_t dev, phandle_t node,
11746988dd5eSEmmanuel Vadot     struct axp2xx_regdef *def)
1175b3d4851eSEmmanuel Vadot {
11766988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg_sc;
1177b3d4851eSEmmanuel Vadot 	struct regnode_init_def initdef;
1178b3d4851eSEmmanuel Vadot 	struct regnode *regnode;
1179b3d4851eSEmmanuel Vadot 
1180b3d4851eSEmmanuel Vadot 	memset(&initdef, 0, sizeof(initdef));
1181b3d4851eSEmmanuel Vadot 	if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) {
1182b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1183b3d4851eSEmmanuel Vadot 		return (NULL);
1184b3d4851eSEmmanuel Vadot 	}
1185b3d4851eSEmmanuel Vadot 	if (initdef.std_param.min_uvolt == 0)
1186b3d4851eSEmmanuel Vadot 		initdef.std_param.min_uvolt = def->voltage_min * 1000;
1187b3d4851eSEmmanuel Vadot 	if (initdef.std_param.max_uvolt == 0)
1188b3d4851eSEmmanuel Vadot 		initdef.std_param.max_uvolt = def->voltage_max * 1000;
1189b3d4851eSEmmanuel Vadot 	initdef.id = def->id;
1190b3d4851eSEmmanuel Vadot 	initdef.ofw_node = node;
11916988dd5eSEmmanuel Vadot 	regnode = regnode_create(dev, &axp2xx_regnode_class, &initdef);
1192b3d4851eSEmmanuel Vadot 	if (regnode == NULL) {
1193b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1194b3d4851eSEmmanuel Vadot 		return (NULL);
1195b3d4851eSEmmanuel Vadot 	}
1196b3d4851eSEmmanuel Vadot 
1197b3d4851eSEmmanuel Vadot 	reg_sc = regnode_get_softc(regnode);
1198b3d4851eSEmmanuel Vadot 	reg_sc->regnode = regnode;
1199b3d4851eSEmmanuel Vadot 	reg_sc->base_dev = dev;
1200b3d4851eSEmmanuel Vadot 	reg_sc->def = def;
1201b3d4851eSEmmanuel Vadot 	reg_sc->xref = OF_xref_from_node(node);
1202b3d4851eSEmmanuel Vadot 	reg_sc->param = regnode_get_stdparam(regnode);
1203b3d4851eSEmmanuel Vadot 
1204b3d4851eSEmmanuel Vadot 	regnode_register(regnode);
1205b3d4851eSEmmanuel Vadot 
1206b3d4851eSEmmanuel Vadot 	return (reg_sc);
1207b3d4851eSEmmanuel Vadot }
1208b3d4851eSEmmanuel Vadot 
1209b3d4851eSEmmanuel Vadot static int
12106988dd5eSEmmanuel Vadot axp2xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
1211b3d4851eSEmmanuel Vadot     intptr_t *num)
1212b3d4851eSEmmanuel Vadot {
12136988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1214b3d4851eSEmmanuel Vadot 	int i;
1215b3d4851eSEmmanuel Vadot 
1216b3d4851eSEmmanuel Vadot 	sc = device_get_softc(dev);
1217b3d4851eSEmmanuel Vadot 	for (i = 0; i < sc->nregs; i++) {
1218b3d4851eSEmmanuel Vadot 		if (sc->regs[i] == NULL)
1219b3d4851eSEmmanuel Vadot 			continue;
1220b3d4851eSEmmanuel Vadot 		if (sc->regs[i]->xref == xref) {
1221b3d4851eSEmmanuel Vadot 			*num = sc->regs[i]->def->id;
1222b3d4851eSEmmanuel Vadot 			return (0);
1223b3d4851eSEmmanuel Vadot 		}
1224b3d4851eSEmmanuel Vadot 	}
1225b3d4851eSEmmanuel Vadot 
1226b3d4851eSEmmanuel Vadot 	return (ENXIO);
1227b3d4851eSEmmanuel Vadot }
1228b3d4851eSEmmanuel Vadot 
122930068a1dSEmmanuel Vadot static void
12306988dd5eSEmmanuel Vadot axp2xx_start(void *pdev)
123130068a1dSEmmanuel Vadot {
123230068a1dSEmmanuel Vadot 	device_t dev;
12336988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1234276b1ac9SAndrew Turner 	const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
12356988dd5eSEmmanuel Vadot 	int i;
12366988dd5eSEmmanuel Vadot 	uint8_t reg, data;
12372ff143afSAndrew Turner 	uint8_t pwr_src;
12382ff143afSAndrew Turner 
123930068a1dSEmmanuel Vadot 	dev = pdev;
12402ff143afSAndrew Turner 
124130068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
12422ff143afSAndrew Turner 	sc->addr = iicbus_get_addr(dev);
124330068a1dSEmmanuel Vadot 	sc->dev = dev;
12442ff143afSAndrew Turner 
1245276b1ac9SAndrew Turner 	if (bootverbose) {
12462ff143afSAndrew Turner 		/*
1247276b1ac9SAndrew Turner 		 * Read the Power State register.
1248276b1ac9SAndrew Turner 		 * Shift the AC presence into bit 0.
1249276b1ac9SAndrew Turner 		 * Shift the Battery presence into bit 1.
12502ff143afSAndrew Turner 		 */
12516988dd5eSEmmanuel Vadot 		axp2xx_read(dev, AXP2XX_PSR, &data, 1);
12526988dd5eSEmmanuel Vadot 		pwr_src = ((data & AXP2XX_PSR_ACIN) >> AXP2XX_PSR_ACIN_SHIFT) |
12536988dd5eSEmmanuel Vadot 		    ((data & AXP2XX_PSR_VBUS) >> (AXP2XX_PSR_VBUS_SHIFT - 1));
12542ff143afSAndrew Turner 
12556988dd5eSEmmanuel Vadot 		device_printf(dev, "Powered by %s\n",
12562ff143afSAndrew Turner 		    pwr_name[pwr_src]);
1257276b1ac9SAndrew Turner 	}
12582ff143afSAndrew Turner 
125930068a1dSEmmanuel Vadot 	/* Only enable interrupts that we are interested in */
12606988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ1_ENABLE,
12616988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_OVERVOLT |
12626988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_DISCONN |
12636988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_CONN |
12646988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_OVERVOLT |
12656988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_DISCONN |
12666988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_CONN);
12676988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ2_ENABLE,
12686988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CONN |
12696988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_DISCONN |
12706988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON |
12716988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF |
12726988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGING |
12736988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGED |
12746988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_OVER |
12756988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_LOW);
12766988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ3_ENABLE,
12776988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ3_PEK_SHORT | AXP2XX_IRQ3_PEK_LONG);
12786988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ4_ENABLE, AXP2XX_IRQ4_APS_LOW_2);
12796988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ5_ENABLE, 0x0);
128030068a1dSEmmanuel Vadot 
12816988dd5eSEmmanuel Vadot 	EVENTHANDLER_REGISTER(shutdown_final, axp2xx_shutdown, dev,
12822ff143afSAndrew Turner 	    SHUTDOWN_PRI_LAST);
12832ff143afSAndrew Turner 
128430068a1dSEmmanuel Vadot 	/* Enable ADC sensors */
12856988dd5eSEmmanuel Vadot 	for (i = 0; i < sc->nsensors; i++) {
12866988dd5eSEmmanuel Vadot 		if (axp2xx_read(dev, sc->sensors[i].enable_reg, &reg, 1) == -1) {
12876988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12886988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12896988dd5eSEmmanuel Vadot 			continue;
12906988dd5eSEmmanuel Vadot 		}
12916988dd5eSEmmanuel Vadot 		reg |= sc->sensors[i].enable_mask;
12926988dd5eSEmmanuel Vadot 		if (axp2xx_write(dev, sc->sensors[i].enable_reg, reg) == -1) {
12936988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12946988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12956988dd5eSEmmanuel Vadot 			continue;
12966988dd5eSEmmanuel Vadot 		}
129730068a1dSEmmanuel Vadot 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
129830068a1dSEmmanuel Vadot 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
12996988dd5eSEmmanuel Vadot 		    OID_AUTO, sc->sensors[i].name,
130030068a1dSEmmanuel Vadot 		    CTLTYPE_INT | CTLFLAG_RD,
13016988dd5eSEmmanuel Vadot 		    dev, sc->sensors[i].id, axp2xx_sysctl,
13026988dd5eSEmmanuel Vadot 		    sc->sensors[i].format,
13036988dd5eSEmmanuel Vadot 		    sc->sensors[i].desc);
130430068a1dSEmmanuel Vadot 	}
130530068a1dSEmmanuel Vadot 
130630068a1dSEmmanuel Vadot 	if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
13076988dd5eSEmmanuel Vadot 	      NULL, axp2xx_intr, sc, &sc->intrcookie)))
130830068a1dSEmmanuel Vadot 		device_printf(dev, "unable to register interrupt handler\n");
130930068a1dSEmmanuel Vadot 
131030068a1dSEmmanuel Vadot 	config_intrhook_disestablish(&sc->intr_hook);
131130068a1dSEmmanuel Vadot }
131230068a1dSEmmanuel Vadot 
131330068a1dSEmmanuel Vadot static int
13146988dd5eSEmmanuel Vadot axp2xx_probe(device_t dev)
131530068a1dSEmmanuel Vadot {
131630068a1dSEmmanuel Vadot 
131730068a1dSEmmanuel Vadot 	if (!ofw_bus_status_okay(dev))
131830068a1dSEmmanuel Vadot 		return (ENXIO);
131930068a1dSEmmanuel Vadot 
13206988dd5eSEmmanuel Vadot 	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
13216988dd5eSEmmanuel Vadot 	{
13226988dd5eSEmmanuel Vadot 	case AXP209:
132330068a1dSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
13246988dd5eSEmmanuel Vadot 		break;
13256988dd5eSEmmanuel Vadot 	case AXP221:
13266988dd5eSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP221 Power Management Unit");
13276988dd5eSEmmanuel Vadot 		break;
13286988dd5eSEmmanuel Vadot 	default:
13296988dd5eSEmmanuel Vadot 		return (ENXIO);
13306988dd5eSEmmanuel Vadot 	}
133130068a1dSEmmanuel Vadot 
133230068a1dSEmmanuel Vadot 	return (BUS_PROBE_DEFAULT);
133330068a1dSEmmanuel Vadot }
133430068a1dSEmmanuel Vadot 
133530068a1dSEmmanuel Vadot static int
13366988dd5eSEmmanuel Vadot axp2xx_attach(device_t dev)
133730068a1dSEmmanuel Vadot {
13386988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
13396988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg;
13406988dd5eSEmmanuel Vadot 	struct axp2xx_regdef *regdefs;
1341b3d4851eSEmmanuel Vadot 	phandle_t rnode, child;
1342b3d4851eSEmmanuel Vadot 	int i;
134330068a1dSEmmanuel Vadot 
134430068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
134530068a1dSEmmanuel Vadot 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
134630068a1dSEmmanuel Vadot 
134730068a1dSEmmanuel Vadot 	if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) {
134830068a1dSEmmanuel Vadot 		device_printf(dev, "can't allocate device resources\n");
134930068a1dSEmmanuel Vadot 		return (ENXIO);
135030068a1dSEmmanuel Vadot 	}
135130068a1dSEmmanuel Vadot 
13526988dd5eSEmmanuel Vadot 	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
13536988dd5eSEmmanuel Vadot 	switch (sc->type) {
13546988dd5eSEmmanuel Vadot 	case AXP209:
13556988dd5eSEmmanuel Vadot 		sc->pins = axp209_pins;
13566988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp209_pins);
13576988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13586988dd5eSEmmanuel Vadot 
13596988dd5eSEmmanuel Vadot 		sc->sensors = axp209_sensors;
13606988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp209_sensors);
13616988dd5eSEmmanuel Vadot 
13626988dd5eSEmmanuel Vadot 		regdefs = axp209_regdefs;
13636988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp209_regdefs);
13646988dd5eSEmmanuel Vadot 		break;
13656988dd5eSEmmanuel Vadot 	case AXP221:
13666988dd5eSEmmanuel Vadot 		sc->pins = axp221_pins;
13676988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp221_pins);
13686988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13696988dd5eSEmmanuel Vadot 
13706988dd5eSEmmanuel Vadot 		sc->sensors = axp221_sensors;
13716988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp221_sensors);
13726988dd5eSEmmanuel Vadot 
13736988dd5eSEmmanuel Vadot 		regdefs = axp221_regdefs;
13746988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp221_regdefs);
13756988dd5eSEmmanuel Vadot 		break;
13766988dd5eSEmmanuel Vadot 	}
13776988dd5eSEmmanuel Vadot 
13786988dd5eSEmmanuel Vadot 	sc->regs = malloc(sizeof(struct axp2xx_reg_sc *) * sc->nregs,
13796988dd5eSEmmanuel Vadot 	    M_AXP2XX_REG, M_WAITOK | M_ZERO);
13806988dd5eSEmmanuel Vadot 
13816988dd5eSEmmanuel Vadot 	sc->intr_hook.ich_func = axp2xx_start;
138230068a1dSEmmanuel Vadot 	sc->intr_hook.ich_arg = dev;
138330068a1dSEmmanuel Vadot 
138430068a1dSEmmanuel Vadot 	if (config_intrhook_establish(&sc->intr_hook) != 0)
138530068a1dSEmmanuel Vadot 		return (ENOMEM);
138630068a1dSEmmanuel Vadot 
1387b3d4851eSEmmanuel Vadot 	/* Attach known regulators that exist in the DT */
1388b3d4851eSEmmanuel Vadot 	rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
1389b3d4851eSEmmanuel Vadot 	if (rnode > 0) {
1390b3d4851eSEmmanuel Vadot 		for (i = 0; i < sc->nregs; i++) {
1391b3d4851eSEmmanuel Vadot 			child = ofw_bus_find_child(rnode,
13926988dd5eSEmmanuel Vadot 			    regdefs[i].name);
1393b3d4851eSEmmanuel Vadot 			if (child == 0)
1394b3d4851eSEmmanuel Vadot 				continue;
13956988dd5eSEmmanuel Vadot 			reg = axp2xx_reg_attach(dev, child, &regdefs[i]);
1396b3d4851eSEmmanuel Vadot 			if (reg == NULL) {
1397b3d4851eSEmmanuel Vadot 				device_printf(dev,
1398b3d4851eSEmmanuel Vadot 				    "cannot attach regulator %s\n",
13996988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1400b3d4851eSEmmanuel Vadot 				continue;
1401b3d4851eSEmmanuel Vadot 			}
1402b3d4851eSEmmanuel Vadot 			sc->regs[i] = reg;
14036988dd5eSEmmanuel Vadot 			if (bootverbose)
14046988dd5eSEmmanuel Vadot 				device_printf(dev, "Regulator %s attached\n",
14056988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1406b3d4851eSEmmanuel Vadot 		}
1407b3d4851eSEmmanuel Vadot 	}
1408b3d4851eSEmmanuel Vadot 
14092ff143afSAndrew Turner 	return (0);
14102ff143afSAndrew Turner }
14112ff143afSAndrew Turner 
14126988dd5eSEmmanuel Vadot static device_method_t axp2xx_methods[] = {
14136988dd5eSEmmanuel Vadot 	DEVMETHOD(device_probe,		axp2xx_probe),
14146988dd5eSEmmanuel Vadot 	DEVMETHOD(device_attach,	axp2xx_attach),
141530068a1dSEmmanuel Vadot 
141630068a1dSEmmanuel Vadot 	/* GPIO interface */
14176988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_get_bus,		axp2xx_gpio_get_bus),
14186988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_max,		axp2xx_gpio_pin_max),
14196988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getname,	axp2xx_gpio_pin_getname),
14206988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getcaps,	axp2xx_gpio_pin_getcaps),
14216988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getflags,	axp2xx_gpio_pin_getflags),
14226988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_setflags,	axp2xx_gpio_pin_setflags),
14236988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_get,		axp2xx_gpio_pin_get),
14246988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_set,		axp2xx_gpio_pin_set),
14256988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_toggle,	axp2xx_gpio_pin_toggle),
14266988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_map_gpios,	axp2xx_gpio_map_gpios),
142730068a1dSEmmanuel Vadot 
1428b3d4851eSEmmanuel Vadot 	/* Regdev interface */
14296988dd5eSEmmanuel Vadot 	DEVMETHOD(regdev_map,		axp2xx_regdev_map),
1430b3d4851eSEmmanuel Vadot 
143130068a1dSEmmanuel Vadot 	/* OFW bus interface */
14326988dd5eSEmmanuel Vadot 	DEVMETHOD(ofw_bus_get_node,	axp2xx_get_node),
143330068a1dSEmmanuel Vadot 
143430068a1dSEmmanuel Vadot 	DEVMETHOD_END
14352ff143afSAndrew Turner };
14362ff143afSAndrew Turner 
14376988dd5eSEmmanuel Vadot static driver_t axp2xx_driver = {
14386988dd5eSEmmanuel Vadot 	"axp2xx_pmu",
14396988dd5eSEmmanuel Vadot 	axp2xx_methods,
14406988dd5eSEmmanuel Vadot 	sizeof(struct axp2xx_softc),
14412ff143afSAndrew Turner };
14422ff143afSAndrew Turner 
14436988dd5eSEmmanuel Vadot static devclass_t axp2xx_devclass;
144430068a1dSEmmanuel Vadot extern devclass_t ofwgpiobus_devclass, gpioc_devclass;
144530068a1dSEmmanuel Vadot extern driver_t ofw_gpiobus_driver, gpioc_driver;
14462ff143afSAndrew Turner 
14476988dd5eSEmmanuel Vadot EARLY_DRIVER_MODULE(axp2xx, iicbus, axp2xx_driver, axp2xx_devclass,
144880ab358eSEmmanuel Vadot   0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
14496988dd5eSEmmanuel Vadot EARLY_DRIVER_MODULE(ofw_gpiobus, axp2xx_pmu, ofw_gpiobus_driver,
145080ab358eSEmmanuel Vadot     ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
14516988dd5eSEmmanuel Vadot DRIVER_MODULE(gpioc, axp2xx_pmu, gpioc_driver, gpioc_devclass,
145280ab358eSEmmanuel Vadot     0, 0);
14536988dd5eSEmmanuel Vadot MODULE_VERSION(axp2xx, 1);
14546988dd5eSEmmanuel Vadot MODULE_DEPEND(axp2xx, iicbus, 1, 1, 1);
1455