xref: /freebsd/sys/arm/allwinner/axp209.c (revision b2f0caf1)
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 /*
296988dd5eSEmmanuel Vadot * X-Power AXP209/AXP211 PMU for Allwinner SoCs
302ff143afSAndrew Turner */
316988dd5eSEmmanuel Vadot 
322ff143afSAndrew Turner #include <sys/param.h>
332ff143afSAndrew Turner #include <sys/systm.h>
342ff143afSAndrew Turner #include <sys/eventhandler.h>
352ff143afSAndrew Turner #include <sys/kernel.h>
362ff143afSAndrew Turner #include <sys/module.h>
372ff143afSAndrew Turner #include <sys/clock.h>
382ff143afSAndrew Turner #include <sys/time.h>
392ff143afSAndrew Turner #include <sys/bus.h>
402ff143afSAndrew Turner #include <sys/proc.h>
4130068a1dSEmmanuel Vadot #include <sys/gpio.h>
422ff143afSAndrew Turner #include <sys/reboot.h>
432ff143afSAndrew Turner #include <sys/resource.h>
442ff143afSAndrew Turner #include <sys/rman.h>
4586914a0fSAndrew Turner #include <sys/sysctl.h>
462ff143afSAndrew Turner 
472ff143afSAndrew Turner #include <dev/iicbus/iiconf.h>
482ff143afSAndrew Turner 
4930068a1dSEmmanuel Vadot #include <dev/gpio/gpiobusvar.h>
5030068a1dSEmmanuel Vadot 
512ff143afSAndrew Turner #include <dev/ofw/ofw_bus.h>
522ff143afSAndrew Turner #include <dev/ofw/ofw_bus_subr.h>
532ff143afSAndrew Turner 
54b2f0caf1SEmmanuel Vadot #include <dev/regulator/regulator.h>
55b3d4851eSEmmanuel Vadot 
5630068a1dSEmmanuel Vadot #include <arm/allwinner/axp209reg.h>
5730068a1dSEmmanuel Vadot 
5830068a1dSEmmanuel Vadot #include "gpio_if.h"
59b3d4851eSEmmanuel Vadot #include "regdev_if.h"
60b3d4851eSEmmanuel Vadot 
616988dd5eSEmmanuel Vadot MALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator");
62b3d4851eSEmmanuel Vadot 
636988dd5eSEmmanuel Vadot struct axp2xx_regdef {
64b3d4851eSEmmanuel Vadot 	intptr_t		id;
65b3d4851eSEmmanuel Vadot 	char			*name;
66b3d4851eSEmmanuel Vadot 	uint8_t			enable_reg;
67b3d4851eSEmmanuel Vadot 	uint8_t			enable_mask;
68b3d4851eSEmmanuel Vadot 	uint8_t			voltage_reg;
69b3d4851eSEmmanuel Vadot 	uint8_t			voltage_mask;
70b3d4851eSEmmanuel Vadot 	uint8_t			voltage_shift;
71b3d4851eSEmmanuel Vadot 	int			voltage_min;
72b3d4851eSEmmanuel Vadot 	int			voltage_max;
73b3d4851eSEmmanuel Vadot 	int			voltage_step;
74b3d4851eSEmmanuel Vadot 	int			voltage_nstep;
75b3d4851eSEmmanuel Vadot };
76b3d4851eSEmmanuel Vadot 
776988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp209_regdefs[] = {
78b3d4851eSEmmanuel Vadot 	{
79b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC2,
80b3d4851eSEmmanuel Vadot 		.name = "dcdc2",
81b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
82b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC2,
83b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC2_VOLTAGE,
84b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x3f,
85b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
86b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
87b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
88b3d4851eSEmmanuel Vadot 		.voltage_nstep = 64,
89b3d4851eSEmmanuel Vadot 	},
90b3d4851eSEmmanuel Vadot 	{
91b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_DCDC3,
92b3d4851eSEmmanuel Vadot 		.name = "dcdc3",
93b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
94b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_DCDC3,
95b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_DCDC3_VOLTAGE,
96b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
97b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
98b3d4851eSEmmanuel Vadot 		.voltage_max = 3500,
99b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
100b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
101b3d4851eSEmmanuel Vadot 	},
102b3d4851eSEmmanuel Vadot 	{
103b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO2,
104b3d4851eSEmmanuel Vadot 		.name = "ldo2",
105b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
106b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO2,
107b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO24_VOLTAGE,
108b3d4851eSEmmanuel Vadot 		.voltage_mask = 0xf0,
109b3d4851eSEmmanuel Vadot 		.voltage_shift = 4,
110b3d4851eSEmmanuel Vadot 		.voltage_min = 1800,
111b3d4851eSEmmanuel Vadot 		.voltage_max = 3300,
112b3d4851eSEmmanuel Vadot 		.voltage_step = 100,
113b3d4851eSEmmanuel Vadot 		.voltage_nstep = 16,
114b3d4851eSEmmanuel Vadot 	},
115b3d4851eSEmmanuel Vadot 	{
116b3d4851eSEmmanuel Vadot 		.id = AXP209_REG_ID_LDO3,
117b3d4851eSEmmanuel Vadot 		.name = "ldo3",
118b3d4851eSEmmanuel Vadot 		.enable_reg = AXP209_POWERCTL,
119b3d4851eSEmmanuel Vadot 		.enable_mask = AXP209_POWERCTL_LDO3,
120b3d4851eSEmmanuel Vadot 		.voltage_reg = AXP209_REG_LDO3_VOLTAGE,
121b3d4851eSEmmanuel Vadot 		.voltage_mask = 0x7f,
122b3d4851eSEmmanuel Vadot 		.voltage_min = 700,
123b3d4851eSEmmanuel Vadot 		.voltage_max = 2275,
124b3d4851eSEmmanuel Vadot 		.voltage_step = 25,
125b3d4851eSEmmanuel Vadot 		.voltage_nstep = 128,
126b3d4851eSEmmanuel Vadot 	},
127b3d4851eSEmmanuel Vadot };
128b3d4851eSEmmanuel Vadot 
1296988dd5eSEmmanuel Vadot static struct axp2xx_regdef axp221_regdefs[] = {
1306988dd5eSEmmanuel Vadot 	{
1316988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO1,
1326988dd5eSEmmanuel Vadot 		.name = "dldo1",
1336988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1346988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO1,
1356988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO1_VOLTAGE,
1366988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1376988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1386988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1396988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1406988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1416988dd5eSEmmanuel Vadot 	},
1426988dd5eSEmmanuel Vadot 	{
1436988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO2,
1446988dd5eSEmmanuel Vadot 		.name = "dldo2",
1456988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1466988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO2,
1476988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO2_VOLTAGE,
1486988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1496988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1506988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1516988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1526988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1536988dd5eSEmmanuel Vadot 	},
1546988dd5eSEmmanuel Vadot 	{
1556988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO3,
1566988dd5eSEmmanuel Vadot 		.name = "dldo3",
1576988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1586988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO3,
1596988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO3_VOLTAGE,
1606988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1616988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1626988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1636988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1646988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1656988dd5eSEmmanuel Vadot 	},
1666988dd5eSEmmanuel Vadot 	{
1676988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DLDO4,
1686988dd5eSEmmanuel Vadot 		.name = "dldo4",
1696988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1706988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DLDO4,
1716988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DLDO4_VOLTAGE,
1726988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1736988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1746988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1756988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1766988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1776988dd5eSEmmanuel Vadot 	},
1786988dd5eSEmmanuel Vadot 	{
1796988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO1,
1806988dd5eSEmmanuel Vadot 		.name = "eldo1",
1816988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1826988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO1,
1836988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO1_VOLTAGE,
1846988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1856988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1866988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1876988dd5eSEmmanuel Vadot 		.voltage_step = 100,
1886988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
1896988dd5eSEmmanuel Vadot 	},
1906988dd5eSEmmanuel Vadot 	{
1916988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO2,
1926988dd5eSEmmanuel Vadot 		.name = "eldo2",
1936988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
1946988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO2,
1956988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO2_VOLTAGE,
1966988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
1976988dd5eSEmmanuel Vadot 		.voltage_min = 700,
1986988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
1996988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2006988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2016988dd5eSEmmanuel Vadot 	},
2026988dd5eSEmmanuel Vadot 	{
2036988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ELDO3,
2046988dd5eSEmmanuel Vadot 		.name = "eldo3",
2056988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
2066988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_ELDO3,
2076988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ELDO3_VOLTAGE,
2086988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2096988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2106988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2116988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2126988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2136988dd5eSEmmanuel Vadot 	},
2146988dd5eSEmmanuel Vadot 	{
2156988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC5LDO,
2166988dd5eSEmmanuel Vadot 		.name = "dc5ldo",
2176988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2186988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DC5LDO,
2196988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DC5LDO_VOLTAGE,
2206988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3,
2216988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2226988dd5eSEmmanuel Vadot 		.voltage_max = 1400,
2236988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2246988dd5eSEmmanuel Vadot 		.voltage_nstep = 7,
2256988dd5eSEmmanuel Vadot 	},
2266988dd5eSEmmanuel Vadot 	{
2276988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC1,
2286988dd5eSEmmanuel Vadot 		.name = "dcdc1",
2296988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2306988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC1,
2316988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC1_VOLTAGE,
2326988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2336988dd5eSEmmanuel Vadot 		.voltage_min = 1600,
2346988dd5eSEmmanuel Vadot 		.voltage_max = 3400,
2356988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2366988dd5eSEmmanuel Vadot 		.voltage_nstep = 18,
2376988dd5eSEmmanuel Vadot 	},
2386988dd5eSEmmanuel Vadot 	{
2396988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC2,
2406988dd5eSEmmanuel Vadot 		.name = "dcdc2",
2416988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2426988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC2,
2436988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC2_VOLTAGE,
2446988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2456988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2466988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2476988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2486988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2496988dd5eSEmmanuel Vadot 	},
2506988dd5eSEmmanuel Vadot 	{
2516988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC3,
2526988dd5eSEmmanuel Vadot 		.name = "dcdc3",
2536988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2546988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC3,
2556988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC3_VOLTAGE,
2566988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2576988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2586988dd5eSEmmanuel Vadot 		.voltage_max = 1860,
2596988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2606988dd5eSEmmanuel Vadot 		.voltage_nstep = 63,
2616988dd5eSEmmanuel Vadot 	},
2626988dd5eSEmmanuel Vadot 	{
2636988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC4,
2646988dd5eSEmmanuel Vadot 		.name = "dcdc4",
2656988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2666988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC4,
2676988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC4_VOLTAGE,
2686988dd5eSEmmanuel Vadot 		.voltage_mask = 0x3f,
2696988dd5eSEmmanuel Vadot 		.voltage_min = 600,
2706988dd5eSEmmanuel Vadot 		.voltage_max = 1540,
2716988dd5eSEmmanuel Vadot 		.voltage_step = 20,
2726988dd5eSEmmanuel Vadot 		.voltage_nstep = 47,
2736988dd5eSEmmanuel Vadot 	},
2746988dd5eSEmmanuel Vadot 	{
2756988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DCDC5,
2766988dd5eSEmmanuel Vadot 		.name = "dcdc5",
2776988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2786988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_DCDC5,
2796988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_DCDC5_VOLTAGE,
2806988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2816988dd5eSEmmanuel Vadot 		.voltage_min = 1000,
2826988dd5eSEmmanuel Vadot 		.voltage_max = 2550,
2836988dd5eSEmmanuel Vadot 		.voltage_step = 50,
2846988dd5eSEmmanuel Vadot 		.voltage_nstep = 31,
2856988dd5eSEmmanuel Vadot 	},
2866988dd5eSEmmanuel Vadot 	{
2876988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO1,
2886988dd5eSEmmanuel Vadot 		.name = "aldo1",
2896988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
2906988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO1,
2916988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO1_VOLTAGE,
2926988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
2936988dd5eSEmmanuel Vadot 		.voltage_min = 700,
2946988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
2956988dd5eSEmmanuel Vadot 		.voltage_step = 100,
2966988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
2976988dd5eSEmmanuel Vadot 	},
2986988dd5eSEmmanuel Vadot 	{
2996988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO2,
3006988dd5eSEmmanuel Vadot 		.name = "aldo2",
3016988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_1,
3026988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL1_ALDO2,
3036988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO2_VOLTAGE,
3046988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3056988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3066988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3076988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3086988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3096988dd5eSEmmanuel Vadot 	},
3106988dd5eSEmmanuel Vadot 	{
3116988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_ALDO3,
3126988dd5eSEmmanuel Vadot 		.name = "aldo3",
3136988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_3,
3146988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL3_ALDO3,
3156988dd5eSEmmanuel Vadot 		.voltage_reg = AXP221_REG_ALDO3_VOLTAGE,
3166988dd5eSEmmanuel Vadot 		.voltage_mask = 0x1f,
3176988dd5eSEmmanuel Vadot 		.voltage_min = 700,
3186988dd5eSEmmanuel Vadot 		.voltage_max = 3300,
3196988dd5eSEmmanuel Vadot 		.voltage_step = 100,
3206988dd5eSEmmanuel Vadot 		.voltage_nstep = 26,
3216988dd5eSEmmanuel Vadot 	},
3226988dd5eSEmmanuel Vadot 	{
3236988dd5eSEmmanuel Vadot 		.id = AXP221_REG_ID_DC1SW,
3246988dd5eSEmmanuel Vadot 		.name = "dc1sw",
3256988dd5eSEmmanuel Vadot 		.enable_reg = AXP221_POWERCTL_2,
3266988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_POWERCTL2_DC1SW,
3276988dd5eSEmmanuel Vadot 	},
3286988dd5eSEmmanuel Vadot };
3296988dd5eSEmmanuel Vadot 
3306988dd5eSEmmanuel Vadot struct axp2xx_reg_sc {
331b3d4851eSEmmanuel Vadot 	struct regnode		*regnode;
332b3d4851eSEmmanuel Vadot 	device_t		base_dev;
3336988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*def;
334b3d4851eSEmmanuel Vadot 	phandle_t		xref;
335b3d4851eSEmmanuel Vadot 	struct regnode_std_param *param;
336b3d4851eSEmmanuel Vadot };
33786914a0fSAndrew Turner 
3386988dd5eSEmmanuel Vadot struct axp2xx_pins {
3396988dd5eSEmmanuel Vadot 	const char	*name;
3406988dd5eSEmmanuel Vadot 	uint8_t		ctrl_reg;
3416988dd5eSEmmanuel Vadot 	uint8_t		status_reg;
3426988dd5eSEmmanuel Vadot 	uint8_t		status_mask;
3436988dd5eSEmmanuel Vadot 	uint8_t		status_shift;
3446988dd5eSEmmanuel Vadot };
3456988dd5eSEmmanuel Vadot 
3466988dd5eSEmmanuel Vadot /* GPIO3 is different, don't expose it for now */
3476988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp209_pins[] = {
3486988dd5eSEmmanuel Vadot 	{
3496988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3506988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3516988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3526988dd5eSEmmanuel Vadot 		.status_mask = 0x10,
3536988dd5eSEmmanuel Vadot 		.status_shift = 4,
3546988dd5eSEmmanuel Vadot 	},
3556988dd5eSEmmanuel Vadot 	{
3566988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3576988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO1_CTRL,
3586988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3596988dd5eSEmmanuel Vadot 		.status_mask = 0x20,
3606988dd5eSEmmanuel Vadot 		.status_shift = 5,
3616988dd5eSEmmanuel Vadot 	},
3626988dd5eSEmmanuel Vadot 	{
3636988dd5eSEmmanuel Vadot 		.name = "GPIO2",
3646988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP209_GPIO2_CTRL,
3656988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3666988dd5eSEmmanuel Vadot 		.status_mask = 0x40,
3676988dd5eSEmmanuel Vadot 		.status_shift = 6,
3686988dd5eSEmmanuel Vadot 	},
3696988dd5eSEmmanuel Vadot };
3706988dd5eSEmmanuel Vadot 
3716988dd5eSEmmanuel Vadot static const struct axp2xx_pins axp221_pins[] = {
3726988dd5eSEmmanuel Vadot 	{
3736988dd5eSEmmanuel Vadot 		.name = "GPIO0",
3746988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3756988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3766988dd5eSEmmanuel Vadot 		.status_mask = 0x1,
3776988dd5eSEmmanuel Vadot 		.status_shift = 0x0,
3786988dd5eSEmmanuel Vadot 	},
3796988dd5eSEmmanuel Vadot 	{
3806988dd5eSEmmanuel Vadot 		.name = "GPIO1",
3816988dd5eSEmmanuel Vadot 		.ctrl_reg = AXP2XX_GPIO0_CTRL,
3826988dd5eSEmmanuel Vadot 		.status_reg = AXP2XX_GPIO_STATUS,
3836988dd5eSEmmanuel Vadot 		.status_mask = 0x2,
3846988dd5eSEmmanuel Vadot 		.status_shift = 0x1,
3856988dd5eSEmmanuel Vadot 	},
3866988dd5eSEmmanuel Vadot };
3876988dd5eSEmmanuel Vadot 
3886988dd5eSEmmanuel Vadot struct axp2xx_sensors {
3896988dd5eSEmmanuel Vadot 	int		id;
3906988dd5eSEmmanuel Vadot 	const char	*name;
3916988dd5eSEmmanuel Vadot 	const char	*desc;
3926988dd5eSEmmanuel Vadot 	const char	*format;
3936988dd5eSEmmanuel Vadot 	uint8_t		enable_reg;
3946988dd5eSEmmanuel Vadot 	uint8_t		enable_mask;
3956988dd5eSEmmanuel Vadot 	uint8_t		value_reg;
3966988dd5eSEmmanuel Vadot 	uint8_t		value_size;
3976988dd5eSEmmanuel Vadot 	uint8_t		h_value_mask;
3986988dd5eSEmmanuel Vadot 	uint8_t		h_value_shift;
3996988dd5eSEmmanuel Vadot 	uint8_t		l_value_mask;
4006988dd5eSEmmanuel Vadot 	uint8_t		l_value_shift;
4016988dd5eSEmmanuel Vadot 	int		value_step;
4026988dd5eSEmmanuel Vadot 	int		value_convert;
4036988dd5eSEmmanuel Vadot };
4046988dd5eSEmmanuel Vadot 
4056988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp209_sensors[] = {
4066988dd5eSEmmanuel Vadot 	{
4076988dd5eSEmmanuel Vadot 		.id = AXP209_ACVOLT,
4086988dd5eSEmmanuel Vadot 		.name = "acvolt",
4096988dd5eSEmmanuel Vadot 		.desc = "AC Voltage (microvolt)",
4106988dd5eSEmmanuel Vadot 		.format = "I",
4116988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4126988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACVOLT,
4136988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_VOLTAGE,
4146988dd5eSEmmanuel Vadot 		.value_size = 2,
4156988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4166988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4176988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4186988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4196988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4206988dd5eSEmmanuel Vadot 	},
4216988dd5eSEmmanuel Vadot 	{
4226988dd5eSEmmanuel Vadot 		.id = AXP209_ACCURRENT,
4236988dd5eSEmmanuel Vadot 		.name = "accurrent",
4246988dd5eSEmmanuel Vadot 		.desc = "AC Current (microAmpere)",
4256988dd5eSEmmanuel Vadot 		.format = "I",
4266988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4276988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_ACCURRENT,
4286988dd5eSEmmanuel Vadot 		.value_reg = AXP209_ACIN_CURRENT,
4296988dd5eSEmmanuel Vadot 		.value_size = 2,
4306988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4316988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4326988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4336988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4346988dd5eSEmmanuel Vadot 		.value_step = AXP209_ACCURRENT_STEP,
4356988dd5eSEmmanuel Vadot 	},
4366988dd5eSEmmanuel Vadot 	{
4376988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSVOLT,
4386988dd5eSEmmanuel Vadot 		.name = "vbusvolt",
4396988dd5eSEmmanuel Vadot 		.desc = "VBUS Voltage (microVolt)",
4406988dd5eSEmmanuel Vadot 		.format = "I",
4416988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4426988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSVOLT,
4436988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_VOLTAGE,
4446988dd5eSEmmanuel Vadot 		.value_size = 2,
4456988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4466988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4476988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4486988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4496988dd5eSEmmanuel Vadot 		.value_step = AXP209_VOLT_STEP,
4506988dd5eSEmmanuel Vadot 	},
4516988dd5eSEmmanuel Vadot 	{
4526988dd5eSEmmanuel Vadot 		.id = AXP209_VBUSCURRENT,
4536988dd5eSEmmanuel Vadot 		.name = "vbuscurrent",
4546988dd5eSEmmanuel Vadot 		.desc = "VBUS Current (microAmpere)",
4556988dd5eSEmmanuel Vadot 		.format = "I",
4566988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4576988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC1_VBUSCURRENT,
4586988dd5eSEmmanuel Vadot 		.value_reg = AXP209_VBUS_CURRENT,
4596988dd5eSEmmanuel Vadot 		.value_size = 2,
4606988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4616988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4626988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4636988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4646988dd5eSEmmanuel Vadot 		.value_step = AXP209_VBUSCURRENT_STEP,
4656988dd5eSEmmanuel Vadot 	},
4666988dd5eSEmmanuel Vadot 	{
4676988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
4686988dd5eSEmmanuel Vadot 		.name = "batvolt",
4696988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
4706988dd5eSEmmanuel Vadot 		.format = "I",
4716988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4726988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
4736988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
4746988dd5eSEmmanuel Vadot 		.value_size = 2,
4756988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4766988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
4776988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
4786988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4796988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
4806988dd5eSEmmanuel Vadot 	},
4816988dd5eSEmmanuel Vadot 	{
4826988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
4836988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
4846988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
4856988dd5eSEmmanuel Vadot 		.format = "I",
4866988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
4876988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
4886988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
4896988dd5eSEmmanuel Vadot 		.value_size = 2,
4906988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
4916988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
4926988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
4936988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
4946988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
4956988dd5eSEmmanuel Vadot 	},
4966988dd5eSEmmanuel Vadot 	{
4976988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
4986988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
4996988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5006988dd5eSEmmanuel Vadot 		.format = "I",
5016988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5026988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5036988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5046988dd5eSEmmanuel Vadot 		.value_size = 2,
5056988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5066988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5076988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5086988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5096988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5106988dd5eSEmmanuel Vadot 	},
5116988dd5eSEmmanuel Vadot 	{
5126988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5136988dd5eSEmmanuel Vadot 		.name = "temp",
5146988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5156988dd5eSEmmanuel Vadot 		.format = "IK",
5166988dd5eSEmmanuel Vadot 		.enable_reg = AXP209_ADC_ENABLE2,
5176988dd5eSEmmanuel Vadot 		.enable_mask = AXP209_ADC2_TEMP,
5186988dd5eSEmmanuel Vadot 		.value_reg = AXP209_TEMPMON,
5196988dd5eSEmmanuel Vadot 		.value_size = 2,
5206988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5216988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5226988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5236988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5246988dd5eSEmmanuel Vadot 		.value_step = 1,
5256988dd5eSEmmanuel Vadot 		.value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K),
5266988dd5eSEmmanuel Vadot 	},
5276988dd5eSEmmanuel Vadot };
5286988dd5eSEmmanuel Vadot 
5296988dd5eSEmmanuel Vadot static const struct axp2xx_sensors axp221_sensors[] = {
5306988dd5eSEmmanuel Vadot 	{
5316988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATVOLT,
5326988dd5eSEmmanuel Vadot 		.name = "batvolt",
5336988dd5eSEmmanuel Vadot 		.desc = "Battery Voltage (microVolt)",
5346988dd5eSEmmanuel Vadot 		.format = "I",
5356988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5366988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATVOLT,
5376988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_VOLTAGE,
5386988dd5eSEmmanuel Vadot 		.value_size = 2,
5396988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5406988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5416988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5426988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5436988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATVOLT_STEP,
5446988dd5eSEmmanuel Vadot 	},
5456988dd5eSEmmanuel Vadot 	{
5466988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATCHARGECURRENT,
5476988dd5eSEmmanuel Vadot 		.name = "batchargecurrent",
5486988dd5eSEmmanuel Vadot 		.desc = "Battery Charging Current (microAmpere)",
5496988dd5eSEmmanuel Vadot 		.format = "I",
5506988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5516988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5526988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
5536988dd5eSEmmanuel Vadot 		.value_size = 2,
5546988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5556988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5566988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5576988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5586988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5596988dd5eSEmmanuel Vadot 	},
5606988dd5eSEmmanuel Vadot 	{
5616988dd5eSEmmanuel Vadot 		.id = AXP2XX_BATDISCHARGECURRENT,
5626988dd5eSEmmanuel Vadot 		.name = "batdischargecurrent",
5636988dd5eSEmmanuel Vadot 		.desc = "Battery Discharging Current (microAmpere)",
5646988dd5eSEmmanuel Vadot 		.format = "I",
5656988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5666988dd5eSEmmanuel Vadot 		.enable_mask = AXP2XX_ADC1_BATCURRENT,
5676988dd5eSEmmanuel Vadot 		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
5686988dd5eSEmmanuel Vadot 		.value_size = 2,
5696988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5706988dd5eSEmmanuel Vadot 		.h_value_shift = 5,
5716988dd5eSEmmanuel Vadot 		.l_value_mask = 0x1f,
5726988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5736988dd5eSEmmanuel Vadot 		.value_step = AXP2XX_BATCURRENT_STEP,
5746988dd5eSEmmanuel Vadot 	},
5756988dd5eSEmmanuel Vadot 	{
5766988dd5eSEmmanuel Vadot 		.id = AXP2XX_TEMP,
5776988dd5eSEmmanuel Vadot 		.name = "temp",
5786988dd5eSEmmanuel Vadot 		.desc = "Internal Temperature",
5796988dd5eSEmmanuel Vadot 		.format = "IK",
5806988dd5eSEmmanuel Vadot 		.enable_reg = AXP2XX_ADC_ENABLE1,
5816988dd5eSEmmanuel Vadot 		.enable_mask = AXP221_ADC1_TEMP,
5826988dd5eSEmmanuel Vadot 		.value_reg = AXP221_TEMPMON,
5836988dd5eSEmmanuel Vadot 		.value_size = 2,
5846988dd5eSEmmanuel Vadot 		.h_value_mask = 0xff,
5856988dd5eSEmmanuel Vadot 		.h_value_shift = 4,
5866988dd5eSEmmanuel Vadot 		.l_value_mask = 0xf,
5876988dd5eSEmmanuel Vadot 		.l_value_shift = 0,
5886988dd5eSEmmanuel Vadot 		.value_step = 1,
5896988dd5eSEmmanuel Vadot 		.value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K),
5906988dd5eSEmmanuel Vadot 	},
5916988dd5eSEmmanuel Vadot };
5926988dd5eSEmmanuel Vadot 
5936988dd5eSEmmanuel Vadot enum AXP2XX_TYPE {
5946988dd5eSEmmanuel Vadot 	AXP209 = 1,
5956988dd5eSEmmanuel Vadot 	AXP221,
5966988dd5eSEmmanuel Vadot };
5976988dd5eSEmmanuel Vadot 
5986988dd5eSEmmanuel Vadot struct axp2xx_softc {
59930068a1dSEmmanuel Vadot 	device_t		dev;
60030068a1dSEmmanuel Vadot 	struct resource *	res[1];
60130068a1dSEmmanuel Vadot 	void *			intrcookie;
60230068a1dSEmmanuel Vadot 	struct intr_config_hook	intr_hook;
60330068a1dSEmmanuel Vadot 	struct mtx		mtx;
6046988dd5eSEmmanuel Vadot 	uint8_t			type;
6056988dd5eSEmmanuel Vadot 
6066988dd5eSEmmanuel Vadot 	/* GPIO */
6076988dd5eSEmmanuel Vadot 	device_t		gpiodev;
6086988dd5eSEmmanuel Vadot 	int			npins;
6096988dd5eSEmmanuel Vadot 	const struct axp2xx_pins	*pins;
6106988dd5eSEmmanuel Vadot 
6116988dd5eSEmmanuel Vadot 	/* Sensors */
6126988dd5eSEmmanuel Vadot 	const struct axp2xx_sensors	*sensors;
6136988dd5eSEmmanuel Vadot 	int				nsensors;
614b3d4851eSEmmanuel Vadot 
615b3d4851eSEmmanuel Vadot 	/* Regulators */
6166988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc	**regs;
617b3d4851eSEmmanuel Vadot 	int			nregs;
6186988dd5eSEmmanuel Vadot 	struct axp2xx_regdef	*regdefs;
6192ff143afSAndrew Turner };
6202ff143afSAndrew Turner 
6216988dd5eSEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
6226988dd5eSEmmanuel Vadot 	{ "x-powers,axp209",		AXP209 },
6236988dd5eSEmmanuel Vadot 	{ "x-powers,axp221",		AXP221 },
6246988dd5eSEmmanuel Vadot 	{ NULL,				0 }
62586914a0fSAndrew Turner };
62686914a0fSAndrew Turner 
62730068a1dSEmmanuel Vadot static struct resource_spec axp_res_spec[] = {
62830068a1dSEmmanuel Vadot 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
62930068a1dSEmmanuel Vadot 	{ -1,			0,	0 }
63030068a1dSEmmanuel Vadot };
63130068a1dSEmmanuel Vadot 
63230068a1dSEmmanuel Vadot #define	AXP_LOCK(sc)	mtx_lock(&(sc)->mtx)
63330068a1dSEmmanuel Vadot #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
63430068a1dSEmmanuel Vadot 
6352ff143afSAndrew Turner static int
axp2xx_read(device_t dev,uint8_t reg,uint8_t * data,uint8_t size)6366988dd5eSEmmanuel Vadot axp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
6372ff143afSAndrew Turner {
6382ff143afSAndrew Turner 
639094e5e7eSIan Lepore 	return (iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT));
6402ff143afSAndrew Turner }
6412ff143afSAndrew Turner 
6422ff143afSAndrew Turner static int
axp2xx_write(device_t dev,uint8_t reg,uint8_t data)6436988dd5eSEmmanuel Vadot axp2xx_write(device_t dev, uint8_t reg, uint8_t data)
6442ff143afSAndrew Turner {
6452ff143afSAndrew Turner 
646094e5e7eSIan Lepore 	return (iicdev_writeto(dev, reg, &data, sizeof(data), IIC_INTRWAIT));
6472ff143afSAndrew Turner }
6482ff143afSAndrew Turner 
64986914a0fSAndrew Turner static int
axp2xx_regnode_init(struct regnode * regnode)6506988dd5eSEmmanuel Vadot axp2xx_regnode_init(struct regnode *regnode)
651b3d4851eSEmmanuel Vadot {
652b3d4851eSEmmanuel Vadot 	return (0);
653b3d4851eSEmmanuel Vadot }
654b3d4851eSEmmanuel Vadot 
655b3d4851eSEmmanuel Vadot static int
axp2xx_regnode_enable(struct regnode * regnode,bool enable,int * udelay)6566988dd5eSEmmanuel Vadot axp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
657b3d4851eSEmmanuel Vadot {
6586988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
659b3d4851eSEmmanuel Vadot 	uint8_t val;
660b3d4851eSEmmanuel Vadot 
661b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
662b3d4851eSEmmanuel Vadot 
6636988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
664b3d4851eSEmmanuel Vadot 	if (enable)
665b3d4851eSEmmanuel Vadot 		val |= sc->def->enable_mask;
666b3d4851eSEmmanuel Vadot 	else
667b3d4851eSEmmanuel Vadot 		val &= ~sc->def->enable_mask;
6686988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->enable_reg, val);
669b3d4851eSEmmanuel Vadot 
670b3d4851eSEmmanuel Vadot 	*udelay = 0;
671b3d4851eSEmmanuel Vadot 
672b3d4851eSEmmanuel Vadot 	return (0);
673b3d4851eSEmmanuel Vadot }
674b3d4851eSEmmanuel Vadot 
675b3d4851eSEmmanuel Vadot static void
axp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc * sc,uint8_t val,int * uv)6766988dd5eSEmmanuel Vadot axp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv)
677b3d4851eSEmmanuel Vadot {
678b3d4851eSEmmanuel Vadot 	if (val < sc->def->voltage_nstep)
679b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min + val * sc->def->voltage_step;
680b3d4851eSEmmanuel Vadot 	else
681b3d4851eSEmmanuel Vadot 		*uv = sc->def->voltage_min +
682b3d4851eSEmmanuel Vadot 		       (sc->def->voltage_nstep * sc->def->voltage_step);
683b3d4851eSEmmanuel Vadot 	*uv *= 1000;
684b3d4851eSEmmanuel Vadot }
685b3d4851eSEmmanuel Vadot 
686b3d4851eSEmmanuel Vadot static int
axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc * sc,int min_uvolt,int max_uvolt,uint8_t * val)6876988dd5eSEmmanuel Vadot axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt,
688b3d4851eSEmmanuel Vadot     int max_uvolt, uint8_t *val)
689b3d4851eSEmmanuel Vadot {
690b3d4851eSEmmanuel Vadot 	uint8_t nval;
691b3d4851eSEmmanuel Vadot 	int nstep, uvolt;
692b3d4851eSEmmanuel Vadot 
693b3d4851eSEmmanuel Vadot 	nval = 0;
694b3d4851eSEmmanuel Vadot 	uvolt = sc->def->voltage_min * 1000;
695b3d4851eSEmmanuel Vadot 
696b3d4851eSEmmanuel Vadot 	for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
697b3d4851eSEmmanuel Vadot 	     nstep++) {
698b3d4851eSEmmanuel Vadot 		++nval;
699b3d4851eSEmmanuel Vadot 		uvolt += (sc->def->voltage_step * 1000);
700b3d4851eSEmmanuel Vadot 	}
701b3d4851eSEmmanuel Vadot 	if (uvolt > max_uvolt)
702b3d4851eSEmmanuel Vadot 		return (EINVAL);
703b3d4851eSEmmanuel Vadot 
704b3d4851eSEmmanuel Vadot 	*val = nval;
705b3d4851eSEmmanuel Vadot 	return (0);
706b3d4851eSEmmanuel Vadot }
707b3d4851eSEmmanuel Vadot 
708b3d4851eSEmmanuel Vadot static int
axp2xx_regnode_status(struct regnode * regnode,int * status)709ca438784SEmmanuel Vadot axp2xx_regnode_status(struct regnode *regnode, int *status)
710ca438784SEmmanuel Vadot {
711ca438784SEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
712ca438784SEmmanuel Vadot 	uint8_t val;
713ca438784SEmmanuel Vadot 
714ca438784SEmmanuel Vadot 	sc = regnode_get_softc(regnode);
715ca438784SEmmanuel Vadot 
716ca438784SEmmanuel Vadot 	*status = 0;
717ca438784SEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
718ca438784SEmmanuel Vadot 	if (val & sc->def->enable_mask)
719ca438784SEmmanuel Vadot 		*status = REGULATOR_STATUS_ENABLED;
720ca438784SEmmanuel Vadot 
721ca438784SEmmanuel Vadot 	return (0);
722ca438784SEmmanuel Vadot }
723ca438784SEmmanuel Vadot 
724ca438784SEmmanuel Vadot static int
axp2xx_regnode_set_voltage(struct regnode * regnode,int min_uvolt,int max_uvolt,int * udelay)7256988dd5eSEmmanuel Vadot axp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
726b3d4851eSEmmanuel Vadot     int max_uvolt, int *udelay)
727b3d4851eSEmmanuel Vadot {
7286988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
729b3d4851eSEmmanuel Vadot 	uint8_t val;
730b3d4851eSEmmanuel Vadot 
731b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
732b3d4851eSEmmanuel Vadot 
733b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
734b3d4851eSEmmanuel Vadot 		return (ENXIO);
735b3d4851eSEmmanuel Vadot 
7366988dd5eSEmmanuel Vadot 	if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
737b3d4851eSEmmanuel Vadot 		return (ERANGE);
738b3d4851eSEmmanuel Vadot 
7396988dd5eSEmmanuel Vadot 	axp2xx_write(sc->base_dev, sc->def->voltage_reg, val);
740b3d4851eSEmmanuel Vadot 
741b3d4851eSEmmanuel Vadot 	*udelay = 0;
742b3d4851eSEmmanuel Vadot 
743b3d4851eSEmmanuel Vadot 	return (0);
744b3d4851eSEmmanuel Vadot }
745b3d4851eSEmmanuel Vadot 
746b3d4851eSEmmanuel Vadot static int
axp2xx_regnode_get_voltage(struct regnode * regnode,int * uvolt)7476988dd5eSEmmanuel Vadot axp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
748b3d4851eSEmmanuel Vadot {
7496988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *sc;
750b3d4851eSEmmanuel Vadot 	uint8_t val;
751b3d4851eSEmmanuel Vadot 
752b3d4851eSEmmanuel Vadot 	sc = regnode_get_softc(regnode);
753b3d4851eSEmmanuel Vadot 
754b3d4851eSEmmanuel Vadot 	if (!sc->def->voltage_step)
755b3d4851eSEmmanuel Vadot 		return (ENXIO);
756b3d4851eSEmmanuel Vadot 
7576988dd5eSEmmanuel Vadot 	axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
7586988dd5eSEmmanuel Vadot 	axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
759b3d4851eSEmmanuel Vadot 
760b3d4851eSEmmanuel Vadot 	return (0);
761b3d4851eSEmmanuel Vadot }
762b3d4851eSEmmanuel Vadot 
7636988dd5eSEmmanuel Vadot static regnode_method_t axp2xx_regnode_methods[] = {
764b3d4851eSEmmanuel Vadot 	/* Regulator interface */
7656988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_init,		axp2xx_regnode_init),
7666988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_enable,		axp2xx_regnode_enable),
767ca438784SEmmanuel Vadot 	REGNODEMETHOD(regnode_status,		axp2xx_regnode_status),
7686988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_set_voltage,	axp2xx_regnode_set_voltage),
7696988dd5eSEmmanuel Vadot 	REGNODEMETHOD(regnode_get_voltage,	axp2xx_regnode_get_voltage),
7709c3a56d0SEmmanuel Vadot 	REGNODEMETHOD(regnode_check_voltage,	regnode_method_check_voltage),
771b3d4851eSEmmanuel Vadot 	REGNODEMETHOD_END
772b3d4851eSEmmanuel Vadot };
7736988dd5eSEmmanuel Vadot DEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods,
7746988dd5eSEmmanuel Vadot     sizeof(struct axp2xx_reg_sc), regnode_class);
775b3d4851eSEmmanuel Vadot 
776b3d4851eSEmmanuel Vadot static int
axp2xx_sysctl(SYSCTL_HANDLER_ARGS)7776988dd5eSEmmanuel Vadot axp2xx_sysctl(SYSCTL_HANDLER_ARGS)
77886914a0fSAndrew Turner {
7796988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
78086914a0fSAndrew Turner 	device_t dev = arg1;
7816988dd5eSEmmanuel Vadot 	enum axp2xx_sensor sensor = arg2;
78286914a0fSAndrew Turner 	uint8_t data[2];
7836988dd5eSEmmanuel Vadot 	int val, error, i, found;
78486914a0fSAndrew Turner 
7856988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
78686914a0fSAndrew Turner 
7876988dd5eSEmmanuel Vadot 	for (found = 0, i = 0; i < sc->nsensors; i++) {
7886988dd5eSEmmanuel Vadot 		if (sc->sensors[i].id == sensor) {
7896988dd5eSEmmanuel Vadot 			found = 1;
79030068a1dSEmmanuel Vadot 			break;
79130068a1dSEmmanuel Vadot 		}
7926988dd5eSEmmanuel Vadot 	}
7936988dd5eSEmmanuel Vadot 
7946988dd5eSEmmanuel Vadot 	if (found == 0)
7956988dd5eSEmmanuel Vadot 		return (ENOENT);
7966988dd5eSEmmanuel Vadot 
7976988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2);
7986988dd5eSEmmanuel Vadot 	if (error != 0)
7996988dd5eSEmmanuel Vadot 		return (error);
8006988dd5eSEmmanuel Vadot 
8016988dd5eSEmmanuel Vadot 	val = ((data[0] & sc->sensors[i].h_value_mask) <<
8026988dd5eSEmmanuel Vadot 	    sc->sensors[i].h_value_shift);
8036988dd5eSEmmanuel Vadot 	val |= ((data[1] & sc->sensors[i].l_value_mask) <<
8046988dd5eSEmmanuel Vadot 	    sc->sensors[i].l_value_shift);
8056988dd5eSEmmanuel Vadot 	val *= sc->sensors[i].value_step;
8066988dd5eSEmmanuel Vadot 	val += sc->sensors[i].value_convert;
80786914a0fSAndrew Turner 
80886914a0fSAndrew Turner 	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
80986914a0fSAndrew Turner }
81086914a0fSAndrew Turner 
8112ff143afSAndrew Turner static void
axp2xx_shutdown(void * devp,int howto)8126988dd5eSEmmanuel Vadot axp2xx_shutdown(void *devp, int howto)
8132ff143afSAndrew Turner {
8142ff143afSAndrew Turner 	device_t dev;
8152ff143afSAndrew Turner 
8162ff143afSAndrew Turner 	if (!(howto & RB_POWEROFF))
8172ff143afSAndrew Turner 		return;
8182ff143afSAndrew Turner 	dev = (device_t)devp;
8192ff143afSAndrew Turner 
8202ff143afSAndrew Turner 	if (bootverbose)
8216988dd5eSEmmanuel Vadot 		device_printf(dev, "Shutdown AXP2xx\n");
8222ff143afSAndrew Turner 
8236988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN);
8242ff143afSAndrew Turner }
8252ff143afSAndrew Turner 
82630068a1dSEmmanuel Vadot static void
axp2xx_intr(void * arg)8276988dd5eSEmmanuel Vadot axp2xx_intr(void *arg)
8282ff143afSAndrew Turner {
8296988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
83030068a1dSEmmanuel Vadot 	uint8_t reg;
8312ff143afSAndrew Turner 
83230068a1dSEmmanuel Vadot 	sc = arg;
8332ff143afSAndrew Turner 
8346988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, &reg, 1);
83530068a1dSEmmanuel Vadot 	if (reg) {
8366988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_OVERVOLT)
83730068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "overvoltage", NULL);
8386988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT)
83930068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "overvoltage", NULL);
8406988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_LOW)
84130068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "undervoltage", NULL);
8426988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_CONN)
84330068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "plugged", NULL);
8446988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_AC_DISCONN)
84530068a1dSEmmanuel Vadot 			devctl_notify("PMU", "AC", "unplugged", NULL);
8466988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_CONN)
84730068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "plugged", NULL);
8486988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ1_VBUS_DISCONN)
84930068a1dSEmmanuel Vadot 			devctl_notify("PMU", "USB", "unplugged", NULL);
8506988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK);
85130068a1dSEmmanuel Vadot 	}
8522ff143afSAndrew Turner 
8536988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, &reg, 1);
85430068a1dSEmmanuel Vadot 	if (reg) {
8556988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGED)
85630068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charged", NULL);
8576988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CHARGING)
85830068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "charging", NULL);
8596988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_CONN)
86030068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "connected", NULL);
8616988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_DISCONN)
86230068a1dSEmmanuel Vadot 			devctl_notify("PMU", "Battery", "disconnected", NULL);
8636988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW)
86480bd2aadSWarner Losh 			devctl_notify("PMU", "Battery", "low-temp", NULL);
8656988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER)
86680bd2aadSWarner Losh 			devctl_notify("PMU", "Battery", "high-temp", NULL);
8676988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK);
86830068a1dSEmmanuel Vadot 	}
8692ff143afSAndrew Turner 
8706988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, &reg, 1);
87130068a1dSEmmanuel Vadot 	if (reg) {
8726988dd5eSEmmanuel Vadot 		if (reg & AXP2XX_IRQ3_PEK_SHORT)
87330068a1dSEmmanuel Vadot 			shutdown_nice(RB_POWEROFF);
8746988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK);
87530068a1dSEmmanuel Vadot 	}
87630068a1dSEmmanuel Vadot 
8776988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, &reg, 1);
87830068a1dSEmmanuel Vadot 	if (reg) {
8796988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK);
88030068a1dSEmmanuel Vadot 	}
88130068a1dSEmmanuel Vadot 
8826988dd5eSEmmanuel Vadot 	axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, &reg, 1);
88330068a1dSEmmanuel Vadot 	if (reg) {
8846988dd5eSEmmanuel Vadot 		axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK);
88530068a1dSEmmanuel Vadot 	}
88630068a1dSEmmanuel Vadot }
88730068a1dSEmmanuel Vadot 
88830068a1dSEmmanuel Vadot static device_t
axp2xx_gpio_get_bus(device_t dev)8896988dd5eSEmmanuel Vadot axp2xx_gpio_get_bus(device_t dev)
89030068a1dSEmmanuel Vadot {
8916988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
89230068a1dSEmmanuel Vadot 
89330068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
89430068a1dSEmmanuel Vadot 
89530068a1dSEmmanuel Vadot 	return (sc->gpiodev);
8962ff143afSAndrew Turner }
8972ff143afSAndrew Turner 
8982ff143afSAndrew Turner static int
axp2xx_gpio_pin_max(device_t dev,int * maxpin)8996988dd5eSEmmanuel Vadot axp2xx_gpio_pin_max(device_t dev, int *maxpin)
9002ff143afSAndrew Turner {
9016988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9026988dd5eSEmmanuel Vadot 
9036988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9046988dd5eSEmmanuel Vadot 
9056988dd5eSEmmanuel Vadot 	*maxpin = sc->npins - 1;
90630068a1dSEmmanuel Vadot 
90730068a1dSEmmanuel Vadot 	return (0);
90830068a1dSEmmanuel Vadot }
90930068a1dSEmmanuel Vadot 
91030068a1dSEmmanuel Vadot static int
axp2xx_gpio_pin_getname(device_t dev,uint32_t pin,char * name)9116988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
91230068a1dSEmmanuel Vadot {
9136988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9146988dd5eSEmmanuel Vadot 
9156988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9166988dd5eSEmmanuel Vadot 
9176988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
91830068a1dSEmmanuel Vadot 		return (EINVAL);
91930068a1dSEmmanuel Vadot 
92030068a1dSEmmanuel Vadot 	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
92130068a1dSEmmanuel Vadot 
92230068a1dSEmmanuel Vadot 	return (0);
92330068a1dSEmmanuel Vadot }
92430068a1dSEmmanuel Vadot 
92530068a1dSEmmanuel Vadot static int
axp2xx_gpio_pin_getcaps(device_t dev,uint32_t pin,uint32_t * caps)9266988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
92730068a1dSEmmanuel Vadot {
9286988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
9296988dd5eSEmmanuel Vadot 
9306988dd5eSEmmanuel Vadot 	sc = device_get_softc(dev);
9316988dd5eSEmmanuel Vadot 
9326988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
93330068a1dSEmmanuel Vadot 		return (EINVAL);
93430068a1dSEmmanuel Vadot 
93530068a1dSEmmanuel Vadot 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
93630068a1dSEmmanuel Vadot 
93730068a1dSEmmanuel Vadot 	return (0);
93830068a1dSEmmanuel Vadot }
93930068a1dSEmmanuel Vadot 
94030068a1dSEmmanuel Vadot static int
axp2xx_gpio_pin_getflags(device_t dev,uint32_t pin,uint32_t * flags)9416988dd5eSEmmanuel Vadot axp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
94230068a1dSEmmanuel Vadot {
9436988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
94430068a1dSEmmanuel Vadot 	uint8_t data, func;
94530068a1dSEmmanuel Vadot 	int error;
94630068a1dSEmmanuel Vadot 
94730068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
94830068a1dSEmmanuel Vadot 
9496988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9506988dd5eSEmmanuel Vadot 		return (EINVAL);
9516988dd5eSEmmanuel Vadot 
95230068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9536988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
95430068a1dSEmmanuel Vadot 	if (error == 0) {
9556988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
9566988dd5eSEmmanuel Vadot 		if (func == AXP2XX_GPIO_FUNC_INPUT)
95730068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_INPUT;
9586988dd5eSEmmanuel Vadot 		else if (func == AXP2XX_GPIO_FUNC_DRVLO ||
9596988dd5eSEmmanuel Vadot 		    func == AXP2XX_GPIO_FUNC_DRVHI)
96030068a1dSEmmanuel Vadot 			*flags = GPIO_PIN_OUTPUT;
96130068a1dSEmmanuel Vadot 		else
96230068a1dSEmmanuel Vadot 			*flags = 0;
96330068a1dSEmmanuel Vadot 	}
96430068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
96530068a1dSEmmanuel Vadot 
96630068a1dSEmmanuel Vadot 	return (error);
96730068a1dSEmmanuel Vadot }
96830068a1dSEmmanuel Vadot 
96930068a1dSEmmanuel Vadot static int
axp2xx_gpio_pin_setflags(device_t dev,uint32_t pin,uint32_t flags)9706988dd5eSEmmanuel Vadot axp2xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
97130068a1dSEmmanuel Vadot {
9726988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
97330068a1dSEmmanuel Vadot 	uint8_t data;
97430068a1dSEmmanuel Vadot 	int error;
97530068a1dSEmmanuel Vadot 
97630068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
97730068a1dSEmmanuel Vadot 
9786988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
9796988dd5eSEmmanuel Vadot 		return (EINVAL);
9806988dd5eSEmmanuel Vadot 
98130068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
9826988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
98330068a1dSEmmanuel Vadot 	if (error == 0) {
9846988dd5eSEmmanuel Vadot 		data &= ~AXP2XX_GPIO_FUNC_MASK;
98530068a1dSEmmanuel Vadot 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
98630068a1dSEmmanuel Vadot 			if ((flags & GPIO_PIN_OUTPUT) == 0)
9876988dd5eSEmmanuel Vadot 				data |= AXP2XX_GPIO_FUNC_INPUT;
98830068a1dSEmmanuel Vadot 		}
9896988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
99030068a1dSEmmanuel Vadot 	}
99130068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
99230068a1dSEmmanuel Vadot 
99330068a1dSEmmanuel Vadot 	return (error);
99430068a1dSEmmanuel Vadot }
99530068a1dSEmmanuel Vadot 
99630068a1dSEmmanuel Vadot static int
axp2xx_gpio_pin_get(device_t dev,uint32_t pin,unsigned int * val)9976988dd5eSEmmanuel Vadot axp2xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
99830068a1dSEmmanuel Vadot {
9996988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
100030068a1dSEmmanuel Vadot 	uint8_t data, func;
100130068a1dSEmmanuel Vadot 	int error;
100230068a1dSEmmanuel Vadot 
100330068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
100430068a1dSEmmanuel Vadot 
10056988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10066988dd5eSEmmanuel Vadot 		return (EINVAL);
10076988dd5eSEmmanuel Vadot 
100830068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10096988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
101030068a1dSEmmanuel Vadot 	if (error == 0) {
10116988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
101230068a1dSEmmanuel Vadot 		switch (func) {
10136988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
101430068a1dSEmmanuel Vadot 			*val = 0;
101530068a1dSEmmanuel Vadot 			break;
10166988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
101730068a1dSEmmanuel Vadot 			*val = 1;
101830068a1dSEmmanuel Vadot 			break;
10196988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_INPUT:
10206988dd5eSEmmanuel Vadot 			error = axp2xx_read(dev, sc->pins[pin].status_reg,
10216988dd5eSEmmanuel Vadot 			    &data, 1);
10226988dd5eSEmmanuel Vadot 			if (error == 0) {
10236988dd5eSEmmanuel Vadot 				*val = (data & sc->pins[pin].status_mask);
10246988dd5eSEmmanuel Vadot 				*val >>= sc->pins[pin].status_shift;
10256988dd5eSEmmanuel Vadot 			}
102630068a1dSEmmanuel Vadot 			break;
102730068a1dSEmmanuel Vadot 		default:
102830068a1dSEmmanuel Vadot 			error = EIO;
102930068a1dSEmmanuel Vadot 			break;
103030068a1dSEmmanuel Vadot 		}
103130068a1dSEmmanuel Vadot 	}
103230068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
103330068a1dSEmmanuel Vadot 
103430068a1dSEmmanuel Vadot 	return (error);
103530068a1dSEmmanuel Vadot }
103630068a1dSEmmanuel Vadot 
103730068a1dSEmmanuel Vadot static int
axp2xx_gpio_pin_set(device_t dev,uint32_t pin,unsigned int val)10386988dd5eSEmmanuel Vadot axp2xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
103930068a1dSEmmanuel Vadot {
10406988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
104130068a1dSEmmanuel Vadot 	uint8_t data, func;
104230068a1dSEmmanuel Vadot 	int error;
104330068a1dSEmmanuel Vadot 
104430068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
104530068a1dSEmmanuel Vadot 
10466988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10476988dd5eSEmmanuel Vadot 		return (EINVAL);
10486988dd5eSEmmanuel Vadot 
104930068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10506988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
105130068a1dSEmmanuel Vadot 	if (error == 0) {
10526988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
105330068a1dSEmmanuel Vadot 		switch (func) {
10546988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
10556988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
105630068a1dSEmmanuel Vadot 			/* GPIO2 can't be set to 1 */
105730068a1dSEmmanuel Vadot 			if (pin == 2 && val == 1) {
105830068a1dSEmmanuel Vadot 				error = EINVAL;
105930068a1dSEmmanuel Vadot 				break;
106030068a1dSEmmanuel Vadot 			}
10616988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
106230068a1dSEmmanuel Vadot 			data |= val;
106330068a1dSEmmanuel Vadot 			break;
106430068a1dSEmmanuel Vadot 		default:
106530068a1dSEmmanuel Vadot 			error = EIO;
106630068a1dSEmmanuel Vadot 			break;
106730068a1dSEmmanuel Vadot 		}
106830068a1dSEmmanuel Vadot 	}
106930068a1dSEmmanuel Vadot 	if (error == 0)
10706988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
107130068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
107230068a1dSEmmanuel Vadot 
107330068a1dSEmmanuel Vadot 	return (error);
107430068a1dSEmmanuel Vadot }
107530068a1dSEmmanuel Vadot 
107630068a1dSEmmanuel Vadot static int
axp2xx_gpio_pin_toggle(device_t dev,uint32_t pin)10776988dd5eSEmmanuel Vadot axp2xx_gpio_pin_toggle(device_t dev, uint32_t pin)
107830068a1dSEmmanuel Vadot {
10796988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
108030068a1dSEmmanuel Vadot 	uint8_t data, func;
108130068a1dSEmmanuel Vadot 	int error;
108230068a1dSEmmanuel Vadot 
108330068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
108430068a1dSEmmanuel Vadot 
10856988dd5eSEmmanuel Vadot 	if (pin >= sc->npins)
10866988dd5eSEmmanuel Vadot 		return (EINVAL);
10876988dd5eSEmmanuel Vadot 
108830068a1dSEmmanuel Vadot 	AXP_LOCK(sc);
10896988dd5eSEmmanuel Vadot 	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
109030068a1dSEmmanuel Vadot 	if (error == 0) {
10916988dd5eSEmmanuel Vadot 		func = data & AXP2XX_GPIO_FUNC_MASK;
109230068a1dSEmmanuel Vadot 		switch (func) {
10936988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVLO:
109430068a1dSEmmanuel Vadot 			/* Pin 2 can't be set to 1*/
109530068a1dSEmmanuel Vadot 			if (pin == 2) {
109630068a1dSEmmanuel Vadot 				error = EINVAL;
109730068a1dSEmmanuel Vadot 				break;
109830068a1dSEmmanuel Vadot 			}
10996988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
11006988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVHI;
110130068a1dSEmmanuel Vadot 			break;
11026988dd5eSEmmanuel Vadot 		case AXP2XX_GPIO_FUNC_DRVHI:
11036988dd5eSEmmanuel Vadot 			data &= ~AXP2XX_GPIO_FUNC_MASK;
11046988dd5eSEmmanuel Vadot 			data |= AXP2XX_GPIO_FUNC_DRVLO;
110530068a1dSEmmanuel Vadot 			break;
110630068a1dSEmmanuel Vadot 		default:
110730068a1dSEmmanuel Vadot 			error = EIO;
110830068a1dSEmmanuel Vadot 			break;
110930068a1dSEmmanuel Vadot 		}
111030068a1dSEmmanuel Vadot 	}
111130068a1dSEmmanuel Vadot 	if (error == 0)
11126988dd5eSEmmanuel Vadot 		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
111330068a1dSEmmanuel Vadot 	AXP_UNLOCK(sc);
111430068a1dSEmmanuel Vadot 
111530068a1dSEmmanuel Vadot 	return (error);
111630068a1dSEmmanuel Vadot }
111730068a1dSEmmanuel Vadot 
111830068a1dSEmmanuel Vadot static int
axp2xx_gpio_map_gpios(device_t bus,phandle_t dev,phandle_t gparent,int gcells,pcell_t * gpios,uint32_t * pin,uint32_t * flags)11196988dd5eSEmmanuel Vadot axp2xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
112030068a1dSEmmanuel Vadot     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
112130068a1dSEmmanuel Vadot {
11226988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
11236988dd5eSEmmanuel Vadot 
11246988dd5eSEmmanuel Vadot 	sc = device_get_softc(bus);
11256988dd5eSEmmanuel Vadot 
11266988dd5eSEmmanuel Vadot 	if (gpios[0] >= sc->npins)
112730068a1dSEmmanuel Vadot 		return (EINVAL);
112830068a1dSEmmanuel Vadot 
112930068a1dSEmmanuel Vadot 	*pin = gpios[0];
113030068a1dSEmmanuel Vadot 	*flags = gpios[1];
113130068a1dSEmmanuel Vadot 
113230068a1dSEmmanuel Vadot 	return (0);
113330068a1dSEmmanuel Vadot }
113430068a1dSEmmanuel Vadot 
113530068a1dSEmmanuel Vadot static phandle_t
axp2xx_get_node(device_t dev,device_t bus)11366988dd5eSEmmanuel Vadot axp2xx_get_node(device_t dev, device_t bus)
113730068a1dSEmmanuel Vadot {
113830068a1dSEmmanuel Vadot 	return (ofw_bus_get_node(dev));
113930068a1dSEmmanuel Vadot }
114030068a1dSEmmanuel Vadot 
11416988dd5eSEmmanuel Vadot static struct axp2xx_reg_sc *
axp2xx_reg_attach(device_t dev,phandle_t node,struct axp2xx_regdef * def)11426988dd5eSEmmanuel Vadot axp2xx_reg_attach(device_t dev, phandle_t node,
11436988dd5eSEmmanuel Vadot     struct axp2xx_regdef *def)
1144b3d4851eSEmmanuel Vadot {
11456988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg_sc;
1146b3d4851eSEmmanuel Vadot 	struct regnode_init_def initdef;
1147b3d4851eSEmmanuel Vadot 	struct regnode *regnode;
1148b3d4851eSEmmanuel Vadot 
1149b3d4851eSEmmanuel Vadot 	memset(&initdef, 0, sizeof(initdef));
1150b3d4851eSEmmanuel Vadot 	if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) {
1151b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1152b3d4851eSEmmanuel Vadot 		return (NULL);
1153b3d4851eSEmmanuel Vadot 	}
1154b3d4851eSEmmanuel Vadot 	if (initdef.std_param.min_uvolt == 0)
1155b3d4851eSEmmanuel Vadot 		initdef.std_param.min_uvolt = def->voltage_min * 1000;
1156b3d4851eSEmmanuel Vadot 	if (initdef.std_param.max_uvolt == 0)
1157b3d4851eSEmmanuel Vadot 		initdef.std_param.max_uvolt = def->voltage_max * 1000;
1158b3d4851eSEmmanuel Vadot 	initdef.id = def->id;
1159b3d4851eSEmmanuel Vadot 	initdef.ofw_node = node;
11606988dd5eSEmmanuel Vadot 	regnode = regnode_create(dev, &axp2xx_regnode_class, &initdef);
1161b3d4851eSEmmanuel Vadot 	if (regnode == NULL) {
1162b3d4851eSEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
1163b3d4851eSEmmanuel Vadot 		return (NULL);
1164b3d4851eSEmmanuel Vadot 	}
1165b3d4851eSEmmanuel Vadot 
1166b3d4851eSEmmanuel Vadot 	reg_sc = regnode_get_softc(regnode);
1167b3d4851eSEmmanuel Vadot 	reg_sc->regnode = regnode;
1168b3d4851eSEmmanuel Vadot 	reg_sc->base_dev = dev;
1169b3d4851eSEmmanuel Vadot 	reg_sc->def = def;
1170b3d4851eSEmmanuel Vadot 	reg_sc->xref = OF_xref_from_node(node);
1171b3d4851eSEmmanuel Vadot 	reg_sc->param = regnode_get_stdparam(regnode);
1172b3d4851eSEmmanuel Vadot 
1173b3d4851eSEmmanuel Vadot 	regnode_register(regnode);
1174b3d4851eSEmmanuel Vadot 
1175b3d4851eSEmmanuel Vadot 	return (reg_sc);
1176b3d4851eSEmmanuel Vadot }
1177b3d4851eSEmmanuel Vadot 
1178b3d4851eSEmmanuel Vadot static int
axp2xx_regdev_map(device_t dev,phandle_t xref,int ncells,pcell_t * cells,intptr_t * num)11796988dd5eSEmmanuel Vadot axp2xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
1180b3d4851eSEmmanuel Vadot     intptr_t *num)
1181b3d4851eSEmmanuel Vadot {
11826988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1183b3d4851eSEmmanuel Vadot 	int i;
1184b3d4851eSEmmanuel Vadot 
1185b3d4851eSEmmanuel Vadot 	sc = device_get_softc(dev);
1186b3d4851eSEmmanuel Vadot 	for (i = 0; i < sc->nregs; i++) {
1187b3d4851eSEmmanuel Vadot 		if (sc->regs[i] == NULL)
1188b3d4851eSEmmanuel Vadot 			continue;
1189b3d4851eSEmmanuel Vadot 		if (sc->regs[i]->xref == xref) {
1190b3d4851eSEmmanuel Vadot 			*num = sc->regs[i]->def->id;
1191b3d4851eSEmmanuel Vadot 			return (0);
1192b3d4851eSEmmanuel Vadot 		}
1193b3d4851eSEmmanuel Vadot 	}
1194b3d4851eSEmmanuel Vadot 
1195b3d4851eSEmmanuel Vadot 	return (ENXIO);
1196b3d4851eSEmmanuel Vadot }
1197b3d4851eSEmmanuel Vadot 
119830068a1dSEmmanuel Vadot static void
axp2xx_start(void * pdev)11996988dd5eSEmmanuel Vadot axp2xx_start(void *pdev)
120030068a1dSEmmanuel Vadot {
120130068a1dSEmmanuel Vadot 	device_t dev;
12026988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
1203276b1ac9SAndrew Turner 	const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
12046988dd5eSEmmanuel Vadot 	int i;
12056988dd5eSEmmanuel Vadot 	uint8_t reg, data;
12062ff143afSAndrew Turner 	uint8_t pwr_src;
12072ff143afSAndrew Turner 
120830068a1dSEmmanuel Vadot 	dev = pdev;
12092ff143afSAndrew Turner 
121030068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
121130068a1dSEmmanuel Vadot 	sc->dev = dev;
12122ff143afSAndrew Turner 
1213276b1ac9SAndrew Turner 	if (bootverbose) {
12142ff143afSAndrew Turner 		/*
1215276b1ac9SAndrew Turner 		 * Read the Power State register.
1216276b1ac9SAndrew Turner 		 * Shift the AC presence into bit 0.
1217276b1ac9SAndrew Turner 		 * Shift the Battery presence into bit 1.
12182ff143afSAndrew Turner 		 */
12196988dd5eSEmmanuel Vadot 		axp2xx_read(dev, AXP2XX_PSR, &data, 1);
12206988dd5eSEmmanuel Vadot 		pwr_src = ((data & AXP2XX_PSR_ACIN) >> AXP2XX_PSR_ACIN_SHIFT) |
12216988dd5eSEmmanuel Vadot 		    ((data & AXP2XX_PSR_VBUS) >> (AXP2XX_PSR_VBUS_SHIFT - 1));
12222ff143afSAndrew Turner 
12236988dd5eSEmmanuel Vadot 		device_printf(dev, "Powered by %s\n",
12242ff143afSAndrew Turner 		    pwr_name[pwr_src]);
1225276b1ac9SAndrew Turner 	}
12262ff143afSAndrew Turner 
122730068a1dSEmmanuel Vadot 	/* Only enable interrupts that we are interested in */
12286988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ1_ENABLE,
12296988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_OVERVOLT |
12306988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_DISCONN |
12316988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_AC_CONN |
12326988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_OVERVOLT |
12336988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_DISCONN |
12346988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ1_VBUS_CONN);
12356988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ2_ENABLE,
12366988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CONN |
12376988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_DISCONN |
12386988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON |
12396988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF |
12406988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGING |
12416988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_CHARGED |
12426988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_OVER |
12436988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ2_BATT_TEMP_LOW);
12446988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ3_ENABLE,
12456988dd5eSEmmanuel Vadot 	    AXP2XX_IRQ3_PEK_SHORT | AXP2XX_IRQ3_PEK_LONG);
12466988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ4_ENABLE, AXP2XX_IRQ4_APS_LOW_2);
12476988dd5eSEmmanuel Vadot 	axp2xx_write(dev, AXP2XX_IRQ5_ENABLE, 0x0);
124830068a1dSEmmanuel Vadot 
12496988dd5eSEmmanuel Vadot 	EVENTHANDLER_REGISTER(shutdown_final, axp2xx_shutdown, dev,
12502ff143afSAndrew Turner 	    SHUTDOWN_PRI_LAST);
12512ff143afSAndrew Turner 
125230068a1dSEmmanuel Vadot 	/* Enable ADC sensors */
12536988dd5eSEmmanuel Vadot 	for (i = 0; i < sc->nsensors; i++) {
12546988dd5eSEmmanuel Vadot 		if (axp2xx_read(dev, sc->sensors[i].enable_reg, &reg, 1) == -1) {
12556988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12566988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12576988dd5eSEmmanuel Vadot 			continue;
12586988dd5eSEmmanuel Vadot 		}
12596988dd5eSEmmanuel Vadot 		reg |= sc->sensors[i].enable_mask;
12606988dd5eSEmmanuel Vadot 		if (axp2xx_write(dev, sc->sensors[i].enable_reg, reg) == -1) {
12616988dd5eSEmmanuel Vadot 			device_printf(dev, "Cannot enable sensor '%s'\n",
12626988dd5eSEmmanuel Vadot 			    sc->sensors[i].name);
12636988dd5eSEmmanuel Vadot 			continue;
12646988dd5eSEmmanuel Vadot 		}
126530068a1dSEmmanuel Vadot 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
126630068a1dSEmmanuel Vadot 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
12676988dd5eSEmmanuel Vadot 		    OID_AUTO, sc->sensors[i].name,
12688eea36aeSPawel Biernacki 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
12696988dd5eSEmmanuel Vadot 		    dev, sc->sensors[i].id, axp2xx_sysctl,
12706988dd5eSEmmanuel Vadot 		    sc->sensors[i].format,
12716988dd5eSEmmanuel Vadot 		    sc->sensors[i].desc);
127230068a1dSEmmanuel Vadot 	}
127330068a1dSEmmanuel Vadot 
127430068a1dSEmmanuel Vadot 	if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
12756988dd5eSEmmanuel Vadot 	      NULL, axp2xx_intr, sc, &sc->intrcookie)))
127630068a1dSEmmanuel Vadot 		device_printf(dev, "unable to register interrupt handler\n");
127730068a1dSEmmanuel Vadot 
127830068a1dSEmmanuel Vadot 	config_intrhook_disestablish(&sc->intr_hook);
127930068a1dSEmmanuel Vadot }
128030068a1dSEmmanuel Vadot 
128130068a1dSEmmanuel Vadot static int
axp2xx_probe(device_t dev)12826988dd5eSEmmanuel Vadot axp2xx_probe(device_t dev)
128330068a1dSEmmanuel Vadot {
128430068a1dSEmmanuel Vadot 
128530068a1dSEmmanuel Vadot 	if (!ofw_bus_status_okay(dev))
128630068a1dSEmmanuel Vadot 		return (ENXIO);
128730068a1dSEmmanuel Vadot 
12886988dd5eSEmmanuel Vadot 	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
12896988dd5eSEmmanuel Vadot 	{
12906988dd5eSEmmanuel Vadot 	case AXP209:
129130068a1dSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
12926988dd5eSEmmanuel Vadot 		break;
12936988dd5eSEmmanuel Vadot 	case AXP221:
12946988dd5eSEmmanuel Vadot 		device_set_desc(dev, "X-Powers AXP221 Power Management Unit");
12956988dd5eSEmmanuel Vadot 		break;
12966988dd5eSEmmanuel Vadot 	default:
12976988dd5eSEmmanuel Vadot 		return (ENXIO);
12986988dd5eSEmmanuel Vadot 	}
129930068a1dSEmmanuel Vadot 
130030068a1dSEmmanuel Vadot 	return (BUS_PROBE_DEFAULT);
130130068a1dSEmmanuel Vadot }
130230068a1dSEmmanuel Vadot 
130330068a1dSEmmanuel Vadot static int
axp2xx_attach(device_t dev)13046988dd5eSEmmanuel Vadot axp2xx_attach(device_t dev)
130530068a1dSEmmanuel Vadot {
13066988dd5eSEmmanuel Vadot 	struct axp2xx_softc *sc;
13076988dd5eSEmmanuel Vadot 	struct axp2xx_reg_sc *reg;
13086988dd5eSEmmanuel Vadot 	struct axp2xx_regdef *regdefs;
1309b3d4851eSEmmanuel Vadot 	phandle_t rnode, child;
1310b3d4851eSEmmanuel Vadot 	int i;
131130068a1dSEmmanuel Vadot 
131230068a1dSEmmanuel Vadot 	sc = device_get_softc(dev);
131330068a1dSEmmanuel Vadot 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
131430068a1dSEmmanuel Vadot 
131530068a1dSEmmanuel Vadot 	if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) {
131630068a1dSEmmanuel Vadot 		device_printf(dev, "can't allocate device resources\n");
131730068a1dSEmmanuel Vadot 		return (ENXIO);
131830068a1dSEmmanuel Vadot 	}
131930068a1dSEmmanuel Vadot 
13206988dd5eSEmmanuel Vadot 	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
13216988dd5eSEmmanuel Vadot 	switch (sc->type) {
13226988dd5eSEmmanuel Vadot 	case AXP209:
13236988dd5eSEmmanuel Vadot 		sc->pins = axp209_pins;
13246988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp209_pins);
13256988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13266988dd5eSEmmanuel Vadot 
13276988dd5eSEmmanuel Vadot 		sc->sensors = axp209_sensors;
13286988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp209_sensors);
13296988dd5eSEmmanuel Vadot 
13306988dd5eSEmmanuel Vadot 		regdefs = axp209_regdefs;
13316988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp209_regdefs);
13326988dd5eSEmmanuel Vadot 		break;
13336988dd5eSEmmanuel Vadot 	case AXP221:
13346988dd5eSEmmanuel Vadot 		sc->pins = axp221_pins;
13356988dd5eSEmmanuel Vadot 		sc->npins = nitems(axp221_pins);
13366988dd5eSEmmanuel Vadot 		sc->gpiodev = gpiobus_attach_bus(dev);
13376988dd5eSEmmanuel Vadot 
13386988dd5eSEmmanuel Vadot 		sc->sensors = axp221_sensors;
13396988dd5eSEmmanuel Vadot 		sc->nsensors = nitems(axp221_sensors);
13406988dd5eSEmmanuel Vadot 
13416988dd5eSEmmanuel Vadot 		regdefs = axp221_regdefs;
13426988dd5eSEmmanuel Vadot 		sc->nregs = nitems(axp221_regdefs);
13436988dd5eSEmmanuel Vadot 		break;
13446988dd5eSEmmanuel Vadot 	}
13456988dd5eSEmmanuel Vadot 
13466988dd5eSEmmanuel Vadot 	sc->regs = malloc(sizeof(struct axp2xx_reg_sc *) * sc->nregs,
13476988dd5eSEmmanuel Vadot 	    M_AXP2XX_REG, M_WAITOK | M_ZERO);
13486988dd5eSEmmanuel Vadot 
13496988dd5eSEmmanuel Vadot 	sc->intr_hook.ich_func = axp2xx_start;
135030068a1dSEmmanuel Vadot 	sc->intr_hook.ich_arg = dev;
135130068a1dSEmmanuel Vadot 
135230068a1dSEmmanuel Vadot 	if (config_intrhook_establish(&sc->intr_hook) != 0)
135330068a1dSEmmanuel Vadot 		return (ENOMEM);
135430068a1dSEmmanuel Vadot 
1355b3d4851eSEmmanuel Vadot 	/* Attach known regulators that exist in the DT */
1356b3d4851eSEmmanuel Vadot 	rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
1357b3d4851eSEmmanuel Vadot 	if (rnode > 0) {
1358b3d4851eSEmmanuel Vadot 		for (i = 0; i < sc->nregs; i++) {
1359b3d4851eSEmmanuel Vadot 			child = ofw_bus_find_child(rnode,
13606988dd5eSEmmanuel Vadot 			    regdefs[i].name);
1361b3d4851eSEmmanuel Vadot 			if (child == 0)
1362b3d4851eSEmmanuel Vadot 				continue;
13636988dd5eSEmmanuel Vadot 			reg = axp2xx_reg_attach(dev, child, &regdefs[i]);
1364b3d4851eSEmmanuel Vadot 			if (reg == NULL) {
1365b3d4851eSEmmanuel Vadot 				device_printf(dev,
1366b3d4851eSEmmanuel Vadot 				    "cannot attach regulator %s\n",
13676988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1368b3d4851eSEmmanuel Vadot 				continue;
1369b3d4851eSEmmanuel Vadot 			}
1370b3d4851eSEmmanuel Vadot 			sc->regs[i] = reg;
13716988dd5eSEmmanuel Vadot 			if (bootverbose)
13726988dd5eSEmmanuel Vadot 				device_printf(dev, "Regulator %s attached\n",
13736988dd5eSEmmanuel Vadot 				    regdefs[i].name);
1374b3d4851eSEmmanuel Vadot 		}
1375b3d4851eSEmmanuel Vadot 	}
1376b3d4851eSEmmanuel Vadot 
13772ff143afSAndrew Turner 	return (0);
13782ff143afSAndrew Turner }
13792ff143afSAndrew Turner 
13806988dd5eSEmmanuel Vadot static device_method_t axp2xx_methods[] = {
13816988dd5eSEmmanuel Vadot 	DEVMETHOD(device_probe,		axp2xx_probe),
13826988dd5eSEmmanuel Vadot 	DEVMETHOD(device_attach,	axp2xx_attach),
138330068a1dSEmmanuel Vadot 
138430068a1dSEmmanuel Vadot 	/* GPIO interface */
13856988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_get_bus,		axp2xx_gpio_get_bus),
13866988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_max,		axp2xx_gpio_pin_max),
13876988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getname,	axp2xx_gpio_pin_getname),
13886988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getcaps,	axp2xx_gpio_pin_getcaps),
13896988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_getflags,	axp2xx_gpio_pin_getflags),
13906988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_setflags,	axp2xx_gpio_pin_setflags),
13916988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_get,		axp2xx_gpio_pin_get),
13926988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_set,		axp2xx_gpio_pin_set),
13936988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_pin_toggle,	axp2xx_gpio_pin_toggle),
13946988dd5eSEmmanuel Vadot 	DEVMETHOD(gpio_map_gpios,	axp2xx_gpio_map_gpios),
139530068a1dSEmmanuel Vadot 
1396b3d4851eSEmmanuel Vadot 	/* Regdev interface */
13976988dd5eSEmmanuel Vadot 	DEVMETHOD(regdev_map,		axp2xx_regdev_map),
1398b3d4851eSEmmanuel Vadot 
139930068a1dSEmmanuel Vadot 	/* OFW bus interface */
14006988dd5eSEmmanuel Vadot 	DEVMETHOD(ofw_bus_get_node,	axp2xx_get_node),
140130068a1dSEmmanuel Vadot 
140230068a1dSEmmanuel Vadot 	DEVMETHOD_END
14032ff143afSAndrew Turner };
14042ff143afSAndrew Turner 
14056988dd5eSEmmanuel Vadot static driver_t axp2xx_driver = {
14066988dd5eSEmmanuel Vadot 	"axp2xx_pmu",
14076988dd5eSEmmanuel Vadot 	axp2xx_methods,
14086988dd5eSEmmanuel Vadot 	sizeof(struct axp2xx_softc),
14092ff143afSAndrew Turner };
14102ff143afSAndrew Turner 
141130068a1dSEmmanuel Vadot extern driver_t ofw_gpiobus_driver, gpioc_driver;
14122ff143afSAndrew Turner 
14137e1e2ba1SJohn Baldwin EARLY_DRIVER_MODULE(axp2xx, iicbus, axp2xx_driver, 0, 0,
14147e1e2ba1SJohn Baldwin     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
1415e8590c97SJohn Baldwin EARLY_DRIVER_MODULE(ofw_gpiobus, axp2xx_pmu, ofw_gpiobus_driver, 0, 0,
1416e8590c97SJohn Baldwin     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
1417d885615aSJohn Baldwin DRIVER_MODULE(gpioc, axp2xx_pmu, gpioc_driver, 0, 0);
14186988dd5eSEmmanuel Vadot MODULE_VERSION(axp2xx, 1);
1419094e5e7eSIan Lepore MODULE_DEPEND(axp2xx, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
1420