axp20x.c revision 1.11 1 /* $NetBSD: axp20x.c,v 1.11 2018/06/16 21:22:13 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.11 2018/06/16 21:22:13 thorpej Exp $");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/conf.h>
38 #include <sys/bus.h>
39 #include <sys/kmem.h>
40
41 #include <dev/i2c/i2cvar.h>
42 #include <dev/i2c/axp20xvar.h>
43
44 #include <dev/sysmon/sysmonvar.h>
45
46 #ifdef FDT
47 #include <dev/fdt/fdtvar.h>
48 #endif
49
50 #define AXP209_I2C_ADDR 0x34
51
52 #define AXP_INPUT_STATUS 0x00
53 #define AXP_INPUT_STATUS_AC_PRESENT __BIT(7)
54 #define AXP_INPUT_STATUS_AC_OK __BIT(6)
55 #define AXP_INPUT_STATUS_VBUS_PRESENT __BIT(5)
56 #define AXP_INPUT_STATUS_VBUS_OK __BIT(4)
57
58 #define AXP_POWER_MODE 0x01
59 #define AXP_POWER_MODE_OVERTEMP __BIT(7)
60 #define AXP_POWER_MODE_CHARGING __BIT(6)
61 #define AXP_POWER_MODE_BATTOK __BIT(5)
62
63 #define AXP_POWEROUT_CTRL 0x12
64 #define AXP_POWEROUT_CTRL_LDO3 __BIT(6)
65 #define AXP_POWEROUT_CTRL_DCDC2 __BIT(4)
66 #define AXP_POWEROUT_CTRL_LDO4 __BIT(3)
67 #define AXP_POWEROUT_CTRL_LDO2 __BIT(2)
68 #define AXP_POWEROUT_CTRL_DCDC3 __BIT(1)
69 #define AXP_POWEROUT_CTRL_EXTEN __BIT(0)
70
71 #define AXP_DCDC2 0x23
72 #define AXP_DCDC2_VOLT_MASK __BITS(0,5)
73 #define AXP_DCDC2_VOLT_SHIFT 0
74
75 #define AXP_DCDC2_LDO3_VRC 0x25
76
77 #define AXP_DCDC3 0x27
78 #define AXP_DCDC3_VOLT_MASK __BITS(0,6)
79 #define AXP_DCDC3_VOLT_SHIFT 0
80
81 #define AXP_LDO2_4 0x28
82 #define AXP_LDO2_VOLT_MASK __BITS(4,7)
83 #define AXP_LDO2_VOLT_SHIFT 4
84 #define AXP_LDO4_VOLT_MASK __BITS(0,3)
85 #define AXP_LDO4_VOLT_SHIFT 0
86 static int ldo4_mvV[] = {
87 1250,
88 1300,
89 1400,
90 1500,
91 1600,
92 1700,
93 1800,
94 1900,
95 2000,
96 2500,
97 2700,
98 2800,
99 3000,
100 3100,
101 3200,
102 3300
103 };
104
105 #define AXP_LDO3 0x29
106 #define AXP_LDO3_TRACK __BIT(7)
107 #define AXP_LDO3_VOLT_MASK __BITS(0,6)
108 #define AXP_LDO3_VOLT_SHIFT 0
109
110 #define AXP_SHUTDOWN 0x32
111 #define AXP_SHUTDOWN_CTRL __BIT(7)
112
113 #define AXP_BKUP_CTRL 0x35
114 #define AXP_BKUP_CTRL_ENABLE __BIT(7)
115 #define AXP_BKUP_CTRL_VOLT_MASK __BITS(5,6)
116 #define AXP_BKUP_CTRL_VOLT_SHIFT 5
117 #define AXP_BKUP_CTRL_VOLT_3V1 0
118 #define AXP_BKUP_CTRL_VOLT_3V0 1
119 #define AXP_BKUP_CTRL_VOLT_3V6 2
120 #define AXP_BKUP_CTRL_VOLT_2V5 3
121 static int bkup_volt[] = {
122 3100,
123 3000,
124 3600,
125 2500
126 };
127 #define AXP_BKUP_CTRL_CURR_MASK __BITS(0,1)
128 #define AXP_BKUP_CTRL_CURR_SHIFT 0
129 #define AXP_BKUP_CTRL_CURR_50U 0
130 #define AXP_BKUP_CTRL_CURR_100U 1
131 #define AXP_BKUP_CTRL_CURR_200U 2
132 #define AXP_BKUP_CTRL_CURR_400U 3
133 static int bkup_curr[] = {
134 50,
135 100,
136 200,
137 400
138 };
139
140 #define AXP_ACV_MON_REG 0x56 /* 2 bytes */
141 #define AXP_ACI_MON_REG 0x58 /* 2 bytes */
142 #define AXP_VBUSV_MON_REG 0x5a /* 2 bytes */
143 #define AXP_VBUSI_MON_REG 0x5c /* 2 bytes */
144 #define AXP_TEMP_MON_REG 0x5e /* 2 bytes */
145 #define AXP_BATTV_MON_REG 0x78 /* 2 bytes */
146 #define AXP_BATTCI_MON_REG 0x7a /* 2 bytes */
147 #define AXP_BATTDI_MON_REG 0x7c /* 2 bytes */
148 #define AXP_APSV_MON_REG 0x7e /* 2 bytes */
149
150 #define AXP_ADC_EN1 0x82
151 #define AXP_ADC_EN1_BATTV __BIT(7)
152 #define AXP_ADC_EN1_BATTI __BIT(6)
153 #define AXP_ADC_EN1_ACV __BIT(5)
154 #define AXP_ADC_EN1_ACI __BIT(4)
155 #define AXP_ADC_EN1_VBUSV __BIT(3)
156 #define AXP_ADC_EN1_VBUSI __BIT(2)
157 #define AXP_ADC_EN1_APSV __BIT(1)
158 #define AXP_ADC_EN1_TS __BIT(0)
159 #define AXP_ADC_EN2 0x83
160 #define AXP_ADC_EN2_TEMP __BIT(7)
161
162 #define AXP_SENSOR_ACOK 0
163 #define AXP_SENSOR_ACV 1
164 #define AXP_SENSOR_ACI 2
165 #define AXP_SENSOR_VBUSOK 3
166 #define AXP_SENSOR_VBUSV 4
167 #define AXP_SENSOR_VBUSI 5
168 #define AXP_SENSOR_BATTOK 6
169 #define AXP_SENSOR_BATTV 7
170 #define AXP_SENSOR_BATTI 8
171 #define AXP_SENSOR_APSV 9
172 #define AXP_SENSOR_TEMP 10
173 #define AXP_NSENSORS (AXP_SENSOR_TEMP + 1)
174
175 /* define per-ADC LSB to uV/uA values */
176 static int axp20x_sensors_lsb[] = {
177 0, /* AXP_SENSOR_ACOK */
178 1700, /* AXP_SENSOR_ACV */
179 625, /* AXP_SENSOR_ACI */
180 0,
181 1700, /* AXP_SENSOR_VBUSV */
182 375, /* AXP_SENSOR_VBUSI */
183 0,
184 1100, /* AXP_SENSOR_BATTV */
185 500, /* AXP_SENSOR_BATTI */
186 1400, /* AXP_SENSOR_APSV */
187 };
188
189
190 struct axp20x_softc {
191 device_t sc_dev;
192 i2c_tag_t sc_i2c;
193 i2c_addr_t sc_addr;
194 int sc_phandle;
195
196 uint8_t sc_inputstatus;
197 uint8_t sc_powermode;
198
199 struct sysmon_envsys *sc_sme;
200 envsys_data_t sc_sensor[AXP_NSENSORS];
201 };
202
203 static int axp20x_match(device_t, cfdata_t, void *);
204 static void axp20x_attach(device_t, device_t, void *);
205
206 static void axp20x_sensors_refresh(struct sysmon_envsys *, envsys_data_t *);
207 static int axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
208 static int axp20x_write(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
209
210 #ifdef FDT
211 static void axp20x_fdt_attach(struct axp20x_softc *);
212 #endif
213
214 CFATTACH_DECL_NEW(axp20x, sizeof(struct axp20x_softc),
215 axp20x_match, axp20x_attach, NULL, NULL);
216
217 static const char * compatible[] = {
218 "x-powers,axp209",
219 NULL
220 };
221
222 static 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, compatible, &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 ®, 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 ®, 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, ®, 1,
607 poll ? I2C_F_POLL : 0);
608 if (ret)
609 return ret;
610 if (axp20x_read(sc, AXP_DCDC2, ®, 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, ®, 1,
624 poll ? I2C_F_POLL : 0);
625 if (ret)
626 return ret;
627 if (axp20x_read(sc, AXP_DCDC3, ®, 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, ®, 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, ®, 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, ®, 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, ®, NULL);
818 }
819 }
820 #endif /* FDT */
821