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