Thu Oct 15 13:41:11 2015 UTC ()
Implement sensor reports for power supplies (voltage and intensities).
Implement a callback to change DCDC2 and DCDC3 voltages, so that
CPU management can change CPU core voltage when changing frequency.


(bouyer)
diff -r1.2 -r1.3 src/sys/dev/i2c/axp20x.c
diff -r0 -r1.1 src/sys/dev/i2c/axp20xvar.h

cvs diff -r1.2 -r1.3 src/sys/dev/i2c/axp20x.c (expand / switch to unified diff)

--- src/sys/dev/i2c/axp20x.c 2014/09/09 23:39:16 1.2
+++ src/sys/dev/i2c/axp20x.c 2015/10/15 13:41:11 1.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: axp20x.c,v 1.2 2014/09/09 23:39:16 jmcneill Exp $ */ 1/* $NetBSD: axp20x.c,v 1.3 2015/10/15 13:41:11 bouyer Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,107 +17,549 @@ @@ -17,107 +17,549 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 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 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.2 2014/09/09 23:39:16 jmcneill Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.3 2015/10/15 13:41:11 bouyer Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/device.h> 34#include <sys/device.h>
35#include <sys/conf.h> 35#include <sys/conf.h>
36#include <sys/bus.h> 36#include <sys/bus.h>
37#include <sys/kmem.h> 37#include <sys/kmem.h>
38 38
39#include <dev/i2c/i2cvar.h> 39#include <dev/i2c/i2cvar.h>
 40#include <dev/i2c/axp20xvar.h>
40 41
41#include <dev/sysmon/sysmonvar.h> 42#include <dev/sysmon/sysmonvar.h>
42 43
 44#define AXP_INPUT_STATUS 0x00
 45#define AXP_INPUT_STATUS_AC_PRESENT __BIT(7)
 46#define AXP_INPUT_STATUS_AC_OK __BIT(6)
 47#define AXP_INPUT_STATUS_VBUS_PRESENT __BIT(5)
 48#define AXP_INPUT_STATUS_VBUS_OK __BIT(4)
 49
 50#define AXP_POWER_MODE 0x01
 51#define AXP_POWER_MODE_OVERTEMP __BIT(7)
 52#define AXP_POWER_MODE_CHARGING __BIT(6)
 53#define AXP_POWER_MODE_BATTOK __BIT(5)
 54
 55#define AXP_POWEROUT_CTRL 0x12
 56#define AXP_POWEROUT_CTRL_LDO3 __BIT(6)
 57#define AXP_POWEROUT_CTRL_DCDC2 __BIT(4)
 58#define AXP_POWEROUT_CTRL_LDO4 __BIT(3)
 59#define AXP_POWEROUT_CTRL_LDO2 __BIT(2)
 60#define AXP_POWEROUT_CTRL_DCDC3 __BIT(1)
 61#define AXP_POWEROUT_CTRL_EXTEN __BIT(0)
 62
 63#define AXP_DCDC2 0x23
 64#define AXP_DCDC2_VOLT_MASK __BITS(0,5)
 65#define AXP_DCDC2_VOLT_SHIFT 0
 66
 67#define AXP_DCDC2_LDO3_VRC 0x25
 68
 69#define AXP_DCDC3 0x27
 70#define AXP_DCDC3_VOLT_MASK __BITS(0,6)
 71#define AXP_DCDC3_VOLT_SHIFT 0
 72
 73#define AXP_LDO2_4 0x28
 74#define AXP_LDO2_VOLT_MASK __BITS(4,7)
 75#define AXP_LDO2_VOLT_SHIFT 4
 76#define AXP_LDO4_VOLT_MASK __BITS(0,3)
 77#define AXP_LDO4_VOLT_SHIFT 0
 78static int ldo4_mvV[] = {
 79 1250,
 80 1300,
 81 1400,
 82 1500,
 83 1600,
 84 1700,
 85 1800,
 86 1900,
 87 2000,
 88 2500,
 89 2700,
 90 2800,
 91 3000,
 92 3100,
 93 3200,
 94 3300
 95};
 96
 97#define AXP_LDO3 0x29
 98#define AXP_LDO3_TRACK __BIT(7)
 99#define AXP_LDO3_VOLT_MASK __BITS(0,6)
 100#define AXP_LDO3_VOLT_SHIFT 0
 101
 102#define AXP_ACV_MON_REG 0x56 /* 2 bytes */
 103#define AXP_ACI_MON_REG 0x58 /* 2 bytes */
 104#define AXP_VBUSV_MON_REG 0x5a /* 2 bytes */
 105#define AXP_VBUSI_MON_REG 0x5c /* 2 bytes */
