axp20x.c revision 1.15 1 /* $NetBSD: axp20x.c,v 1.15 2019/12/23 19:12:22 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.15 2019/12/23 19:12:22 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, 0);
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, 0);
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, 0);
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, 0);
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, 0);
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, 0) == 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, 0) == 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, 0) == 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, 0) == 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, 0) == 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
571 ret = iic_acquire_bus(sc->sc_i2c, flags);
572 if (ret == 0) {
573 ret = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr,
574 ®, 1, val, len, flags);
575 iic_release_bus(sc->sc_i2c, flags);
576 }
577
578 return ret;
579
580 }
581
582 static int
583 axp20x_write(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len,
584 int flags)
585 {
586 int ret;
587
588 ret = iic_acquire_bus(sc->sc_i2c, flags);
589 if (ret == 0) {
590 ret = iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
591 ®, 1, val, len, flags);
592 iic_release_bus(sc->sc_i2c, flags);
593 }
594
595 return ret;
596 }
597
598 int
599 axp20x_set_dcdc(device_t dev, int dcdc, int mvolt, bool poll)
600 {
601 struct axp20x_softc *sc = device_private(dev);
602 int ret;
603 int value;
604 uint8_t reg;
605
606 KASSERT(sc != NULL);
607 value = (mvolt - 700) / 25;
608 switch (dcdc) {
609 case AXP20X_DCDC2:
610 value <<= AXP_DCDC2_VOLT_SHIFT;
611 if (value > AXP_DCDC2_VOLT_MASK)
612 return EINVAL;
613 reg = value & AXP_DCDC2_VOLT_MASK;
614 ret = axp20x_write(sc, AXP_DCDC2, ®, 1,
615 poll ? I2C_F_POLL : 0);
616 if (ret)
617 return ret;
618 if (axp20x_read(sc, AXP_DCDC2, ®, 1, poll ? I2C_F_POLL : 0)
619 == 0) {
620 aprint_debug_dev(sc->sc_dev,
621 "DCDC2 changed to %dmV\n",
622 (int)(700 + (reg & AXP_DCDC2_VOLT_MASK) * 25));
623 }
624 return 0;
625
626 case AXP20X_DCDC3:
627 value <<= AXP_DCDC3_VOLT_SHIFT;
628 if (value > AXP_DCDC3_VOLT_MASK)
629 return EINVAL;
630 reg = value & AXP_DCDC3_VOLT_MASK;
631 ret = axp20x_write(sc, AXP_DCDC3, ®, 1,
632 poll ? I2C_F_POLL : 0);
633 if (ret)
634 return ret;
635 if (axp20x_read(sc, AXP_DCDC3, ®, 1, poll ? I2C_F_POLL : 0)
636 == 0) {
637 aprint_debug_dev(sc->sc_dev,
638 "DCDC3 changed to %dmV\n",
639 (int)(700 + (reg & AXP_DCDC3_VOLT_MASK) * 25));
640 }
641 return 0;
642 default:
643 aprint_error_dev(dev, "wrong DCDC %d\n", dcdc);
644 return EINVAL;
645 }
646 }
647
648 int
649 axp20x_get_dcdc(device_t dev, int dcdc, int *pmvolt, bool poll)
650 {
651 struct axp20x_softc *sc = device_private(dev);
652 uint8_t reg;
653 int error;
654
655 switch (dcdc) {
656 case AXP20X_DCDC2:
657 error = axp20x_read(sc, AXP_DCDC2, ®, 1, poll ? I2C_F_POLL : 0);
658 if (error != 0)
659 return error;
660 *pmvolt = __SHIFTOUT(reg, AXP_DCDC2_VOLT_MASK) * 25 + 700;
661 return 0;
662 case AXP20X_DCDC3:
663 error = axp20x_read(sc, AXP_DCDC3, ®, 1, poll ? I2C_F_POLL : 0);
664 if (error != 0)
665 return error;
666 *pmvolt = __SHIFTOUT(reg, AXP_DCDC3_VOLT_MASK) * 25 + 700;
667 return 0;
668 default:
669 return EINVAL;
670 }
671 }
672
673 void
674 axp20x_poweroff(device_t dev)
675 {
676 struct axp20x_softc * const sc = device_private(dev);
677 uint8_t reg = AXP_SHUTDOWN_CTRL;
678 int error;
679
680 error = axp20x_write(sc, AXP_SHUTDOWN, ®, 1, I2C_F_POLL);
681 if (error) {
682 device_printf(dev, "WARNING: unable to power off, error %d\n",
683 error);
684 }
685 }
686
687 #ifdef FDT
688 static const struct axp20xregdef {
689 const char *name;
690 int dcdc;
691 } axp20x_regdefs[] = {
692 { "dcdc2", AXP20X_DCDC2 },
693 { "dcdc3", AXP20X_DCDC3 },
694 };
695
696 struct axp20xreg_softc {
697 device_t sc_dev;
698 int sc_phandle;
699 const struct axp20xregdef *sc_regdef;
700 };
701
702 struct axp20xreg_attach_args {
703 int reg_phandle;
704 };
705
706 static int
707 axp20xreg_acquire(device_t dev)
708 {
709 return 0;
710 }
711
712 static void
713 axp20xreg_release(device_t dev)
714 {
715 }
716
717 static int
718 axp20xreg_enable(device_t dev, bool enable)
719 {
720 /* TODO */
721 return enable ? 0 : EINVAL;
722 }
723
724 static int
725 axp20xreg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
726 {
727 struct axp20xreg_softc * const sc = device_private(dev);
728
729 return axp20x_set_dcdc(device_parent(dev), sc->sc_regdef->dcdc, min_uvol / 1000, false);
730 }
731
732 static int
733 axp20xreg_get_voltage(device_t dev, u_int *puvol)
734 {
735 struct axp20xreg_softc * const sc = device_private(dev);
736 int mvol, error;
737
738 error = axp20x_get_dcdc(device_parent(dev), sc->sc_regdef->dcdc, &mvol, false);
739 if (error != 0)
740 return error;
741
742 *puvol = mvol * 1000;
743 return 0;
744 }
745
746 static struct fdtbus_regulator_controller_func axp20xreg_funcs = {
747 .acquire = axp20xreg_acquire,
748 .release = axp20xreg_release,
749 .enable = axp20xreg_enable,
750 .set_voltage = axp20xreg_set_voltage,
751 .get_voltage = axp20xreg_get_voltage,
752 };
753
754 static const struct axp20xregdef *
755 axp20xreg_lookup(int phandle)
756 {
757 const char *name;
758 int n;
759
760 name = fdtbus_get_string(phandle, "name");
761 if (name == NULL)
762 return NULL;
763
764 for (n = 0; n < __arraycount(axp20x_regdefs); n++)
765 if (strcmp(name, axp20x_regdefs[n].name) == 0)
766 return &axp20x_regdefs[n];
767
768 return NULL;
769 }
770
771 static int
772 axp20xreg_match(device_t parent, cfdata_t match, void *aux)
773 {
774 const struct axp20xreg_attach_args *reg = aux;
775
776 return axp20xreg_lookup(reg->reg_phandle) != NULL;
777 }
778
779 static void
780 axp20xreg_attach(device_t parent, device_t self, void *aux)
781 {
782 struct axp20xreg_softc * const sc = device_private(self);
783 const struct axp20xreg_attach_args *reg = aux;
784 const char *regulator_name;
785
786 sc->sc_dev = self;
787 sc->sc_phandle = reg->reg_phandle;
788 sc->sc_regdef = axp20xreg_lookup(reg->reg_phandle);
789
790 regulator_name = fdtbus_get_string(reg->reg_phandle, "regulator-name");
791
792 aprint_naive("\n");
793 if (regulator_name)
794 aprint_normal(": %s (%s)\n", sc->sc_regdef->name, regulator_name);
795 else
796 aprint_normal(": %s\n", sc->sc_regdef->name);
797
798 fdtbus_register_regulator_controller(self, sc->sc_phandle, &axp20xreg_funcs);
799 }
800
801 CFATTACH_DECL_NEW(axp20xreg, sizeof(struct axp20xreg_softc),
802 axp20xreg_match, axp20xreg_attach, NULL, NULL);
803
804 static void
805 axp20x_fdt_poweroff(device_t dev)
806 {
807 delay(1000000);
808 axp20x_poweroff(dev);
809 }
810
811 static struct fdtbus_power_controller_func axp20x_fdt_power_funcs = {
812 .poweroff = axp20x_fdt_poweroff,
813 };
814
815 static void
816 axp20x_fdt_attach(struct axp20x_softc *sc)
817 {
818 int regulators_phandle, child;
819
820 fdtbus_register_power_controller(sc->sc_dev, sc->sc_phandle,
821 &axp20x_fdt_power_funcs);
822
823 regulators_phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators");
824 if (regulators_phandle == -1)
825 return;
826
827 for (child = OF_child(regulators_phandle); child; child = OF_peer(child)) {
828 struct axp20xreg_attach_args reg = { .reg_phandle = child };
829 config_found(sc->sc_dev, ®, NULL);
830 }
831 }
832 #endif /* FDT */
833