1295634Sandrew/*- 2300777Smanu * Copyright (c) 2015-2016 Emmanuel Vadot <manu@freebsd.org> 3300777Smanu * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca> 4295634Sandrew * All rights reserved. 5295634Sandrew * 6295634Sandrew * Redistribution and use in source and binary forms, with or without 7295634Sandrew * modification, are permitted provided that the following conditions 8295634Sandrew * are met: 9295634Sandrew * 1. Redistributions of source code must retain the above copyright 10295634Sandrew * notice, this list of conditions and the following disclaimer. 11295634Sandrew * 2. Redistributions in binary form must reproduce the above copyright 12295634Sandrew * notice, this list of conditions and the following disclaimer in the 13295634Sandrew * documentation and/or other materials provided with the distribution. 14295634Sandrew * 15295634Sandrew * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16295634Sandrew * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17295634Sandrew * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18295634Sandrew * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19295634Sandrew * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20295634Sandrew * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21295634Sandrew * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22295634Sandrew * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23295634Sandrew * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24295634Sandrew * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25295634Sandrew * SUCH DAMAGE. 26295634Sandrew */ 27295634Sandrew 28295634Sandrew#include <sys/cdefs.h> 29295634Sandrew__FBSDID("$FreeBSD: stable/11/sys/arm/allwinner/axp209.c 323467 2017-09-11 22:21:15Z ian $"); 30309758Smanu 31295634Sandrew/* 32309758Smanu* X-Power AXP209/AXP211 PMU for Allwinner SoCs 33295634Sandrew*/ 34309758Smanu 35295634Sandrew#include <sys/param.h> 36295634Sandrew#include <sys/systm.h> 37295634Sandrew#include <sys/eventhandler.h> 38295634Sandrew#include <sys/kernel.h> 39295634Sandrew#include <sys/module.h> 40295634Sandrew#include <sys/clock.h> 41295634Sandrew#include <sys/time.h> 42295634Sandrew#include <sys/bus.h> 43295634Sandrew#include <sys/proc.h> 44300777Smanu#include <sys/gpio.h> 45295634Sandrew#include <sys/reboot.h> 46295634Sandrew#include <sys/resource.h> 47295634Sandrew#include <sys/rman.h> 48295658Sandrew#include <sys/sysctl.h> 49295634Sandrew 50295634Sandrew#include <dev/iicbus/iiconf.h> 51295634Sandrew 52300777Smanu#include <dev/gpio/gpiobusvar.h> 53300777Smanu 54295634Sandrew#include <dev/ofw/ofw_bus.h> 55295634Sandrew#include <dev/ofw/ofw_bus_subr.h> 56295634Sandrew 57307885Smanu#include <dev/extres/regulator/regulator.h> 58307885Smanu 59300777Smanu#include <arm/allwinner/axp209reg.h> 60300777Smanu 61300777Smanu#include "gpio_if.h" 62307885Smanu#include "regdev_if.h" 63295634Sandrew 64309758SmanuMALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator"); 65307885Smanu 66309758Smanustruct axp2xx_regdef { 67307885Smanu intptr_t id; 68307885Smanu char *name; 69307885Smanu uint8_t enable_reg; 70307885Smanu uint8_t enable_mask; 71307885Smanu uint8_t voltage_reg; 72307885Smanu uint8_t voltage_mask; 73307885Smanu uint8_t voltage_shift; 74307885Smanu int voltage_min; 75307885Smanu int voltage_max; 76307885Smanu int voltage_step; 77307885Smanu int voltage_nstep; 78307885Smanu}; 79307885Smanu 80309758Smanustatic struct axp2xx_regdef axp209_regdefs[] = { 81307885Smanu { 82307885Smanu .id = AXP209_REG_ID_DCDC2, 83307885Smanu .name = "dcdc2", 84307885Smanu .enable_reg = AXP209_POWERCTL, 85307885Smanu .enable_mask = AXP209_POWERCTL_DCDC2, 86307885Smanu .voltage_reg = AXP209_REG_DCDC2_VOLTAGE, 87307885Smanu .voltage_mask = 0x3f, 88307885Smanu .voltage_min = 700, 89307885Smanu .voltage_max = 2275, 90307885Smanu .voltage_step = 25, 91307885Smanu .voltage_nstep = 64, 92307885Smanu }, 93307885Smanu { 94307885Smanu .id = AXP209_REG_ID_DCDC3, 95307885Smanu .name = "dcdc3", 96307885Smanu .enable_reg = AXP209_POWERCTL, 97307885Smanu .enable_mask = AXP209_POWERCTL_DCDC3, 98307885Smanu .voltage_reg = AXP209_REG_DCDC3_VOLTAGE, 99307885Smanu .voltage_mask = 0x7f, 100307885Smanu .voltage_min = 700, 101307885Smanu .voltage_max = 3500, 102307885Smanu .voltage_step = 25, 103307885Smanu .voltage_nstep = 128, 104307885Smanu }, 105307885Smanu { 106307885Smanu .id = AXP209_REG_ID_LDO2, 107307885Smanu .name = "ldo2", 108307885Smanu .enable_reg = AXP209_POWERCTL, 109307885Smanu .enable_mask = AXP209_POWERCTL_LDO2, 110307885Smanu .voltage_reg = AXP209_REG_LDO24_VOLTAGE, 111307885Smanu .voltage_mask = 0xf0, 112307885Smanu .voltage_shift = 4, 113307885Smanu .voltage_min = 1800, 114307885Smanu .voltage_max = 3300, 115307885Smanu .voltage_step = 100, 116307885Smanu .voltage_nstep = 16, 117307885Smanu }, 118307885Smanu { 119307885Smanu .id = AXP209_REG_ID_LDO3, 120307885Smanu .name = "ldo3", 121307885Smanu .enable_reg = AXP209_POWERCTL, 122307885Smanu .enable_mask = AXP209_POWERCTL_LDO3, 123307885Smanu .voltage_reg = AXP209_REG_LDO3_VOLTAGE, 124307885Smanu .voltage_mask = 0x7f, 125307885Smanu .voltage_min = 700, 126307885Smanu .voltage_max = 2275, 127307885Smanu .voltage_step = 25, 128307885Smanu .voltage_nstep = 128, 129307885Smanu }, 130307885Smanu}; 131307885Smanu 132309758Smanustatic struct axp2xx_regdef axp221_regdefs[] = { 133309758Smanu { 134309758Smanu .id = AXP221_REG_ID_DLDO1, 135309758Smanu .name = "dldo1", 136309758Smanu .enable_reg = AXP221_POWERCTL_2, 137309758Smanu .enable_mask = AXP221_POWERCTL2_DLDO1, 138309758Smanu .voltage_reg = AXP221_REG_DLDO1_VOLTAGE, 139309758Smanu .voltage_mask = 0x1f, 140309758Smanu .voltage_min = 700, 141309758Smanu .voltage_max = 3300, 142309758Smanu .voltage_step = 100, 143309758Smanu .voltage_nstep = 26, 144309758Smanu }, 145309758Smanu { 146309758Smanu .id = AXP221_REG_ID_DLDO2, 147309758Smanu .name = "dldo2", 148309758Smanu .enable_reg = AXP221_POWERCTL_2, 149309758Smanu .enable_mask = AXP221_POWERCTL2_DLDO2, 150309758Smanu .voltage_reg = AXP221_REG_DLDO2_VOLTAGE, 151309758Smanu .voltage_mask = 0x1f, 152309758Smanu .voltage_min = 700, 153309758Smanu .voltage_max = 3300, 154309758Smanu .voltage_step = 100, 155309758Smanu .voltage_nstep = 26, 156309758Smanu }, 157309758Smanu { 158309758Smanu .id = AXP221_REG_ID_DLDO3, 159309758Smanu .name = "dldo3", 160309758Smanu .enable_reg = AXP221_POWERCTL_2, 161309758Smanu .enable_mask = AXP221_POWERCTL2_DLDO3, 162309758Smanu .voltage_reg = AXP221_REG_DLDO3_VOLTAGE, 163309758Smanu .voltage_mask = 0x1f, 164309758Smanu .voltage_min = 700, 165309758Smanu .voltage_max = 3300, 166309758Smanu .voltage_step = 100, 167309758Smanu .voltage_nstep = 26, 168309758Smanu }, 169309758Smanu { 170309758Smanu .id = AXP221_REG_ID_DLDO4, 171309758Smanu .name = "dldo4", 172309758Smanu .enable_reg = AXP221_POWERCTL_2, 173309758Smanu .enable_mask = AXP221_POWERCTL2_DLDO4, 174309758Smanu .voltage_reg = AXP221_REG_DLDO4_VOLTAGE, 175309758Smanu .voltage_mask = 0x1f, 176309758Smanu .voltage_min = 700, 177309758Smanu .voltage_max = 3300, 178309758Smanu .voltage_step = 100, 179309758Smanu .voltage_nstep = 26, 180309758Smanu }, 181309758Smanu { 182309758Smanu .id = AXP221_REG_ID_ELDO1, 183309758Smanu .name = "eldo1", 184309758Smanu .enable_reg = AXP221_POWERCTL_2, 185309758Smanu .enable_mask = AXP221_POWERCTL2_ELDO1, 186309758Smanu .voltage_reg = AXP221_REG_ELDO1_VOLTAGE, 187309758Smanu .voltage_mask = 0x1f, 188309758Smanu .voltage_min = 700, 189309758Smanu .voltage_max = 3300, 190309758Smanu .voltage_step = 100, 191309758Smanu .voltage_nstep = 26, 192309758Smanu }, 193309758Smanu { 194309758Smanu .id = AXP221_REG_ID_ELDO2, 195309758Smanu .name = "eldo2", 196309758Smanu .enable_reg = AXP221_POWERCTL_2, 197309758Smanu .enable_mask = AXP221_POWERCTL2_ELDO2, 198309758Smanu .voltage_reg = AXP221_REG_ELDO2_VOLTAGE, 199309758Smanu .voltage_mask = 0x1f, 200309758Smanu .voltage_min = 700, 201309758Smanu .voltage_max = 3300, 202309758Smanu .voltage_step = 100, 203309758Smanu .voltage_nstep = 26, 204309758Smanu }, 205309758Smanu { 206309758Smanu .id = AXP221_REG_ID_ELDO3, 207309758Smanu .name = "eldo3", 208309758Smanu .enable_reg = AXP221_POWERCTL_2, 209309758Smanu .enable_mask = AXP221_POWERCTL2_ELDO3, 210309758Smanu .voltage_reg = AXP221_REG_ELDO3_VOLTAGE, 211309758Smanu .voltage_mask = 0x1f, 212309758Smanu .voltage_min = 700, 213309758Smanu .voltage_max = 3300, 214309758Smanu .voltage_step = 100, 215309758Smanu .voltage_nstep = 26, 216309758Smanu }, 217309758Smanu { 218309758Smanu .id = AXP221_REG_ID_DC5LDO, 219309758Smanu .name = "dc5ldo", 220309758Smanu .enable_reg = AXP221_POWERCTL_1, 221309758Smanu .enable_mask = AXP221_POWERCTL1_DC5LDO, 222309758Smanu .voltage_reg = AXP221_REG_DC5LDO_VOLTAGE, 223309758Smanu .voltage_mask = 0x3, 224309758Smanu .voltage_min = 700, 225309758Smanu .voltage_max = 1400, 226309758Smanu .voltage_step = 100, 227309758Smanu .voltage_nstep = 7, 228309758Smanu }, 229309758Smanu { 230309758Smanu .id = AXP221_REG_ID_DCDC1, 231309758Smanu .name = "dcdc1", 232309758Smanu .enable_reg = AXP221_POWERCTL_1, 233309758Smanu .enable_mask = AXP221_POWERCTL1_DCDC1, 234309758Smanu .voltage_reg = AXP221_REG_DCDC1_VOLTAGE, 235309758Smanu .voltage_mask = 0x1f, 236309758Smanu .voltage_min = 1600, 237309758Smanu .voltage_max = 3400, 238309758Smanu .voltage_step = 100, 239309758Smanu .voltage_nstep = 18, 240309758Smanu }, 241309758Smanu { 242309758Smanu .id = AXP221_REG_ID_DCDC2, 243309758Smanu .name = "dcdc2", 244309758Smanu .enable_reg = AXP221_POWERCTL_1, 245309758Smanu .enable_mask = AXP221_POWERCTL1_DCDC2, 246309758Smanu .voltage_reg = AXP221_REG_DCDC2_VOLTAGE, 247309758Smanu .voltage_mask = 0x3f, 248309758Smanu .voltage_min = 600, 249309758Smanu .voltage_max = 1540, 250309758Smanu .voltage_step = 20, 251309758Smanu .voltage_nstep = 47, 252309758Smanu }, 253309758Smanu { 254309758Smanu .id = AXP221_REG_ID_DCDC3, 255309758Smanu .name = "dcdc3", 256309758Smanu .enable_reg = AXP221_POWERCTL_1, 257309758Smanu .enable_mask = AXP221_POWERCTL1_DCDC3, 258309758Smanu .voltage_reg = AXP221_REG_DCDC3_VOLTAGE, 259309758Smanu .voltage_mask = 0x3f, 260309758Smanu .voltage_min = 600, 261309758Smanu .voltage_max = 1860, 262309758Smanu .voltage_step = 20, 263309758Smanu .voltage_nstep = 63, 264309758Smanu }, 265309758Smanu { 266309758Smanu .id = AXP221_REG_ID_DCDC4, 267309758Smanu .name = "dcdc4", 268309758Smanu .enable_reg = AXP221_POWERCTL_1, 269309758Smanu .enable_mask = AXP221_POWERCTL1_DCDC4, 270309758Smanu .voltage_reg = AXP221_REG_DCDC4_VOLTAGE, 271309758Smanu .voltage_mask = 0x3f, 272309758Smanu .voltage_min = 600, 273309758Smanu .voltage_max = 1540, 274309758Smanu .voltage_step = 20, 275309758Smanu .voltage_nstep = 47, 276309758Smanu }, 277309758Smanu { 278309758Smanu .id = AXP221_REG_ID_DCDC5, 279309758Smanu .name = "dcdc5", 280309758Smanu .enable_reg = AXP221_POWERCTL_1, 281309758Smanu .enable_mask = AXP221_POWERCTL1_DCDC5, 282309758Smanu .voltage_reg = AXP221_REG_DCDC5_VOLTAGE, 283309758Smanu .voltage_mask = 0x1f, 284309758Smanu .voltage_min = 1000, 285309758Smanu .voltage_max = 2550, 286309758Smanu .voltage_step = 50, 287309758Smanu .voltage_nstep = 31, 288309758Smanu }, 289309758Smanu { 290309758Smanu .id = AXP221_REG_ID_ALDO1, 291309758Smanu .name = "aldo1", 292309758Smanu .enable_reg = AXP221_POWERCTL_1, 293309758Smanu .enable_mask = AXP221_POWERCTL1_ALDO1, 294309758Smanu .voltage_reg = AXP221_REG_ALDO1_VOLTAGE, 295309758Smanu .voltage_mask = 0x1f, 296309758Smanu .voltage_min = 700, 297309758Smanu .voltage_max = 3300, 298309758Smanu .voltage_step = 100, 299309758Smanu .voltage_nstep = 26, 300309758Smanu }, 301309758Smanu { 302309758Smanu .id = AXP221_REG_ID_ALDO2, 303309758Smanu .name = "aldo2", 304309758Smanu .enable_reg = AXP221_POWERCTL_1, 305309758Smanu .enable_mask = AXP221_POWERCTL1_ALDO2, 306309758Smanu .voltage_reg = AXP221_REG_ALDO2_VOLTAGE, 307309758Smanu .voltage_mask = 0x1f, 308309758Smanu .voltage_min = 700, 309309758Smanu .voltage_max = 3300, 310309758Smanu .voltage_step = 100, 311309758Smanu .voltage_nstep = 26, 312309758Smanu }, 313309758Smanu { 314309758Smanu .id = AXP221_REG_ID_ALDO3, 315309758Smanu .name = "aldo3", 316309758Smanu .enable_reg = AXP221_POWERCTL_3, 317309758Smanu .enable_mask = AXP221_POWERCTL3_ALDO3, 318309758Smanu .voltage_reg = AXP221_REG_ALDO3_VOLTAGE, 319309758Smanu .voltage_mask = 0x1f, 320309758Smanu .voltage_min = 700, 321309758Smanu .voltage_max = 3300, 322309758Smanu .voltage_step = 100, 323309758Smanu .voltage_nstep = 26, 324309758Smanu }, 325309758Smanu { 326309758Smanu .id = AXP221_REG_ID_DC1SW, 327309758Smanu .name = "dc1sw", 328309758Smanu .enable_reg = AXP221_POWERCTL_2, 329309758Smanu .enable_mask = AXP221_POWERCTL2_DC1SW, 330309758Smanu }, 331309758Smanu}; 332309758Smanu 333309758Smanustruct axp2xx_reg_sc { 334307885Smanu struct regnode *regnode; 335307885Smanu device_t base_dev; 336309758Smanu struct axp2xx_regdef *def; 337307885Smanu phandle_t xref; 338307885Smanu struct regnode_std_param *param; 339307885Smanu}; 340307885Smanu 341309758Smanustruct axp2xx_pins { 342309758Smanu const char *name; 343309758Smanu uint8_t ctrl_reg; 344309758Smanu uint8_t status_reg; 345309758Smanu uint8_t status_mask; 346309758Smanu uint8_t status_shift; 347309758Smanu}; 348309758Smanu 349309758Smanu/* GPIO3 is different, don't expose it for now */ 350309758Smanustatic const struct axp2xx_pins axp209_pins[] = { 351309758Smanu { 352309758Smanu .name = "GPIO0", 353309758Smanu .ctrl_reg = AXP2XX_GPIO0_CTRL, 354309758Smanu .status_reg = AXP2XX_GPIO_STATUS, 355309758Smanu .status_mask = 0x10, 356309758Smanu .status_shift = 4, 357309758Smanu }, 358309758Smanu { 359309758Smanu .name = "GPIO1", 360309758Smanu .ctrl_reg = AXP2XX_GPIO1_CTRL, 361309758Smanu .status_reg = AXP2XX_GPIO_STATUS, 362309758Smanu .status_mask = 0x20, 363309758Smanu .status_shift = 5, 364309758Smanu }, 365309758Smanu { 366309758Smanu .name = "GPIO2", 367309758Smanu .ctrl_reg = AXP209_GPIO2_CTRL, 368309758Smanu .status_reg = AXP2XX_GPIO_STATUS, 369309758Smanu .status_mask = 0x40, 370309758Smanu .status_shift = 6, 371309758Smanu }, 372309758Smanu}; 373309758Smanu 374309758Smanustatic const struct axp2xx_pins axp221_pins[] = { 375309758Smanu { 376309758Smanu .name = "GPIO0", 377309758Smanu .ctrl_reg = AXP2XX_GPIO0_CTRL, 378309758Smanu .status_reg = AXP2XX_GPIO_STATUS, 379309758Smanu .status_mask = 0x1, 380309758Smanu .status_shift = 0x0, 381309758Smanu }, 382309758Smanu { 383309758Smanu .name = "GPIO1", 384309758Smanu .ctrl_reg = AXP2XX_GPIO0_CTRL, 385309758Smanu .status_reg = AXP2XX_GPIO_STATUS, 386309758Smanu .status_mask = 0x2, 387309758Smanu .status_shift = 0x1, 388309758Smanu }, 389309758Smanu}; 390309758Smanu 391309758Smanustruct axp2xx_sensors { 392309758Smanu int id; 393309758Smanu const char *name; 394309758Smanu const char *desc; 395309758Smanu const char *format; 396309758Smanu uint8_t enable_reg; 397309758Smanu uint8_t enable_mask; 398309758Smanu uint8_t value_reg; 399309758Smanu uint8_t value_size; 400309758Smanu uint8_t h_value_mask; 401309758Smanu uint8_t h_value_shift; 402309758Smanu uint8_t l_value_mask; 403309758Smanu uint8_t l_value_shift; 404309758Smanu int value_step; 405309758Smanu int value_convert; 406309758Smanu}; 407309758Smanu 408309758Smanustatic const struct axp2xx_sensors axp209_sensors[] = { 409309758Smanu { 410309758Smanu .id = AXP209_ACVOLT, 411309758Smanu .name = "acvolt", 412309758Smanu .desc = "AC Voltage (microvolt)", 413309758Smanu .format = "I", 414309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 415309758Smanu .enable_mask = AXP209_ADC1_ACVOLT, 416309758Smanu .value_reg = AXP209_ACIN_VOLTAGE, 417309758Smanu .value_size = 2, 418309758Smanu .h_value_mask = 0xff, 419309758Smanu .h_value_shift = 4, 420309758Smanu .l_value_mask = 0xf, 421309758Smanu .l_value_shift = 0, 422309758Smanu .value_step = AXP209_VOLT_STEP, 423309758Smanu }, 424309758Smanu { 425309758Smanu .id = AXP209_ACCURRENT, 426309758Smanu .name = "accurrent", 427309758Smanu .desc = "AC Current (microAmpere)", 428309758Smanu .format = "I", 429309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 430309758Smanu .enable_mask = AXP209_ADC1_ACCURRENT, 431309758Smanu .value_reg = AXP209_ACIN_CURRENT, 432309758Smanu .value_size = 2, 433309758Smanu .h_value_mask = 0xff, 434309758Smanu .h_value_shift = 4, 435309758Smanu .l_value_mask = 0xf, 436309758Smanu .l_value_shift = 0, 437309758Smanu .value_step = AXP209_ACCURRENT_STEP, 438309758Smanu }, 439309758Smanu { 440309758Smanu .id = AXP209_VBUSVOLT, 441309758Smanu .name = "vbusvolt", 442309758Smanu .desc = "VBUS Voltage (microVolt)", 443309758Smanu .format = "I", 444309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 445309758Smanu .enable_mask = AXP209_ADC1_VBUSVOLT, 446309758Smanu .value_reg = AXP209_VBUS_VOLTAGE, 447309758Smanu .value_size = 2, 448309758Smanu .h_value_mask = 0xff, 449309758Smanu .h_value_shift = 4, 450309758Smanu .l_value_mask = 0xf, 451309758Smanu .l_value_shift = 0, 452309758Smanu .value_step = AXP209_VOLT_STEP, 453309758Smanu }, 454309758Smanu { 455309758Smanu .id = AXP209_VBUSCURRENT, 456309758Smanu .name = "vbuscurrent", 457309758Smanu .desc = "VBUS Current (microAmpere)", 458309758Smanu .format = "I", 459309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 460309758Smanu .enable_mask = AXP209_ADC1_VBUSCURRENT, 461309758Smanu .value_reg = AXP209_VBUS_CURRENT, 462309758Smanu .value_size = 2, 463309758Smanu .h_value_mask = 0xff, 464309758Smanu .h_value_shift = 4, 465309758Smanu .l_value_mask = 0xf, 466309758Smanu .l_value_shift = 0, 467309758Smanu .value_step = AXP209_VBUSCURRENT_STEP, 468309758Smanu }, 469309758Smanu { 470309758Smanu .id = AXP2XX_BATVOLT, 471309758Smanu .name = "batvolt", 472309758Smanu .desc = "Battery Voltage (microVolt)", 473309758Smanu .format = "I", 474309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 475309758Smanu .enable_mask = AXP2XX_ADC1_BATVOLT, 476309758Smanu .value_reg = AXP2XX_BAT_VOLTAGE, 477309758Smanu .value_size = 2, 478309758Smanu .h_value_mask = 0xff, 479309758Smanu .h_value_shift = 4, 480309758Smanu .l_value_mask = 0xf, 481309758Smanu .l_value_shift = 0, 482309758Smanu .value_step = AXP2XX_BATVOLT_STEP, 483309758Smanu }, 484309758Smanu { 485309758Smanu .id = AXP2XX_BATCHARGECURRENT, 486309758Smanu .name = "batchargecurrent", 487309758Smanu .desc = "Battery Charging Current (microAmpere)", 488309758Smanu .format = "I", 489309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 490309758Smanu .enable_mask = AXP2XX_ADC1_BATCURRENT, 491309758Smanu .value_reg = AXP2XX_BAT_CHARGE_CURRENT, 492309758Smanu .value_size = 2, 493309758Smanu .h_value_mask = 0xff, 494309758Smanu .h_value_shift = 5, 495309758Smanu .l_value_mask = 0x1f, 496309758Smanu .l_value_shift = 0, 497309758Smanu .value_step = AXP2XX_BATCURRENT_STEP, 498309758Smanu }, 499309758Smanu { 500309758Smanu .id = AXP2XX_BATDISCHARGECURRENT, 501309758Smanu .name = "batdischargecurrent", 502309758Smanu .desc = "Battery Discharging Current (microAmpere)", 503309758Smanu .format = "I", 504309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 505309758Smanu .enable_mask = AXP2XX_ADC1_BATCURRENT, 506309758Smanu .value_reg = AXP2XX_BAT_DISCHARGE_CURRENT, 507309758Smanu .value_size = 2, 508309758Smanu .h_value_mask = 0xff, 509309758Smanu .h_value_shift = 5, 510309758Smanu .l_value_mask = 0x1f, 511309758Smanu .l_value_shift = 0, 512309758Smanu .value_step = AXP2XX_BATCURRENT_STEP, 513309758Smanu }, 514309758Smanu { 515309758Smanu .id = AXP2XX_TEMP, 516309758Smanu .name = "temp", 517309758Smanu .desc = "Internal Temperature", 518309758Smanu .format = "IK", 519309758Smanu .enable_reg = AXP209_ADC_ENABLE2, 520309758Smanu .enable_mask = AXP209_ADC2_TEMP, 521309758Smanu .value_reg = AXP209_TEMPMON, 522309758Smanu .value_size = 2, 523309758Smanu .h_value_mask = 0xff, 524309758Smanu .h_value_shift = 4, 525309758Smanu .l_value_mask = 0xf, 526309758Smanu .l_value_shift = 0, 527309758Smanu .value_step = 1, 528309758Smanu .value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K), 529309758Smanu }, 530309758Smanu}; 531309758Smanu 532309758Smanustatic const struct axp2xx_sensors axp221_sensors[] = { 533309758Smanu { 534309758Smanu .id = AXP2XX_BATVOLT, 535309758Smanu .name = "batvolt", 536309758Smanu .desc = "Battery Voltage (microVolt)", 537309758Smanu .format = "I", 538309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 539309758Smanu .enable_mask = AXP2XX_ADC1_BATVOLT, 540309758Smanu .value_reg = AXP2XX_BAT_VOLTAGE, 541309758Smanu .value_size = 2, 542309758Smanu .h_value_mask = 0xff, 543309758Smanu .h_value_shift = 4, 544309758Smanu .l_value_mask = 0xf, 545309758Smanu .l_value_shift = 0, 546309758Smanu .value_step = AXP2XX_BATVOLT_STEP, 547309758Smanu }, 548309758Smanu { 549309758Smanu .id = AXP2XX_BATCHARGECURRENT, 550309758Smanu .name = "batchargecurrent", 551309758Smanu .desc = "Battery Charging Current (microAmpere)", 552309758Smanu .format = "I", 553309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 554309758Smanu .enable_mask = AXP2XX_ADC1_BATCURRENT, 555309758Smanu .value_reg = AXP2XX_BAT_CHARGE_CURRENT, 556309758Smanu .value_size = 2, 557309758Smanu .h_value_mask = 0xff, 558309758Smanu .h_value_shift = 5, 559309758Smanu .l_value_mask = 0x1f, 560309758Smanu .l_value_shift = 0, 561309758Smanu .value_step = AXP2XX_BATCURRENT_STEP, 562309758Smanu }, 563309758Smanu { 564309758Smanu .id = AXP2XX_BATDISCHARGECURRENT, 565309758Smanu .name = "batdischargecurrent", 566309758Smanu .desc = "Battery Discharging Current (microAmpere)", 567309758Smanu .format = "I", 568309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 569309758Smanu .enable_mask = AXP2XX_ADC1_BATCURRENT, 570309758Smanu .value_reg = AXP2XX_BAT_DISCHARGE_CURRENT, 571309758Smanu .value_size = 2, 572309758Smanu .h_value_mask = 0xff, 573309758Smanu .h_value_shift = 5, 574309758Smanu .l_value_mask = 0x1f, 575309758Smanu .l_value_shift = 0, 576309758Smanu .value_step = AXP2XX_BATCURRENT_STEP, 577309758Smanu }, 578309758Smanu { 579309758Smanu .id = AXP2XX_TEMP, 580309758Smanu .name = "temp", 581309758Smanu .desc = "Internal Temperature", 582309758Smanu .format = "IK", 583309758Smanu .enable_reg = AXP2XX_ADC_ENABLE1, 584309758Smanu .enable_mask = AXP221_ADC1_TEMP, 585309758Smanu .value_reg = AXP221_TEMPMON, 586309758Smanu .value_size = 2, 587309758Smanu .h_value_mask = 0xff, 588309758Smanu .h_value_shift = 4, 589309758Smanu .l_value_mask = 0xf, 590309758Smanu .l_value_shift = 0, 591309758Smanu .value_step = 1, 592309758Smanu .value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K), 593309758Smanu }, 594309758Smanu}; 595309758Smanu 596309758Smanuenum AXP2XX_TYPE { 597309758Smanu AXP209 = 1, 598309758Smanu AXP221, 599309758Smanu}; 600309758Smanu 601309758Smanustruct axp2xx_softc { 602300777Smanu device_t dev; 603300777Smanu struct resource * res[1]; 604300777Smanu void * intrcookie; 605300777Smanu struct intr_config_hook intr_hook; 606300777Smanu struct mtx mtx; 607309758Smanu uint8_t type; 608307885Smanu 609309758Smanu /* GPIO */ 610309758Smanu device_t gpiodev; 611309758Smanu int npins; 612309758Smanu const struct axp2xx_pins *pins; 613309758Smanu 614309758Smanu /* Sensors */ 615309758Smanu const struct axp2xx_sensors *sensors; 616309758Smanu int nsensors; 617309758Smanu 618307885Smanu /* Regulators */ 619309758Smanu struct axp2xx_reg_sc **regs; 620307885Smanu int nregs; 621309758Smanu struct axp2xx_regdef *regdefs; 622295634Sandrew}; 623295634Sandrew 624309758Smanustatic struct ofw_compat_data compat_data[] = { 625309758Smanu { "x-powers,axp209", AXP209 }, 626309758Smanu { "x-powers,axp221", AXP221 }, 627309758Smanu { NULL, 0 } 628295658Sandrew}; 629295658Sandrew 630300777Smanustatic struct resource_spec axp_res_spec[] = { 631300777Smanu { SYS_RES_IRQ, 0, RF_ACTIVE }, 632300777Smanu { -1, 0, 0 } 633300777Smanu}; 634300777Smanu 635300777Smanu#define AXP_LOCK(sc) mtx_lock(&(sc)->mtx) 636300777Smanu#define AXP_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 637300777Smanu 638295634Sandrewstatic int 639309758Smanuaxp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) 640295634Sandrew{ 641295634Sandrew 642323467Sian return (iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT)); 643295634Sandrew} 644295634Sandrew 645295634Sandrewstatic int 646309758Smanuaxp2xx_write(device_t dev, uint8_t reg, uint8_t data) 647295634Sandrew{ 648295634Sandrew 649323467Sian return (iicdev_writeto(dev, reg, &data, sizeof(data), IIC_INTRWAIT)); 650295634Sandrew} 651295634Sandrew 652295658Sandrewstatic int 653309758Smanuaxp2xx_regnode_init(struct regnode *regnode) 654307885Smanu{ 655307885Smanu return (0); 656307885Smanu} 657307885Smanu 658307885Smanustatic int 659309758Smanuaxp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay) 660307885Smanu{ 661309758Smanu struct axp2xx_reg_sc *sc; 662307885Smanu uint8_t val; 663307885Smanu 664307885Smanu sc = regnode_get_softc(regnode); 665307885Smanu 666309758Smanu axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1); 667307885Smanu if (enable) 668307885Smanu val |= sc->def->enable_mask; 669307885Smanu else 670307885Smanu val &= ~sc->def->enable_mask; 671309758Smanu axp2xx_write(sc->base_dev, sc->def->enable_reg, val); 672307885Smanu 673307885Smanu *udelay = 0; 674307885Smanu 675307885Smanu return (0); 676307885Smanu} 677307885Smanu 678307885Smanustatic void 679309758Smanuaxp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv) 680307885Smanu{ 681307885Smanu if (val < sc->def->voltage_nstep) 682307885Smanu *uv = sc->def->voltage_min + val * sc->def->voltage_step; 683307885Smanu else 684307885Smanu *uv = sc->def->voltage_min + 685307885Smanu (sc->def->voltage_nstep * sc->def->voltage_step); 686307885Smanu *uv *= 1000; 687307885Smanu} 688307885Smanu 689307885Smanustatic int 690309758Smanuaxp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt, 691307885Smanu int max_uvolt, uint8_t *val) 692307885Smanu{ 693307885Smanu uint8_t nval; 694307885Smanu int nstep, uvolt; 695307885Smanu 696307885Smanu nval = 0; 697307885Smanu uvolt = sc->def->voltage_min * 1000; 698307885Smanu 699307885Smanu for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt; 700307885Smanu nstep++) { 701307885Smanu ++nval; 702307885Smanu uvolt += (sc->def->voltage_step * 1000); 703307885Smanu } 704307885Smanu if (uvolt > max_uvolt) 705307885Smanu return (EINVAL); 706307885Smanu 707307885Smanu *val = nval; 708307885Smanu return (0); 709307885Smanu} 710307885Smanu 711307885Smanustatic int 712309758Smanuaxp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt, 713307885Smanu int max_uvolt, int *udelay) 714307885Smanu{ 715309758Smanu struct axp2xx_reg_sc *sc; 716307885Smanu uint8_t val; 717307885Smanu 718307885Smanu sc = regnode_get_softc(regnode); 719307885Smanu 720307885Smanu if (!sc->def->voltage_step) 721307885Smanu return (ENXIO); 722307885Smanu 723309758Smanu if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0) 724307885Smanu return (ERANGE); 725307885Smanu 726309758Smanu axp2xx_write(sc->base_dev, sc->def->voltage_reg, val); 727307885Smanu 728307885Smanu *udelay = 0; 729307885Smanu 730307885Smanu return (0); 731307885Smanu} 732307885Smanu 733307885Smanustatic int 734309758Smanuaxp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt) 735307885Smanu{ 736309758Smanu struct axp2xx_reg_sc *sc; 737307885Smanu uint8_t val; 738307885Smanu 739307885Smanu sc = regnode_get_softc(regnode); 740307885Smanu 741307885Smanu if (!sc->def->voltage_step) 742307885Smanu return (ENXIO); 743307885Smanu 744309758Smanu axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1); 745309758Smanu axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt); 746307885Smanu 747307885Smanu return (0); 748307885Smanu} 749307885Smanu 750309758Smanustatic regnode_method_t axp2xx_regnode_methods[] = { 751307885Smanu /* Regulator interface */ 752309758Smanu REGNODEMETHOD(regnode_init, axp2xx_regnode_init), 753309758Smanu REGNODEMETHOD(regnode_enable, axp2xx_regnode_enable), 754309758Smanu REGNODEMETHOD(regnode_set_voltage, axp2xx_regnode_set_voltage), 755309758Smanu REGNODEMETHOD(regnode_get_voltage, axp2xx_regnode_get_voltage), 756307885Smanu REGNODEMETHOD_END 757307885Smanu}; 758309758SmanuDEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods, 759309758Smanu sizeof(struct axp2xx_reg_sc), regnode_class); 760307885Smanu 761307885Smanustatic int 762309758Smanuaxp2xx_sysctl(SYSCTL_HANDLER_ARGS) 763295658Sandrew{ 764309758Smanu struct axp2xx_softc *sc; 765295658Sandrew device_t dev = arg1; 766309758Smanu enum axp2xx_sensor sensor = arg2; 767295658Sandrew uint8_t data[2]; 768309758Smanu int val, error, i, found; 769295658Sandrew 770309758Smanu sc = device_get_softc(dev); 771295658Sandrew 772309758Smanu for (found = 0, i = 0; i < sc->nsensors; i++) { 773309758Smanu if (sc->sensors[i].id == sensor) { 774309758Smanu found = 1; 775309758Smanu break; 776309758Smanu } 777309758Smanu } 778295658Sandrew 779309758Smanu if (found == 0) 780309758Smanu return (ENOENT); 781295658Sandrew 782309758Smanu error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2); 783309758Smanu if (error != 0) 784309758Smanu return (error); 785300777Smanu 786309758Smanu val = ((data[0] & sc->sensors[i].h_value_mask) << 787309758Smanu sc->sensors[i].h_value_shift); 788309758Smanu val |= ((data[1] & sc->sensors[i].l_value_mask) << 789309758Smanu sc->sensors[i].l_value_shift); 790309758Smanu val *= sc->sensors[i].value_step; 791309758Smanu val += sc->sensors[i].value_convert; 792300777Smanu 793295658Sandrew return sysctl_handle_opaque(oidp, &val, sizeof(val), req); 794295658Sandrew} 795295658Sandrew 796295634Sandrewstatic void 797309758Smanuaxp2xx_shutdown(void *devp, int howto) 798295634Sandrew{ 799295634Sandrew device_t dev; 800295634Sandrew 801295634Sandrew if (!(howto & RB_POWEROFF)) 802295634Sandrew return; 803295634Sandrew dev = (device_t)devp; 804295634Sandrew 805295634Sandrew if (bootverbose) 806309758Smanu device_printf(dev, "Shutdown AXP2xx\n"); 807295634Sandrew 808309758Smanu axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN); 809295634Sandrew} 810295634Sandrew 811300777Smanustatic void 812309758Smanuaxp2xx_intr(void *arg) 813300777Smanu{ 814309758Smanu struct axp2xx_softc *sc; 815300777Smanu uint8_t reg; 816300777Smanu 817300777Smanu sc = arg; 818300777Smanu 819309758Smanu axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, ®, 1); 820300777Smanu if (reg) { 821309758Smanu if (reg & AXP2XX_IRQ1_AC_OVERVOLT) 822300777Smanu devctl_notify("PMU", "AC", "overvoltage", NULL); 823309758Smanu if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT) 824300777Smanu devctl_notify("PMU", "USB", "overvoltage", NULL); 825309758Smanu if (reg & AXP2XX_IRQ1_VBUS_LOW) 826300777Smanu devctl_notify("PMU", "USB", "undervoltage", NULL); 827309758Smanu if (reg & AXP2XX_IRQ1_AC_CONN) 828300777Smanu devctl_notify("PMU", "AC", "plugged", NULL); 829309758Smanu if (reg & AXP2XX_IRQ1_AC_DISCONN) 830300777Smanu devctl_notify("PMU", "AC", "unplugged", NULL); 831309758Smanu if (reg & AXP2XX_IRQ1_VBUS_CONN) 832300777Smanu devctl_notify("PMU", "USB", "plugged", NULL); 833309758Smanu if (reg & AXP2XX_IRQ1_VBUS_DISCONN) 834300777Smanu devctl_notify("PMU", "USB", "unplugged", NULL); 835309758Smanu axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK); 836300777Smanu } 837300777Smanu 838309758Smanu axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, ®, 1); 839300777Smanu if (reg) { 840309758Smanu if (reg & AXP2XX_IRQ2_BATT_CHARGED) 841300777Smanu devctl_notify("PMU", "Battery", "charged", NULL); 842309758Smanu if (reg & AXP2XX_IRQ2_BATT_CHARGING) 843300777Smanu devctl_notify("PMU", "Battery", "charging", NULL); 844309758Smanu if (reg & AXP2XX_IRQ2_BATT_CONN) 845300777Smanu devctl_notify("PMU", "Battery", "connected", NULL); 846309758Smanu if (reg & AXP2XX_IRQ2_BATT_DISCONN) 847300777Smanu devctl_notify("PMU", "Battery", "disconnected", NULL); 848309758Smanu if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW) 849300777Smanu devctl_notify("PMU", "Battery", "low temp", NULL); 850309758Smanu if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER) 851300777Smanu devctl_notify("PMU", "Battery", "high temp", NULL); 852309758Smanu axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK); 853300777Smanu } 854300777Smanu 855309758Smanu axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, ®, 1); 856300777Smanu if (reg) { 857309758Smanu if (reg & AXP2XX_IRQ3_PEK_SHORT) 858300777Smanu shutdown_nice(RB_POWEROFF); 859309758Smanu axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK); 860300777Smanu } 861300777Smanu 862309758Smanu axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, ®, 1); 863300777Smanu if (reg) { 864309758Smanu axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK); 865300777Smanu } 866300777Smanu 867309758Smanu axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, ®, 1); 868300777Smanu if (reg) { 869309758Smanu axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK); 870300777Smanu } 871300777Smanu} 872300777Smanu 873300777Smanustatic device_t 874309758Smanuaxp2xx_gpio_get_bus(device_t dev) 875300777Smanu{ 876309758Smanu struct axp2xx_softc *sc; 877300777Smanu 878300777Smanu sc = device_get_softc(dev); 879300777Smanu 880300777Smanu return (sc->gpiodev); 881300777Smanu} 882300777Smanu 883295634Sandrewstatic int 884309758Smanuaxp2xx_gpio_pin_max(device_t dev, int *maxpin) 885295634Sandrew{ 886309758Smanu struct axp2xx_softc *sc; 887295634Sandrew 888309758Smanu sc = device_get_softc(dev); 889309758Smanu 890309758Smanu *maxpin = sc->npins - 1; 891309758Smanu 892300777Smanu return (0); 893300777Smanu} 894295634Sandrew 895300777Smanustatic int 896309758Smanuaxp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 897300777Smanu{ 898309758Smanu struct axp2xx_softc *sc; 899309758Smanu 900309758Smanu sc = device_get_softc(dev); 901309758Smanu 902309758Smanu if (pin >= sc->npins) 903300777Smanu return (EINVAL); 904295634Sandrew 905300777Smanu snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name); 906295634Sandrew 907300777Smanu return (0); 908295634Sandrew} 909295634Sandrew 910295634Sandrewstatic int 911309758Smanuaxp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 912295634Sandrew{ 913309758Smanu struct axp2xx_softc *sc; 914309758Smanu 915309758Smanu sc = device_get_softc(dev); 916309758Smanu 917309758Smanu if (pin >= sc->npins) 918300777Smanu return (EINVAL); 919300777Smanu 920300777Smanu *caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 921300777Smanu 922300777Smanu return (0); 923300777Smanu} 924300777Smanu 925300777Smanustatic int 926309758Smanuaxp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 927300777Smanu{ 928309758Smanu struct axp2xx_softc *sc; 929300777Smanu uint8_t data, func; 930300777Smanu int error; 931300777Smanu 932309758Smanu sc = device_get_softc(dev); 933309758Smanu 934309758Smanu if (pin >= sc->npins) 935300777Smanu return (EINVAL); 936300777Smanu 937300777Smanu AXP_LOCK(sc); 938309758Smanu error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1); 939300777Smanu if (error == 0) { 940309758Smanu func = data & AXP2XX_GPIO_FUNC_MASK; 941309758Smanu if (func == AXP2XX_GPIO_FUNC_INPUT) 942300777Smanu *flags = GPIO_PIN_INPUT; 943309758Smanu else if (func == AXP2XX_GPIO_FUNC_DRVLO || 944309758Smanu func == AXP2XX_GPIO_FUNC_DRVHI) 945300777Smanu *flags = GPIO_PIN_OUTPUT; 946300777Smanu else 947300777Smanu *flags = 0; 948300777Smanu } 949300777Smanu AXP_UNLOCK(sc); 950300777Smanu 951300777Smanu return (error); 952300777Smanu} 953300777Smanu 954300777Smanustatic int 955309758Smanuaxp2xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 956300777Smanu{ 957309758Smanu struct axp2xx_softc *sc; 958300777Smanu uint8_t data; 959300777Smanu int error; 960300777Smanu 961309758Smanu sc = device_get_softc(dev); 962309758Smanu 963309758Smanu if (pin >= sc->npins) 964300777Smanu return (EINVAL); 965300777Smanu 966300777Smanu AXP_LOCK(sc); 967309758Smanu error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1); 968300777Smanu if (error == 0) { 969309758Smanu data &= ~AXP2XX_GPIO_FUNC_MASK; 970300777Smanu if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) { 971300777Smanu if ((flags & GPIO_PIN_OUTPUT) == 0) 972309758Smanu data |= AXP2XX_GPIO_FUNC_INPUT; 973300777Smanu } 974309758Smanu error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data); 975300777Smanu } 976300777Smanu AXP_UNLOCK(sc); 977300777Smanu 978300777Smanu return (error); 979300777Smanu} 980300777Smanu 981300777Smanustatic int 982309758Smanuaxp2xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 983300777Smanu{ 984309758Smanu struct axp2xx_softc *sc; 985300777Smanu uint8_t data, func; 986300777Smanu int error; 987300777Smanu 988309758Smanu sc = device_get_softc(dev); 989309758Smanu 990309758Smanu if (pin >= sc->npins) 991300777Smanu return (EINVAL); 992300777Smanu 993300777Smanu AXP_LOCK(sc); 994309758Smanu error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1); 995300777Smanu if (error == 0) { 996309758Smanu func = data & AXP2XX_GPIO_FUNC_MASK; 997300777Smanu switch (func) { 998309758Smanu case AXP2XX_GPIO_FUNC_DRVLO: 999300777Smanu *val = 0; 1000300777Smanu break; 1001309758Smanu case AXP2XX_GPIO_FUNC_DRVHI: 1002300777Smanu *val = 1; 1003300777Smanu break; 1004309758Smanu case AXP2XX_GPIO_FUNC_INPUT: 1005309758Smanu error = axp2xx_read(dev, sc->pins[pin].status_reg, 1006309758Smanu &data, 1); 1007309758Smanu if (error == 0) { 1008309758Smanu *val = (data & sc->pins[pin].status_mask); 1009309758Smanu *val >>= sc->pins[pin].status_shift; 1010309758Smanu } 1011300777Smanu break; 1012300777Smanu default: 1013300777Smanu error = EIO; 1014300777Smanu break; 1015300777Smanu } 1016300777Smanu } 1017300777Smanu AXP_UNLOCK(sc); 1018300777Smanu 1019300777Smanu return (error); 1020300777Smanu} 1021300777Smanu 1022300777Smanustatic int 1023309758Smanuaxp2xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val) 1024300777Smanu{ 1025309758Smanu struct axp2xx_softc *sc; 1026300777Smanu uint8_t data, func; 1027300777Smanu int error; 1028300777Smanu 1029309758Smanu sc = device_get_softc(dev); 1030309758Smanu 1031309758Smanu if (pin >= sc->npins) 1032300777Smanu return (EINVAL); 1033300777Smanu 1034300777Smanu AXP_LOCK(sc); 1035309758Smanu error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1); 1036300777Smanu if (error == 0) { 1037309758Smanu func = data & AXP2XX_GPIO_FUNC_MASK; 1038300777Smanu switch (func) { 1039309758Smanu case AXP2XX_GPIO_FUNC_DRVLO: 1040309758Smanu case AXP2XX_GPIO_FUNC_DRVHI: 1041300777Smanu /* GPIO2 can't be set to 1 */ 1042300777Smanu if (pin == 2 && val == 1) { 1043300777Smanu error = EINVAL; 1044300777Smanu break; 1045300777Smanu } 1046309758Smanu data &= ~AXP2XX_GPIO_FUNC_MASK; 1047300777Smanu data |= val; 1048300777Smanu break; 1049300777Smanu default: 1050300777Smanu error = EIO; 1051300777Smanu break; 1052300777Smanu } 1053300777Smanu } 1054300777Smanu if (error == 0) 1055309758Smanu error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data); 1056300777Smanu AXP_UNLOCK(sc); 1057300777Smanu 1058300777Smanu return (error); 1059300777Smanu} 1060300777Smanu 1061300777Smanu 1062300777Smanustatic int 1063309758Smanuaxp2xx_gpio_pin_toggle(device_t dev, uint32_t pin) 1064300777Smanu{ 1065309758Smanu struct axp2xx_softc *sc; 1066300777Smanu uint8_t data, func; 1067300777Smanu int error; 1068300777Smanu 1069309758Smanu sc = device_get_softc(dev); 1070309758Smanu 1071309758Smanu if (pin >= sc->npins) 1072300777Smanu return (EINVAL); 1073300777Smanu 1074300777Smanu AXP_LOCK(sc); 1075309758Smanu error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1); 1076300777Smanu if (error == 0) { 1077309758Smanu func = data & AXP2XX_GPIO_FUNC_MASK; 1078300777Smanu switch (func) { 1079309758Smanu case AXP2XX_GPIO_FUNC_DRVLO: 1080300777Smanu /* Pin 2 can't be set to 1*/ 1081300777Smanu if (pin == 2) { 1082300777Smanu error = EINVAL; 1083300777Smanu break; 1084300777Smanu } 1085309758Smanu data &= ~AXP2XX_GPIO_FUNC_MASK; 1086309758Smanu data |= AXP2XX_GPIO_FUNC_DRVHI; 1087300777Smanu break; 1088309758Smanu case AXP2XX_GPIO_FUNC_DRVHI: 1089309758Smanu data &= ~AXP2XX_GPIO_FUNC_MASK; 1090309758Smanu data |= AXP2XX_GPIO_FUNC_DRVLO; 1091300777Smanu break; 1092300777Smanu default: 1093300777Smanu error = EIO; 1094300777Smanu break; 1095300777Smanu } 1096300777Smanu } 1097300777Smanu if (error == 0) 1098309758Smanu error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data); 1099300777Smanu AXP_UNLOCK(sc); 1100300777Smanu 1101300777Smanu return (error); 1102300777Smanu} 1103300777Smanu 1104300777Smanustatic int 1105309758Smanuaxp2xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, 1106300777Smanu int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags) 1107300777Smanu{ 1108309758Smanu struct axp2xx_softc *sc; 1109309758Smanu 1110309758Smanu sc = device_get_softc(bus); 1111309758Smanu 1112309758Smanu if (gpios[0] >= sc->npins) 1113300777Smanu return (EINVAL); 1114300777Smanu 1115300777Smanu *pin = gpios[0]; 1116300777Smanu *flags = gpios[1]; 1117300777Smanu 1118300777Smanu return (0); 1119300777Smanu} 1120300777Smanu 1121300777Smanustatic phandle_t 1122309758Smanuaxp2xx_get_node(device_t dev, device_t bus) 1123300777Smanu{ 1124300777Smanu return (ofw_bus_get_node(dev)); 1125300777Smanu} 1126300777Smanu 1127309758Smanustatic struct axp2xx_reg_sc * 1128309758Smanuaxp2xx_reg_attach(device_t dev, phandle_t node, 1129309758Smanu struct axp2xx_regdef *def) 1130307885Smanu{ 1131309758Smanu struct axp2xx_reg_sc *reg_sc; 1132307885Smanu struct regnode_init_def initdef; 1133307885Smanu struct regnode *regnode; 1134307885Smanu 1135307885Smanu memset(&initdef, 0, sizeof(initdef)); 1136307885Smanu if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) { 1137307885Smanu device_printf(dev, "cannot create regulator\n"); 1138307885Smanu return (NULL); 1139307885Smanu } 1140307885Smanu if (initdef.std_param.min_uvolt == 0) 1141307885Smanu initdef.std_param.min_uvolt = def->voltage_min * 1000; 1142307885Smanu if (initdef.std_param.max_uvolt == 0) 1143307885Smanu initdef.std_param.max_uvolt = def->voltage_max * 1000; 1144307885Smanu initdef.id = def->id; 1145307885Smanu initdef.ofw_node = node; 1146309758Smanu regnode = regnode_create(dev, &axp2xx_regnode_class, &initdef); 1147307885Smanu if (regnode == NULL) { 1148307885Smanu device_printf(dev, "cannot create regulator\n"); 1149307885Smanu return (NULL); 1150307885Smanu } 1151307885Smanu 1152307885Smanu reg_sc = regnode_get_softc(regnode); 1153307885Smanu reg_sc->regnode = regnode; 1154307885Smanu reg_sc->base_dev = dev; 1155307885Smanu reg_sc->def = def; 1156307885Smanu reg_sc->xref = OF_xref_from_node(node); 1157307885Smanu reg_sc->param = regnode_get_stdparam(regnode); 1158307885Smanu 1159307885Smanu regnode_register(regnode); 1160307885Smanu 1161307885Smanu return (reg_sc); 1162307885Smanu} 1163307885Smanu 1164307885Smanustatic int 1165309758Smanuaxp2xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells, 1166307885Smanu intptr_t *num) 1167307885Smanu{ 1168309758Smanu struct axp2xx_softc *sc; 1169307885Smanu int i; 1170307885Smanu 1171307885Smanu sc = device_get_softc(dev); 1172307885Smanu for (i = 0; i < sc->nregs; i++) { 1173307885Smanu if (sc->regs[i] == NULL) 1174307885Smanu continue; 1175307885Smanu if (sc->regs[i]->xref == xref) { 1176307885Smanu *num = sc->regs[i]->def->id; 1177307885Smanu return (0); 1178307885Smanu } 1179307885Smanu } 1180307885Smanu 1181307885Smanu return (ENXIO); 1182307885Smanu} 1183307885Smanu 1184300777Smanustatic void 1185309758Smanuaxp2xx_start(void *pdev) 1186300777Smanu{ 1187300777Smanu device_t dev; 1188309758Smanu struct axp2xx_softc *sc; 1189295654Sandrew const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"}; 1190309758Smanu int i; 1191309758Smanu uint8_t reg, data; 1192295634Sandrew uint8_t pwr_src; 1193295634Sandrew 1194300777Smanu dev = pdev; 1195300777Smanu 1196295634Sandrew sc = device_get_softc(dev); 1197300777Smanu sc->dev = dev; 1198295634Sandrew 1199295654Sandrew if (bootverbose) { 1200295654Sandrew /* 1201295654Sandrew * Read the Power State register. 1202295654Sandrew * Shift the AC presence into bit 0. 1203295654Sandrew * Shift the Battery presence into bit 1. 1204295654Sandrew */ 1205309758Smanu axp2xx_read(dev, AXP2XX_PSR, &data, 1); 1206309758Smanu pwr_src = ((data & AXP2XX_PSR_ACIN) >> AXP2XX_PSR_ACIN_SHIFT) | 1207309758Smanu ((data & AXP2XX_PSR_VBUS) >> (AXP2XX_PSR_VBUS_SHIFT - 1)); 1208295634Sandrew 1209309758Smanu device_printf(dev, "Powered by %s\n", 1210295634Sandrew pwr_name[pwr_src]); 1211295654Sandrew } 1212295634Sandrew 1213300777Smanu /* Only enable interrupts that we are interested in */ 1214309758Smanu axp2xx_write(dev, AXP2XX_IRQ1_ENABLE, 1215309758Smanu AXP2XX_IRQ1_AC_OVERVOLT | 1216309758Smanu AXP2XX_IRQ1_AC_DISCONN | 1217309758Smanu AXP2XX_IRQ1_AC_CONN | 1218309758Smanu AXP2XX_IRQ1_VBUS_OVERVOLT | 1219309758Smanu AXP2XX_IRQ1_VBUS_DISCONN | 1220309758Smanu AXP2XX_IRQ1_VBUS_CONN); 1221309758Smanu axp2xx_write(dev, AXP2XX_IRQ2_ENABLE, 1222309758Smanu AXP2XX_IRQ2_BATT_CONN | 1223309758Smanu AXP2XX_IRQ2_BATT_DISCONN | 1224309758Smanu AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON | 1225309758Smanu AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF | 1226309758Smanu AXP2XX_IRQ2_BATT_CHARGING | 1227309758Smanu AXP2XX_IRQ2_BATT_CHARGED | 1228309758Smanu AXP2XX_IRQ2_BATT_TEMP_OVER | 1229309758Smanu AXP2XX_IRQ2_BATT_TEMP_LOW); 1230309758Smanu axp2xx_write(dev, AXP2XX_IRQ3_ENABLE, 1231309758Smanu AXP2XX_IRQ3_PEK_SHORT | AXP2XX_IRQ3_PEK_LONG); 1232309758Smanu axp2xx_write(dev, AXP2XX_IRQ4_ENABLE, AXP2XX_IRQ4_APS_LOW_2); 1233309758Smanu axp2xx_write(dev, AXP2XX_IRQ5_ENABLE, 0x0); 1234300777Smanu 1235309758Smanu EVENTHANDLER_REGISTER(shutdown_final, axp2xx_shutdown, dev, 1236295634Sandrew SHUTDOWN_PRI_LAST); 1237295634Sandrew 1238300777Smanu /* Enable ADC sensors */ 1239309758Smanu for (i = 0; i < sc->nsensors; i++) { 1240309758Smanu if (axp2xx_read(dev, sc->sensors[i].enable_reg, ®, 1) == -1) { 1241309758Smanu device_printf(dev, "Cannot enable sensor '%s'\n", 1242309758Smanu sc->sensors[i].name); 1243309758Smanu continue; 1244309758Smanu } 1245309758Smanu reg |= sc->sensors[i].enable_mask; 1246309758Smanu if (axp2xx_write(dev, sc->sensors[i].enable_reg, reg) == -1) { 1247309758Smanu device_printf(dev, "Cannot enable sensor '%s'\n", 1248309758Smanu sc->sensors[i].name); 1249309758Smanu continue; 1250309758Smanu } 1251300777Smanu SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1252300777Smanu SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1253309758Smanu OID_AUTO, sc->sensors[i].name, 1254300777Smanu CTLTYPE_INT | CTLFLAG_RD, 1255309758Smanu dev, sc->sensors[i].id, axp2xx_sysctl, 1256309758Smanu sc->sensors[i].format, 1257309758Smanu sc->sensors[i].desc); 1258300777Smanu } 1259300777Smanu 1260300777Smanu if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE, 1261309758Smanu NULL, axp2xx_intr, sc, &sc->intrcookie))) 1262300777Smanu device_printf(dev, "unable to register interrupt handler\n"); 1263300777Smanu 1264300777Smanu config_intrhook_disestablish(&sc->intr_hook); 1265300777Smanu} 1266300777Smanu 1267300777Smanustatic int 1268309758Smanuaxp2xx_probe(device_t dev) 1269300777Smanu{ 1270300777Smanu 1271300777Smanu if (!ofw_bus_status_okay(dev)) 1272300777Smanu return (ENXIO); 1273300777Smanu 1274309758Smanu switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) 1275309758Smanu { 1276309758Smanu case AXP209: 1277309758Smanu device_set_desc(dev, "X-Powers AXP209 Power Management Unit"); 1278309758Smanu break; 1279309758Smanu case AXP221: 1280309758Smanu device_set_desc(dev, "X-Powers AXP221 Power Management Unit"); 1281309758Smanu break; 1282309758Smanu default: 1283300777Smanu return (ENXIO); 1284309758Smanu } 1285300777Smanu 1286300777Smanu return (BUS_PROBE_DEFAULT); 1287300777Smanu} 1288300777Smanu 1289300777Smanustatic int 1290309758Smanuaxp2xx_attach(device_t dev) 1291300777Smanu{ 1292309758Smanu struct axp2xx_softc *sc; 1293309758Smanu struct axp2xx_reg_sc *reg; 1294309758Smanu struct axp2xx_regdef *regdefs; 1295307885Smanu phandle_t rnode, child; 1296307885Smanu int i; 1297300777Smanu 1298300777Smanu sc = device_get_softc(dev); 1299300777Smanu mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); 1300300777Smanu 1301300777Smanu if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) { 1302300777Smanu device_printf(dev, "can't allocate device resources\n"); 1303300777Smanu return (ENXIO); 1304300777Smanu } 1305300777Smanu 1306309758Smanu sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; 1307309758Smanu switch (sc->type) { 1308309758Smanu case AXP209: 1309309758Smanu sc->pins = axp209_pins; 1310309758Smanu sc->npins = nitems(axp209_pins); 1311309758Smanu sc->gpiodev = gpiobus_attach_bus(dev); 1312309758Smanu 1313309758Smanu sc->sensors = axp209_sensors; 1314309758Smanu sc->nsensors = nitems(axp209_sensors); 1315309758Smanu 1316309758Smanu regdefs = axp209_regdefs; 1317309758Smanu sc->nregs = nitems(axp209_regdefs); 1318309758Smanu break; 1319309758Smanu case AXP221: 1320309758Smanu sc->pins = axp221_pins; 1321309758Smanu sc->npins = nitems(axp221_pins); 1322309758Smanu sc->gpiodev = gpiobus_attach_bus(dev); 1323309758Smanu 1324309758Smanu sc->sensors = axp221_sensors; 1325309758Smanu sc->nsensors = nitems(axp221_sensors); 1326309758Smanu 1327309758Smanu regdefs = axp221_regdefs; 1328309758Smanu sc->nregs = nitems(axp221_regdefs); 1329309758Smanu break; 1330309758Smanu } 1331309758Smanu 1332309758Smanu sc->regs = malloc(sizeof(struct axp2xx_reg_sc *) * sc->nregs, 1333309758Smanu M_AXP2XX_REG, M_WAITOK | M_ZERO); 1334309758Smanu 1335309758Smanu sc->intr_hook.ich_func = axp2xx_start; 1336300777Smanu sc->intr_hook.ich_arg = dev; 1337300777Smanu 1338300777Smanu if (config_intrhook_establish(&sc->intr_hook) != 0) 1339300777Smanu return (ENOMEM); 1340300777Smanu 1341307885Smanu /* Attach known regulators that exist in the DT */ 1342307885Smanu rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators"); 1343307885Smanu if (rnode > 0) { 1344307885Smanu for (i = 0; i < sc->nregs; i++) { 1345307885Smanu child = ofw_bus_find_child(rnode, 1346309758Smanu regdefs[i].name); 1347307885Smanu if (child == 0) 1348307885Smanu continue; 1349309758Smanu reg = axp2xx_reg_attach(dev, child, ®defs[i]); 1350307885Smanu if (reg == NULL) { 1351307885Smanu device_printf(dev, 1352307885Smanu "cannot attach regulator %s\n", 1353309758Smanu regdefs[i].name); 1354307885Smanu continue; 1355307885Smanu } 1356307885Smanu sc->regs[i] = reg; 1357309758Smanu if (bootverbose) 1358309758Smanu device_printf(dev, "Regulator %s attached\n", 1359309758Smanu regdefs[i].name); 1360307885Smanu } 1361307885Smanu } 1362307885Smanu 1363295634Sandrew return (0); 1364295634Sandrew} 1365295634Sandrew 1366309758Smanustatic device_method_t axp2xx_methods[] = { 1367309758Smanu DEVMETHOD(device_probe, axp2xx_probe), 1368309758Smanu DEVMETHOD(device_attach, axp2xx_attach), 1369300777Smanu 1370300777Smanu /* GPIO interface */ 1371309758Smanu DEVMETHOD(gpio_get_bus, axp2xx_gpio_get_bus), 1372309758Smanu DEVMETHOD(gpio_pin_max, axp2xx_gpio_pin_max), 1373309758Smanu DEVMETHOD(gpio_pin_getname, axp2xx_gpio_pin_getname), 1374309758Smanu DEVMETHOD(gpio_pin_getcaps, axp2xx_gpio_pin_getcaps), 1375309758Smanu DEVMETHOD(gpio_pin_getflags, axp2xx_gpio_pin_getflags), 1376309758Smanu DEVMETHOD(gpio_pin_setflags, axp2xx_gpio_pin_setflags), 1377309758Smanu DEVMETHOD(gpio_pin_get, axp2xx_gpio_pin_get), 1378309758Smanu DEVMETHOD(gpio_pin_set, axp2xx_gpio_pin_set), 1379309758Smanu DEVMETHOD(gpio_pin_toggle, axp2xx_gpio_pin_toggle), 1380309758Smanu DEVMETHOD(gpio_map_gpios, axp2xx_gpio_map_gpios), 1381300777Smanu 1382307885Smanu /* Regdev interface */ 1383309758Smanu DEVMETHOD(regdev_map, axp2xx_regdev_map), 1384307885Smanu 1385300777Smanu /* OFW bus interface */ 1386309758Smanu DEVMETHOD(ofw_bus_get_node, axp2xx_get_node), 1387300777Smanu 1388300777Smanu DEVMETHOD_END 1389295634Sandrew}; 1390295634Sandrew 1391309758Smanustatic driver_t axp2xx_driver = { 1392309758Smanu "axp2xx_pmu", 1393309758Smanu axp2xx_methods, 1394309758Smanu sizeof(struct axp2xx_softc), 1395295634Sandrew}; 1396295634Sandrew 1397309758Smanustatic devclass_t axp2xx_devclass; 1398300777Smanuextern devclass_t ofwgpiobus_devclass, gpioc_devclass; 1399300777Smanuextern driver_t ofw_gpiobus_driver, gpioc_driver; 1400295634Sandrew 1401309758SmanuEARLY_DRIVER_MODULE(axp2xx, iicbus, axp2xx_driver, axp2xx_devclass, 1402304214Smanu 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 1403309758SmanuEARLY_DRIVER_MODULE(ofw_gpiobus, axp2xx_pmu, ofw_gpiobus_driver, 1404304214Smanu ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 1405309758SmanuDRIVER_MODULE(gpioc, axp2xx_pmu, gpioc_driver, gpioc_devclass, 1406304214Smanu 0, 0); 1407309758SmanuMODULE_VERSION(axp2xx, 1); 1408323467SianMODULE_DEPEND(axp2xx, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 1409