xref: /netbsd-src/sys/dev/i2c/axp20x.c (revision 404ee5b9334f618040b6cdef96a0ff35a6fc4636)
1 /* $NetBSD: axp20x.c,v 1.13 2018/06/26 06:03:57 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 2014-2017 Jared McNeill <jmcneill@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.13 2018/06/26 06:03:57 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 struct device_compatible_entry compat_data[] = {
218 	{ "x-powers,axp209",		0 },
219 	{ NULL,				0 }
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, compat_data, &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