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