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