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