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