1 /* $NetBSD: axp20x.c,v 1.21 2021/08/07 16:19:11 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2014-2017 Jared McNeill <jmcneill@invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.21 2021/08/07 16:19:11 thorpej Exp $");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
35 #include <sys/conf.h>
36 #include <sys/bus.h>
37 #include <sys/kmem.h>
38
39 #include <dev/i2c/i2cvar.h>
40
41 #include <dev/sysmon/sysmonvar.h>
42
43 #include <dev/fdt/fdtvar.h>
44
45 #define AXP20X_DCDC2 2
46 #define AXP20X_DCDC3 3
47
48 #define AXP209_I2C_ADDR 0x34
49
50 #define AXP_INPUT_STATUS 0x00
51 #define AXP_INPUT_STATUS_AC_PRESENT __BIT(7)
52 #define AXP_INPUT_STATUS_AC_OK __BIT(6)
53 #define AXP_INPUT_STATUS_VBUS_PRESENT __BIT(5)
54 #define AXP_INPUT_STATUS_VBUS_OK __BIT(4)
55
56 #define AXP_POWER_MODE 0x01
57 #define AXP_POWER_MODE_OVERTEMP __BIT(7)
58 #define AXP_POWER_MODE_CHARGING __BIT(6)
59 #define AXP_POWER_MODE_BATTOK __BIT(5)
60
61 #define AXP_POWEROUT_CTRL 0x12
62 #define AXP_POWEROUT_CTRL_LDO3 __BIT(6)
63 #define AXP_POWEROUT_CTRL_DCDC2 __BIT(4)
64 #define AXP_POWEROUT_CTRL_LDO4 __BIT(3)
65 #define AXP_POWEROUT_CTRL_LDO2 __BIT(2)
66 #define AXP_POWEROUT_CTRL_DCDC3 __BIT(1)
67 #define AXP_POWEROUT_CTRL_EXTEN __BIT(0)
68
69 #define AXP_DCDC2 0x23
70 #define AXP_DCDC2_VOLT_MASK __BITS(0,5)
71 #define AXP_DCDC2_VOLT_SHIFT 0
72
73 #define AXP_DCDC2_LDO3_VRC 0x25
74
75 #define AXP_DCDC3 0x27
76 #define AXP_DCDC3_VOLT_MASK __BITS(0,6)
77 #define AXP_DCDC3_VOLT_SHIFT 0
78
79 #define AXP_LDO2_4 0x28
80 #define AXP_LDO2_VOLT_MASK __BITS(4,7)
81 #define AXP_LDO2_VOLT_SHIFT 4
82 #define AXP_LDO4_VOLT_MASK __BITS(0,3)
83 #define AXP_LDO4_VOLT_SHIFT 0
84 static int ldo4_mvV[] = {
85 1250,
86 1300,
87 1400,
88 1500,
89 1600,
90 1700,
91 1800,
92 1900,
93 2000,
94 2500,
95 2700,
96 2800,
97 3000,
98 3100,
99 3200,
100 3300
101 };
102
103 #define AXP_LDO3 0x29
104 #define AXP_LDO3_TRACK __BIT(7)
105 #define AXP_LDO3_VOLT_MASK __BITS(0,6)
106 #define AXP_LDO3_VOLT_SHIFT 0
107
108 #define AXP_SHUTDOWN 0x32
109 #define AXP_SHUTDOWN_CTRL __BIT(7)
110
111 #define AXP_BKUP_CTRL 0x35
112 #define AXP_BKUP_CTRL_ENABLE __BIT(7)
113 #define AXP_BKUP_CTRL_VOLT_MASK __BITS(5,6)
114 #define AXP_BKUP_CTRL_VOLT_SHIFT 5
115 #define AXP_BKUP_CTRL_VOLT_3V1 0
116 #define AXP_BKUP_CTRL_VOLT_3V0 1
117 #define AXP_BKUP_CTRL_VOLT_3V6 2
118 #define AXP_BKUP_CTRL_VOLT_2V5 3
119 static int bkup_volt[] = {
120 3100,
121 3000,
122 3600,
123 2500
124 };
125 #define AXP_BKUP_CTRL_CURR_MASK __BITS(0,1)
126 #define AXP_BKUP_CTRL_CURR_SHIFT 0
127 #define AXP_BKUP_CTRL_CURR_50U 0
128 #define AXP_BKUP_CTRL_CURR_100U 1
129 #define AXP_BKUP_CTRL_CURR_200U 2
130 #define AXP_BKUP_CTRL_CURR_400U 3
131 static int bkup_curr[] = {
132 50,
133 100,
134 200,
135 400
136 };
137
138 #define AXP_ACV_MON_REG 0x56 /* 2 bytes */
139 #define AXP_ACI_MON_REG 0x58 /* 2 bytes */
140 #define AXP_VBUSV_MON_REG 0x5a /* 2 bytes */
141 #define AXP_VBUSI_MON_REG 0x5c /* 2 bytes */
142 #define AXP_TEMP_MON_REG 0x5e /* 2 bytes */
143 #define AXP_BATTV_MON_REG 0x78 /* 2 bytes */
144 #define AXP_BATTCI_MON_REG 0x7a /* 2 bytes */
145 #define AXP_BATTDI_MON_REG 0x7c /* 2 bytes */
146 #define AXP_APSV_MON_REG 0x7e /* 2 bytes */
147
148 #define AXP_ADC_EN1 0x82
149 #define AXP_ADC_EN1_BATTV __BIT(7)
150 #define AXP_ADC_EN1_BATTI __BIT(6)
151 #define AXP_ADC_EN1_ACV __BIT(5)
152 #define AXP_ADC_EN1_ACI __BIT(4)
153 #define AXP_ADC_EN1_VBUSV __BIT(3)
154 #define AXP_ADC_EN1_VBUSI __BIT(2)
155 #define AXP_ADC_EN1_APSV __BIT(1)
156 #define AXP_ADC_EN1_TS __BIT(0)
157 #define AXP_ADC_EN2 0x83
158 #define AXP_ADC_EN2_TEMP __BIT(7)
159
160 #define AXP_SENSOR_ACOK 0
161 #define AXP_SENSOR_ACV 1
162 #define AXP_SENSOR_ACI 2
163 #define AXP_SENSOR_VBUSOK 3
164 #define AXP_SENSOR_VBUSV 4
165 #define AXP_SENSOR_VBUSI 5
166 #define AXP_SENSOR_BATTOK 6
167 #define AXP_SENSOR_BATTV 7
168 #define AXP_SENSOR_BATTI 8
169 #define AXP_SENSOR_APSV 9
170 #define AXP_SENSOR_TEMP 10
171 #define AXP_NSENSORS (AXP_SENSOR_TEMP + 1)
172
173 /* define per-ADC LSB to uV/uA values */
174 static int axp20x_sensors_lsb[] = {
175 0, /* AXP_SENSOR_ACOK */
176 1700, /* AXP_SENSOR_ACV */
177 625, /* AXP_SENSOR_ACI */
178 0,
179 1700, /* AXP_SENSOR_VBUSV */
180 375, /* AXP_SENSOR_VBUSI */
181 0,
182 1100, /* AXP_SENSOR_BATTV */
183 500, /* AXP_SENSOR_BATTI */
184 1400, /* AXP_SENSOR_APSV */
185 };
186
187
188 struct axp20x_softc {
189 device_t sc_dev;
190 i2c_tag_t sc_i2c;
191 i2c_addr_t sc_addr;
192 int sc_phandle;
193
194 uint8_t sc_inputstatus;
195 uint8_t sc_powermode;
196
197 struct sysmon_envsys *sc_sme;
198 envsys_data_t sc_sensor[AXP_NSENSORS];
199 };
200
201 static int axp20x_match(device_t, cfdata_t, void *);
202 static void axp20x_attach(device_t, device_t, void *);
203
204 static void axp20x_sensors_refresh(struct sysmon_envsys *, envsys_data_t *);
205 static int axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t);
206 static int axp20x_write(struct axp20x_softc *, uint8_t, uint8_t *, size_t);
207
208 static void axp20x_fdt_attach(struct axp20x_softc *);
209
210 CFATTACH_DECL_NEW(axp20x, sizeof(struct axp20x_softc),
211 axp20x_match, axp20x_attach, NULL, NULL);
212
213 static const struct device_compatible_entry compat_data[] = {
214 { .compat = "x-powers,axp209" },
215 DEVICE_COMPAT_EOL
216 };
217
218 static int
axp20x_match(device_t parent,cfdata_t match,void * aux)219 axp20x_match(device_t parent, cfdata_t match, void *aux)
220 {
221 struct i2c_attach_args * const ia = aux;
222 int match_result;
223
224 if (iic_use_direct_match(ia, match, compat_data, &match_result))
225 return match_result;
226
227 /* This device is direct-config only. */
228
229 return 0;
230 }
231
232 static void
axp20x_attach(device_t parent,device_t self,void * aux)233 axp20x_attach(device_t parent, device_t self, void *aux)
234 {
235 struct axp20x_softc *sc = device_private(self);
236 struct i2c_attach_args *ia = aux;
237 int first;
238 int error;
239 uint8_t value;
240
241 sc->sc_dev = self;
242 sc->sc_i2c = ia->ia_tag;
243 sc->sc_addr = ia->ia_addr;
244 sc->sc_phandle = ia->ia_cookie;
245
246 error = axp20x_read(sc, AXP_INPUT_STATUS,
247 &sc->sc_inputstatus, 1);
248 if (error) {
249 aprint_error(": can't read status: %d\n", error);
250 return;
251 }
252 error = axp20x_read(sc, AXP_POWER_MODE,
253 &sc->sc_powermode, 1);
254 if (error) {
255 aprint_error(": can't read power mode: %d\n", error);
256 return;
257 }
258 value = AXP_ADC_EN1_ACV | AXP_ADC_EN1_ACI | AXP_ADC_EN1_VBUSV | AXP_ADC_EN1_VBUSI | AXP_ADC_EN1_APSV | AXP_ADC_EN1_TS;
259 if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
260 value |= AXP_ADC_EN1_BATTV | AXP_ADC_EN1_BATTI;
261 error = axp20x_write(sc, AXP_ADC_EN1, &value, 1);
262 if (error) {
263 aprint_error(": can't set AXP_ADC_EN1\n");
264 return;
265 }
266 error = axp20x_read(sc, AXP_ADC_EN2, &value, 1);
267 if (error) {
268 aprint_error(": can't read AXP_ADC_EN2\n");
269 return;
270 }
271 value |= AXP_ADC_EN2_TEMP;
272 error = axp20x_write(sc, AXP_ADC_EN2, &value, 1);
273 if (error) {
274 aprint_error(": can't set AXP_ADC_EN2\n");
275 return;
276 }
277
278 aprint_naive("\n");
279 first = 1;
280 if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) {
281 aprint_verbose(": AC used");
282 first = 0;
283 } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_PRESENT) {
284 aprint_verbose(": AC present (but unused)");
285 first = 0;
286 }
287 if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) {
288 aprint_verbose("%s VBUS used", first ? ":" : ",");
289 first = 0;
290 } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_PRESENT) {
291 aprint_verbose("%s VBUS present (but unused)", first ? ":" : ",");
292 first = 0;
293 }
294 if (sc->sc_powermode & AXP_POWER_MODE_BATTOK) {
295 aprint_verbose("%s battery present", first ? ":" : ",");
296 }
297 aprint_normal("\n");
298
299 sc->sc_sme = sysmon_envsys_create();
300 sc->sc_sme->sme_name = device_xname(self);
301 sc->sc_sme->sme_cookie = sc;
302 sc->sc_sme->sme_refresh = axp20x_sensors_refresh;
303
304 sc->sc_sensor[AXP_SENSOR_ACOK].units = ENVSYS_INDICATOR;
305 sc->sc_sensor[AXP_SENSOR_ACOK].state = ENVSYS_SVALID;
306 sc->sc_sensor[AXP_SENSOR_ACOK].value_cur =
307 (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
308 snprintf(sc->sc_sensor[AXP_SENSOR_ACOK].desc,
309 sizeof(sc->sc_sensor[AXP_SENSOR_ACOK].desc), "AC input");
310 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACOK]);
311 sc->sc_sensor[AXP_SENSOR_ACV].units = ENVSYS_SVOLTS_DC;
312 sc->sc_sensor[AXP_SENSOR_ACV].state = ENVSYS_SINVALID;
313 sc->sc_sensor[AXP_SENSOR_ACV].flags = ENVSYS_FHAS_ENTROPY;
314 snprintf(sc->sc_sensor[AXP_SENSOR_ACV].desc,
315 sizeof(sc->sc_sensor[AXP_SENSOR_ACV].desc), "AC input voltage");
316 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACV]);
317 sc->sc_sensor[AXP_SENSOR_ACI].units = ENVSYS_SAMPS;
318 sc->sc_sensor[AXP_SENSOR_ACI].state = ENVSYS_SINVALID;
319 sc->sc_sensor[AXP_SENSOR_ACI].flags = ENVSYS_FHAS_ENTROPY;
320 snprintf(sc->sc_sensor[AXP_SENSOR_ACI].desc,
321 sizeof(sc->sc_sensor[AXP_SENSOR_ACI].desc), "AC input current");
322 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACI]);
323
324 sc->sc_sensor[AXP_SENSOR_VBUSOK].units = ENVSYS_INDICATOR;
325 sc->sc_sensor[AXP_SENSOR_VBUSOK].state = ENVSYS_SVALID;
326 sc->sc_sensor[AXP_SENSOR_VBUSOK].value_cur =
327 (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
328 snprintf(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc,
329 sizeof(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc), "VBUS input");
330 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSOK]);
331 sc->sc_sensor[AXP_SENSOR_VBUSV].units = ENVSYS_SVOLTS_DC;
332 sc->sc_sensor[AXP_SENSOR_VBUSV].state = ENVSYS_SINVALID;
333 sc->sc_sensor[AXP_SENSOR_VBUSV].flags = ENVSYS_FHAS_ENTROPY;
334 snprintf(sc->sc_sensor[AXP_SENSOR_VBUSV].desc,
335 sizeof(sc->sc_sensor[AXP_SENSOR_VBUSV].desc), "VBUS input voltage");
336 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSV]);
337 sc->sc_sensor[AXP_SENSOR_VBUSI].units = ENVSYS_SAMPS;
338 sc->sc_sensor[AXP_SENSOR_VBUSI].state = ENVSYS_SINVALID;
339 sc->sc_sensor[AXP_SENSOR_VBUSI].flags = ENVSYS_FHAS_ENTROPY;
340 snprintf(sc->sc_sensor[AXP_SENSOR_VBUSI].desc,
341 sizeof(sc->sc_sensor[AXP_SENSOR_VBUSI].desc), "VBUS input current");
342 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSI]);
343
344 sc->sc_sensor[AXP_SENSOR_BATTOK].units = ENVSYS_INDICATOR;
345 sc->sc_sensor[AXP_SENSOR_BATTOK].state = ENVSYS_SVALID;
346 sc->sc_sensor[AXP_SENSOR_BATTOK].value_cur =
347 (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
348 snprintf(sc->sc_sensor[AXP_SENSOR_BATTOK].desc,
349 sizeof(sc->sc_sensor[AXP_SENSOR_BATTOK].desc), "battery");
350 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTOK]);
351 sc->sc_sensor[AXP_SENSOR_BATTV].units = ENVSYS_SVOLTS_DC;
352 sc->sc_sensor[AXP_SENSOR_BATTV].state = ENVSYS_SINVALID;
353 sc->sc_sensor[AXP_SENSOR_BATTV].flags = ENVSYS_FHAS_ENTROPY;
354 snprintf(sc->sc_sensor[AXP_SENSOR_BATTV].desc,
355 sizeof(sc->sc_sensor[AXP_SENSOR_BATTV].desc), "battery voltage");
356 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTV]);
357 sc->sc_sensor[AXP_SENSOR_BATTI].units = ENVSYS_SAMPS;
358 sc->sc_sensor[AXP_SENSOR_BATTI].state = ENVSYS_SINVALID;
359 sc->sc_sensor[AXP_SENSOR_BATTI].flags = ENVSYS_FHAS_ENTROPY;
360 snprintf(sc->sc_sensor[AXP_SENSOR_BATTI].desc,
361 sizeof(sc->sc_sensor[AXP_SENSOR_BATTI].desc), "battery current");
362 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTI]);
363
364 sc->sc_sensor[AXP_SENSOR_APSV].units = ENVSYS_SVOLTS_DC;
365 sc->sc_sensor[AXP_SENSOR_APSV].state = ENVSYS_SINVALID;
366 sc->sc_sensor[AXP_SENSOR_APSV].flags = ENVSYS_FHAS_ENTROPY;
367 snprintf(sc->sc_sensor[AXP_SENSOR_APSV].desc,
368 sizeof(sc->sc_sensor[AXP_SENSOR_APSV].desc), "APS output voltage");
369 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_APSV]);
370 sc->sc_sensor[AXP_SENSOR_TEMP].units = ENVSYS_STEMP;
371 sc->sc_sensor[AXP_SENSOR_TEMP].state = ENVSYS_SINVALID;
372 sc->sc_sensor[AXP_SENSOR_TEMP].flags = ENVSYS_FHAS_ENTROPY;
373 snprintf(sc->sc_sensor[AXP_SENSOR_TEMP].desc,
374 sizeof(sc->sc_sensor[AXP_SENSOR_TEMP].desc),
375 "internal temperature");
376 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_TEMP]);
377
378 sysmon_envsys_register(sc->sc_sme);
379
380 if (axp20x_read(sc, AXP_DCDC2, &value, 1) == 0) {
381 aprint_verbose_dev(sc->sc_dev, "DCDC2 %dmV\n",
382 (int)(700 + (value & AXP_DCDC2_VOLT_MASK) * 25));
383 }
384 if (axp20x_read(sc, AXP_DCDC3, &value, 1) == 0) {
385 aprint_verbose_dev(sc->sc_dev, "DCDC3 %dmV\n",
386 (int)(700 + (value & AXP_DCDC3_VOLT_MASK) * 25));
387 }
388 if (axp20x_read(sc, AXP_LDO2_4, &value, 1) == 0) {
389 aprint_verbose_dev(sc->sc_dev, "LDO2 %dmV, LDO4 %dmV\n",
390 (int)(1800 +
391 ((value & AXP_LDO2_VOLT_MASK) >> AXP_LDO2_VOLT_SHIFT) * 100
392 ),
393 ldo4_mvV[(value & AXP_LDO4_VOLT_MASK) >> AXP_LDO4_VOLT_SHIFT]);
394 }
395 if (axp20x_read(sc, AXP_LDO3, &value, 1) == 0) {
396 if (value & AXP_LDO3_TRACK) {
397 aprint_verbose_dev(sc->sc_dev, "LDO3: tracking\n");
398 } else {
399 aprint_verbose_dev(sc->sc_dev, "LDO3 %dmV\n",
400 (int)(700 + (value & AXP_LDO3_VOLT_MASK) * 25));
401 }
402 }
403
404 if (axp20x_read(sc, AXP_BKUP_CTRL, &value, 1) == 0) {
405 if (value & AXP_BKUP_CTRL_ENABLE) {
406 aprint_verbose_dev(sc->sc_dev,
407 "RTC supercap charger enabled: %dmV at %duA\n",
408 bkup_volt[(value & AXP_BKUP_CTRL_VOLT_MASK) >>
409 AXP_BKUP_CTRL_VOLT_SHIFT],
410 bkup_curr[(value & AXP_BKUP_CTRL_CURR_MASK) >>
411 AXP_BKUP_CTRL_CURR_SHIFT]
412 );
413 }
414 }
415
416 axp20x_fdt_attach(sc);
417 }
418
419 static void
axp20x_sensors_refresh_volt(struct axp20x_softc * sc,int reg,envsys_data_t * edata)420 axp20x_sensors_refresh_volt(struct axp20x_softc *sc, int reg,
421 envsys_data_t *edata)
422 {
423 uint8_t buf[2];
424 int error;
425
426 error = axp20x_read(sc, reg, buf, sizeof(buf));
427 if (error) {
428 edata->state = ENVSYS_SINVALID;
429 } else {
430 edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
431 axp20x_sensors_lsb[edata->sensor];
432 edata->state = ENVSYS_SVALID;
433 }
434 }
435
436 static void
axp20x_sensors_refresh_amp(struct axp20x_softc * sc,int reg,envsys_data_t * edata)437 axp20x_sensors_refresh_amp(struct axp20x_softc *sc, int reg,
438 envsys_data_t *edata)
439 {
440 uint8_t buf[2];
441 int error;
442
443 error = axp20x_read(sc, reg, buf, sizeof(buf));
444 if (error) {
445 edata->state = ENVSYS_SINVALID;
446 } else {
447 edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
448 axp20x_sensors_lsb[edata->sensor];
449 edata->state = ENVSYS_SVALID;
450 }
451 }
452
453 static void
axp20x_sensors_refresh(struct sysmon_envsys * sme,envsys_data_t * edata)454 axp20x_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
455 {
456 struct axp20x_softc *sc = sme->sme_cookie;
457 uint8_t buf[2];
458 int error;
459
460 switch(edata->sensor) {
461 case AXP_SENSOR_ACOK:
462 case AXP_SENSOR_VBUSOK:
463 error = axp20x_read(sc, AXP_INPUT_STATUS,
464 &sc->sc_inputstatus, 1);
465 if (error) {
466 edata->state = ENVSYS_SINVALID;
467 return;
468 }
469 if (edata->sensor == AXP_SENSOR_ACOK) {
470 edata->value_cur =
471 (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
472 } else {
473 edata->value_cur =
474 (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
475 }
476 edata->state = ENVSYS_SVALID;
477 return;
478 case AXP_SENSOR_BATTOK:
479 error = axp20x_read(sc, AXP_POWER_MODE,
480 &sc->sc_powermode, 1);
481 if (error) {
482 edata->state = ENVSYS_SINVALID;
483 return;
484 }
485 edata->value_cur =
486 (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
487 return;
488 case AXP_SENSOR_ACV:
489 if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
490 axp20x_sensors_refresh_volt(sc, AXP_ACV_MON_REG, edata);
491 else
492 edata->state = ENVSYS_SINVALID;
493 return;
494 case AXP_SENSOR_ACI:
495 if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
496 axp20x_sensors_refresh_amp(sc, AXP_ACI_MON_REG, edata);
497 else
498 edata->state = ENVSYS_SINVALID;
499 return;
500 case AXP_SENSOR_VBUSV:
501 if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
502 axp20x_sensors_refresh_volt(sc, AXP_VBUSV_MON_REG, edata);
503 else
504 edata->state = ENVSYS_SINVALID;
505 return;
506 case AXP_SENSOR_VBUSI:
507 if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
508 axp20x_sensors_refresh_amp(sc, AXP_VBUSI_MON_REG, edata);
509 else
510 edata->state = ENVSYS_SINVALID;
511 return;
512 case AXP_SENSOR_BATTV:
513 if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
514 axp20x_sensors_refresh_volt(sc, AXP_BATTV_MON_REG, edata);
515 else
516 edata->state = ENVSYS_SINVALID;
517 return;
518 case AXP_SENSOR_BATTI:
519 if ((sc->sc_powermode & AXP_POWER_MODE_BATTOK) == 0) {
520 edata->state = ENVSYS_SINVALID;
521 return;
522 }
523 error = axp20x_read(sc, AXP_POWER_MODE,
524 &sc->sc_inputstatus, 1);
525 if (error) {
526 edata->state = ENVSYS_SINVALID;
527 return;
528 }
529 if (sc->sc_inputstatus & AXP_POWER_MODE_CHARGING) {
530 axp20x_sensors_refresh_amp(sc, AXP_BATTCI_MON_REG,
531 edata);
532 edata->value_cur = -edata->value_cur;
533 } else {
534 axp20x_sensors_refresh_amp(sc, AXP_BATTDI_MON_REG,
535 edata);
536 }
537 return;
538 case AXP_SENSOR_APSV:
539 axp20x_sensors_refresh_volt(sc, AXP_APSV_MON_REG, edata);
540 return;
541 case AXP_SENSOR_TEMP:
542 error = axp20x_read(sc, AXP_TEMP_MON_REG, buf, sizeof(buf));
543 if (error) {
544 edata->state = ENVSYS_SINVALID;
545 } else {
546 /* between -144.7C and 264.8C, step +0.1C */
547 edata->value_cur =
548 (((buf[0] << 4) | (buf[1] & 0xf)) - 1447)
549 * 100000 + 273150000;
550 edata->state = ENVSYS_SVALID;
551 }
552 return;
553 default:
554 aprint_error_dev(sc->sc_dev, "invalid sensor %d\n",
555 edata->sensor);
556 }
557 }
558
559 static int
axp20x_read(struct axp20x_softc * sc,uint8_t reg,uint8_t * val,size_t len)560 axp20x_read(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len)
561 {
562 int ret;
563
564 ret = iic_acquire_bus(sc->sc_i2c, 0);
565 if (ret == 0) {
566 ret = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr,
567 ®, 1, val, len, 0);
568 iic_release_bus(sc->sc_i2c, 0);
569 }
570
571 return ret;
572
573 }
574
575 static int
axp20x_write(struct axp20x_softc * sc,uint8_t reg,uint8_t * val,size_t len)576 axp20x_write(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len)
577 {
578 int ret;
579
580 ret = iic_acquire_bus(sc->sc_i2c, 0);
581 if (ret == 0) {
582 ret = iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
583 ®, 1, val, len, 0);
584 iic_release_bus(sc->sc_i2c, 0);
585 }
586
587 return ret;
588 }
589
590 static int
axp20x_set_dcdc(device_t dev,int dcdc,int mvolt)591 axp20x_set_dcdc(device_t dev, int dcdc, int mvolt)
592 {
593 struct axp20x_softc *sc = device_private(dev);
594 int ret;
595 int value;
596 uint8_t reg;
597
598 KASSERT(sc != NULL);
599 value = (mvolt - 700) / 25;
600 switch (dcdc) {
601 case AXP20X_DCDC2:
602 value <<= AXP_DCDC2_VOLT_SHIFT;
603 if (value > AXP_DCDC2_VOLT_MASK)
604 return EINVAL;
605 reg = value & AXP_DCDC2_VOLT_MASK;
606 ret = axp20x_write(sc, AXP_DCDC2, ®, 1);
607 if (ret)
608 return ret;
609 if (axp20x_read(sc, AXP_DCDC2, ®, 1) == 0) {
610 aprint_debug_dev(sc->sc_dev,
611 "DCDC2 changed to %dmV\n",
612 (int)(700 + (reg & AXP_DCDC2_VOLT_MASK) * 25));
613 }
614 return 0;
615
616 case AXP20X_DCDC3:
617 value <<= AXP_DCDC3_VOLT_SHIFT;
618 if (value > AXP_DCDC3_VOLT_MASK)
619 return EINVAL;
620 reg = value & AXP_DCDC3_VOLT_MASK;
621 ret = axp20x_write(sc, AXP_DCDC3, ®, 1);
622 if (ret)
623 return ret;
624 if (axp20x_read(sc, AXP_DCDC3, ®, 1) == 0) {
625 aprint_debug_dev(sc->sc_dev,
626 "DCDC3 changed to %dmV\n",
627 (int)(700 + (reg & AXP_DCDC3_VOLT_MASK) * 25));
628 }
629 return 0;
630 default:
631 aprint_error_dev(dev, "wrong DCDC %d\n", dcdc);
632 return EINVAL;
633 }
634 }
635
636 static int
axp20x_get_dcdc(device_t dev,int dcdc,int * pmvolt)637 axp20x_get_dcdc(device_t dev, int dcdc, int *pmvolt)
638 {
639 struct axp20x_softc *sc = device_private(dev);
640 uint8_t reg;
641 int error;
642
643 switch (dcdc) {
644 case AXP20X_DCDC2:
645 error = axp20x_read(sc, AXP_DCDC2, ®, 1);
646 if (error != 0)
647 return error;
648 *pmvolt = __SHIFTOUT(reg, AXP_DCDC2_VOLT_MASK) * 25 + 700;
649 return 0;
650 case AXP20X_DCDC3:
651 error = axp20x_read(sc, AXP_DCDC3, ®, 1);
652 if (error != 0)
653 return error;
654 *pmvolt = __SHIFTOUT(reg, AXP_DCDC3_VOLT_MASK) * 25 + 700;
655 return 0;
656 default:
657 return EINVAL;
658 }
659 }
660
661 static void
axp20x_poweroff(device_t dev)662 axp20x_poweroff(device_t dev)
663 {
664 struct axp20x_softc * const sc = device_private(dev);
665 uint8_t reg = AXP_SHUTDOWN_CTRL;
666 int error;
667
668 error = axp20x_write(sc, AXP_SHUTDOWN, ®, 1);
669 if (error) {
670 device_printf(dev, "WARNING: unable to power off, error %d\n",
671 error);
672 }
673 }
674
675 static const struct axp20xregdef {
676 const char *name;
677 int dcdc;
678 } axp20x_regdefs[] = {
679 { "dcdc2", AXP20X_DCDC2 },
680 { "dcdc3", AXP20X_DCDC3 },
681 };
682
683 struct axp20xreg_softc {
684 device_t sc_dev;
685 int sc_phandle;
686 const struct axp20xregdef *sc_regdef;
687 };
688
689 struct axp20xreg_attach_args {
690 int reg_phandle;
691 };
692
693 static int
axp20xreg_acquire(device_t dev)694 axp20xreg_acquire(device_t dev)
695 {
696 return 0;
697 }
698
699 static void
axp20xreg_release(device_t dev)700 axp20xreg_release(device_t dev)
701 {
702 }
703
704 static int
axp20xreg_enable(device_t dev,bool enable)705 axp20xreg_enable(device_t dev, bool enable)
706 {
707 /* TODO */
708 return enable ? 0 : EINVAL;
709 }
710
711 static int
axp20xreg_set_voltage(device_t dev,u_int min_uvol,u_int max_uvol)712 axp20xreg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
713 {
714 struct axp20xreg_softc * const sc = device_private(dev);
715
716 return axp20x_set_dcdc(device_parent(dev), sc->sc_regdef->dcdc, min_uvol / 1000);
717 }
718
719 static int
axp20xreg_get_voltage(device_t dev,u_int * puvol)720 axp20xreg_get_voltage(device_t dev, u_int *puvol)
721 {
722 struct axp20xreg_softc * const sc = device_private(dev);
723 int mvol, error;
724
725 error = axp20x_get_dcdc(device_parent(dev), sc->sc_regdef->dcdc, &mvol);
726 if (error != 0)
727 return error;
728
729 *puvol = mvol * 1000;
730 return 0;
731 }
732
733 static struct fdtbus_regulator_controller_func axp20xreg_funcs = {
734 .acquire = axp20xreg_acquire,
735 .release = axp20xreg_release,
736 .enable = axp20xreg_enable,
737 .set_voltage = axp20xreg_set_voltage,
738 .get_voltage = axp20xreg_get_voltage,
739 };
740
741 static const struct axp20xregdef *
axp20xreg_lookup(int phandle)742 axp20xreg_lookup(int phandle)
743 {
744 const char *name;
745 int n;
746
747 name = fdtbus_get_string(phandle, "name");
748 if (name == NULL)
749 return NULL;
750
751 for (n = 0; n < __arraycount(axp20x_regdefs); n++)
752 if (strcmp(name, axp20x_regdefs[n].name) == 0)
753 return &axp20x_regdefs[n];
754
755 return NULL;
756 }
757
758 static int
axp20xreg_match(device_t parent,cfdata_t match,void * aux)759 axp20xreg_match(device_t parent, cfdata_t match, void *aux)
760 {
761 const struct axp20xreg_attach_args *reg = aux;
762
763 return axp20xreg_lookup(reg->reg_phandle) != NULL;
764 }
765
766 static void
axp20xreg_attach(device_t parent,device_t self,void * aux)767 axp20xreg_attach(device_t parent, device_t self, void *aux)
768 {
769 struct axp20xreg_softc * const sc = device_private(self);
770 const struct axp20xreg_attach_args *reg = aux;
771 const char *regulator_name;
772
773 sc->sc_dev = self;
774 sc->sc_phandle = reg->reg_phandle;
775 sc->sc_regdef = axp20xreg_lookup(reg->reg_phandle);
776
777 regulator_name = fdtbus_get_string(reg->reg_phandle, "regulator-name");
778
779 aprint_naive("\n");
780 if (regulator_name)
781 aprint_normal(": %s (%s)\n", sc->sc_regdef->name, regulator_name);
782 else
783 aprint_normal(": %s\n", sc->sc_regdef->name);
784
785 fdtbus_register_regulator_controller(self, sc->sc_phandle, &axp20xreg_funcs);
786 }
787
788 CFATTACH_DECL_NEW(axp20xreg, sizeof(struct axp20xreg_softc),
789 axp20xreg_match, axp20xreg_attach, NULL, NULL);
790
791 static void
axp20x_fdt_poweroff(device_t dev)792 axp20x_fdt_poweroff(device_t dev)
793 {
794 delay(1000000);
795 axp20x_poweroff(dev);
796 }
797
798 static struct fdtbus_power_controller_func axp20x_fdt_power_funcs = {
799 .poweroff = axp20x_fdt_poweroff,
800 };
801
802 static void
axp20x_fdt_attach(struct axp20x_softc * sc)803 axp20x_fdt_attach(struct axp20x_softc *sc)
804 {
805 int regulators_phandle, child;
806
807 fdtbus_register_power_controller(sc->sc_dev, sc->sc_phandle,
808 &axp20x_fdt_power_funcs);
809
810 regulators_phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators");
811 if (regulators_phandle == -1)
812 return;
813
814 for (child = OF_child(regulators_phandle); child; child = OF_peer(child)) {
815 struct axp20xreg_attach_args reg = { .reg_phandle = child };
816 config_found(sc->sc_dev, ®, NULL, CFARGS_NONE);
817 }
818 }
819