43#define AXP_TEMP_MON_REG 0x5e /* 2 bytes */ 106#define AXP_TEMP_MON_REG 0x5e /* 2 bytes */
 107#define AXP_BATTV_MON_REG 0x78 /* 2 bytes */
 108#define AXP_BATTCI_MON_REG 0x7a /* 2 bytes */
 109#define AXP_BATTDI_MON_REG 0x7c /* 2 bytes */
 110#define AXP_APSV_MON_REG 0x7e /* 2 bytes */
 111
 112#define AXP_ADC_EN1 0x82
 113#define AXP_ADC_EN1_BATTV __BIT(7)
 114#define AXP_ADC_EN1_BATTI __BIT(6)
 115#define AXP_ADC_EN1_ACV __BIT(5)
 116#define AXP_ADC_EN1_ACI __BIT(4)
 117#define AXP_ADC_EN1_VBUSV __BIT(3)
 118#define AXP_ADC_EN1_VBUSI __BIT(2)
 119#define AXP_ADC_EN1_APSV __BIT(1)
 120#define AXP_ADC_EN1_TS __BIT(0)
 121#define AXP_ADC_EN2 0x83
 122#define AXP_ADC_EN2_TEMP __BIT(7)
 123
 124#define AXP_SENSOR_ACOK 0
 125#define AXP_SENSOR_ACV 1
 126#define AXP_SENSOR_ACI 2
 127#define AXP_SENSOR_VBUSOK 3
 128#define AXP_SENSOR_VBUSV 4
 129#define AXP_SENSOR_VBUSI 5
 130#define AXP_SENSOR_BATTOK 6
 131#define AXP_SENSOR_BATTV 7
 132#define AXP_SENSOR_BATTI 8
 133#define AXP_SENSOR_APSV 9
 134#define AXP_SENSOR_TEMP 10
 135#define AXP_NSENSORS (AXP_SENSOR_TEMP + 1)
 136
 137/* define per-ADC LSB to uV/uA values */
 138static int axp20x_sensors_lsb[] = {
 139 0, /* AXP_SENSOR_ACOK */
 140 1700, /* AXP_SENSOR_ACV */
 141 625, /* AXP_SENSOR_ACI */
 142 0,
 143 1700, /* AXP_SENSOR_VBUSV */
 144 375, /* AXP_SENSOR_VBUSI */
 145 0,
 146 1100, /* AXP_SENSOR_BATTV */
 147 500, /* AXP_SENSOR_BATTI */
 148 1400, /* AXP_SENSOR_APSV */
 149};
 150
