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