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