Home | History | Annotate | Line # | Download | only in i2c
axp20x.c revision 1.12
      1 /* $NetBSD: axp20x.c,v 1.12 2018/06/18 17:07:07 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.12 2018/06/18 17:07:07 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 const struct device_compatible_entry axp20x_compat_data[] = {
    223 	DEVICE_COMPAT_ENTRY(compatible),
    224 	DEVICE_COMPAT_TERMINATOR
    225 };
    226 
    227 static int
    228 axp20x_match(device_t parent, cfdata_t match, void *aux)
    229 {
    230 	struct i2c_attach_args * const ia = aux;
    231 	int match_result;
    232 
    233 	if (iic_use_direct_match(ia, match, axp20x_compat_data, &match_result))
    234 		return match_result;
    235 
    236 	/* This device is direct-config only. */
    237 
    238 	return 0;
    239 }
    240 
    241 static void
    242 axp20x_attach(device_t parent, device_t self, void *aux)
    243 {
    244 	struct axp20x_softc *sc = device_private(self);
    245 	struct i2c_attach_args *ia = aux;
    246 	int first;
    247 	int error;
    248 	uint8_t value;
    249 
    250 	sc->sc_dev = self;
    251 	sc->sc_i2c = ia->ia_tag;
    252 	sc->sc_addr = ia->ia_addr;
    253 	sc->sc_phandle = ia->ia_cookie;
    254 
    255 	error = axp20x_read(sc, AXP_INPUT_STATUS,
    256 	    &sc->sc_inputstatus, 1, I2C_F_POLL);
    257 	if (error) {
    258 		aprint_error(": can't read status: %d\n", error);
    259 		return;
    260 	}
    261 	error = axp20x_read(sc, AXP_POWER_MODE,
    262 	    &sc->sc_powermode, 1, I2C_F_POLL);
    263 	if (error) {
    264 		aprint_error(": can't read power mode: %d\n", error);
    265 		return;
    266 	}
    267 	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;
    268 	if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
    269 		value |= AXP_ADC_EN1_BATTV | AXP_ADC_EN1_BATTI;
    270 	error = axp20x_write(sc, AXP_ADC_EN1, &value, 1, I2C_F_POLL);
    271 	if (error) {
    272 		aprint_error(": can't set AXP_ADC_EN1\n");
    273 		return;
    274 	}
    275 	error = axp20x_read(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
    276 	if (error) {
    277 		aprint_error(": can't read AXP_ADC_EN2\n");
    278 		return;
    279 	}
    280 	value |= AXP_ADC_EN2_TEMP;
    281 	error = axp20x_write(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
    282 	if (error) {
    283 		aprint_error(": can't set AXP_ADC_EN2\n");
    284 		return;
    285 	}
    286 
    287 	aprint_naive("\n");
    288 	first = 1;
    289 	if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) {
    290 		aprint_verbose(": AC used");
    291 		first = 0;
    292 	} else if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_PRESENT) {
    293 		aprint_verbose(": AC present (but unused)");
    294 		first = 0;
    295 	}
    296 	if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) {
    297 		aprint_verbose("%s VBUS used", first ? ":" : ",");
    298 		first = 0;
    299 	} else if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_PRESENT) {
    300 		aprint_verbose("%s VBUS present (but unused)", first ? ":" : ",");
    301 		first = 0;
    302 	}
    303 	if (sc->sc_powermode & AXP_POWER_MODE_BATTOK) {
    304 		aprint_verbose("%s battery present", first ? ":" : ",");
    305 	}
    306 	aprint_normal("\n");
    307 
    308 	sc->sc_sme = sysmon_envsys_create();
    309 	sc->sc_sme->sme_name = device_xname(self);
    310 	sc->sc_sme->sme_cookie = sc;
    311 	sc->sc_sme->sme_refresh = axp20x_sensors_refresh;
    312 
    313 	sc->sc_sensor[AXP_SENSOR_ACOK].units = ENVSYS_INDICATOR;
    314 	sc->sc_sensor[AXP_SENSOR_ACOK].state = ENVSYS_SVALID;
    315 	sc->sc_sensor[AXP_SENSOR_ACOK].value_cur =
    316 	    (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
    317 	snprintf(sc->sc_sensor[AXP_SENSOR_ACOK].desc,
    318 	    sizeof(sc->sc_sensor[AXP_SENSOR_ACOK].desc), "AC input");
    319 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACOK]);
    320 	sc->sc_sensor[AXP_SENSOR_ACV].units = ENVSYS_SVOLTS_DC;
    321 	sc->sc_sensor[AXP_SENSOR_ACV].state = ENVSYS_SINVALID;
    322 	sc->sc_sensor[AXP_SENSOR_ACV].flags = ENVSYS_FHAS_ENTROPY;
    323 	snprintf(sc->sc_sensor[AXP_SENSOR_ACV].desc,
    324 	    sizeof(sc->sc_sensor[AXP_SENSOR_ACV].desc), "AC input voltage");
    325 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACV]);
    326 	sc->sc_sensor[AXP_SENSOR_ACI].units = ENVSYS_SAMPS;
    327 	sc->sc_sensor[AXP_SENSOR_ACI].state = ENVSYS_SINVALID;
    328 	sc->sc_sensor[AXP_SENSOR_ACI].flags = ENVSYS_FHAS_ENTROPY;
    329 	snprintf(sc->sc_sensor[AXP_SENSOR_ACI].desc,
    330 	    sizeof(sc->sc_sensor[AXP_SENSOR_ACI].desc), "AC input current");
    331 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACI]);
    332 
    333 	sc->sc_sensor[AXP_SENSOR_VBUSOK].units = ENVSYS_INDICATOR;
    334 	sc->sc_sensor[AXP_SENSOR_VBUSOK].state = ENVSYS_SVALID;
    335 	sc->sc_sensor[AXP_SENSOR_VBUSOK].value_cur =
    336 	    (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
    337 	snprintf(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc,
    338 	    sizeof(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc), "VBUS input");
    339 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSOK]);
    340 	sc->sc_sensor[AXP_SENSOR_VBUSV].units = ENVSYS_SVOLTS_DC;
    341 	sc->sc_sensor[AXP_SENSOR_VBUSV].state = ENVSYS_SINVALID;
    342 	sc->sc_sensor[AXP_SENSOR_VBUSV].flags = ENVSYS_FHAS_ENTROPY;
    343 	snprintf(sc->sc_sensor[AXP_SENSOR_VBUSV].desc,
    344 	    sizeof(sc->sc_sensor[AXP_SENSOR_VBUSV].desc), "VBUS input voltage");
    345 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSV]);
    346 	sc->sc_sensor[AXP_SENSOR_VBUSI].units = ENVSYS_SAMPS;
    347 	sc->sc_sensor[AXP_SENSOR_VBUSI].state = ENVSYS_SINVALID;
    348 	sc->sc_sensor[AXP_SENSOR_VBUSI].flags = ENVSYS_FHAS_ENTROPY;
    349 	snprintf(sc->sc_sensor[AXP_SENSOR_VBUSI].desc,
    350 	    sizeof(sc->sc_sensor[AXP_SENSOR_VBUSI].desc), "VBUS input current");
    351 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSI]);
    352 
    353 	sc->sc_sensor[AXP_SENSOR_BATTOK].units = ENVSYS_INDICATOR;
    354 	sc->sc_sensor[AXP_SENSOR_BATTOK].state = ENVSYS_SVALID;
    355 	sc->sc_sensor[AXP_SENSOR_BATTOK].value_cur =
    356 	    (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
    357 	snprintf(sc->sc_sensor[AXP_SENSOR_BATTOK].desc,
    358 	    sizeof(sc->sc_sensor[AXP_SENSOR_BATTOK].desc), "battery");
    359 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTOK]);
    360 	sc->sc_sensor[AXP_SENSOR_BATTV].units = ENVSYS_SVOLTS_DC;
    361 	sc->sc_sensor[AXP_SENSOR_BATTV].state = ENVSYS_SINVALID;
    362 	sc->sc_sensor[AXP_SENSOR_BATTV].flags = ENVSYS_FHAS_ENTROPY;
    363 	snprintf(sc->sc_sensor[AXP_SENSOR_BATTV].desc,
    364 	    sizeof(sc->sc_sensor[AXP_SENSOR_BATTV].desc), "battery voltage");
    365 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTV]);
    366 	sc->sc_sensor[AXP_SENSOR_BATTI].units = ENVSYS_SAMPS;
    367 	sc->sc_sensor[AXP_SENSOR_BATTI].state = ENVSYS_SINVALID;
    368 	sc->sc_sensor[AXP_SENSOR_BATTI].flags = ENVSYS_FHAS_ENTROPY;
    369 	snprintf(sc->sc_sensor[AXP_SENSOR_BATTI].desc,
    370 	    sizeof(sc->sc_sensor[AXP_SENSOR_BATTI].desc), "battery current");
    371 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTI]);
    372 
    373 	sc->sc_sensor[AXP_SENSOR_APSV].units = ENVSYS_SVOLTS_DC;
    374 	sc->sc_sensor[AXP_SENSOR_APSV].state = ENVSYS_SINVALID;
    375 	sc->sc_sensor[AXP_SENSOR_APSV].flags = ENVSYS_FHAS_ENTROPY;
    376 	snprintf(sc->sc_sensor[AXP_SENSOR_APSV].desc,
    377 	    sizeof(sc->sc_sensor[AXP_SENSOR_APSV].desc), "APS output voltage");
    378 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_APSV]);
    379 	sc->sc_sensor[AXP_SENSOR_TEMP].units = ENVSYS_STEMP;
    380 	sc->sc_sensor[AXP_SENSOR_TEMP].state = ENVSYS_SINVALID;
    381 	sc->sc_sensor[AXP_SENSOR_TEMP].flags = ENVSYS_FHAS_ENTROPY;
    382 	snprintf(sc->sc_sensor[AXP_SENSOR_TEMP].desc,
    383 	    sizeof(sc->sc_sensor[AXP_SENSOR_TEMP].desc),
    384 	    "internal temperature");
    385 	sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_TEMP]);
    386 
    387 	sysmon_envsys_register(sc->sc_sme);
    388 
    389 	if (axp20x_read(sc, AXP_DCDC2, &value, 1, I2C_F_POLL) == 0) {
    390 		aprint_verbose_dev(sc->sc_dev, "DCDC2 %dmV\n",
    391 		    (int)(700 + (value & AXP_DCDC2_VOLT_MASK) * 25));
    392 	}
    393 	if (axp20x_read(sc, AXP_DCDC3, &value, 1, I2C_F_POLL) == 0) {
    394 		aprint_verbose_dev(sc->sc_dev, "DCDC3 %dmV\n",
    395 		    (int)(700 + (value & AXP_DCDC3_VOLT_MASK) * 25));
    396 	}
    397 	if (axp20x_read(sc, AXP_LDO2_4, &value, 1, I2C_F_POLL) == 0) {
    398 		aprint_verbose_dev(sc->sc_dev, "LDO2 %dmV, LDO4 %dmV\n",
    399 		    (int)(1800 +
    400 		    ((value & AXP_LDO2_VOLT_MASK) >> AXP_LDO2_VOLT_SHIFT) * 100
    401 		    ),
    402 		    ldo4_mvV[(value & AXP_LDO4_VOLT_MASK) >> AXP_LDO4_VOLT_SHIFT]);
    403 	}
    404 	if (axp20x_read(sc, AXP_LDO3, &value, 1, I2C_F_POLL) == 0) {
    405 		if (value & AXP_LDO3_TRACK) {
    406 			aprint_verbose_dev(sc->sc_dev, "LDO3: tracking\n");
    407 		} else {
    408 			aprint_verbose_dev(sc->sc_dev, "LDO3 %dmV\n",
    409 			    (int)(700 + (value & AXP_LDO3_VOLT_MASK) * 25));
    410 		}
    411 	}
    412 
    413 	if (axp20x_read(sc, AXP_BKUP_CTRL, &value, 1, I2C_F_POLL) == 0) {
    414 		if (value & AXP_BKUP_CTRL_ENABLE) {
    415 			aprint_verbose_dev(sc->sc_dev,
    416 			    "RTC supercap charger enabled: %dmV at %duA\n",
    417 			    bkup_volt[(value & AXP_BKUP_CTRL_VOLT_MASK) >>
    418 			    AXP_BKUP_CTRL_VOLT_SHIFT],
    419 			    bkup_curr[(value & AXP_BKUP_CTRL_CURR_MASK) >>
    420 			    AXP_BKUP_CTRL_CURR_SHIFT]
    421 			);
    422 		}
    423 	}
    424 
    425 #ifdef FDT
    426 	axp20x_fdt_attach(sc);
    427 #endif
    428 }
    429 
    430 static void
    431 axp20x_sensors_refresh_volt(struct axp20x_softc *sc, int reg,
    432     envsys_data_t *edata)
    433 {
    434 	uint8_t buf[2];
    435 	int error;
    436 
    437 	error = axp20x_read(sc, reg, buf, sizeof(buf), 0);
    438 	if (error) {
    439 		edata->state = ENVSYS_SINVALID;
    440 	} else {
    441 		edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
    442 		    axp20x_sensors_lsb[edata->sensor];
    443 		edata->state = ENVSYS_SVALID;
    444 	}
    445 }
    446 
    447 static void
    448 axp20x_sensors_refresh_amp(struct axp20x_softc *sc, int reg,
    449     envsys_data_t *edata)
    450 {
    451 	uint8_t buf[2];
    452 	int error;
    453 
    454 	error = axp20x_read(sc, reg, buf, sizeof(buf), 0);
    455 	if (error) {
    456 		edata->state = ENVSYS_SINVALID;
    457 	} else {
    458 		edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
    459 		    axp20x_sensors_lsb[edata->sensor];
    460 		edata->state = ENVSYS_SVALID;
    461 	}
    462 }
    463 
    464 static void
    465 axp20x_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
    466 {
    467 	struct axp20x_softc *sc = sme->sme_cookie;
    468 	uint8_t buf[2];
    469 	int error;
    470 
    471 	switch(edata->sensor) {
    472 	case AXP_SENSOR_ACOK:
    473 	case AXP_SENSOR_VBUSOK:
    474 		error = axp20x_read(sc, AXP_INPUT_STATUS,
    475 		    &sc->sc_inputstatus, 1, 0);
    476 		if (error) {
    477 			edata->state = ENVSYS_SINVALID;
    478 			return;
    479 		}
    480 		if (edata->sensor == AXP_SENSOR_ACOK) {
    481 		    edata->value_cur =
    482 			(sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
    483 		} else {
    484 		    edata->value_cur =
    485 			(sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
    486 		}
    487 		edata->state = ENVSYS_SVALID;
    488 		return;
    489 	case AXP_SENSOR_BATTOK:
    490 		error = axp20x_read(sc, AXP_POWER_MODE,
    491 		    &sc->sc_powermode, 1, 0);
    492 		if (error) {
    493 			edata->state = ENVSYS_SINVALID;
    494 			return;
    495 		}
    496 		edata->value_cur =
    497 		    (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
    498 		return;
    499 	case AXP_SENSOR_ACV:
    500 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
    501 			axp20x_sensors_refresh_volt(sc, AXP_ACV_MON_REG, edata);
    502 		else
    503 			edata->state = ENVSYS_SINVALID;
    504 		return;
    505 	case AXP_SENSOR_ACI:
    506 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
    507 			axp20x_sensors_refresh_amp(sc, AXP_ACI_MON_REG, edata);
    508 		else
    509 			edata->state = ENVSYS_SINVALID;
    510 		return;
    511 	case AXP_SENSOR_VBUSV:
    512 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
    513 			axp20x_sensors_refresh_volt(sc, AXP_VBUSV_MON_REG, edata);
    514 		else
    515 			edata->state = ENVSYS_SINVALID;
    516 		return;
    517 	case AXP_SENSOR_VBUSI:
    518 		if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
    519 			axp20x_sensors_refresh_amp(sc, AXP_VBUSI_MON_REG, edata);
    520 		else
    521 			edata->state = ENVSYS_SINVALID;
    522 		return;
    523 	case AXP_SENSOR_BATTV:
    524 		if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
    525 			axp20x_sensors_refresh_volt(sc, AXP_BATTV_MON_REG, edata);
    526 		else
    527 			edata->state = ENVSYS_SINVALID;
    528 		return;
    529 	case AXP_SENSOR_BATTI:
    530 		if ((sc->sc_powermode & AXP_POWER_MODE_BATTOK) == 0) {
    531 			edata->state = ENVSYS_SINVALID;
    532 			return;
    533 		}
    534 		error = axp20x_read(sc, AXP_POWER_MODE,
    535 		    &sc->sc_inputstatus, 1, 0);
    536 		if (error) {
    537 			edata->state = ENVSYS_SINVALID;
    538 			return;
    539 		}
    540 		if (sc->sc_inputstatus & AXP_POWER_MODE_CHARGING) {
    541 			axp20x_sensors_refresh_amp(sc, AXP_BATTCI_MON_REG,
    542 			    edata);
    543 			edata->value_cur = -edata->value_cur;
    544 		} else {
    545 			axp20x_sensors_refresh_amp(sc, AXP_BATTDI_MON_REG,
    546 			    edata);
    547 		}
    548 		return;
    549 	case AXP_SENSOR_APSV:
    550 		axp20x_sensors_refresh_volt(sc, AXP_APSV_MON_REG, edata);
    551 		return;
    552 	case AXP_SENSOR_TEMP:
    553 		error = axp20x_read(sc, AXP_TEMP_MON_REG, buf, sizeof(buf), 0);
    554 		if (error) {
    555 			edata->state = ENVSYS_SINVALID;
    556 		} else {
    557 			/* between -144.7C and 264.8C, step +0.1C */
    558 			edata->value_cur =
    559 			    (((buf[0] << 4) | (buf[1] & 0xf)) - 1447)
    560 			   * 100000 + 273150000;
    561 			edata->state = ENVSYS_SVALID;
    562 		}
    563 		return;
    564 	default:
    565 		aprint_error_dev(sc->sc_dev, "invalid sensor %d\n",
    566 		    edata->sensor);
    567 	}
    568 }
    569 
    570 static int
    571 axp20x_read(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len,
    572     int flags)
    573 {
    574 	int ret;
    575 	iic_acquire_bus(sc->sc_i2c, flags);
    576 	ret = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr,
    577 	    &reg, 1, val, len, flags);
    578 	iic_release_bus(sc->sc_i2c, flags);
    579 	return ret;
    580 
    581 }
    582 
    583 static int
    584 axp20x_write(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len,
    585     int flags)
    586 {
    587 	int ret;
    588 	iic_acquire_bus(sc->sc_i2c, flags);
    589 	ret = iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
    590 	    &reg, 1, val, len, flags);
    591 	iic_release_bus(sc->sc_i2c, flags);
    592 	return ret;
    593 }
    594 
    595 int
    596 axp20x_set_dcdc(device_t dev, int dcdc, int mvolt, bool poll)
    597 {
    598 	struct axp20x_softc *sc = device_private(dev);
    599 	int ret;
    600 	int value;
    601 	uint8_t reg;
    602 
    603 	KASSERT(sc != NULL);
    604 	value = (mvolt - 700) / 25;
    605 	switch (dcdc) {
    606 	case AXP20X_DCDC2:
    607 		value <<= AXP_DCDC2_VOLT_SHIFT;
    608 		if (value > AXP_DCDC2_VOLT_MASK)
    609 			return EINVAL;
    610 		reg = value & AXP_DCDC2_VOLT_MASK;
    611 		ret = axp20x_write(sc, AXP_DCDC2, &reg, 1,
    612 		    poll ? I2C_F_POLL : 0);
    613 		if (ret)
    614 			return ret;
    615 		if (axp20x_read(sc, AXP_DCDC2, &reg, 1, poll ? I2C_F_POLL : 0)
    616 		  == 0) {
    617 			aprint_debug_dev(sc->sc_dev,
    618 			    "DCDC2 changed to %dmV\n",
    619 			    (int)(700 + (reg & AXP_DCDC2_VOLT_MASK) * 25));
    620 		}
    621 		return 0;
    622 
    623 	case AXP20X_DCDC3:
    624 		value <<= AXP_DCDC3_VOLT_SHIFT;
    625 		if (value > AXP_DCDC3_VOLT_MASK)
    626 			return EINVAL;
    627 		reg = value & AXP_DCDC3_VOLT_MASK;
    628 		ret = axp20x_write(sc, AXP_DCDC3, &reg, 1,
    629 		    poll ? I2C_F_POLL : 0);
    630 		if (ret)
    631 			return ret;
    632 		if (axp20x_read(sc, AXP_DCDC3, &reg, 1, poll ? I2C_F_POLL : 0)
    633 		  == 0) {
    634 			aprint_debug_dev(sc->sc_dev,
    635 			    "DCDC3 changed to %dmV\n",
    636 			    (int)(700 + (reg & AXP_DCDC3_VOLT_MASK) * 25));
    637 		}
    638 		return 0;
    639 	default:
    640 		aprint_error_dev(dev, "wrong DCDC %d\n", dcdc);
    641 		return EINVAL;
    642 	}
    643 }
    644 
    645 int
    646 axp20x_get_dcdc(device_t dev, int dcdc, int *pmvolt, bool poll)
    647 {
    648 	struct axp20x_softc *sc = device_private(dev);
    649 	uint8_t reg;
    650 	int error;
    651 
    652 	switch (dcdc) {
    653 	case AXP20X_DCDC2:
    654 		error = axp20x_read(sc, AXP_DCDC2, &reg, 1, poll ? I2C_F_POLL : 0);
    655 		if (error != 0)
    656 			return error;
    657 		*pmvolt = __SHIFTOUT(reg, AXP_DCDC2_VOLT_MASK) * 25 + 700;
    658 		return 0;
    659 	case AXP20X_DCDC3:
    660 		error = axp20x_read(sc, AXP_DCDC3, &reg, 1, poll ? I2C_F_POLL : 0);
    661 		if (error != 0)
    662 			return error;
    663 		*pmvolt = __SHIFTOUT(reg, AXP_DCDC3_VOLT_MASK) * 25 + 700;
    664 		return 0;
    665 	default:
    666 		return EINVAL;
    667 	}
    668 }
    669 
    670 void
    671 axp20x_poweroff(device_t dev)
    672 {
    673 	struct axp20x_softc * const sc = device_private(dev);
    674 	uint8_t reg = AXP_SHUTDOWN_CTRL;
    675 
    676 	if (axp20x_write(sc, AXP_SHUTDOWN, &reg, 1, I2C_F_POLL) != 0)
    677 		device_printf(dev, "WARNING: poweroff failed\n");
    678 }
    679 
    680 #ifdef FDT
    681 static const struct axp20xregdef {
    682 	const char *name;
    683 	int dcdc;
    684 } axp20x_regdefs[] = {
    685 	{ "dcdc2", AXP20X_DCDC2 },
    686 	{ "dcdc3", AXP20X_DCDC3 },
    687 };
    688 
    689 struct axp20xreg_softc {
    690 	device_t	sc_dev;
    691 	int		sc_phandle;
    692 	const struct axp20xregdef *sc_regdef;
    693 };
    694 
    695 struct axp20xreg_attach_args {
    696 	int		reg_phandle;
    697 };
    698 
    699 static int
    700 axp20xreg_acquire(device_t dev)
    701 {
    702 	return 0;
    703 }
    704 
    705 static void
    706 axp20xreg_release(device_t dev)
    707 {
    708 }
    709 
    710 static int
    711 axp20xreg_enable(device_t dev, bool enable)
    712 {
    713 	/* TODO */
    714 	return enable ? 0 : EINVAL;
    715 }
    716 
    717 static int
    718 axp20xreg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
    719 {
    720 	struct axp20xreg_softc * const sc = device_private(dev);
    721 
    722 	return axp20x_set_dcdc(device_parent(dev), sc->sc_regdef->dcdc, min_uvol / 1000, true);
    723 }
    724 
    725 static int
    726 axp20xreg_get_voltage(device_t dev, u_int *puvol)
    727 {
    728 	struct axp20xreg_softc * const sc = device_private(dev);
    729 	int mvol, error;
    730 
    731 	error = axp20x_get_dcdc(device_parent(dev), sc->sc_regdef->dcdc, &mvol, true);
    732 	if (error != 0)
    733 		return error;
    734 
    735 	*puvol = mvol * 1000;
    736 	return 0;
    737 }
    738 
    739 static struct fdtbus_regulator_controller_func axp20xreg_funcs = {
    740 	.acquire = axp20xreg_acquire,
    741 	.release = axp20xreg_release,
    742 	.enable = axp20xreg_enable,
    743 	.set_voltage = axp20xreg_set_voltage,
    744 	.get_voltage = axp20xreg_get_voltage,
    745 };
    746 
    747 static const struct axp20xregdef *
    748 axp20xreg_lookup(int phandle)
    749 {
    750 	const char *name;
    751 	int n;
    752 
    753 	name = fdtbus_get_string(phandle, "name");
    754 	if (name == NULL)
    755 		return NULL;
    756 
    757 	for (n = 0; n < __arraycount(axp20x_regdefs); n++)
    758 		if (strcmp(name, axp20x_regdefs[n].name) == 0)
    759 			return &axp20x_regdefs[n];
    760 
    761 	return NULL;
    762 }
    763 
    764 static int
    765 axp20xreg_match(device_t parent, cfdata_t match, void *aux)
    766 {
    767 	const struct axp20xreg_attach_args *reg = aux;
    768 
    769 	return axp20xreg_lookup(reg->reg_phandle) != NULL;
    770 }
    771 
    772 static void
    773 axp20xreg_attach(device_t parent, device_t self, void *aux)
    774 {
    775 	struct axp20xreg_softc * const sc = device_private(self);
    776 	const struct axp20xreg_attach_args *reg = aux;
    777 	const char *regulator_name;
    778 
    779 	sc->sc_dev = self;
    780 	sc->sc_phandle = reg->reg_phandle;
    781 	sc->sc_regdef = axp20xreg_lookup(reg->reg_phandle);
    782 
    783 	regulator_name = fdtbus_get_string(reg->reg_phandle, "regulator-name");
    784 
    785 	aprint_naive("\n");
    786 	if (regulator_name)
    787 		aprint_normal(": %s (%s)\n", sc->sc_regdef->name, regulator_name);
    788 	else
    789 		aprint_normal(": %s\n", sc->sc_regdef->name);
    790 
    791 	fdtbus_register_regulator_controller(self, sc->sc_phandle, &axp20xreg_funcs);
    792 }
    793 
    794 CFATTACH_DECL_NEW(axp20xreg, sizeof(struct axp20xreg_softc),
    795     axp20xreg_match, axp20xreg_attach, NULL, NULL);
    796 
    797 static void
    798 axp20x_fdt_poweroff(device_t dev)
    799 {
    800 	delay(1000000);
    801 	axp20x_poweroff(dev);
    802 }
    803 
    804 static struct fdtbus_power_controller_func axp20x_fdt_power_funcs = {
    805 	.poweroff = axp20x_fdt_poweroff,
    806 };
    807 
    808 static void
    809 axp20x_fdt_attach(struct axp20x_softc *sc)
    810 {
    811 	int regulators_phandle, child;
    812 
    813 	fdtbus_register_power_controller(sc->sc_dev, sc->sc_phandle,
    814 	    &axp20x_fdt_power_funcs);
    815 
    816 	regulators_phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators");
    817 	if (regulators_phandle == -1)
    818 		return;
    819 
    820 	for (child = OF_child(regulators_phandle); child; child = OF_peer(child)) {
    821 		struct axp20xreg_attach_args reg = { .reg_phandle = child };
    822 		config_found(sc->sc_dev, &reg, NULL);
    823 	}
    824 }
    825 #endif /* FDT */
    826