1 /* $NetBSD: axp20x.c,v 1.4 2015/10/15 13:48:57 bouyer Exp $ */ 2 3 /*- 4 * Copyright (c) 2014 Jared D. 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.4 2015/10/15 13:48:57 bouyer 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 #include <dev/i2c/axp20xvar.h> 41 42 #include <dev/sysmon/sysmonvar.h> 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 78 static 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 */ 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 */ 138 static 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 151 152 struct axp20x_softc { 153 device_t sc_dev; 154 i2c_tag_t sc_i2c; 155 i2c_addr_t sc_addr; 156 157 uint8_t sc_inputstatus; 158 uint8_t sc_powermode; 159 160 struct sysmon_envsys *sc_sme; 161 envsys_data_t sc_sensor[AXP_NSENSORS]; 162 }; 163 164 static int axp20x_match(device_t, cfdata_t, void *); 165 static void axp20x_attach(device_t, device_t, void *); 166 167 static void axp20x_sensors_refresh(struct sysmon_envsys *, envsys_data_t *); 168 static int axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int); 169 static int axp20x_write(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int); 170 171 CFATTACH_DECL_NEW(axp20x, sizeof(struct axp20x_softc), 172 axp20x_match, axp20x_attach, NULL, NULL); 173 174 static int 175 axp20x_match(device_t parent, cfdata_t match, void *aux) 176 { 177 return 1; 178 } 179 180 static void 181 axp20x_attach(device_t parent, device_t self, void *aux) 182 { 183 struct axp20x_softc *sc = device_private(self); 184 struct i2c_attach_args *ia = aux; 185 int first; 186 int error; 187 uint8_t value; 188 189 sc->sc_dev = self; 190 sc->sc_i2c = ia->ia_tag; 191 sc->sc_addr = ia->ia_addr; 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 225 aprint_naive("\n"); 226 first = 1; 227 if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) { 228 aprint_verbose(": AC used"); 229 first = 0; 230 } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_PRESENT) { 231 aprint_verbose(": AC present (but unused)"); 232 first = 0; 233 } 234 if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) { 235 aprint_verbose("%s VBUS used", first ? ":" : ","); 236 first = 0; 237 } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_PRESENT) { 238 aprint_verbose("%s VBUS present (but unused)", first ? ":" : ","); 239 first = 0; 240 } 241 if (sc->sc_powermode & AXP_POWER_MODE_BATTOK) { 242 aprint_verbose("%s battery present", first ? ":" : ","); 243 } 244 aprint_normal("\n"); 245 246 sc->sc_sme = sysmon_envsys_create(); 247 sc->sc_sme->sme_name = device_xname(self); 248 sc->sc_sme->sme_cookie = sc; 249 sc->sc_sme->sme_refresh = axp20x_sensors_refresh; 250 251 sc->sc_sensor[AXP_SENSOR_ACOK].units = ENVSYS_INDICATOR; 252 sc->sc_sensor[AXP_SENSOR_ACOK].state = ENVSYS_SVALID; 253 sc->sc_sensor[AXP_SENSOR_ACOK].value_cur = 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), 322 "internal temperature"); 323 sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_TEMP]); 324 325 sysmon_envsys_register(sc->sc_sme); 326 327 if (axp20x_read(sc, AXP_DCDC2, &value, 1, I2C_F_POLL) == 0) { 328 aprint_verbose_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_verbose_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_verbose_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_verbose_dev(sc->sc_dev, ": LDO3: tracking\n"); 345 } else { 346 aprint_verbose_dev(sc->sc_dev, ": LDO3 %dmV\n", 347 (int)(700 + (value & AXP_LDO3_VOLT_MASK) * 25)); 348 } 349 } 350 } 351 352 static void 353 axp20x_sensors_refresh_volt(struct axp20x_softc *sc, int reg, 354 envsys_data_t *edata) 355 { 356 uint8_t buf[2]; 357 int error; 358 359 error = axp20x_read(sc, reg, buf, sizeof(buf), 0); 360 if (error) { 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 369 static void 370 axp20x_sensors_refresh_amp(struct axp20x_softc *sc, int reg, 371 envsys_data_t *edata) 372 { 373 uint8_t buf[2]; 374 int error; 375 376 error = axp20x_read(sc, reg, buf, sizeof(buf), 0); 377 if (error) { 378 edata->state = ENVSYS_SINVALID; 379 } else { 380 edata->value_cur = ((buf[0] << 4) | (buf[1] & 0xf)) * 381 axp20x_sensors_lsb[edata->sensor]; 382 edata->state = ENVSYS_SVALID; 383 } 384 } 385 386 static void 387 axp20x_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 492 static int 493 axp20x_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 505 static int 506 axp20x_write(struct axp20x_softc *sc, uint8_t reg, uint8_t *val, size_t len, 507 int flags) 508 { 509 int ret; 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 517 int 518 axp20x_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, ®, 1, 534 poll ? I2C_F_POLL : 0); 535 if (ret) 536 return ret; 537 if (axp20x_read(sc, AXP_DCDC2, ®, 1, poll ? I2C_F_POLL : 0) 538 == 0) { 539 aprint_verbose_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_DCDC3_VOLT_SHIFT; 547 if (value > AXP_DCDC3_VOLT_MASK) 548 return EINVAL; 549 reg = value & AXP_DCDC3_VOLT_MASK; 550 ret = axp20x_write(sc, AXP_DCDC3, ®, 1, 551 poll ? I2C_F_POLL : 0); 552 if (ret) 553 return ret; 554 if (axp20x_read(sc, AXP_DCDC3, ®, 1, poll ? I2C_F_POLL : 0) 555 == 0) { 556 aprint_verbose_dev(sc->sc_dev, 557 ": DCDC3 changed to %dmV\n", 558 (int)(700 + (reg & AXP_DCDC3_VOLT_MASK) * 25)); 559 } 560 return 0; 561 default: 562 aprint_error_dev(dev, "wrong DCDC %d\n", dcdc); 563 return EINVAL; 564 } 565 } 566