44 151
45struct axp20x_softc { 152struct axp20x_softc {
46 device_t sc_dev; 153 device_t sc_dev;
47 i2c_tag_t sc_i2c; 154 i2c_tag_t sc_i2c;
48 i2c_addr_t sc_addr; 155 i2c_addr_t sc_addr;
49 156
 157 uint8_t sc_inputstatus;
 158 uint8_t sc_powermode;
 159
50 struct sysmon_envsys *sc_sme; 160 struct sysmon_envsys *sc_sme;
51 envsys_data_t sc_sensor_temp; 161 envsys_data_t sc_sensor[AXP_NSENSORS];
52}; 162};
53 163
54static int axp20x_match(device_t, cfdata_t, void *); 164static int axp20x_match(device_t, cfdata_t, void *);
55static void axp20x_attach(device_t, device_t, void *); 165static void axp20x_attach(device_t, device_t, void *);
56 166
57static void axp20x_sensors_refresh(struct sysmon_envsys *, envsys_data_t *); 167static void axp20x_sensors_refresh(struct sysmon_envsys *, envsys_data_t *);
58static int axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t); 168static int axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
 169static int axp20x_write(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
59 170
60CFATTACH_DECL_NEW(axp20x, sizeof(struct axp20x_softc), 171CFATTACH_DECL_NEW(axp20x, sizeof(struct axp20x_softc),
61 axp20x_match, axp20x_attach, NULL, NULL); 172 axp20x_match, axp20x_attach, NULL, NULL);
62 173
63static int 174static int
64axp20x_match(device_t parent, cfdata_t match, void *aux) 175axp20x_match(device_t parent, cfdata_t match, void *aux)
65{ 176{
66 return 1; 177 return 1;
67} 178}
68 179
69static void 180static void
70axp20x_attach(device_t parent, device_t self, void *aux) 181axp20x_attach(device_t parent, device_t self, void *aux)
71{ 182{
72 struct axp20x_softc *sc = device_private(self); 183 struct axp20x_softc *sc = device_private(self);
73 struct i2c_attach_args *ia = aux; 184 struct i2c_attach_args *ia = aux;
 185 int first;
 186 int error;
 187 uint8_t value;
74 188
75 sc->sc_dev = self; 189 sc->sc_dev = self;
76 sc->sc_i2c = ia->ia_tag; 190 sc->sc_i2c = ia->ia_tag;
77 sc->sc_addr = ia->ia_addr; 191 sc->sc_addr = ia->ia_addr;
78 192
 193 error = axp20x_read(sc, AXP_INPUT_STATUS,
 194 &sc->sc_inputstatus, 1, I2C_F_POLL);
 195 if (error) {
 196 aprint_error(": can't read status: %d\n", error);
 197 return;
 198 }
 199 error = axp20x_read(sc, AXP_POWER_MODE,
 200 &sc->sc_powermode, 1, I2C_F_POLL);
 201 if (error) {
 202 aprint_error(": can't read power mode: %d\n", error);
 203 return;
 204 }
 205 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;
 206 if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
 207 value |= AXP_ADC_EN1_BATTV | AXP_ADC_EN1_BATTI;
 208 error = axp20x_write(sc, AXP_ADC_EN1, &value, 1, I2C_F_POLL);
 209 if (error) {
 210 aprint_error(": can't set AXP_ADC_EN1\n");
 211 return;
 212 }
 213 error = axp20x_read(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
 214 if (error) {
 215 aprint_error(": can't read AXP_ADC_EN2\n");
 216 return;
 217 }
 218 value |= AXP_ADC_EN2_TEMP;
 219 error = axp20x_write(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
 220 if (error) {
 221 aprint_error(": can't set AXP_ADC_EN2\n");
 222 return;
 223 }
 224
79 aprint_naive("\n"); 225 aprint_naive("\n");
 226 first = 1;
 227 if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) {
 228 aprint_normal(": AC used");
 229 first = 0;
 230 } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_PRESENT) {
 231 aprint_normal(": AC present (but unused)");
 232 first = 0;
 233 }
 234 if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) {
 235 aprint_normal("%s VBUS used", first ? ":" : ",");
 236 first = 0;
 237 } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_PRESENT) {
 238 aprint_normal("%s VBUS present (but unused)", first ? ":" : ",");
 239 first = 0;
 240 }
 241 if (sc->sc_powermode & AXP_POWER_MODE_BATTOK) {
 242 aprint_normal("%s battery present", first ? ":" : ",");
 243 }
80 aprint_normal("\n"); 244 aprint_normal("\n");
81 245
82 sc->sc_sme = sysmon_envsys_create(); 246 sc->sc_sme = sysmon_envsys_create();
83 sc->sc_sme->sme_name = device_xname(self); 247 sc->sc_sme->sme_name = device_xname(self);
84 sc->sc_sme->sme_cookie = sc; 248 sc->sc_sme->sme_cookie = sc;
85 sc->sc_sme->sme_refresh = axp20x_sensors_refresh; 249 sc->sc_sme->sme_refresh = axp20x_sensors_refresh;
86 250
87 sc->sc_sensor_temp.units = ENVSYS_STEMP; 251 sc->sc_sensor[AXP_SENSOR_ACOK].units = ENVSYS_INDICATOR;
88 sc->sc_sensor_temp.state = ENVSYS_SINVALID; 252 sc->sc_sensor[AXP_SENSOR_ACOK].state = ENVSYS_SVALID;
89 sc->sc_sensor_temp.flags = ENVSYS_FHAS_ENTROPY; 253 sc->sc_sensor[AXP_SENSOR_ACOK].value_cur =
90 snprintf(sc->sc_sensor_temp.desc, sizeof(sc->sc_sensor_temp.desc), 254 (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
 255 snprintf(sc->sc_sensor[AXP_SENSOR_ACOK].desc,
 256 sizeof(sc->sc_sensor[AXP_SENSOR_ACOK].desc), "AC input");
 257 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACOK]);
 258 sc->sc_sensor[AXP_SENSOR_ACV].units = ENVSYS_SVOLTS_DC;
 259 sc->sc_sensor[AXP_SENSOR_ACV].state = ENVSYS_SINVALID;
 260 sc->sc_sensor[AXP_SENSOR_ACV].flags = ENVSYS_FHAS_ENTROPY;
 261 snprintf(sc->sc_sensor[AXP_SENSOR_ACV].desc,
 262 sizeof(sc->sc_sensor[AXP_SENSOR_ACV].desc), "AC input voltage");
 263 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACV]);
 264 sc->sc_sensor[AXP_SENSOR_ACI].units = ENVSYS_SAMPS;
 265 sc->sc_sensor[AXP_SENSOR_ACI].state = ENVSYS_SINVALID;
 266 sc->sc_sensor[AXP_SENSOR_ACI].flags = ENVSYS_FHAS_ENTROPY;
 267 snprintf(sc->sc_sensor[AXP_SENSOR_ACI].desc,
 268 sizeof(sc->sc_sensor[AXP_SENSOR_ACI].desc), "AC input current");
 269 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACI]);
 270
 271 sc->sc_sensor[AXP_SENSOR_VBUSOK].units = ENVSYS_INDICATOR;
 272 sc->sc_sensor[AXP_SENSOR_VBUSOK].state = ENVSYS_SVALID;
 273 sc->sc_sensor[AXP_SENSOR_VBUSOK].value_cur =
 274 (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
 275 snprintf(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc,
 276 sizeof(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc), "VBUS input");
 277 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSOK]);
 278 sc->sc_sensor[AXP_SENSOR_VBUSV].units = ENVSYS_SVOLTS_DC;
 279 sc->sc_sensor[AXP_SENSOR_VBUSV].state = ENVSYS_SINVALID;
 280 sc->sc_sensor[AXP_SENSOR_VBUSV].flags = ENVSYS_FHAS_ENTROPY;
 281 snprintf(sc->sc_sensor[AXP_SENSOR_VBUSV].desc,
 282 sizeof(sc->sc_sensor[AXP_SENSOR_VBUSV].desc), "VBUS input voltage");
 283 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSV]);
 284 sc->sc_sensor[AXP_SENSOR_VBUSI].units = ENVSYS_SAMPS;
 285 sc->sc_sensor[AXP_SENSOR_VBUSI].state = ENVSYS_SINVALID;
 286 sc->sc_sensor[AXP_SENSOR_VBUSI].flags = ENVSYS_FHAS_ENTROPY;
 287 snprintf(sc->sc_sensor[AXP_SENSOR_VBUSI].desc,
 288 sizeof(sc->sc_sensor[AXP_SENSOR_VBUSI].desc), "VBUS input current");
 289 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSI]);
 290
 291 sc->sc_sensor[AXP_SENSOR_BATTOK].units = ENVSYS_INDICATOR;
 292 sc->sc_sensor[AXP_SENSOR_BATTOK].state = ENVSYS_SVALID;
 293 sc->sc_sensor[AXP_SENSOR_BATTOK].value_cur =
 294 (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
 295 snprintf(sc->sc_sensor[AXP_SENSOR_BATTOK].desc,
 296 sizeof(sc->sc_sensor[AXP_SENSOR_BATTOK].desc), "battery");
 297 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTOK]);
 298 sc->sc_sensor[AXP_SENSOR_BATTV].units = ENVSYS_SVOLTS_DC;
 299 sc->sc_sensor[AXP_SENSOR_BATTV].state = ENVSYS_SINVALID;
 300 sc->sc_sensor[AXP_SENSOR_BATTV].flags = ENVSYS_FHAS_ENTROPY;
 301 snprintf(sc->sc_sensor[AXP_SENSOR_BATTV].desc,
 302 sizeof(sc->sc_sensor[AXP_SENSOR_BATTV].desc), "battery voltage");
 303 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTV]);
 304 sc->sc_sensor[AXP_SENSOR_BATTI].units = ENVSYS_SAMPS;
 305 sc->sc_sensor[AXP_SENSOR_BATTI].state = ENVSYS_SINVALID;
 306 sc->sc_sensor[AXP_SENSOR_BATTI].flags = ENVSYS_FHAS_ENTROPY;
 307 snprintf(sc->sc_sensor[AXP_SENSOR_BATTI].desc,
 308 sizeof(sc->sc_sensor[AXP_SENSOR_BATTI].desc), "battery current");
 309 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTI]);
 310
 311 sc->sc_sensor[AXP_SENSOR_APSV].units = ENVSYS_SVOLTS_DC;
 312 sc->sc_sensor[AXP_SENSOR_APSV].state = ENVSYS_SINVALID;
 313 sc->sc_sensor[AXP_SENSOR_APSV].flags = ENVSYS_FHAS_ENTROPY;
 314 snprintf(sc->sc_sensor[AXP_SENSOR_APSV].desc,
 315 sizeof(sc->sc_sensor[AXP_SENSOR_APSV].desc), "APS output voltage");
 316 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_APSV]);
 317 sc->sc_sensor[AXP_SENSOR_TEMP].units = ENVSYS_STEMP;
 318 sc->sc_sensor[AXP_SENSOR_TEMP].state = ENVSYS_SINVALID;
 319 sc->sc_sensor[AXP_SENSOR_TEMP].flags = ENVSYS_FHAS_ENTROPY;
 320 snprintf(sc->sc_sensor[AXP_SENSOR_TEMP].desc,
 321 sizeof(sc->sc_sensor[AXP_SENSOR_TEMP].desc),
91 "internal temperature"); 322 "internal temperature");
92 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor_temp); 323 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_TEMP]);
93 324
94 sysmon_envsys_register(sc->sc_sme); 325 sysmon_envsys_register(sc->sc_sme);
 326
 327 if (axp20x_read(sc, AXP_DCDC2, &value, 1, I2C_F_POLL) == 0) {
 328 aprint_normal_dev(sc->sc_dev, ": DCDC2 %dmV\n",
 329 (int)(700 + (value & AXP_DCDC2_VOLT_MASK) * 25));
 330 }
 331 if (axp20x_read(sc, AXP_DCDC3, &value, 1, I2C_F_POLL) == 0) {
 332 aprint_normal_dev(sc->sc_dev, ": DCDC3 %dmV\n",
 333 (int)(700 + (value & AXP_DCDC3_VOLT_MASK) * 25));
 334 }
 335 if (axp20x_read(sc, AXP_LDO2_4, &value, 1, I2C_F_POLL) == 0) {
 336 aprint_normal_dev(sc->sc_dev, ": LDO2 %dmV, LDO4 %dmV\n",
 337 (int)(1800 +
 338 ((value & AXP_LDO2_VOLT_MASK) >> AXP_LDO2_VOLT_SHIFT) * 100
 339 ),
 340 ldo4_mvV[(value & AXP_LDO4_VOLT_MASK) >> AXP_LDO4_VOLT_SHIFT]);
 341 }
 342 if (axp20x_read(sc, AXP_LDO3, &value, 1, I2C_F_POLL) == 0) {
 343 if (value & AXP_LDO3_TRACK) {
 344 aprint_normal_dev(sc->sc_dev, ": LDO3: tracking\n");
 345 } else {
 346 aprint_normal_dev(sc->sc_dev, ": LDO3 %dmV\n",
 347 (int)(700 + (value & AXP_LDO3_VOLT_MASK) * 25));
 348 }
 349 }
