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