1 /* $NetBSD: axp20x.c,v 1.10 2017/10/22 11:00:28 jmcneill 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 "opt_fdt.h" 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.10 2017/10/22 11:00:28 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_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, 567 ®, 1, 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_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 580 ®, 1, 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