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