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