1 /* $NetBSD: tps65217pmic.c,v 1.10 2014/07/20 23:01:22 bouyer Exp $ */ 2 3 /*- 4 * Copyright (c) 2013 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Radoslaw Kujawa. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Texas Instruments TPS65217 Power Management IC driver. 34 * TODO: battery, sequencer, pgood 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: tps65217pmic.c,v 1.10 2014/07/20 23:01:22 bouyer Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 #include <sys/kernel.h> 44 #include <sys/mutex.h> 45 46 #include <sys/bus.h> 47 #include <dev/i2c/i2cvar.h> 48 49 #include <dev/sysmon/sysmonvar.h> 50 51 #include <dev/i2c/tps65217pmicreg.h> 52 #include <dev/i2c/tps65217pmicvar.h> 53 54 #define NTPS_REG 7 55 #define SNUM_REGS NTPS_REG-1 56 #define SNUM_USBSTATUS NTPS_REG 57 #define SNUM_ACSTATUS NTPS_REG+1 58 59 struct tps65217pmic_softc { 60 device_t sc_dev; 61 62 i2c_tag_t sc_tag; 63 i2c_addr_t sc_addr; 64 65 uint8_t sc_version; 66 uint8_t sc_revision; 67 68 kmutex_t sc_lock; 69 70 bool sc_acstatus; 71 bool sc_usbstatus; 72 bool sc_acenabled; 73 bool sc_usbenabled; 74 75 callout_t sc_powerpollco; 76 77 /* sysmon(4) stuff */ 78 struct sysmon_envsys *sc_sme; 79 envsys_data_t sc_regsensor[NTPS_REG]; 80 envsys_data_t sc_acsensor; 81 envsys_data_t sc_usbsensor; 82 83 struct sysmon_pswitch sc_smpsw; 84 }; 85 86 /* Voltage regulators */ 87 enum tps_reg_num { 88 TPS65217PMIC_LDO1, 89 TPS65217PMIC_LDO2, 90 TPS65217PMIC_LDO3LS, 91 TPS65217PMIC_LDO4LS, 92 TPS65217PMIC_DCDC1, 93 TPS65217PMIC_DCDC2, 94 TPS65217PMIC_DCDC3 95 }; 96 97 struct tps_reg_param { 98 /* parameters configured statically */ 99 100 const char* name; 101 uint16_t voltage_min; /* in mV */ 102 uint16_t voltage_max; /* in mV */ 103 const uint16_t *voltages; /* all possible voltage settings */ 104 uint8_t nvoltages; /* number of voltage settings */ 105 106 bool can_track; /* regulator can track U of other r. */ 107 struct tps_reg_param *tracked_reg; /* ptr to tracked regulator */ 108 bool can_xadj; /* voltage can be adjusted externally */ 109 bool can_ls; /* can be a load switch instead of r. */ 110 111 uint8_t defreg_num; /* DEF register */ 112 uint8_t enable_bit; /* position in ENABLE register */ 113 114 /* 115 * Run-time parameters configured during attachment and later, these 116 * probably should be split into separate struct that would be a part 117 * of softc. But since we can have only one TPS chip, that should be 118 * okay for now. 119 */ 120 121 bool is_enabled; /* regulator is enabled */ 122 bool is_pg; /* regulator is "power good" */ 123 bool is_tracking; /* voltage is tracking other reg. */ 124 bool is_ls; /* is a load switch */ 125 bool is_xadj; /* voltage is adjusted externally */ 126 127 uint16_t current_voltage; /* in mV */ 128 129 }; 130 131 static int tps65217pmic_match(device_t, cfdata_t, void *); 132 static void tps65217pmic_attach(device_t, device_t, void *); 133 134 static uint8_t tps65217pmic_reg_read(struct tps65217pmic_softc *, uint8_t); 135 static void tps65217pmic_reg_write(struct tps65217pmic_softc *, uint8_t, 136 uint8_t); 137 138 static void tps65217pmic_reg_refresh(struct tps65217pmic_softc *); 139 140 static uint16_t tps65217pmic_ppath_max_usb_current(uint8_t); 141 static uint16_t tps65217pmic_ppath_max_ac_current(uint8_t); 142 143 static void tps65217pmic_regulator_read_config(struct tps65217pmic_softc *, 144 struct tps_reg_param *); 145 146 static void tps65217pmic_print_ppath(struct tps65217pmic_softc *); 147 static void tps65217pmic_print_ldos(struct tps65217pmic_softc *); 148 149 static void tps65217pmic_version(struct tps65217pmic_softc *); 150 151 static void tps65217pmic_envsys_register(struct tps65217pmic_softc *); 152 static void tps65217pmic_envsys_refresh(struct sysmon_envsys *, envsys_data_t *); 153 154 static void tps65217pmic_power_monitor_init(struct tps65217pmic_softc *); 155 static void tps65217pmic_power_monitor(void *); 156 157 CFATTACH_DECL_NEW(tps65217pmic, sizeof (struct tps65217pmic_softc), 158 tps65217pmic_match, tps65217pmic_attach, NULL, NULL); 159 160 /* Possible settings of LDO1 in mV. */ 161 static const uint16_t ldo1voltages[] = { 1000, 1100, 1200, 1250, 1300, 1350, 162 1400, 1500, 1600, 1800, 2500, 2750, 2800, 3000, 3100, 3300 }; 163 /* Possible settings of LDO2, DCDC1, DCDC2, DCDC3 in mV. */ 164 static const uint16_t ldo2voltages[] = { 900, 925, 950, 975, 1000, 1025, 1050, 165 1075, 1100, 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, 1325, 1350, 166 1375, 1400, 1425, 1450, 1475, 1500, 1550, 1600, 1650, 1700, 1750, 1800, 167 1850, 1900, 1950, 2000, 2050, 2100, 2150, 2200, 2250, 2300, 2350, 2400, 168 2450, 2500, 2550, 2600, 2650, 2700, 2750, 2800, 2850, 2900, 3000, 3100, 169 3200, 3300, 3300, 3300, 3300, 3300, 3300, 3300, 3300 }; 170 /* Possible settings of LDO3, LDO4 in mV. */ 171 static const uint16_t ldo3voltages[] = { 1500, 1550, 1600, 1650, 1700, 1750, 172 1800, 1850, 1900, 2000, 2100, 2200, 2300, 2400, 2450, 2500, 2550, 2600, 173 2650, 2700, 2750, 2800, 2850, 2900,2950, 3000, 3050, 3100, 3150, 3200, 174 3250, 3300 }; 175 176 static struct tps_reg_param tps_regulators[] = { 177 { 178 .name = "LDO1", 179 .voltage_min = 1000, 180 .voltage_max = 3300, 181 .voltages = ldo1voltages, 182 .nvoltages = 16, 183 .can_track = false, 184 .tracked_reg = NULL, 185 .can_xadj = false, 186 .can_ls = false, 187 .defreg_num = TPS65217PMIC_DEFLDO1, 188 .enable_bit = TPS65217PMIC_ENABLE_LDO1 189 }, 190 { 191 .name = "LDO2", 192 .voltage_min = 900, 193 .voltage_max = 3300, 194 .voltages = ldo2voltages, 195 .nvoltages = 64, 196 .can_track = true, 197 .tracked_reg = &(tps_regulators[TPS65217PMIC_DCDC3]), 198 .can_xadj = false, 199 .can_ls = false, 200 .defreg_num = TPS65217PMIC_DEFLDO2, 201 .enable_bit = TPS65217PMIC_ENABLE_LDO2 202 }, 203 { 204 .name = "LDO3", 205 .voltage_min = 1500, 206 .voltage_max = 3300, 207 .voltages = ldo3voltages, 208 .nvoltages = 32, 209 .can_track = false, 210 .tracked_reg = NULL, 211 .can_xadj = false, 212 .can_ls = true, 213 .defreg_num = TPS65217PMIC_DEFLDO3, 214 .enable_bit = TPS65217PMIC_ENABLE_LDO3 215 }, 216 { 217 .name = "LDO4", 218 .voltage_min = 1500, 219 .voltage_max = 3300, 220 .voltages = ldo3voltages, 221 .nvoltages = 32, 222 .can_track = false, 223 .tracked_reg = NULL, 224 .can_xadj = false, 225 .can_ls = true, 226 .defreg_num = TPS65217PMIC_DEFLDO4, 227 .enable_bit = TPS65217PMIC_ENABLE_LDO4 228 }, 229 { 230 .name = "DCDC1", 231 .voltage_min = 900, 232 .voltage_max = 3300, 233 .voltages = ldo2voltages, 234 .nvoltages = 64, 235 .can_track = false, 236 .tracked_reg = NULL, 237 .can_xadj = true, 238 .can_ls = false, 239 .defreg_num = TPS65217PMIC_DEFDCDC1, 240 .enable_bit = TPS65217PMIC_ENABLE_DCDC1 241 }, 242 { 243 .name = "DCDC2", 244 .voltage_min = 900, 245 .voltage_max = 3300, 246 .voltages = ldo2voltages, 247 .nvoltages = 64, 248 .can_track = false, 249 .tracked_reg = NULL, 250 .can_xadj = true, 251 .can_ls = false, 252 .defreg_num = TPS65217PMIC_DEFDCDC2, 253 .enable_bit = TPS65217PMIC_ENABLE_DCDC2 254 }, 255 { 256 .name = "DCDC3", 257 .voltage_min = 900, 258 .voltage_max = 3300, 259 .voltages = ldo2voltages, 260 .nvoltages = 64, 261 .can_track = false, 262 .tracked_reg = NULL, 263 .can_xadj = true, 264 .can_ls = false, 265 .defreg_num = TPS65217PMIC_DEFDCDC3, 266 .enable_bit = TPS65217PMIC_ENABLE_DCDC3 267 } 268 }; 269 270 static bool matched = false; 271 272 static int 273 tps65217pmic_match(device_t parent, cfdata_t cf, void *aux) 274 { 275 struct i2c_attach_args *ia = aux; 276 277 if (ia->ia_addr == TPS65217PMIC_ADDR) { 278 /* we can only have one */ 279 if (matched) 280 return 0; 281 else 282 matched = true; 283 284 return 1; 285 } 286 return 0; 287 } 288 289 static void 290 tps65217pmic_attach(device_t parent, device_t self, void *aux) 291 { 292 struct tps65217pmic_softc *sc = device_private(self); 293 struct i2c_attach_args *ia = aux; 294 295 sc->sc_dev = self; 296 sc->sc_addr = ia->ia_addr; 297 sc->sc_tag = ia->ia_tag; 298 299 tps65217pmic_version(sc); 300 301 aprint_normal(": TPS65217"); 302 switch (sc->sc_version) { 303 case TPS65217PMIC_CHIPID_VER_A: 304 aprint_normal("A"); 305 break; 306 case TPS65217PMIC_CHIPID_VER_B: 307 aprint_normal("B"); 308 break; 309 case TPS65217PMIC_CHIPID_VER_C: 310 aprint_normal("C"); 311 break; 312 case TPS65217PMIC_CHIPID_VER_D: 313 aprint_normal("D"); 314 break; 315 default: 316 /* unknown version */ 317 break; 318 } 319 320 aprint_normal(" Power Management Multi-Channel IC (rev 1.%d)\n", 321 sc->sc_revision); 322 323 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 324 325 sc->sc_smpsw.smpsw_name = device_xname(self); 326 sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_ACADAPTER; 327 sysmon_pswitch_register(&sc->sc_smpsw); 328 329 tps65217pmic_reg_refresh(sc); 330 331 tps65217pmic_print_ppath(sc); 332 tps65217pmic_print_ldos(sc); 333 334 tps65217pmic_power_monitor_init(sc); 335 336 tps65217pmic_envsys_register(sc); 337 } 338 339 static void 340 tps65217pmic_power_monitor_init(struct tps65217pmic_softc *sc) 341 { 342 uint8_t intr, intrmask, status, ppath; 343 344 intrmask = TPS65217PMIC_INT_USBM | TPS65217PMIC_INT_ACM | 345 TPS65217PMIC_INT_PBM; 346 347 status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS); 348 ppath = tps65217pmic_reg_read(sc, TPS65217PMIC_PPATH); 349 /* acknowledge and disregard whatever interrupt was generated earlier */ 350 intr = tps65217pmic_reg_read(sc, TPS65217PMIC_INT); 351 352 sc->sc_usbstatus = status & TPS65217PMIC_STATUS_USBPWR; 353 sc->sc_acstatus = status & TPS65217PMIC_STATUS_ACPWR; 354 sc->sc_usbenabled = ppath & TPS65217PMIC_PPATH_USB_EN; 355 sc->sc_acenabled = ppath & TPS65217PMIC_PPATH_AC_EN; 356 357 if (intr & intrmask) 358 aprint_normal_dev(sc->sc_dev, 359 "WARNING: hardware interrupt enabled but not supported"); 360 361 /* set up callout to poll for power source changes */ 362 callout_init(&sc->sc_powerpollco, 0); 363 callout_setfunc(&sc->sc_powerpollco, tps65217pmic_power_monitor, sc); 364 365 callout_schedule(&sc->sc_powerpollco, hz); 366 } 367 368 static void 369 tps65217pmic_power_monitor(void *aux) 370 { 371 struct tps65217pmic_softc *sc; 372 uint8_t status; 373 bool usbstatus, acstatus; 374 375 sc = aux; 376 377 mutex_enter(&sc->sc_lock); 378 379 status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS); 380 usbstatus = status & TPS65217PMIC_STATUS_USBPWR; 381 acstatus = status & TPS65217PMIC_STATUS_ACPWR; 382 383 if (usbstatus != sc->sc_usbstatus) { 384 sc->sc_usbstatus = usbstatus; 385 pmf_event_inject(NULL, PMFE_POWER_CHANGED); 386 if (usbstatus) 387 aprint_normal_dev(sc->sc_dev, 388 "USB power source connected\n"); 389 else 390 aprint_normal_dev(sc->sc_dev, 391 "USB power source disconnected\n"); 392 } 393 394 if (acstatus != sc->sc_acstatus) { 395 sc->sc_acstatus = acstatus; 396 pmf_event_inject(NULL, PMFE_POWER_CHANGED); 397 if (acstatus) { 398 sysmon_pswitch_event(&sc->sc_smpsw, 399 PSWITCH_EVENT_PRESSED); 400 } else { 401 sysmon_pswitch_event(&sc->sc_smpsw, 402 PSWITCH_EVENT_RELEASED); 403 } 404 } 405 406 mutex_exit(&sc->sc_lock); 407 408 callout_schedule(&sc->sc_powerpollco, hz); 409 } 410 411 static void 412 tps65217pmic_reg_refresh(struct tps65217pmic_softc *sc) 413 { 414 int i; 415 struct tps_reg_param *c_reg; 416 417 for (i = 0; i < NTPS_REG; i++) { 418 c_reg = &tps_regulators[i]; 419 tps65217pmic_regulator_read_config(sc, c_reg); 420 } 421 } 422 423 /* Get version and revision of the chip. */ 424 static void 425 tps65217pmic_version(struct tps65217pmic_softc *sc) 426 { 427 uint8_t chipid; 428 429 chipid = tps65217pmic_reg_read(sc, TPS65217PMIC_CHIPID); 430 431 sc->sc_version = chipid & TPS65217PMIC_CHIPID_VER_MASK; 432 sc->sc_revision = chipid & TPS65217PMIC_CHIPID_REV_MASK; 433 } 434 435 static uint16_t 436 tps65217pmic_ppath_max_ac_current(uint8_t ppath) 437 { 438 switch ((ppath & TPS65217PMIC_PPATH_IAC) >> 439 TPS65217PMIC_PPATH_IAC_RSHFIT) { 440 case TPS65217PMIC_PPATH_IAC_100MA: 441 return 100; 442 case TPS65217PMIC_PPATH_IAC_500MA: 443 return 500; 444 case TPS65217PMIC_PPATH_IAC_1300MA: 445 return 1300; 446 case TPS65217PMIC_PPATH_IAC_2500MA: 447 return 2500; 448 } 449 return 0; 450 } 451 452 static uint16_t 453 tps65217pmic_ppath_max_usb_current(uint8_t ppath) 454 { 455 switch (ppath & TPS65217PMIC_PPATH_IUSB) { 456 case TPS65217PMIC_PPATH_IUSB_100MA: 457 return 100; 458 case TPS65217PMIC_PPATH_IUSB_500MA: 459 return 500; 460 case TPS65217PMIC_PPATH_IUSB_1300MA: 461 return 1300; 462 case TPS65217PMIC_PPATH_IUSB_1800MA: 463 return 1800; 464 } 465 return 0; 466 } 467 468 /* Read regulator state and save it to tps_reg_param. */ 469 static void 470 tps65217pmic_regulator_read_config(struct tps65217pmic_softc *sc, struct 471 tps_reg_param *regulator) 472 { 473 uint8_t defreg, regenable; 474 uint16_t voltage; 475 476 regenable = tps65217pmic_reg_read(sc, TPS65217PMIC_ENABLE); 477 478 if (regenable & (regulator->enable_bit)) 479 regulator->is_enabled = true; 480 else { 481 regulator->is_enabled = false; 482 return; 483 } 484 485 defreg = tps65217pmic_reg_read(sc, 486 regulator->defreg_num); 487 488 switch (regulator->nvoltages) { 489 case 16: 490 voltage = regulator->voltages[defreg & 491 TPS65217PMIC_DEFX_VOLTAGE_16]; 492 break; 493 case 32: 494 voltage = regulator->voltages[defreg & 495 TPS65217PMIC_DEFX_VOLTAGE_32]; 496 break; 497 case 64: 498 voltage = regulator->voltages[defreg & 499 TPS65217PMIC_DEFX_VOLTAGE_64]; 500 break; 501 default: 502 /* unsupported number of voltage settings? */ 503 voltage = 0; 504 break; 505 } 506 507 /* Handle regulator tracking other regulator voltage. */ 508 if (regulator->can_track) 509 if (defreg & TPS65217PMIC_DEFX_TRACKING) { 510 regulator->is_tracking = true; 511 voltage = 0; /* see regulator->tracked_reg */ 512 } 513 514 /* Handle regulator configured into load switch mode. */ 515 if (regulator->can_ls) 516 if (!(defreg & TPS65217PMIC_DEFX_LS)) { 517 regulator->is_ls = true; 518 voltage = 0; 519 } 520 521 if (regulator->can_xadj) 522 if (defreg & TPS65217PMIC_DEFX_XADJ) { 523 regulator->is_xadj = true; 524 voltage = 0; 525 526 } 527 528 /* TODO: add PGOOD checking */ 529 530 regulator->current_voltage = voltage; 531 } 532 533 static void 534 tps65217pmic_print_ldos(struct tps65217pmic_softc *sc) 535 { 536 int i; 537 struct tps_reg_param *c_reg; 538 539 aprint_normal_dev(sc->sc_dev, ""); 540 541 for (i = 0; i < NTPS_REG; i++) { 542 c_reg = &tps_regulators[i]; 543 544 if (c_reg->is_enabled) { 545 if (c_reg->is_ls) 546 aprint_normal("[%s: LS] ", c_reg->name); 547 else if (c_reg->is_xadj) 548 aprint_normal("[%s: XADJ] ", c_reg->name); 549 else 550 aprint_normal("[%s: %d mV] ", c_reg->name, 551 c_reg->current_voltage); 552 } 553 } 554 aprint_normal("\n"); 555 } 556 557 static void 558 tps65217pmic_print_ppath(struct tps65217pmic_softc *sc) 559 { 560 uint8_t status, ppath; 561 562 ppath = tps65217pmic_reg_read(sc, TPS65217PMIC_PPATH); 563 status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS); 564 565 aprint_normal_dev(sc->sc_dev, "power sources "); 566 567 if (ppath & TPS65217PMIC_PPATH_USB_EN) { 568 if (status & TPS65217PMIC_STATUS_USBPWR) 569 aprint_normal("[USB] "); 570 else 571 aprint_normal("USB "); 572 aprint_normal("max %d mA, ", 573 tps65217pmic_ppath_max_usb_current(ppath)); 574 } 575 576 if (ppath & TPS65217PMIC_PPATH_AC_EN) { 577 if (status & TPS65217PMIC_STATUS_ACPWR) 578 aprint_normal("[AC] "); 579 else 580 aprint_normal("AC "); 581 aprint_normal("max %d mA", 582 tps65217pmic_ppath_max_ac_current(ppath)); 583 } 584 585 aprint_normal("\n"); 586 } 587 588 static uint8_t 589 tps65217pmic_reg_read(struct tps65217pmic_softc *sc, uint8_t reg) 590 { 591 uint8_t wbuf[2]; 592 uint8_t rv; 593 594 if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) { 595 aprint_error_dev(sc->sc_dev, "cannot acquire bus for read\n"); 596 return 0; 597 } 598 599 wbuf[0] = reg; 600 601 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, wbuf, 602 1, &rv, 1, I2C_F_POLL)) { 603 aprint_error_dev(sc->sc_dev, "cannot execute operation\n"); 604 iic_release_bus(sc->sc_tag, I2C_F_POLL); 605 return 0; 606 } 607 iic_release_bus(sc->sc_tag, I2C_F_POLL); 608 609 return rv; 610 } 611 612 static void 613 tps65217pmic_reg_write_unlocked(struct tps65217pmic_softc *sc, 614 uint8_t reg, uint8_t data) 615 { 616 uint8_t wbuf[2]; 617 618 wbuf[0] = reg; 619 wbuf[1] = data; 620 621 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, NULL, 0, 622 wbuf, 2, I2C_F_POLL)) { 623 aprint_error_dev(sc->sc_dev, "cannot execute I2C write\n"); 624 } 625 } 626 627 static void __unused 628 tps65217pmic_reg_write(struct tps65217pmic_softc *sc, uint8_t reg, uint8_t data) 629 { 630 631 if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) { 632 aprint_error_dev(sc->sc_dev, "cannot acquire bus for write\n"); 633 return; 634 } 635 636 tps65217pmic_reg_write_unlocked(sc, reg, data); 637 638 iic_release_bus(sc->sc_tag, I2C_F_POLL); 639 } 640 641 static void 642 tps65217pmic_reg_write_l2(struct tps65217pmic_softc *sc, 643 uint8_t reg, uint8_t data) 644 { 645 uint8_t regpw = reg ^ TPS65217PMIC_PASSWORD_XOR; 646 if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) { 647 aprint_error_dev(sc->sc_dev, "cannot acquire bus for write\n"); 648 return; 649 } 650 651 tps65217pmic_reg_write_unlocked(sc, TPS65217PMIC_PASSWORD, regpw); 652 tps65217pmic_reg_write_unlocked(sc, reg, data); 653 tps65217pmic_reg_write_unlocked(sc, TPS65217PMIC_PASSWORD, regpw); 654 tps65217pmic_reg_write_unlocked(sc, reg, data); 655 iic_release_bus(sc->sc_tag, I2C_F_POLL); 656 } 657 658 static void 659 tps65217pmic_envsys_register(struct tps65217pmic_softc *sc) 660 { 661 int i; 662 663 sc->sc_sme = sysmon_envsys_create(); 664 665 /* iterate over all regulators and attach them as sensors */ 666 for(i = 0; i <= SNUM_REGS; i++) { 667 /* set name */ 668 strlcpy(sc->sc_regsensor[i].desc, tps_regulators[i].name, 669 sizeof(sc->sc_regsensor[i].desc)); 670 sc->sc_regsensor[i].units = ENVSYS_SVOLTS_DC; 671 sc->sc_regsensor[i].state = ENVSYS_SINVALID; 672 673 if (sysmon_envsys_sensor_attach(sc->sc_sme, 674 &sc->sc_regsensor[i])) 675 aprint_error_dev(sc->sc_dev, 676 "error attaching regulator sensor %d\n", i); 677 } 678 679 /* attach power source indicators */ 680 strcpy(sc->sc_usbsensor.desc, "USB power source"); /* SNUM_USBSTATUS */ 681 sc->sc_usbsensor.units = ENVSYS_INDICATOR; 682 sc->sc_usbsensor.state = ENVSYS_SINVALID; 683 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_usbsensor)) 684 aprint_error_dev(sc->sc_dev, 685 "error attaching USB power source sensor\n"); 686 strcpy(sc->sc_acsensor.desc, "AC power source"); /* SNUM_ACSTATUS */ 687 sc->sc_acsensor.units = ENVSYS_INDICATOR; 688 sc->sc_acsensor.state = ENVSYS_SINVALID; 689 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_acsensor)) 690 aprint_error_dev(sc->sc_dev, 691 "error attaching AC power source sensor\n"); 692 693 /* register everything in sysmon */ 694 sc->sc_sme->sme_name = device_xname(sc->sc_dev); 695 sc->sc_sme->sme_cookie = sc; 696 sc->sc_sme->sme_refresh = tps65217pmic_envsys_refresh; 697 698 if (sysmon_envsys_register(sc->sc_sme)) { 699 aprint_error_dev(sc->sc_dev, "unable to register in sysmon\n"); 700 sysmon_envsys_destroy(sc->sc_sme); 701 } 702 } 703 704 static void 705 tps65217pmic_envsys_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 706 { 707 struct tps65217pmic_softc *sc = sme->sme_cookie; 708 709 mutex_enter(&sc->sc_lock); 710 711 tps65217pmic_reg_refresh(sc); 712 713 if (edata->sensor <= SNUM_REGS) { 714 /* TODO: handle special cases like LS, XADJ... */ 715 edata->value_cur = tps_regulators[edata->sensor].current_voltage * 1000; 716 edata->state = ENVSYS_SVALID; 717 } else if (edata->sensor == SNUM_USBSTATUS) { 718 edata->value_cur = sc->sc_usbstatus && sc->sc_usbenabled; 719 edata->state = ENVSYS_SVALID; 720 } else if (edata->sensor == SNUM_ACSTATUS) { 721 edata->value_cur = sc->sc_acstatus && sc->sc_acenabled; 722 edata->state = ENVSYS_SVALID; 723 } else 724 aprint_error_dev(sc->sc_dev, "unknown sensor number\n"); 725 726 mutex_exit(&sc->sc_lock); 727 } 728 729 int 730 tps65217pmic_set_volt(device_t self, const char *name, int mvolt) 731 { 732 int i; 733 struct tps65217pmic_softc *sc = device_private(self); 734 struct tps_reg_param *regulator = NULL; 735 uint8_t val; 736 737 for (i = 0; i < __arraycount(tps_regulators); i++) { 738 if (strcmp(name, tps_regulators[i].name) == 0) { 739 regulator = &tps_regulators[i]; 740 break; 741 } 742 } 743 if (regulator == NULL) 744 return EINVAL; 745 746 if (regulator->voltage_min > mvolt || regulator->voltage_max < mvolt) 747 return EINVAL; 748 749 if (!regulator->is_enabled) 750 return EINVAL; 751 752 if (regulator->is_tracking) 753 return EINVAL; 754 755 if (regulator->is_xadj) 756 return EINVAL; 757 758 /* find closest voltage entry */ 759 for (i = 0; i < regulator->nvoltages; i++) { 760 if (mvolt <= regulator->voltages[i]) { 761 break; 762 } 763 } 764 KASSERT(i < regulator->nvoltages); 765 tps65217pmic_reg_write_l2(sc, regulator->defreg_num, i); 766 767 val = tps65217pmic_reg_read(sc, TPS65217PMIC_DEFSLEW); 768 val |= TPS65217PMIC_DEFSLEW_GO; 769 tps65217pmic_reg_write_l2(sc, TPS65217PMIC_DEFSLEW, val); 770 771 while (val & TPS65217PMIC_DEFSLEW_GO) { 772 val = tps65217pmic_reg_read(sc, TPS65217PMIC_DEFSLEW); 773 } 774 return 0; 775 } 776