xref: /netbsd-src/sys/dev/i2c/axp20x.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1 /* $NetBSD: axp20x.c,v 1.21 2021/08/07 16:19:11 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 <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.21 2021/08/07 16:19:11 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
axp20x_match(device_t parent,cfdata_t match,void * aux)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
axp20x_attach(device_t parent,device_t self,void * aux)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 = ia->ia_cookie;
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
axp20x_sensors_refresh_volt(struct axp20x_softc * sc,int reg,envsys_data_t * edata)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
axp20x_sensors_refresh_amp(struct axp20x_softc * sc,int reg,envsys_data_t * edata)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
axp20x_sensors_refresh(struct sysmon_envsys * sme,envsys_data_t * edata)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
axp20x_read(struct axp20x_softc * sc,uint8_t reg,uint8_t * val,size_t len)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
axp20x_write(struct axp20x_softc * sc,uint8_t reg,uint8_t * val,size_t len)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
axp20x_set_dcdc(device_t dev,int dcdc,int mvolt)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
axp20x_get_dcdc(device_t dev,int dcdc,int * pmvolt)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
axp20x_poweroff(device_t dev)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
axp20xreg_acquire(device_t dev)694 axp20xreg_acquire(device_t dev)
695 {
696 	return 0;
697 }
698 
699 static void
axp20xreg_release(device_t dev)700 axp20xreg_release(device_t dev)
701 {
702 }
703 
704 static int
axp20xreg_enable(device_t dev,bool enable)705 axp20xreg_enable(device_t dev, bool enable)
706 {
707 	/* TODO */
708 	return enable ? 0 : EINVAL;
709 }
710 
711 static int
axp20xreg_set_voltage(device_t dev,u_int min_uvol,u_int max_uvol)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
axp20xreg_get_voltage(device_t dev,u_int * puvol)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 *
axp20xreg_lookup(int phandle)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
axp20xreg_match(device_t parent,cfdata_t match,void * aux)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
axp20xreg_attach(device_t parent,device_t self,void * aux)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
axp20x_fdt_poweroff(device_t dev)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
axp20x_fdt_attach(struct axp20x_softc * sc)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