Home | History | Annotate | Line # | Download | only in i2c
tps65217pmic.c revision 1.6
      1 /*	$NetBSD: tps65217pmic.c,v 1.6 2013/08/04 00:24:28 rkujawa 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.6 2013/08/04 00:24:28 rkujawa 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 
     53 #define NTPS_REG	7
     54 #define SNUM_REGS	NTPS_REG-1
     55 #define SNUM_USBSTATUS	NTPS_REG
     56 #define SNUM_ACSTATUS	NTPS_REG+1
     57 
     58 struct tps65217pmic_softc {
     59 	device_t		sc_dev;
     60 
     61 	i2c_tag_t		sc_tag;
     62 	i2c_addr_t		sc_addr;
     63 
     64 	uint8_t			sc_version;
     65 	uint8_t			sc_revision;
     66 
     67 	kmutex_t		sc_lock;
     68 
     69 	bool			sc_acstatus;
     70 	bool			sc_usbstatus;
     71 	bool			sc_acenabled;
     72 	bool			sc_usbenabled;
     73 
     74 	callout_t		sc_powerpollco;
     75 
     76 	/* sysmon(4) stuff */
     77 	struct sysmon_envsys	*sc_sme;
     78 	envsys_data_t		sc_regsensor[NTPS_REG];
     79 	envsys_data_t		sc_acsensor;
     80 	envsys_data_t		sc_usbsensor;
     81 
     82 	struct sysmon_pswitch	sc_smpsw;
     83 };
     84 
     85 /* Voltage regulators */
     86 enum tps_reg_num {
     87 	TPS65217PMIC_LDO1,
     88 	TPS65217PMIC_LDO2,
     89 	TPS65217PMIC_LDO3LS,
     90 	TPS65217PMIC_LDO4LS,
     91 	TPS65217PMIC_DCDC1,
     92 	TPS65217PMIC_DCDC2,
     93 	TPS65217PMIC_DCDC3
     94 };
     95 
     96 struct tps_reg_param {
     97 	/* parameters configured statically */
     98 
     99 	const char* name;
    100 	uint16_t voltage_min;		/* in mV */
    101 	uint16_t voltage_max;		/* in mV */
    102 	const uint16_t *voltages;	/* all possible voltage settings */
    103 	uint8_t nvoltages;		/* number of voltage settings */
    104 
    105 	bool can_track;			/* regulator can track U of other r. */
    106 	struct tps_reg_param *tracked_reg; /* ptr to tracked regulator */
    107 	bool can_xadj;			/* voltage can be adjusted externally */
    108 	bool can_ls;			/* can be a load switch instead of r. */
    109 
    110 	uint8_t defreg_num;		/* DEF register */
    111 	uint8_t enable_bit;		/* position in ENABLE register */
    112 
    113 	/*
    114 	 * Run-time parameters configured during attachment and later, these
    115 	 * probably should be split into separate struct that would be a part
    116 	 * of softc. But since we can have only one TPS chip, that should be
    117 	 * okay for now.
    118 	 */
    119 
    120 	bool is_enabled;		/* regulator is enabled */
    121 	bool is_pg;			/* regulator is "power good" */
    122 	bool is_tracking;		/* voltage is tracking other reg. */
    123 	bool is_ls;			/* is a load switch */
    124 	bool is_xadj;			/* voltage is adjusted externally */
    125 
    126 	uint16_t current_voltage;	/* in mV */
    127 
    128 };
    129 
    130 static int tps65217pmic_match(device_t, cfdata_t, void *);
    131 static void tps65217pmic_attach(device_t, device_t, void *);
    132 
    133 static uint8_t tps65217pmic_reg_read(struct tps65217pmic_softc *, uint8_t);
    134 
    135 static void tps65217pmic_reg_refresh(struct tps65217pmic_softc *);
    136 
    137 static uint16_t tps65217pmic_ppath_max_usb_current(uint8_t);
    138 static uint16_t tps65217pmic_ppath_max_ac_current(uint8_t);
    139 
    140 static void tps65217pmic_regulator_read_config(struct tps65217pmic_softc *,
    141     struct tps_reg_param *);
    142 
    143 static void tps65217pmic_print_ppath(struct tps65217pmic_softc *);
    144 static void tps65217pmic_print_ldos(struct tps65217pmic_softc *);
    145 
    146 static void tps65217pmic_version(struct tps65217pmic_softc *);
    147 
    148 static void tps65217pmic_envsys_register(struct tps65217pmic_softc *);
    149 static void tps65217pmic_envsys_refresh(struct sysmon_envsys *, envsys_data_t *);
    150 
    151 static void tps65217pmic_power_monitor_init(struct tps65217pmic_softc *);
    152 static void tps65217pmic_power_monitor(void *);
    153 
    154 CFATTACH_DECL_NEW(tps65217pmic, sizeof (struct tps65217pmic_softc),
    155     tps65217pmic_match, tps65217pmic_attach, NULL, NULL);
    156 
    157 /* Possible settings of LDO1 in mV. */
    158 static const uint16_t ldo1voltages[] = { 1000, 1100, 1200, 1250, 1300, 1350,
    159     1400, 1500, 1600, 1800, 2500, 2750, 2800, 3000, 3100, 3300 };
    160 /* Possible settings of LDO2, DCDC1, DCDC2, DCDC3 in mV. */
    161 static const uint16_t ldo2voltages[] = { 900, 925, 950, 975, 1000, 1025, 1050,
    162     1075, 1100, 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, 1325, 1350,
    163     1375, 1400, 1425, 1450, 1475, 1500, 1550, 1600, 1650, 1700, 1750, 1800,
    164     1850, 1900, 1950, 2000, 2050, 2100, 2150, 2200, 2250, 2300, 2350, 2400,
    165     2450, 2500, 2550, 2600, 2650, 2700, 2750, 2800, 2850, 2900, 3000, 3100,
    166     3200, 3300, 3300, 3300, 3300, 3300, 3300, 3300, 3300 };
    167 /* Possible settings of LDO3, LDO4 in mV. */
    168 static const uint16_t ldo3voltages[] = { 1500, 1550, 1600, 1650, 1700, 1750,
    169     1800, 1850, 1900, 2000, 2100, 2200, 2300, 2400, 2450, 2500, 2550, 2600,
    170     2650, 2700, 2750, 2800, 2850, 2900,2950, 3000, 3050, 3100, 3150, 3200,
    171     3250, 3300 };
    172 
    173 static struct tps_reg_param tps_regulators[] = {
    174 	{
    175 		.name = "LDO1",
    176 		.voltage_min = 1000,
    177 		.voltage_max = 3300,
    178 		.voltages = ldo1voltages,
    179 		.nvoltages = 16,
    180 		.can_track = false,
    181 		.tracked_reg = NULL,
    182 		.can_xadj =  false,
    183 		.can_ls = false,
    184 		.defreg_num = TPS65217PMIC_DEFLDO1,
    185 		.enable_bit = TPS65217PMIC_ENABLE_LDO1
    186 	},
    187 	{
    188 		.name = "LDO2",
    189 		.voltage_min = 900,
    190 		.voltage_max = 3300,
    191 		.voltages = ldo2voltages,
    192 		.nvoltages = 64,
    193 		.can_track = true,
    194 		.tracked_reg = &(tps_regulators[TPS65217PMIC_DCDC3]),
    195 		.can_xadj = false,
    196 		.can_ls = false,
    197 		.defreg_num = TPS65217PMIC_DEFLDO2,
    198 		.enable_bit = TPS65217PMIC_ENABLE_LDO2
    199 	},
    200 	{
    201 		.name = "LDO3",
    202 		.voltage_min = 1500,
    203 		.voltage_max = 3300,
    204 		.voltages = ldo3voltages,
    205 		.nvoltages = 32,
    206 		.can_track = false,
    207 		.tracked_reg = NULL,
    208 		.can_xadj = false,
    209 		.can_ls = true,
    210 		.defreg_num = TPS65217PMIC_DEFLDO3,
    211 		.enable_bit = TPS65217PMIC_ENABLE_LDO3
    212 	},
    213 	{
    214 		.name = "LDO4",
    215 		.voltage_min = 1500,
    216 		.voltage_max = 3300,
    217 		.voltages = ldo3voltages,
    218 		.nvoltages = 32,
    219 		.can_track = false,
    220 		.tracked_reg = NULL,
    221 		.can_xadj = false,
    222 		.can_ls = true,
    223 		.defreg_num = TPS65217PMIC_DEFLDO4,
    224 		.enable_bit = TPS65217PMIC_ENABLE_LDO4
    225 	},
    226 	{
    227 		.name = "DCDC1",
    228 		.voltage_min = 900,
    229 		.voltage_max = 3300,
    230 		.voltages = ldo2voltages,
    231 		.nvoltages = 64,
    232 		.can_track = false,
    233 		.tracked_reg = NULL,
    234 		.can_xadj = true,
    235 		.can_ls = false,
    236 		.defreg_num = TPS65217PMIC_DEFDCDC1,
    237 		.enable_bit = TPS65217PMIC_ENABLE_DCDC1
    238 	},
    239 	{
    240 		.name = "DCDC2",
    241 		.voltage_min = 900,
    242 		.voltage_max = 3300,
    243 		.voltages = ldo2voltages,
    244 		.nvoltages = 64,
    245 		.can_track = false,
    246 		.tracked_reg = NULL,
    247 		.can_xadj = true,
    248 		.can_ls = false,
    249 		.defreg_num = TPS65217PMIC_DEFDCDC2,
    250 		.enable_bit = TPS65217PMIC_ENABLE_DCDC2
    251 	},
    252 	{
    253 		.name = "DCDC3",
    254 		.voltage_min = 900,
    255 		.voltage_max = 3300,
    256 		.voltages = ldo2voltages,
    257 		.nvoltages = 64,
    258 		.can_track = false,
    259 		.tracked_reg = NULL,
    260 		.can_xadj = true,
    261 		.can_ls = false,
    262 		.defreg_num = TPS65217PMIC_DEFDCDC3,
    263 		.enable_bit = TPS65217PMIC_ENABLE_DCDC3
    264 	}
    265 };
    266 
    267 static bool matched = false;
    268 
    269 static int
    270 tps65217pmic_match(device_t parent, cfdata_t cf, void *aux)
    271 {
    272 	struct i2c_attach_args *ia = aux;
    273 
    274 	if (ia->ia_addr == TPS65217PMIC_ADDR) {
    275 		/* we can only have one */
    276 		if (matched)
    277 			return 0;
    278 		else
    279 			matched = true;
    280 
    281 		return 1;
    282 	}
    283 	return 0;
    284 }
    285 
    286 static void
    287 tps65217pmic_attach(device_t parent, device_t self, void *aux)
    288 {
    289 	struct tps65217pmic_softc *sc = device_private(self);
    290 	struct i2c_attach_args *ia = aux;
    291 
    292 	sc->sc_dev = self;
    293 	sc->sc_addr = ia->ia_addr;
    294 	sc->sc_tag = ia->ia_tag;
    295 
    296 	tps65217pmic_version(sc);
    297 
    298 	aprint_normal(": TPS65217");
    299 	switch (sc->sc_version) {
    300 	case TPS65217PMIC_CHIPID_VER_A:
    301 		aprint_normal("A");
    302 		break;
    303 	case TPS65217PMIC_CHIPID_VER_B:
    304 		aprint_normal("B");
    305 		break;
    306 	case TPS65217PMIC_CHIPID_VER_C:
    307 		aprint_normal("C");
    308 		break;
    309 	case TPS65217PMIC_CHIPID_VER_D:
    310 		aprint_normal("D");
    311 		break;
    312 	default:
    313 		/* unknown version */
    314 		break;
    315 	}
    316 
    317 	aprint_normal(" Power Management Multi-Channel IC (rev 1.%d)\n",
    318 	    sc->sc_revision);
    319 
    320 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    321 
    322 	sc->sc_smpsw.smpsw_name = device_xname(self);
    323 	sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_ACADAPTER;
    324 	sysmon_pswitch_register(&sc->sc_smpsw);
    325 
    326 	tps65217pmic_reg_refresh(sc);
    327 
    328 	tps65217pmic_print_ppath(sc);
    329 	tps65217pmic_print_ldos(sc);
    330 
    331 	tps65217pmic_power_monitor_init(sc);
    332 
    333 	tps65217pmic_envsys_register(sc);
    334 }
    335 
    336 static void
    337 tps65217pmic_power_monitor_init(struct tps65217pmic_softc *sc)
    338 {
    339 	uint8_t intr, intrmask, status, ppath;
    340 
    341 	intrmask = TPS65217PMIC_INT_USBM | TPS65217PMIC_INT_ACM |
    342 	    TPS65217PMIC_INT_PBM;
    343 
    344 	status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS);
    345 	ppath = tps65217pmic_reg_read(sc, TPS65217PMIC_PPATH);
    346 	/* acknowledge and disregard whatever interrupt was generated earlier */
    347 	intr = tps65217pmic_reg_read(sc, TPS65217PMIC_INT);
    348 
    349 	sc->sc_usbstatus = status & TPS65217PMIC_STATUS_USBPWR;
    350 	sc->sc_acstatus = status & TPS65217PMIC_STATUS_ACPWR;
    351 	sc->sc_usbenabled = ppath & TPS65217PMIC_PPATH_USB_EN;
    352 	sc->sc_acenabled = ppath & TPS65217PMIC_PPATH_AC_EN;
    353 
    354 	if (intr & intrmask)
    355 		aprint_normal_dev(sc->sc_dev,
    356 		    "WARNING: hardware interrupt enabled but not supported");
    357 
    358 	/* set up callout to poll for power source changes */
    359 	callout_init(&sc->sc_powerpollco, 0);
    360 	callout_setfunc(&sc->sc_powerpollco, tps65217pmic_power_monitor, sc);
    361 
    362 	callout_schedule(&sc->sc_powerpollco, hz);
    363 }
    364 
    365 static void
    366 tps65217pmic_power_monitor(void *aux)
    367 {
    368 	struct tps65217pmic_softc *sc;
    369 	uint8_t status;
    370 	bool usbstatus, acstatus;
    371 
    372 	sc = aux;
    373 
    374 	mutex_enter(&sc->sc_lock);
    375 
    376 	status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS);
    377 	usbstatus = status & TPS65217PMIC_STATUS_USBPWR;
    378 	acstatus = status & TPS65217PMIC_STATUS_ACPWR;
    379 
    380 	if (usbstatus != sc->sc_usbstatus) {
    381 		sc->sc_usbstatus = usbstatus;
    382 		pmf_event_inject(NULL, PMFE_POWER_CHANGED);
    383 		if (usbstatus)
    384 			aprint_normal_dev(sc->sc_dev,
    385 			    "USB power source connected\n");
    386 		else
    387 			aprint_normal_dev(sc->sc_dev,
    388 			    "USB power source disconnected\n");
    389 	}
    390 
    391 	if (acstatus != sc->sc_acstatus) {
    392 		sc->sc_acstatus = acstatus;
    393 		pmf_event_inject(NULL, PMFE_POWER_CHANGED);
    394 		if (acstatus) {
    395 			sysmon_pswitch_event(&sc->sc_smpsw,
    396 			    PSWITCH_EVENT_PRESSED);
    397 		} else {
    398 			sysmon_pswitch_event(&sc->sc_smpsw,
    399 			    PSWITCH_EVENT_RELEASED);
    400 		}
    401 	}
    402 
    403 	mutex_exit(&sc->sc_lock);
    404 
    405 	callout_schedule(&sc->sc_powerpollco, hz);
    406 }
    407 
    408 static void
    409 tps65217pmic_reg_refresh(struct tps65217pmic_softc *sc)
    410 {
    411 	int i;
    412 	struct tps_reg_param *c_reg;
    413 
    414 	for (i = 0; i < NTPS_REG; i++) {
    415 		c_reg = &tps_regulators[i];
    416 		tps65217pmic_regulator_read_config(sc, c_reg);
    417 	}
    418 }
    419 
    420 /* Get version and revision of the chip. */
    421 static void
    422 tps65217pmic_version(struct tps65217pmic_softc *sc)
    423 {
    424 	uint8_t chipid;
    425 
    426 	chipid = tps65217pmic_reg_read(sc, TPS65217PMIC_CHIPID);
    427 
    428 	sc->sc_version = chipid & TPS65217PMIC_CHIPID_VER_MASK;
    429 	sc->sc_revision = chipid & TPS65217PMIC_CHIPID_REV_MASK;
    430 }
    431 
    432 static uint16_t
    433 tps65217pmic_ppath_max_ac_current(uint8_t ppath)
    434 {
    435 	switch ((ppath & TPS65217PMIC_PPATH_IAC) >>
    436 	    TPS65217PMIC_PPATH_IAC_RSHFIT) {
    437 	case TPS65217PMIC_PPATH_IAC_100MA:
    438 		return 100;
    439 	case TPS65217PMIC_PPATH_IAC_500MA:
    440 		return 500;
    441 	case TPS65217PMIC_PPATH_IAC_1300MA:
    442 		return 1300;
    443 	case TPS65217PMIC_PPATH_IAC_2500MA:
    444 		return 2500;
    445 	}
    446 	return 0;
    447 }
    448 
    449 static uint16_t
    450 tps65217pmic_ppath_max_usb_current(uint8_t ppath)
    451 {
    452 	switch (ppath & TPS65217PMIC_PPATH_IUSB) {
    453 	case TPS65217PMIC_PPATH_IUSB_100MA:
    454 		return 100;
    455 	case TPS65217PMIC_PPATH_IUSB_500MA:
    456 		return 500;
    457 	case TPS65217PMIC_PPATH_IUSB_1300MA:
    458 		return 1300;
    459 	case TPS65217PMIC_PPATH_IUSB_1800MA:
    460 		return 1800;
    461 	}
    462 	return 0;
    463 }
    464 
    465 /* Read regulator state and save it to tps_reg_param. */
    466 static void
    467 tps65217pmic_regulator_read_config(struct tps65217pmic_softc *sc, struct
    468     tps_reg_param *regulator)
    469 {
    470 	uint8_t defreg, regenable;
    471 	uint16_t voltage;
    472 
    473 	regenable = tps65217pmic_reg_read(sc, TPS65217PMIC_ENABLE);
    474 
    475 	if (regenable & (regulator->enable_bit))
    476 		regulator->is_enabled = true;
    477 	else {
    478 		regulator->is_enabled = false;
    479 		return;
    480 	}
    481 
    482 	defreg = tps65217pmic_reg_read(sc,
    483 	    regulator->defreg_num);
    484 
    485 	switch (regulator->nvoltages) {
    486 	case 16:
    487 		voltage = regulator->voltages[defreg &
    488 		    TPS65217PMIC_DEFX_VOLTAGE_16];
    489 		break;
    490 	case 32:
    491 		voltage = regulator->voltages[defreg &
    492 		    TPS65217PMIC_DEFX_VOLTAGE_32];
    493 		break;
    494 	case 64:
    495 		voltage = regulator->voltages[defreg &
    496 		    TPS65217PMIC_DEFX_VOLTAGE_64];
    497 		break;
    498 	default:
    499 		/* unsupported number of voltage settings? */
    500 		voltage = 0;
    501 		break;
    502 	}
    503 
    504 	/* Handle regulator tracking other regulator voltage. */
    505 	if (regulator->can_track)
    506 		if (defreg & TPS65217PMIC_DEFX_TRACKING) {
    507 			regulator->is_tracking = true;
    508 			voltage = 0; /* see regulator->tracked_reg */
    509 		}
    510 
    511 	/* Handle regulator configured into load switch mode. */
    512 	if (regulator->can_ls)
    513 		if (!(defreg & TPS65217PMIC_DEFX_LS)) {
    514 			regulator->is_ls = true;
    515 			voltage = 0;
    516 		}
    517 
    518 	if (regulator->can_xadj)
    519 		if (defreg & TPS65217PMIC_DEFX_XADJ) {
    520 			regulator->is_xadj = true;
    521 			voltage = 0;
    522 
    523 		}
    524 
    525 	/* TODO: add PGOOD checking */
    526 
    527 	regulator->current_voltage = voltage;
    528 }
    529 
    530 static void
    531 tps65217pmic_print_ldos(struct tps65217pmic_softc *sc)
    532 {
    533 	int i;
    534 	struct tps_reg_param *c_reg;
    535 
    536 	aprint_normal_dev(sc->sc_dev, "");
    537 
    538 	for (i = 0; i < NTPS_REG; i++) {
    539 		c_reg = &tps_regulators[i];
    540 
    541 		if (c_reg->is_enabled) {
    542 			if (c_reg->is_ls)
    543 				aprint_normal("[%s: LS] ", c_reg->name);
    544 			else if (c_reg->is_xadj)
    545 				aprint_normal("[%s: XADJ] ", c_reg->name);
    546 			else
    547 				aprint_normal("[%s: %d mV] ", c_reg->name,
    548 				    c_reg->current_voltage);
    549 		}
    550 	}
    551 	aprint_normal("\n");
    552 }
    553 
    554 static void
    555 tps65217pmic_print_ppath(struct tps65217pmic_softc *sc)
    556 {
    557 	uint8_t status, ppath, regenable;
    558 
    559 	ppath = tps65217pmic_reg_read(sc, TPS65217PMIC_PPATH);
    560 	status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS);
    561 	regenable = tps65217pmic_reg_read(sc, TPS65217PMIC_ENABLE);
    562 
    563 	aprint_normal_dev(sc->sc_dev, "power sources ");
    564 
    565 	if (ppath & TPS65217PMIC_PPATH_USB_EN) {
    566 		if (status & TPS65217PMIC_STATUS_USBPWR)
    567 			aprint_normal("[USB] ");
    568 		else
    569 			aprint_normal("USB ");
    570 		aprint_normal("max %d mA, ",
    571 		    tps65217pmic_ppath_max_usb_current(ppath));
    572 	}
    573 
    574 	if (ppath & TPS65217PMIC_PPATH_AC_EN) {
    575 		if (status & TPS65217PMIC_STATUS_ACPWR)
    576 			aprint_normal("[AC] ");
    577 		else
    578 			aprint_normal("AC ");
    579 		aprint_normal("max %d mA",
    580 		    tps65217pmic_ppath_max_ac_current(ppath));
    581 	}
    582 
    583 	aprint_normal("\n");
    584 }
    585 
    586 static uint8_t
    587 tps65217pmic_reg_read(struct tps65217pmic_softc *sc, uint8_t reg)
    588 {
    589 	uint8_t wbuf[2];
    590 	uint8_t rv;
    591 
    592 	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) {
    593 		aprint_error_dev(sc->sc_dev, "cannot acquire bus for read\n");
    594 		return 0;
    595 	}
    596 
    597 	wbuf[0] = reg;
    598 
    599 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, wbuf,
    600 	    1, &rv, 1, I2C_F_POLL)) {
    601 		aprint_error_dev(sc->sc_dev, "cannot execute operation\n");
    602 		iic_release_bus(sc->sc_tag, I2C_F_POLL);
    603 		return 0;
    604 	}
    605 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
    606 
    607 	return rv;
    608 }
    609 
    610 static void
    611 tps65217pmic_envsys_register(struct tps65217pmic_softc *sc)
    612 {
    613 	int i;
    614 
    615 	sc->sc_sme = sysmon_envsys_create();
    616 
    617 	/* iterate over all regulators and attach them as sensors */
    618 	for(i = 0; i <= SNUM_REGS; i++) {
    619 		/* set name */
    620 		strlcpy(sc->sc_regsensor[i].desc, tps_regulators[i].name,
    621 		    sizeof(sc->sc_regsensor[i].desc));
    622 		sc->sc_regsensor[i].units = ENVSYS_SVOLTS_DC;
    623 		sc->sc_regsensor[i].state = ENVSYS_SINVALID;
    624 
    625 		if (sysmon_envsys_sensor_attach(sc->sc_sme,
    626 		    &sc->sc_regsensor[i]))
    627 			aprint_error_dev(sc->sc_dev,
    628 			    "error attaching regulator sensor %d\n", i);
    629 	}
    630 
    631 	/* attach power source indicators */
    632 	strcpy(sc->sc_usbsensor.desc, "USB power source"); /* SNUM_USBSTATUS */
    633 	sc->sc_usbsensor.units = ENVSYS_INDICATOR;
    634 	sc->sc_usbsensor.state = ENVSYS_SINVALID;
    635 	if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_usbsensor))
    636 		aprint_error_dev(sc->sc_dev,
    637 		    "error attaching USB power source sensor\n");
    638 	strcpy(sc->sc_acsensor.desc, "AC power source"); /* SNUM_ACSTATUS */
    639 	sc->sc_acsensor.units = ENVSYS_INDICATOR;
    640 	sc->sc_acsensor.state = ENVSYS_SINVALID;
    641 	if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_acsensor))
    642 		aprint_error_dev(sc->sc_dev,
    643 	 	    "error attaching AC power source sensor\n");
    644 
    645 	/* register everything in sysmon */
    646 	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
    647 	sc->sc_sme->sme_cookie = sc;
    648 	sc->sc_sme->sme_refresh = tps65217pmic_envsys_refresh;
    649 
    650 	if (sysmon_envsys_register(sc->sc_sme)) {
    651 		aprint_error_dev(sc->sc_dev, "unable to register in sysmon\n");
    652 		sysmon_envsys_destroy(sc->sc_sme);
    653 	}
    654 }
    655 
    656 static void
    657 tps65217pmic_envsys_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
    658 {
    659 	struct tps65217pmic_softc *sc = sme->sme_cookie;
    660 
    661 	mutex_enter(&sc->sc_lock);
    662 
    663 	tps65217pmic_reg_refresh(sc);
    664 
    665 	if (edata->sensor <= SNUM_REGS) {
    666 		/* TODO: handle special cases like LS, XADJ... */
    667 		edata->value_cur = tps_regulators[edata->sensor].current_voltage * 1000;
    668 		edata->state = ENVSYS_SVALID;
    669 	} else if (edata->sensor == SNUM_USBSTATUS) {
    670 		edata->value_cur = sc->sc_usbstatus && sc->sc_usbenabled;
    671 		edata->state = ENVSYS_SVALID;
    672 	} else if (edata->sensor == SNUM_ACSTATUS) {
    673 		edata->value_cur = sc->sc_acstatus && sc->sc_acenabled;
    674 		edata->state = ENVSYS_SVALID;
    675 	} else
    676 		aprint_error_dev(sc->sc_dev, "unknown sensor number\n");
    677 
    678 	mutex_exit(&sc->sc_lock);
    679 }
    680 
    681