xref: /netbsd-src/sys/dev/i2c/tps65217pmic.c (revision d909946ca08dceb44d7d0f22ec9488679695d976)
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