95} 350}
96 351
97static void 352static void
98axp20x_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 353axp20x_sensors_refresh_volt(struct axp20x_softc *sc, int reg,
 354 envsys_data_t *edata)
99{ 355{
100 struct axp20x_softc *sc = sme->sme_cookie; 
101 uint8_t buf[2]; 356 uint8_t buf[2];
102 int error; 357 int error;
103 358
104 iic_acquire_bus(sc->sc_i2c, 0); 359 error = axp20x_read(sc, reg, buf, sizeof(buf), 0);
105 error = axp20x_read(sc, AXP_TEMP_MON_REG, buf, sizeof(buf)); 360 if (error) {
106 iic_release_bus(sc->sc_i2c, 0); 361 edata->state = ENVSYS_SINVALID;
 362 } else {
 363 edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
 364 axp20x_sensors_lsb[edata->sensor];
 365 edata->state = ENVSYS_SVALID;
 366 }
 367}
 368
 369static void
 370axp20x_sensors_refresh_amp(struct axp20x_softc *sc, int reg,
 371 envsys_data_t *edata)
 372{
 373 uint8_t buf[2];
 374 int error;
107 375
 376 error = axp20x_read(sc, reg, buf, sizeof(buf), 0);
108 if (error) { 377 if (error) {
109 edata->state = ENVSYS_SINVALID; 378 edata->state = ENVSYS_SINVALID;
110 } else { 379 } else {
111 /* between -144.7C and 264.8C, step +0.1C */ 380 edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) *
112 edata->value_cur = (((buf[0] << 4) | (buf[1] & 0xf)) - 1447) 381 axp20x_sensors_lsb[edata->sensor];
113 * 100000 + 273150000; 
114 edata->state = ENVSYS_SVALID; 382 edata->state = ENVSYS_SVALID;
115 } 383 }
116} 384}
117 385
 386static void
 387axp20x_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
 388{
 389 struct axp20x_softc *sc = sme->sme_cookie;
 390 uint8_t buf[2];
 391 int error;
 392
 393 switch(edata->sensor) {
 394 case AXP_SENSOR_ACOK:
 395 case AXP_SENSOR_VBUSOK:
 396 error = axp20x_read(sc, AXP_INPUT_STATUS,
 397 &sc->sc_inputstatus, 1, 0);
 398 if (error) {
 399 edata->state = ENVSYS_SINVALID;
 400 return;
 401 }
 402 if (edata->sensor == AXP_SENSOR_ACOK) {
 403 edata->value_cur =
 404 (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
 405 } else {
 406 edata->value_cur =
 407 (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
 408 }
 409 edata->state = ENVSYS_SVALID;
 410 return;
 411 case AXP_SENSOR_BATTOK:
 412 error = axp20x_read(sc, AXP_POWER_MODE,
 413 &sc->sc_powermode, 1, 0);
 414 if (error) {
 415 edata->state = ENVSYS_SINVALID;
 416 return;
 417 }
 418 edata->value_cur =
 419 (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
 420 return;
 421 case AXP_SENSOR_ACV:
 422 if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
 423 axp20x_sensors_refresh_volt(sc, AXP_ACV_MON_REG, edata);
 424 else
 425 edata->state = ENVSYS_SINVALID;
 426 return;
 427 case AXP_SENSOR_ACI:
 428 if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK)
 429 axp20x_sensors_refresh_amp(sc, AXP_ACI_MON_REG, edata);
 430 else
 431 edata->state = ENVSYS_SINVALID;
 432 return;
 433 case AXP_SENSOR_VBUSV:
 434 if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
 435 axp20x_sensors_refresh_volt(sc, AXP_VBUSV_MON_REG, edata);
 436 else
 437 edata->state = ENVSYS_SINVALID;
 438 return;
 439 case AXP_SENSOR_VBUSI:
 440 if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK)
 441 axp20x_sensors_refresh_amp(sc, AXP_VBUSI_MON_REG, edata);
 442 else
 443 edata->state = ENVSYS_SINVALID;
 444 return;
 445 case AXP_SENSOR_BATTV:
 446 if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
 447 axp20x_sensors_refresh_volt(sc, AXP_BATTV_MON_REG, edata);
 448 else
 449 edata->state = ENVSYS_SINVALID;
 450 return;
 451 case AXP_SENSOR_BATTI:
 452 if ((sc->sc_powermode & AXP_POWER_MODE_BATTOK) == 0) {
 453 edata->state = ENVSYS_SINVALID;
 454 return;
 455 }
 456 error = axp20x_read(sc, AXP_POWER_MODE,
 457 &sc->sc_inputstatus, 1, 0);
 458 if (error) {
 459 edata->state = ENVSYS_SINVALID;
 460 return;
 461 }
 462 if (sc->sc_inputstatus & AXP_POWER_MODE_CHARGING) {
 463 axp20x_sensors_refresh_amp(sc, AXP_BATTCI_MON_REG,
 464 edata);
 465 edata->value_cur = -edata->value_cur;
 466 } else {
 467 axp20x_sensors_refresh_amp(sc, AXP_BATTDI_MON_REG,
 468 edata);
 469 }
 470 return;
 471 case AXP_SENSOR_APSV:
 472 axp20x_sensors_refresh_volt(sc, AXP_APSV_MON_REG, edata);
 473 return;
 474 case AXP_SENSOR_TEMP:
 475 error = axp20x_read(sc, AXP_TEMP_MON_REG, buf, sizeof(buf), 0);
 476 if (error) {
 477 edata->state = ENVSYS_SINVALID;
 478 } else {
 479 /* between -144.7C and 264.8C, step +0.1C */
 480 edata->value_cur =
 481 (((buf[0] << 4) | (buf[1] & 0xf)) - 1447)
 482 * 100000 + 273150000;
 483 edata->state = ENVSYS_SVALID;
 484 }
 485 return;
 486 default:
 487 aprint_error_dev(sc->sc_dev, ": invalid sensor %d\n",
 488 edata->sensor);
 489 }
 490}
 491
 492static int
 493axp20x_read(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len,
 494 int flags)
 495{
 496 int ret;
 497 iic_acquire_bus(sc->sc_i2c, flags);
 498 ret = iic_smbus_block_read(sc->sc_i2c, sc->sc_addr,
 499 reg, val, len, flags);
 500 iic_release_bus(sc->sc_i2c, flags);
 501 return ret;
 502
 503}
 504
118static int 505static int
119axp20x_read(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len) 506axp20x_write(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len,
 507 int flags)
120{ 508{
121 return iic_smbus_block_read(sc->sc_i2c, sc->sc_addr, 509 int ret;
122 reg, val, len, 0); 510 iic_acquire_bus(sc->sc_i2c, flags);
 511 ret = iic_smbus_block_write(sc->sc_i2c, sc->sc_addr,
 512 reg, val, len, flags);
 513 iic_release_bus(sc->sc_i2c, flags);
 514 return ret;
 515}
 516
 517int
 518axp20x_set_dcdc(device_t dev, int dcdc, int mvolt, bool poll)
 519{
 520 struct axp20x_softc *sc = device_private(dev);
 521 int ret;
 522 int value;
 523 uint8_t reg;
 524
 525 KASSERT(sc != NULL);
 526 value = (mvolt - 700) / 25;
 527 switch (dcdc) {
 528 case AXP20X_DCDC2:
 529 value <<= AXP_DCDC2_VOLT_SHIFT;
 530 if (value > AXP_DCDC2_VOLT_MASK)
 531 return EINVAL;
 532 reg = value & AXP_DCDC2_VOLT_MASK;
 533 ret = axp20x_write(sc, AXP_DCDC2, &reg, 1,
 534 poll ? I2C_F_POLL : 0);
 535 if (ret)
 536 return ret;
 537 if (axp20x_read(sc, AXP_DCDC2, &reg, 1, poll ? I2C_F_POLL : 0)
 538 == 0) {
 539 aprint_normal_dev(sc->sc_dev,
 540 ": DCDC2 changed to %dmV\n",
 541 (int)(700 + (reg & AXP_DCDC2_VOLT_MASK) * 25));
 542 }
 543 return 0;
 544
 545 case AXP20X_DCDC3:
 546 value <<= AXP_DCDC2_VOLT_SHIFT;
 547 if (value > AXP_DCDC2_VOLT_MASK)
 548 return EINVAL;
 549 reg = value & AXP_DCDC2_VOLT_MASK;
 550 ret = axp20x_write(sc, AXP_DCDC2, &reg, 1,
 551 poll ? I2C_F_POLL : 0);
 552 if (ret)
 553 return ret;
 554 if (axp20x_read(sc, AXP_DCDC2, &reg, 1, poll ? I2C_F_POLL : 0)
 555 == 0) {
 556 aprint_normal_dev(sc->sc_dev,
 557 ": DCDC2 changed to %dmV\n",
 558 (int)(700 + (reg & AXP_DCDC2_VOLT_MASK) * 25));
 559 }
 560 return 0;
 561 default:
 562 aprint_error_dev(dev, "wrong DCDC %d\n", dcdc);
 563 return EINVAL;
 564 }
123} 565}

File Added: src/sys/dev/i2c/Attic/axp20xvar.h
/*      $NetBSD: axp20xvar.h,v 1.1 2015/10/15 13:41:11 bouyer Exp $       */

/*
 * Copyright (c) 1998, 2001 Manuel Bouyer.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _DEV_I2C_AXP20XVAR_H_
#define _DEV_I2C_AXP20XVAR_H_

#define AXP20X_DCDC2	2
#define AXP20X_DCDC3	3

int	axp20x_set_dcdc(device_t, int, int, bool);

#endif /* _DEV_I2C_AXP20XVAR_H_ */