xref: /netbsd-src/sys/dev/i2c/tps65217pmic.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: tps65217pmic.c,v 1.9 2014/01/08 16:49:48 jakllsch 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 2014/01/08 16:49:48 jakllsch 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