Home | History | Annotate | Line # | Download | only in i2c
axp20x.c revision 1.11
      1 /* $NetBSD: axp20x.c,v 1.11 2018/06/16 21:22:13 thorpej Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2014-2017 Jared McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "opt_fdt.h"
     30 
     31 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.11 2018/06/16 21:22:13 thorpej Exp $");
     33 
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/device.h>
     37 #include <sys/conf.h>
     38 #include <sys/bus.h>
     39 #include <sys/kmem.h>
     40 
     41 #include <dev/i2c/i2cvar.h>
     42 #include <dev/i2c/axp20xvar.h>
     43 
     44 #include <dev/sysmon/sysmonvar.h>
     45 
     46 #ifdef FDT
     47 #include <dev/fdt/fdtvar.h>
     48 #endif
     49 
     50 #define	AXP209_I2C_ADDR		0x34
     51 
     52 #define AXP_INPUT_STATUS	0x00
     53 #define AXP_INPUT_STATUS_AC_PRESENT	__BIT(7)
     54 #define AXP_INPUT_STATUS_AC_OK		__BIT(6)
     55 #define AXP_INPUT_STATUS_VBUS_PRESENT	__BIT(5)
     56 #define AXP_INPUT_STATUS_VBUS_OK	__BIT(4)
     57 
     58 #define AXP_POWER_MODE		0x01
     59 #define AXP_POWER_MODE_OVERTEMP		__BIT(7)
     60 #define AXP_POWER_MODE_CHARGING		__BIT(6)
     61 #define AXP_POWER_MODE_BATTOK		__BIT(5)
     62 
     63 #define AXP_POWEROUT_CTRL	0x12
     64 #define AXP_POWEROUT_CTRL_LDO3		__BIT(6)
     65 #define AXP_POWEROUT_CTRL_DCDC2		__BIT(4)
     66 #define AXP_POWEROUT_CTRL_LDO4		__BIT(3)
     67 #define AXP_POWEROUT_CTRL_LDO2		__BIT(2)
     68 #define AXP_POWEROUT_CTRL_DCDC3		__BIT(1)
     69 #define AXP_POWEROUT_CTRL_EXTEN		__BIT(0)
     70 
     71 #define AXP_DCDC2		0x23
     72 #define AXP_DCDC2_VOLT_MASK		__BITS(0,5)
     73 #define AXP_DCDC2_VOLT_SHIFT		0
     74 
     75 #define AXP_DCDC2_LDO3_VRC	0x25
     76 
     77 #define AXP_DCDC3		0x27
     78 #define AXP_DCDC3_VOLT_MASK		__BITS(0,6)
     79 #define AXP_DCDC3_VOLT_SHIFT		0
     80 
     81 #define AXP_LDO2_4		0x28
     82 #define AXP_LDO2_VOLT_MASK		__BITS(4,7)
     83 #define AXP_LDO2_VOLT_SHIFT		4
     84 #define AXP_LDO4_VOLT_MASK		__BITS(0,3)
     85 #define AXP_LDO4_VOLT_SHIFT		0
     86 static int ldo4_mvV[] = {
     87 	1250,
     88 	1300,
     89 	1400,
     90 	1500,
     91 	1600,
     92 	1700,
     93 	1800,
     94 	1900,
     95 	2000,
     96 	2500,
     97 	2700,
     98 	2800,
     99 	3000,
    100 	3100,
    101 	3200,
    102 	3300
    103 };
    104 
    105 #define AXP_LDO3		0x29
    106 #define AXP_LDO3_TRACK			__BIT(7)
    107 #define AXP_LDO3_VOLT_MASK		__BITS(0,6)
    108 #define AXP_LDO3_VOLT_SHIFT		0
    109 
    110 #define	AXP_SHUTDOWN		0x32
    111 #define	AXP_SHUTDOWN_CTRL	__BIT(7)
    112 
    113 #define AXP_BKUP_CTRL			0x35
    114 #define AXP_BKUP_CTRL_ENABLE		__BIT(7)
    115 #define AXP_BKUP_CTRL_VOLT_MASK		__BITS(5,6)
    116 #define AXP_BKUP_CTRL_VOLT_SHIFT	5
    117 #define AXP_BKUP_CTRL_VOLT_3V1		0
    118 #define AXP_BKUP_CTRL_VOLT_3V0		1
    119 #define AXP_BKUP_CTRL_VOLT_3V6		2
    120 #define AXP_BKUP_CTRL_VOLT_2V5		3
    121 static int bkup_volt[] = {
    122 	3100,
    123 	3000,
    124 	3600,
    125 	2500
    126 };
    127 #define AXP_BKUP_CTRL_CURR_MASK		__BITS(0,1)
    128 #define AXP_BKUP_CTRL_CURR_SHIFT	0
    129 #define AXP_BKUP_CTRL_CURR_50U		0
    130 #define AXP_BKUP_CTRL_CURR_100U		1
    131 #define AXP_BKUP_CTRL_CURR_200U		2
    132 #define AXP_BKUP_CTRL_CURR_400U		3
    133 static int bkup_curr[] = {
    134 	50,
    135 	100,
    136 	200,
    137 	400
    138 };
    139 
    140 #define AXP_ACV_MON_REG		0x56	/* 2 bytes */
    141 #define AXP_ACI_MON_REG		0x58	/* 2 bytes */
    142 #define AXP_VBUSV_MON_REG	0x5a	/* 2 bytes */
    143 #define AXP_VBUSI_MON_REG	0x5c	/* 2 bytes */
    144 #define AXP_TEMP_MON_REG	0x5e	/* 2 bytes */
    145 #define AXP_BATTV_MON_REG	0x78	/* 2 bytes */
    146 #define AXP_BATTCI_MON_REG	0x7a	/* 2 bytes */
    147 #define AXP_BATTDI_MON_REG	0x7c	/* 2 bytes */
    148 #define AXP_APSV_MON_REG	0x7e	/* 2 bytes */
    149 
    150 #define AXP_ADC_EN1		0x82
    151 #define AXP_ADC_EN1_BATTV		__BIT(7)
    152 #define AXP_ADC_EN1_BATTI		__BIT(6)
    153 #define AXP_ADC_EN1_ACV			__BIT(5)
    154 #define AXP_ADC_EN1_ACI			__BIT(4)
    155 #define AXP_ADC_EN1_VBUSV		__BIT(3)
    156 #define AXP_ADC_EN1_VBUSI		__BIT(2)
    157 #define AXP_ADC_EN1_APSV		__BIT(1)
    158 #define AXP_ADC_EN1_TS			__BIT(0)
    159 #define AXP_ADC_EN2		0x83
    160 #define AXP_ADC_EN2_TEMP		__BIT(7)
    161 
    162 #define AXP_SENSOR_ACOK		0
    163 #define AXP_SENSOR_ACV		1
    164 #define AXP_SENSOR_ACI		2
    165 #define AXP_SENSOR_VBUSOK	3
    166 #define AXP_SENSOR_VBUSV	4
    167 #define AXP_SENSOR_VBUSI	5
    168 #define AXP_SENSOR_BATTOK	6
    169 #define AXP_SENSOR_BATTV	7
    170 #define AXP_SENSOR_BATTI	8
    171 #define AXP_SENSOR_APSV		9
    172 #define AXP_SENSOR_TEMP		10
    173 #define AXP_NSENSORS (AXP_SENSOR_TEMP + 1)
    174 
    175 /* define per-ADC LSB to uV/uA values */
    176 static int axp20x_sensors_lsb[] = {
    177 	   0, /* AXP_SENSOR_ACOK */
    178 	1700, /* AXP_SENSOR_ACV */
    179 	 625, /* AXP_SENSOR_ACI */
    180 	   0,
    181 	1700, /* AXP_SENSOR_VBUSV */
    182 	 375, /* AXP_SENSOR_VBUSI */
    183 	   0,
    184 	1100, /* AXP_SENSOR_BATTV */
    185 	 500, /* AXP_SENSOR_BATTI */
    186 	1400, /* AXP_SENSOR_APSV */
    187 };
    188 
    189 
    190 struct axp20x_softc {
    191 	device_t	sc_dev;
    192 	i2c_tag_t	sc_i2c;
    193 	i2c_addr_t	sc_addr;
    194 	int		sc_phandle;
    195 
    196 	uint8_t 	sc_inputstatus;
    197 	uint8_t 	sc_powermode;
    198 
    199 	struct sysmon_envsys *sc_sme;
    200 	envsys_data_t	sc_sensor[AXP_NSENSORS];
    201 };
    202 
    203 static int	axp20x_match(device_t, cfdata_t, void *);
    204 static void	axp20x_attach(device_t, device_t, void *);
    205 
    206 static void	axp20x_sensors_refresh(struct sysmon_envsys *, envsys_data_t *);
    207 static int	axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
    208 static int	axp20x_write(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
    209 
    210 #ifdef FDT
    211 static void	axp20x_fdt_attach(struct axp20x_softc *);
    212 #endif
    213 
    214 CFATTACH_DECL_NEW(axp20x, sizeof(struct axp20x_softc),
    215     axp20x_match, axp20x_attach, NULL, NULL);
    216 
    217 static const char * compatible[] = {
    218 	"x-powers,axp209",
    219 	NULL
    220 };
    221 
    222 static int
    223 axp20x_match(device_t parent, cfdata_t match, void *aux)
    224 {
    225 	struct i2c_attach_args * const ia = aux;
    226 	int match_result;
    227 
    228 	if (iic_use_direct_match(ia, match, compatible, &match_result))
    229 		return match_result;
    230 
    231 	/* This device is direct-config only. */
    232 
    233 	return 0;
    234 }
    235 
    236 static void
    237 axp20x_attach(device_t parent, device_t self, void *aux)
    238 {
    239 	struct axp20x_softc *sc = device_private(self);
    240 	struct i2c_attach_args *ia = aux;
    241 	int first;
    242 	int error;
    243 	uint8_t value;
    244 
    245 	sc->sc_dev = self;
    246 	sc->sc_i2c = ia->ia_tag;
    247 	sc->sc_addr = ia->ia_addr;
    248 	sc->sc_phandle = ia->ia_cookie;
    249 
    250 	error = axp20x_read(sc, AXP_INPUT_STATUS,
    251 	    &sc->sc_inputstatus, 1, I2C_F_POLL);
    252 	if (error) {
    253 		aprint_error(": can't read status: %d\n", error);
    254 		return;
    255 	}
    256 	error = axp20x_read(sc, AXP_POWER_MODE,
    257 	    &sc->sc_powermode, 1, I2C_F_POLL);
    258 	if (error) {
    259 		aprint_error(": can't read power mode: %d\n", error);
    260 		return;
    261 	}
    262 	value = AXP_ADC_EN1_ACV | AXP_ADC_EN1_ACI | AXP_ADC_EN1_VBUSV | AXP_ADC_EN1_VBUSI | AXP_ADC_EN1_APSV | AXP_ADC_EN1_TS;
    263 	if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
    264 		value |= AXP_ADC_EN1_BATTV | AXP_ADC_EN1_BATTI;
    265 	error = axp20x_write(sc, AXP_ADC_EN1, &value, 1, I2C_F_POLL);
    266 	if (error) {
    267 		aprint_error(": can't set AXP_ADC_EN1\n");
    268 		return;
    269 	}
    270 	error = axp20x_read(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
    271 	if (error) {
    272 		aprint_error(": can't read AXP_ADC_EN2\n");
    273 		return;
    274 	}
    275 	value |= AXP_ADC_EN2_TEMP;
    276 	error = axp20x_write(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
    277 	if (error) {
    278 		aprint_error(": can't set AXP_ADC_EN2\n");
    279 		return;
    280 	}
    281 
    282 	aprint_naive("\n");
    283 	first = 1;
    284 	if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) {
    285 		aprint_verbose(": AC used");
    286 		first = 0;
    287 	} else if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_PRESENT) {
    288 		aprint_verbose(": AC present (but unused)");
    289 		first = 0;
    290 	}
    291 	if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) {
    292 		aprint_verbose("%s VBUS used", first ? ":" : ",");
    293 		first = 0;
    294 	} else if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_PRESENT) {
    295 		aprint_verbose("%s VBUS present (but unused)", first ? ":" : ",");
    296 		first = 0;
    297 	}
    298 	if (sc->sc_powermode & AXP_POWER_MODE_BATTOK) {
    299 		aprint_verbose("%s battery present", first ? ":" : ",");
    300 	}
    301 	aprint_normal("\n");
    302 
    303 	sc->sc_sme = sysmon_envsys_create();
    304 	sc->sc_sme->sme_name = device_xname(self);
    305 	sc->sc_sme->sme_cookie = sc;
    306 	sc->sc_sme->sme_refresh = axp20x_sensors_refresh;
    307 
    308 	sc->sc_sensor[AXP_SENSOR_ACOK].units = ENVSYS_INDICATOR;
    309 	sc->sc_sensor[AXP_SENSOR_ACOK].state = ENVSYS_SVALID;
    310 	sc->sc_sensor[AXP_SENSOR_ACOK].value_cur =
    311 	    (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
    312 	snprintf(sc->sc_sensor[AXP_SENSOR_ACOK].desc,
    313 	    sizeof(sc->sc_sensor[AXP_SENSOR_ACOK].desc), "AC input");
    314 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACOK]);
    315 	sc->sc_sensor[AXP_SENSOR_ACV].units = ENVSYS_SVOLTS_DC;
    316 	sc->sc_sensor[AXP_SENSOR_ACV].state = ENVSYS_SINVALID;
    317 	sc->sc_sensor[AXP_SENSOR_ACV].flags = ENVSYS_FHAS_ENTROPY;
    318 	snprintf(sc->sc_sensor[AXP_SENSOR_ACV].desc,
    319 	    sizeof(sc->sc_sensor[AXP_SENSOR_ACV].desc), "AC input voltage");
    320 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACV]);
    321 	sc->sc_sensor[AXP_SENSOR_ACI].units = ENVSYS_SAMPS;
    322 	sc->sc_sensor[AXP_SENSOR_ACI].state = ENVSYS_SINVALID;
    323 	sc->sc_sensor[AXP_SENSOR_ACI].flags = ENVSYS_FHAS_ENTROPY;
    324 	snprintf(sc->sc_sensor[AXP_SENSOR_ACI].desc,
    325 	    sizeof(sc->sc_sensor[AXP_SENSOR_ACI].desc), "AC input current");
    326 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACI]);
    327 
    328 	sc->sc_sensor[AXP_SENSOR_VBUSOK].units = ENVSYS_INDICATOR;
    329 	sc->sc_sensor[AXP_SENSOR_VBUSOK].state = ENVSYS_SVALID;
    330 	sc->sc_sensor[AXP_SENSOR_VBUSOK].value_cur =
    331 	    (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
    332 	snprintf(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc,
    333 	    sizeof(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc), "VBUS input");
    334 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSOK]);
    335 	sc->sc_sensor[AXP_SENSOR_VBUSV].units = ENVSYS_SVOLTS_DC;
    336 	sc->sc_sensor[AXP_SENSOR_VBUSV].state = ENVSYS_SINVALID;
    337 	sc->sc_sensor[AXP_SENSOR_VBUSV].flags = ENVSYS_FHAS_ENTROPY;
    338 	snprintf(sc->sc_sensor[AXP_SENSOR_VBUSV].desc,
    339 	    sizeof(sc->sc_sensor[AXP_SENSOR_VBUSV].desc), "VBUS input voltage");
    340 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSV]);
    341 	sc->sc_sensor[AXP_SENSOR_VBUSI].units = ENVSYS_SAMPS;
    342 	sc->sc_sensor[AXP_SENSOR_VBUSI].state = ENVSYS_SINVALID;
    343 	sc->sc_sensor[AXP_SENSOR_VBUSI].flags = ENVSYS_FHAS_ENTROPY;
    344 	snprintf(sc->sc_sensor[AXP_SENSOR_VBUSI].desc,
    345 	    sizeof(sc->sc_sensor[AXP_SENSOR_VBUSI].desc), "VBUS input current");
    346 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSI]);
    347 
    348 	sc->sc_sensor[AXP_SENSOR_BATTOK].units = ENVSYS_INDICATOR;
    349 	sc->sc_sensor[AXP_SENSOR_BATTOK].state = ENVSYS_SVALID;
    350 	sc->sc_sensor[AXP_SENSOR_BATTOK].value_cur =
    351 	    (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
    352 	snprintf(sc->sc_sensor[AXP_SENSOR_BATTOK].desc,
    353 	    sizeof(sc->sc_sensor[AXP_SENSOR_BATTOK].desc), "battery");
    354 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTOK]);
    355 	sc->sc_sensor[AXP_SENSOR_BATTV].units = ENVSYS_SVOLTS_DC;
    356 	sc->sc_sensor[AXP_SENSOR_BATTV].state = ENVSYS_SINVALID;
    357 	sc->sc_sensor[AXP_SENSOR_BATTV].flags = ENVSYS_FHAS_ENTROPY;
    358 	snprintf(sc->sc_sensor[AXP_SENSOR_BATTV].desc,
    359 	    sizeof(sc->sc_sensor[AXP_SENSOR_BATTV].desc), "battery voltage");
    360 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTV]);
    361 	sc->sc_sensor[AXP_SENSOR_BATTI].units = ENVSYS_SAMPS;
    362 	sc->sc_sensor[AXP_SENSOR_BATTI].state = ENVSYS_SINVALID;
    363 	sc->sc_sensor[AXP_SENSOR_BATTI].flags = ENVSYS_FHAS_ENTROPY;
    364 	snprintf(sc->sc_sensor[AXP_SENSOR_BATTI].desc,
    365 	    sizeof(sc->sc_sensor[AXP_SENSOR_BATTI].desc), "battery current");
    366 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTI]);
    367 
    368 	sc->sc_sensor[AXP_SENSOR_APSV].units = ENVSYS_SVOLTS_DC;
    369 	sc->sc_sensor[AXP_SENSOR_APSV].state = ENVSYS_SINVALID;
    370 	sc->sc_sensor[AXP_SENSOR_APSV].flags = ENVSYS_FHAS_ENTROPY;
    371 	snprintf(sc->sc_sensor[AXP_SENSOR_APSV].desc,
    372 	    sizeof(sc->sc_sensor[AXP_SENSOR_APSV].desc), "APS output voltage");
    373 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_APSV]);
    374 	sc->sc_sensor[AXP_SENSOR_TEMP].units = ENVSYS_STEMP;
    375 	sc->sc_sensor[AXP_SENSOR_TEMP].state = ENVSYS_SINVALID;
    376 	sc->sc_sensor[AXP_SENSOR_TEMP].flags = ENVSYS_FHAS_ENTROPY;
    377 	snprintf(sc->sc_sensor[AXP_SENSOR_TEMP].desc,
    378 	    sizeof(sc->sc_sensor[AXP_SENSOR_TEMP].desc),
    379 	    "internal temperature");
    380 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_TEMP]);
    381 
    382 	sysmon_envsys_register(sc->sc_sme);
    383 
    384 	if (axp20x_read(sc, AXP_DCDC2, &value, 1, I2C_F_POLL) == 0) {
    385 		aprint_verbose_dev(sc->sc_dev, "DCDC2 %dmV\n",
    386 		    (int)(700 + (value & AXP_DCDC2_VOLT_MASK) * 25));
    387 	}
    388 	if (axp20x_read(sc, AXP_DCDC3, &value, 1, I2C_F_POLL) == 0) {
    389 		aprint_verbose_dev(sc->sc_dev, "DCDC3 %dmV\n",
    390 		    (int)(700 + (value & AXP_DCDC3_VOLT_MASK) * 25));
    391 	}
    392 	if (axp20x_read(sc, AXP_LDO2_4, &value, 1, I2C_F_POLL) == 0) {
    393 		aprint_verbose_dev(sc->sc_dev, "LDO2 %dmV, LDO4 %dmV\n",
    394 		    (int)(1800 +
    395 		    ((value & AXP_LDO2_VOLT_MASK) >> AXP_LDO2_VOLT_SHIFT) * 100
    396 		    ),
    397 		    ldo4_mvV[(value & AXP_LDO4_VOLT_MASK) >> AXP_LDO4_VOLT_SHIFT]);
    398 	}
    399 	if (axp20x_read(sc, AXP_LDO3, &value, 1, I2C_F_POLL) == 0) {
    400 		if (value & AXP_LDO3_TRACK) {
    401 			aprint_verbose_dev(sc->sc_dev, "LDO3: tracking\n");
    402 		} else {
    403 			aprint_verbose_dev(sc->sc_dev, "LDO3 %dmV\n",
    404 			    (int)(700 + (value & AXP_LDO3_VOLT_MASK) * 25));
    405 		}
    406 	}
    407 
    408 	if (axp20x_read(sc, AXP_BKUP_CTRL, &value, 1, I2C_F_POLL) == 0) {
    409 		if (value & AXP_BKUP_CTRL_ENABLE) {
    410 			aprint_verbose_dev(sc->sc_dev,
    411 			    "RTC supercap charger enabled: %dmV at %duA\n",
    412 			    bkup_volt[(value & AXP_BKUP_CTRL_VOLT_MASK) >>
    413 			    AXP_BKUP_CTRL_VOLT_SHIFT],
    414 			    bkup_curr[(value & AXP_BKUP_CTRL_CURR_MASK) >>
    415 			    AXP_BKUP_CTRL_CURR_SHIFT]
    416 			);
    417 		}
    418 	}
    419 
    420 #ifdef FDT
    421 	axp20x_fdt_attach(sc);
    422 #endif
    423 }
    424 
    425 static void
    426 axp20x_sensors_refresh_volt(struct axp20x_softc *sc, int reg,
    427     envsys_data_t *edata)
    428 {
    429 	uint8_t buf[2];
    430 	int error;
    431 
    432 	error = axp20x_read(sc, reg, buf, sizeof(buf), 0);
    433 	if (error) {
    434 		edata->state = ENVSYS_SINVALID;
    435 	} else {
    436 		edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
    437 		    axp20x_sensors_lsb[edata->sensor];
    438 		edata->state = ENVSYS_SVALID;
    439 	}
    440 }
    441 
    442 static void
    443 axp20x_sensors_refresh_amp(struct axp20x_softc *sc, int reg,
    444     envsys_data_t *edata)
    445 {
    446 	uint8_t buf[2];
    447 	int error;
    448 
    449 	error = axp20x_read(sc, reg, buf, sizeof(buf), 0);
    450 	if (error) {
    451 		edata->state = ENVSYS_SINVALID;
    452 	} else {
    453 		edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
    454 		    axp20x_sensors_lsb[edata->sensor];
    455 		edata->state = ENVSYS_SVALID;
    456 	}
    457 }
    458 
    459 static void
    460 axp20x_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
    461 {
    462 	struct axp20x_softc *sc = sme->sme_cookie;
    463 	uint8_t buf[2];
    464 	int error;
    465 
    466 	switch(edata->sensor) {
    467 	case AXP_SENSOR_ACOK:
    468 	case AXP_SENSOR_VBUSOK:
    469 		error = axp20x_read(sc, AXP_INPUT_STATUS,
    470 		    &sc->sc_inputstatus, 1, 0);
    471 		if (error) {
    472 			edata->state = ENVSYS_SINVALID;
    473 			return;
    474 		}
    475 		if (edata->sensor == AXP_SENSOR_ACOK) {
    476 		    edata->value_cur =
    477 			(sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
    478 		} else {
    479 		    edata->value_cur =
    480 			(sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
    481 		}
    482 		edata->state = ENVSYS_SVALID;
    483 		return;
    484 	case AXP_SENSOR_BATTOK:
    485 		error = axp20x_read(sc, AXP_POWER_MODE,
    486 		    &sc->sc_powermode, 1, 0);
    487 		if (error) {
    488 			edata->state = ENVSYS_SINVALID;
    489 			return;
    490 		}
    491 		edata->value_cur =
    492 		    (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
    493 		return;
    494 	case AXP_SENSOR_ACV:
    495 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
    496 			axp20x_sensors_refresh_volt(sc, AXP_ACV_MON_REG, edata);
    497 		else
    498 			edata->state = ENVSYS_SINVALID;
    499 		return;
    500 	case AXP_SENSOR_ACI:
    501 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
    502 			axp20x_sensors_refresh_amp(sc, AXP_ACI_MON_REG, edata);
    503 		else
    504 			edata->state = ENVSYS_SINVALID;
    505 		return;
    506 	case AXP_SENSOR_VBUSV:
    507 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
    508 			axp20x_sensors_refresh_volt(sc, AXP_VBUSV_MON_REG, edata);
    509 		else
    510 			edata->state = ENVSYS_SINVALID;
    511 		return;
    512 	case AXP_SENSOR_VBUSI:
    513 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
    514 			axp20x_sensors_refresh_amp(sc, AXP_VBUSI_MON_REG, edata);
    515 		else
    516 			edata->state = ENVSYS_SINVALID;
    517 		return;
    518 	case AXP_SENSOR_BATTV:
    519 		if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
    520 			axp20x_sensors_refresh_volt(sc, AXP_BATTV_MON_REG, edata);
    521 		else
    522 			edata->state = ENVSYS_SINVALID;
    523 		return;
    524 	case AXP_SENSOR_BATTI:
    525 		if ((sc->sc_powermode & AXP_POWER_MODE_BATTOK) == 0) {
    526 			edata->state = ENVSYS_SINVALID;
    527 			return;
    528 		}
    529 		error = axp20x_read(sc, AXP_POWER_MODE,
    530 		    &sc->sc_inputstatus, 1, 0);
    531 		if (error) {
    532 			edata->state = ENVSYS_SINVALID;
    533 			return;
    534 		}
    535 		if (sc->sc_inputstatus & AXP_POWER_MODE_CHARGING) {
    536 			axp20x_sensors_refresh_amp(sc, AXP_BATTCI_MON_REG,
    537 			    edata);
    538 			edata->value_cur = -edata->value_cur;
    539 		} else {
    540 			axp20x_sensors_refresh_amp(sc, AXP_BATTDI_MON_REG,
    541 			    edata);
    542 		}
    543 		return;
    544 	case AXP_SENSOR_APSV:
    545 		axp20x_sensors_refresh_volt(sc, AXP_APSV_MON_REG, edata);
    546 		return;
    547 	case AXP_SENSOR_TEMP:
    548 		error = axp20x_read(sc, AXP_TEMP_MON_REG, buf, sizeof(buf), 0);
    549 		if (error) {
    550 			edata->state = ENVSYS_SINVALID;
    551 		} else {
    552 			/* between -144.7C and 264.8C, step +0.1C */
    553 			edata->value_cur =
    554 			    (((buf[0] << 4) | (buf[1] & 0xf)) - 1447)
    555 			   * 100000 + 273150000;
    556 			edata->state = ENVSYS_SVALID;
    557 		}
    558 		return;
    559 	default:
    560 		aprint_error_dev(sc->sc_dev, "invalid sensor %d\n",
    561 		    edata->sensor);
    562 	}
    563 }
    564 
    565 static int
    566 axp20x_read(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len,
    567     int flags)
    568 {
    569 	int ret;
    570 	iic_acquire_bus(sc->sc_i2c, flags);
    571 	ret = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr,
    572 	    &reg, 1, val, len, flags);
    573 	iic_release_bus(sc->sc_i2c, flags);
    574 	return ret;
    575 
    576 }
    577 
    578 static int
    579 axp20x_write(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len,
    580     int flags)
    581 {
    582 	int ret;
    583 	iic_acquire_bus(sc->sc_i2c, flags);
    584 	ret = iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
    585 	    &reg, 1, val, len, flags);
    586 	iic_release_bus(sc->sc_i2c, flags);
    587 	return ret;
    588 }
    589 
    590 int
    591 axp20x_set_dcdc(device_t dev, int dcdc, int mvolt, bool poll)
    592 {
    593 	struct axp20x_softc *sc = device_private(dev);
    594 	int ret;
    595 	int value;
    596 	uint8_t reg;
    597 
    598 	KASSERT(sc != NULL);
    599 	value = (mvolt - 700) / 25;
    600 	switch (dcdc) {
    601 	case AXP20X_DCDC2:
    602 		value <<= AXP_DCDC2_VOLT_SHIFT;
    603 		if (value > AXP_DCDC2_VOLT_MASK)
    604 			return EINVAL;
    605 		reg = value & AXP_DCDC2_VOLT_MASK;
    606 		ret = axp20x_write(sc, AXP_DCDC2, &reg, 1,
    607 		    poll ? I2C_F_POLL : 0);
    608 		if (ret)
    609 			return ret;
    610 		if (axp20x_read(sc, AXP_DCDC2, &reg, 1, poll ? I2C_F_POLL : 0)
    611 		  == 0) {
    612 			aprint_debug_dev(sc->sc_dev,
    613 			    "DCDC2 changed to %dmV\n",
    614 			    (int)(700 + (reg & AXP_DCDC2_VOLT_MASK) * 25));
    615 		}
    616 		return 0;
    617 
    618 	case AXP20X_DCDC3:
    619 		value <<= AXP_DCDC3_VOLT_SHIFT;
    620 		if (value > AXP_DCDC3_VOLT_MASK)
    621 			return EINVAL;
    622 		reg = value & AXP_DCDC3_VOLT_MASK;
    623 		ret = axp20x_write(sc, AXP_DCDC3, &reg, 1,
    624 		    poll ? I2C_F_POLL : 0);
    625 		if (ret)
    626 			return ret;
    627 		if (axp20x_read(sc, AXP_DCDC3, &reg, 1, poll ? I2C_F_POLL : 0)
    628 		  == 0) {
    629 			aprint_debug_dev(sc->sc_dev,
    630 			    "DCDC3 changed to %dmV\n",
    631 			    (int)(700 + (reg & AXP_DCDC3_VOLT_MASK) * 25));
    632 		}
    633 		return 0;
    634 	default:
    635 		aprint_error_dev(dev, "wrong DCDC %d\n", dcdc);
    636 		return EINVAL;
    637 	}
    638 }
    639 
    640 int
    641 axp20x_get_dcdc(device_t dev, int dcdc, int *pmvolt, bool poll)
    642 {
    643 	struct axp20x_softc *sc = device_private(dev);
    644 	uint8_t reg;
    645 	int error;
    646 
    647 	switch (dcdc) {
    648 	case AXP20X_DCDC2:
    649 		error = axp20x_read(sc, AXP_DCDC2, &reg, 1, poll ? I2C_F_POLL : 0);
    650 		if (error != 0)
    651 			return error;
    652 		*pmvolt = __SHIFTOUT(reg, AXP_DCDC2_VOLT_MASK) * 25 + 700;
    653 		return 0;
    654 	case AXP20X_DCDC3:
    655 		error = axp20x_read(sc, AXP_DCDC3, &reg, 1, poll ? I2C_F_POLL : 0);
    656 		if (error != 0)
    657 			return error;
    658 		*pmvolt = __SHIFTOUT(reg, AXP_DCDC3_VOLT_MASK) * 25 + 700;
    659 		return 0;
    660 	default:
    661 		return EINVAL;
    662 	}
    663 }
    664 
    665 void
    666 axp20x_poweroff(device_t dev)
    667 {
    668 	struct axp20x_softc * const sc = device_private(dev);
    669 	uint8_t reg = AXP_SHUTDOWN_CTRL;
    670 
    671 	if (axp20x_write(sc, AXP_SHUTDOWN, &reg, 1, I2C_F_POLL) != 0)
    672 		device_printf(dev, "WARNING: poweroff failed\n");
    673 }
    674 
    675 #ifdef FDT
    676 static const struct axp20xregdef {
    677 	const char *name;
    678 	int dcdc;
    679 } axp20x_regdefs[] = {
    680 	{ "dcdc2", AXP20X_DCDC2 },
    681 	{ "dcdc3", AXP20X_DCDC3 },
    682 };
    683 
    684 struct axp20xreg_softc {
    685 	device_t	sc_dev;
    686 	int		sc_phandle;
    687 	const struct axp20xregdef *sc_regdef;
    688 };
    689 
    690 struct axp20xreg_attach_args {
    691 	int		reg_phandle;
    692 };
    693 
    694 static int
    695 axp20xreg_acquire(device_t dev)
    696 {
    697 	return 0;
    698 }
    699 
    700 static void
    701 axp20xreg_release(device_t dev)
    702 {
    703 }
    704 
    705 static int
    706 axp20xreg_enable(device_t dev, bool enable)
    707 {
    708 	/* TODO */
    709 	return enable ? 0 : EINVAL;
    710 }
    711 
    712 static int
    713 axp20xreg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
    714 {
    715 	struct axp20xreg_softc * const sc = device_private(dev);
    716 
    717 	return axp20x_set_dcdc(device_parent(dev), sc->sc_regdef->dcdc, min_uvol / 1000, true);
    718 }
    719 
    720 static int
    721 axp20xreg_get_voltage(device_t dev, u_int *puvol)
    722 {
    723 	struct axp20xreg_softc * const sc = device_private(dev);
    724 	int mvol, error;
    725 
    726 	error = axp20x_get_dcdc(device_parent(dev), sc->sc_regdef->dcdc, &mvol, true);
    727 	if (error != 0)
    728 		return error;
    729 
    730 	*puvol = mvol * 1000;
    731 	return 0;
    732 }
    733 
    734 static struct fdtbus_regulator_controller_func axp20xreg_funcs = {
    735 	.acquire = axp20xreg_acquire,
    736 	.release = axp20xreg_release,
    737 	.enable = axp20xreg_enable,
    738 	.set_voltage = axp20xreg_set_voltage,
    739 	.get_voltage = axp20xreg_get_voltage,
    740 };
    741 
    742 static const struct axp20xregdef *
    743 axp20xreg_lookup(int phandle)
    744 {
    745 	const char *name;
    746 	int n;
    747 
    748 	name = fdtbus_get_string(phandle, "name");
    749 	if (name == NULL)
    750 		return NULL;
    751 
    752 	for (n = 0; n < __arraycount(axp20x_regdefs); n++)
    753 		if (strcmp(name, axp20x_regdefs[n].name) == 0)
    754 			return &axp20x_regdefs[n];
    755 
    756 	return NULL;
    757 }
    758 
    759 static int
    760 axp20xreg_match(device_t parent, cfdata_t match, void *aux)
    761 {
    762 	const struct axp20xreg_attach_args *reg = aux;
    763 
    764 	return axp20xreg_lookup(reg->reg_phandle) != NULL;
    765 }
    766 
    767 static void
    768 axp20xreg_attach(device_t parent, device_t self, void *aux)
    769 {
    770 	struct axp20xreg_softc * const sc = device_private(self);
    771 	const struct axp20xreg_attach_args *reg = aux;
    772 	const char *regulator_name;
    773 
    774 	sc->sc_dev = self;
    775 	sc->sc_phandle = reg->reg_phandle;
    776 	sc->sc_regdef = axp20xreg_lookup(reg->reg_phandle);
    777 
    778 	regulator_name = fdtbus_get_string(reg->reg_phandle, "regulator-name");
    779 
    780 	aprint_naive("\n");
    781 	if (regulator_name)
    782 		aprint_normal(": %s (%s)\n", sc->sc_regdef->name, regulator_name);
    783 	else
    784 		aprint_normal(": %s\n", sc->sc_regdef->name);
    785 
    786 	fdtbus_register_regulator_controller(self, sc->sc_phandle, &axp20xreg_funcs);
    787 }
    788 
    789 CFATTACH_DECL_NEW(axp20xreg, sizeof(struct axp20xreg_softc),
    790     axp20xreg_match, axp20xreg_attach, NULL, NULL);
    791 
    792 static void
    793 axp20x_fdt_poweroff(device_t dev)
    794 {
    795 	delay(1000000);
    796 	axp20x_poweroff(dev);
    797 }
    798 
    799 static struct fdtbus_power_controller_func axp20x_fdt_power_funcs = {
    800 	.poweroff = axp20x_fdt_poweroff,
    801 };
    802 
    803 static void
    804 axp20x_fdt_attach(struct axp20x_softc *sc)
    805 {
    806 	int regulators_phandle, child;
    807 
    808 	fdtbus_register_power_controller(sc->sc_dev, sc->sc_phandle,
    809 	    &axp20x_fdt_power_funcs);
    810 
    811 	regulators_phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators");
    812 	if (regulators_phandle == -1)
    813 		return;
    814 
    815 	for (child = OF_child(regulators_phandle); child; child = OF_peer(child)) {
    816 		struct axp20xreg_attach_args reg = { .reg_phandle = child };
    817 		config_found(sc->sc_dev, &reg, NULL);
    818 	}
    819 }
    820 #endif /* FDT */
    821