xref: /netbsd-src/sys/dev/i2c/tps65217pmic.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: tps65217pmic.c,v 1.11 2016/10/15 14:40:41 kiyohara 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.11 2016/10/15 14:40:41 kiyohara 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 		else
284 			matched = true;
285 
286 		return 1;
287 	}
288 	return 0;
289 }
290 
291 static void
292 tps65217pmic_attach(device_t parent, device_t self, void *aux)
293 {
294 	struct tps65217pmic_softc *sc = device_private(self);
295 	struct i2c_attach_args *ia = aux;
296 	prop_dictionary_t dict;
297 	int isel, fdim, brightness;
298 
299 	sc->sc_dev = self;
300 	sc->sc_addr = ia->ia_addr;
301 	sc->sc_tag = ia->ia_tag;
302 
303 	dict = device_properties(self);
304 	if (prop_dictionary_get_int32(dict, "isel", &isel)) {
305 		prop_dictionary_get_int32(dict, "fdim", &fdim);
306 		prop_dictionary_get_int32(dict, "brightness", &brightness);
307 	} else
308 		isel = -1;
309 
310 	tps65217pmic_version(sc);
311 
312 	aprint_normal(": TPS65217");
313 	switch (sc->sc_version) {
314 	case TPS65217PMIC_CHIPID_VER_A:
315 		aprint_normal("A");
316 		break;
317 	case TPS65217PMIC_CHIPID_VER_B:
318 		aprint_normal("B");
319 		break;
320 	case TPS65217PMIC_CHIPID_VER_C:
321 		aprint_normal("C");
322 		break;
323 	case TPS65217PMIC_CHIPID_VER_D:
324 		aprint_normal("D");
325 		break;
326 	default:
327 		/* unknown version */
328 		break;
329 	}
330 
331 	aprint_normal(" Power Management Multi-Channel IC (rev 1.%d)\n",
332 	    sc->sc_revision);
333 
334 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
335 
336 	sc->sc_smpsw.smpsw_name = device_xname(self);
337 	sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_ACADAPTER;
338 	sysmon_pswitch_register(&sc->sc_smpsw);
339 
340 	tps65217pmic_reg_refresh(sc);
341 
342 	tps65217pmic_print_ppath(sc);
343 	tps65217pmic_print_ldos(sc);
344 
345 	tps65217pmic_power_monitor_init(sc);
346 
347 	if (isel != -1)
348 		tps65217pmic_wled_init(sc, isel, fdim, brightness);
349 
350 	tps65217pmic_envsys_register(sc);
351 }
352 
353 static void
354 tps65217pmic_power_monitor_init(struct tps65217pmic_softc *sc)
355 {
356 	uint8_t intr, intrmask, status, ppath;
357 
358 	intrmask = TPS65217PMIC_INT_USBM | TPS65217PMIC_INT_ACM |
359 	    TPS65217PMIC_INT_PBM;
360 
361 	status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS);
362 	ppath = tps65217pmic_reg_read(sc, TPS65217PMIC_PPATH);
363 	/* acknowledge and disregard whatever interrupt was generated earlier */
364 	intr = tps65217pmic_reg_read(sc, TPS65217PMIC_INT);
365 
366 	sc->sc_usbstatus = status & TPS65217PMIC_STATUS_USBPWR;
367 	sc->sc_acstatus = status & TPS65217PMIC_STATUS_ACPWR;
368 	sc->sc_usbenabled = ppath & TPS65217PMIC_PPATH_USB_EN;
369 	sc->sc_acenabled = ppath & TPS65217PMIC_PPATH_AC_EN;
370 
371 	if (intr & intrmask)
372 		aprint_normal_dev(sc->sc_dev,
373 		    "WARNING: hardware interrupt enabled but not supported");
374 
375 	/* set up callout to poll for power source changes */
376 	callout_init(&sc->sc_powerpollco, 0);
377 	callout_setfunc(&sc->sc_powerpollco, tps65217pmic_power_monitor, sc);
378 
379 	callout_schedule(&sc->sc_powerpollco, hz);
380 }
381 
382 static void
383 tps65217pmic_power_monitor(void *aux)
384 {
385 	struct tps65217pmic_softc *sc;
386 	uint8_t status;
387 	bool usbstatus, acstatus;
388 
389 	sc = aux;
390 
391 	mutex_enter(&sc->sc_lock);
392 
393 	status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS);
394 	usbstatus = status & TPS65217PMIC_STATUS_USBPWR;
395 	acstatus = status & TPS65217PMIC_STATUS_ACPWR;
396 
397 	if (usbstatus != sc->sc_usbstatus) {
398 		sc->sc_usbstatus = usbstatus;
399 		pmf_event_inject(NULL, PMFE_POWER_CHANGED);
400 		if (usbstatus)
401 			aprint_normal_dev(sc->sc_dev,
402 			    "USB power source connected\n");
403 		else
404 			aprint_normal_dev(sc->sc_dev,
405 			    "USB power source disconnected\n");
406 	}
407 
408 	if (acstatus != sc->sc_acstatus) {
409 		sc->sc_acstatus = acstatus;
410 		pmf_event_inject(NULL, PMFE_POWER_CHANGED);
411 		if (acstatus) {
412 			sysmon_pswitch_event(&sc->sc_smpsw,
413 			    PSWITCH_EVENT_PRESSED);
414 		} else {
415 			sysmon_pswitch_event(&sc->sc_smpsw,
416 			    PSWITCH_EVENT_RELEASED);
417 		}
418 	}
419 
420 	mutex_exit(&sc->sc_lock);
421 
422 	callout_schedule(&sc->sc_powerpollco, hz);
423 }
424 
425 static void
426 tps65217pmic_wled_init(struct tps65217pmic_softc *sc, int isel, int fdim,
427 		       int brightness)
428 {
429 	uint8_t val = 0;
430 
431 	switch (isel) {
432 	case 1:
433 	case 2:
434 		val |= ((isel - 1) << TPS65217PMIC_WLEDCTRL1_ISEL);
435 		break;
436 	default:
437 		aprint_error_dev(sc->sc_dev,
438 		    "WLED ISET selection is 1 or 2: isel %d\n", isel);
439 		return;
440 	}
441 	switch (fdim) {
442 	case 100:
443 		val |= TPS65217PMIC_WLEDCTRL1_FDIM_100Hz;
444 		break;
445 	case 200:
446 		val |= TPS65217PMIC_WLEDCTRL1_FDIM_200Hz;
447 		break;
448 	case 500:
449 		val |= TPS65217PMIC_WLEDCTRL1_FDIM_500Hz;
450 		break;
451 	case 1000:
452 		val |= TPS65217PMIC_WLEDCTRL1_FDIM_1000Hz;
453 		break;
454 	default:
455 		aprint_error_dev(sc->sc_dev,
456 		    "WLED PWM dimming frequency is 100, 200, 500 or 1000:"
457 		    " fdim %d\n", fdim);
458 		return;
459 	}
460 	if (brightness > 100 ||
461 	    brightness < 0) {
462 		aprint_error_dev(sc->sc_dev,
463 		    "invalid brightness: between 0 and 100: %d\n", brightness);
464 		return;
465 	}
466 
467 	tps65217pmic_reg_write(sc, TPS65217PMIC_WLEDCTRL1, val);
468 	tps65217pmic_reg_write(sc, TPS65217PMIC_WLEDCTRL2,
469 	    (brightness - 1) & TPS65217PMIC_WLEDCTRL2_DUTY);
470 	val |= TPS65217PMIC_WLEDCTRL1_ISINK_EN;
471 	tps65217pmic_reg_write(sc, TPS65217PMIC_WLEDCTRL1, val);
472 }
473 
474 static void
475 tps65217pmic_reg_refresh(struct tps65217pmic_softc *sc)
476 {
477 	int i;
478 	struct tps_reg_param *c_reg;
479 
480 	for (i = 0; i < NTPS_REG; i++) {
481 		c_reg = &tps_regulators[i];
482 		tps65217pmic_regulator_read_config(sc, c_reg);
483 	}
484 }
485 
486 /* Get version and revision of the chip. */
487 static void
488 tps65217pmic_version(struct tps65217pmic_softc *sc)
489 {
490 	uint8_t chipid;
491 
492 	chipid = tps65217pmic_reg_read(sc, TPS65217PMIC_CHIPID);
493 
494 	sc->sc_version = chipid & TPS65217PMIC_CHIPID_VER_MASK;
495 	sc->sc_revision = chipid & TPS65217PMIC_CHIPID_REV_MASK;
496 }
497 
498 static uint16_t
499 tps65217pmic_ppath_max_ac_current(uint8_t ppath)
500 {
501 	switch ((ppath & TPS65217PMIC_PPATH_IAC) >>
502 	    TPS65217PMIC_PPATH_IAC_RSHFIT) {
503 	case TPS65217PMIC_PPATH_IAC_100MA:
504 		return 100;
505 	case TPS65217PMIC_PPATH_IAC_500MA:
506 		return 500;
507 	case TPS65217PMIC_PPATH_IAC_1300MA:
508 		return 1300;
509 	case TPS65217PMIC_PPATH_IAC_2500MA:
510 		return 2500;
511 	}
512 	return 0;
513 }
514 
515 static uint16_t
516 tps65217pmic_ppath_max_usb_current(uint8_t ppath)
517 {
518 	switch (ppath & TPS65217PMIC_PPATH_IUSB) {
519 	case TPS65217PMIC_PPATH_IUSB_100MA:
520 		return 100;
521 	case TPS65217PMIC_PPATH_IUSB_500MA:
522 		return 500;
523 	case TPS65217PMIC_PPATH_IUSB_1300MA:
524 		return 1300;
525 	case TPS65217PMIC_PPATH_IUSB_1800MA:
526 		return 1800;
527 	}
528 	return 0;
529 }
530 
531 /* Read regulator state and save it to tps_reg_param. */
532 static void
533 tps65217pmic_regulator_read_config(struct tps65217pmic_softc *sc, struct
534     tps_reg_param *regulator)
535 {
536 	uint8_t defreg, regenable;
537 	uint16_t voltage;
538 
539 	regenable = tps65217pmic_reg_read(sc, TPS65217PMIC_ENABLE);
540 
541 	if (regenable & (regulator->enable_bit))
542 		regulator->is_enabled = true;
543 	else {
544 		regulator->is_enabled = false;
545 		return;
546 	}
547 
548 	defreg = tps65217pmic_reg_read(sc,
549 	    regulator->defreg_num);
550 
551 	switch (regulator->nvoltages) {
552 	case 16:
553 		voltage = regulator->voltages[defreg &
554 		    TPS65217PMIC_DEFX_VOLTAGE_16];
555 		break;
556 	case 32:
557 		voltage = regulator->voltages[defreg &
558 		    TPS65217PMIC_DEFX_VOLTAGE_32];
559 		break;
560 	case 64:
561 		voltage = regulator->voltages[defreg &
562 		    TPS65217PMIC_DEFX_VOLTAGE_64];
563 		break;
564 	default:
565 		/* unsupported number of voltage settings? */
566 		voltage = 0;
567 		break;
568 	}
569 
570 	/* Handle regulator tracking other regulator voltage. */
571 	if (regulator->can_track)
572 		if (defreg & TPS65217PMIC_DEFX_TRACKING) {
573 			regulator->is_tracking = true;
574 			voltage = 0; /* see regulator->tracked_reg */
575 		}
576 
577 	/* Handle regulator configured into load switch mode. */
578 	if (regulator->can_ls)
579 		if (!(defreg & TPS65217PMIC_DEFX_LS)) {
580 			regulator->is_ls = true;
581 			voltage = 0;
582 		}
583 
584 	if (regulator->can_xadj)
585 		if (defreg & TPS65217PMIC_DEFX_XADJ) {
586 			regulator->is_xadj = true;
587 			voltage = 0;
588 
589 		}
590 
591 	/* TODO: add PGOOD checking */
592 
593 	regulator->current_voltage = voltage;
594 }
595 
596 static void
597 tps65217pmic_print_ldos(struct tps65217pmic_softc *sc)
598 {
599 	int i;
600 	struct tps_reg_param *c_reg;
601 
602 	aprint_normal_dev(sc->sc_dev, "");
603 
604 	for (i = 0; i < NTPS_REG; i++) {
605 		c_reg = &tps_regulators[i];
606 
607 		if (c_reg->is_enabled) {
608 			if (c_reg->is_ls)
609 				aprint_normal("[%s: LS] ", c_reg->name);
610 			else if (c_reg->is_xadj)
611 				aprint_normal("[%s: XADJ] ", c_reg->name);
612 			else
613 				aprint_normal("[%s: %d mV] ", c_reg->name,
614 				    c_reg->current_voltage);
615 		}
616 	}
617 	aprint_normal("\n");
618 }
619 
620 static void
621 tps65217pmic_print_ppath(struct tps65217pmic_softc *sc)
622 {
623 	uint8_t status, ppath;
624 
625 	ppath = tps65217pmic_reg_read(sc, TPS65217PMIC_PPATH);
626 	status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS);
627 
628 	aprint_normal_dev(sc->sc_dev, "power sources ");
629 
630 	if (ppath & TPS65217PMIC_PPATH_USB_EN) {
631 		if (status & TPS65217PMIC_STATUS_USBPWR)
632 			aprint_normal("[USB] ");
633 		else
634 			aprint_normal("USB ");
635 		aprint_normal("max %d mA, ",
636 		    tps65217pmic_ppath_max_usb_current(ppath));
637 	}
638 
639 	if (ppath & TPS65217PMIC_PPATH_AC_EN) {
640 		if (status & TPS65217PMIC_STATUS_ACPWR)
641 			aprint_normal("[AC] ");
642 		else
643 			aprint_normal("AC ");
644 		aprint_normal("max %d mA",
645 		    tps65217pmic_ppath_max_ac_current(ppath));
646 	}
647 
648 	aprint_normal("\n");
649 }
650 
651 static uint8_t
652 tps65217pmic_reg_read(struct tps65217pmic_softc *sc, uint8_t reg)
653 {
654 	uint8_t wbuf[2];
655 	uint8_t rv;
656 
657 	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) {
658 		aprint_error_dev(sc->sc_dev, "cannot acquire bus for read\n");
659 		return 0;
660 	}
661 
662 	wbuf[0] = reg;
663 
664 	if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, wbuf,
665 	    1, &rv, 1, I2C_F_POLL)) {
666 		aprint_error_dev(sc->sc_dev, "cannot execute operation\n");
667 		iic_release_bus(sc->sc_tag, I2C_F_POLL);
668 		return 0;
669 	}
670 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
671 
672 	return rv;
673 }
674 
675 static void
676 tps65217pmic_reg_write_unlocked(struct tps65217pmic_softc *sc,
677     uint8_t reg, uint8_t data)
678 {
679 	uint8_t wbuf[2];
680 
681 	wbuf[0] = reg;
682 	wbuf[1] = data;
683 
684 	if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, NULL, 0,
685 	    wbuf, 2, I2C_F_POLL)) {
686 		aprint_error_dev(sc->sc_dev, "cannot execute I2C write\n");
687 	}
688 }
689 
690 static void __unused
691 tps65217pmic_reg_write(struct tps65217pmic_softc *sc, uint8_t reg, uint8_t data)
692 {
693 
694 	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) {
695 		aprint_error_dev(sc->sc_dev, "cannot acquire bus for write\n");
696 		return;
697 	}
698 
699 	tps65217pmic_reg_write_unlocked(sc, reg, data);
700 
701 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
702 }
703 
704 static void
705 tps65217pmic_reg_write_l2(struct tps65217pmic_softc *sc,
706     uint8_t reg, uint8_t data)
707 {
708 	uint8_t regpw = reg ^ TPS65217PMIC_PASSWORD_XOR;
709 	if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL) != 0) {
710 		aprint_error_dev(sc->sc_dev, "cannot acquire bus for write\n");
711 		return;
712 	}
713 
714 	tps65217pmic_reg_write_unlocked(sc, TPS65217PMIC_PASSWORD, regpw);
715 	tps65217pmic_reg_write_unlocked(sc, reg, data);
716 	tps65217pmic_reg_write_unlocked(sc, TPS65217PMIC_PASSWORD, regpw);
717 	tps65217pmic_reg_write_unlocked(sc, reg, data);
718 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
719 }
720 
721 static void
722 tps65217pmic_envsys_register(struct tps65217pmic_softc *sc)
723 {
724 	int i;
725 
726 	sc->sc_sme = sysmon_envsys_create();
727 
728 	/* iterate over all regulators and attach them as sensors */
729 	for(i = 0; i <= SNUM_REGS; i++) {
730 		/* set name */
731 		strlcpy(sc->sc_regsensor[i].desc, tps_regulators[i].name,
732 		    sizeof(sc->sc_regsensor[i].desc));
733 		sc->sc_regsensor[i].units = ENVSYS_SVOLTS_DC;
734 		sc->sc_regsensor[i].state = ENVSYS_SINVALID;
735 
736 		if (sysmon_envsys_sensor_attach(sc->sc_sme,
737 		    &sc->sc_regsensor[i]))
738 			aprint_error_dev(sc->sc_dev,
739 			    "error attaching regulator sensor %d\n", i);
740 	}
741 
742 	/* attach power source indicators */
743 	strcpy(sc->sc_usbsensor.desc, "USB power source"); /* SNUM_USBSTATUS */
744 	sc->sc_usbsensor.units = ENVSYS_INDICATOR;
745 	sc->sc_usbsensor.state = ENVSYS_SINVALID;
746 	if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_usbsensor))
747 		aprint_error_dev(sc->sc_dev,
748 		    "error attaching USB power source sensor\n");
749 	strcpy(sc->sc_acsensor.desc, "AC power source"); /* SNUM_ACSTATUS */
750 	sc->sc_acsensor.units = ENVSYS_INDICATOR;
751 	sc->sc_acsensor.state = ENVSYS_SINVALID;
752 	if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_acsensor))
753 		aprint_error_dev(sc->sc_dev,
754 		    "error attaching AC power source sensor\n");
755 
756 	/* register everything in sysmon */
757 	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
758 	sc->sc_sme->sme_cookie = sc;
759 	sc->sc_sme->sme_refresh = tps65217pmic_envsys_refresh;
760 
761 	if (sysmon_envsys_register(sc->sc_sme)) {
762 		aprint_error_dev(sc->sc_dev, "unable to register in sysmon\n");
763 		sysmon_envsys_destroy(sc->sc_sme);
764 	}
765 }
766 
767 static void
768 tps65217pmic_envsys_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
769 {
770 	struct tps65217pmic_softc *sc = sme->sme_cookie;
771 
772 	mutex_enter(&sc->sc_lock);
773 
774 	tps65217pmic_reg_refresh(sc);
775 
776 	if (edata->sensor <= SNUM_REGS) {
777 		/* TODO: handle special cases like LS, XADJ... */
778 		edata->value_cur = tps_regulators[edata->sensor].current_voltage * 1000;
779 		edata->state = ENVSYS_SVALID;
780 	} else if (edata->sensor == SNUM_USBSTATUS) {
781 		edata->value_cur = sc->sc_usbstatus && sc->sc_usbenabled;
782 		edata->state = ENVSYS_SVALID;
783 	} else if (edata->sensor == SNUM_ACSTATUS) {
784 		edata->value_cur = sc->sc_acstatus && sc->sc_acenabled;
785 		edata->state = ENVSYS_SVALID;
786 	} else
787 		aprint_error_dev(sc->sc_dev, "unknown sensor number\n");
788 
789 	mutex_exit(&sc->sc_lock);
790 }
791 
792 int
793 tps65217pmic_set_volt(device_t self, const char *name, int mvolt)
794 {
795 	int i;
796 	struct tps65217pmic_softc *sc = device_private(self);
797 	struct tps_reg_param *regulator = NULL;
798 	uint8_t val;
799 
800 	for (i = 0; i < __arraycount(tps_regulators); i++) {
801 		if (strcmp(name, tps_regulators[i].name) == 0) {
802 			regulator = &tps_regulators[i];
803 			break;
804 		}
805 	}
806 	if (regulator == NULL)
807 		return EINVAL;
808 
809 	if (regulator->voltage_min > mvolt || regulator->voltage_max < mvolt)
810 		return EINVAL;
811 
812 	if (!regulator->is_enabled)
813 		return EINVAL;
814 
815 	if (regulator->is_tracking)
816 		return EINVAL;
817 
818 	if (regulator->is_xadj)
819 		return EINVAL;
820 
821 	/* find closest voltage entry */
822 	for (i = 0; i < regulator->nvoltages; i++) {
823 		if (mvolt <= regulator->voltages[i]) {
824 			break;
825 		}
826 	}
827 	KASSERT(i < regulator->nvoltages);
828 	tps65217pmic_reg_write_l2(sc, regulator->defreg_num, i);
829 
830 	val = tps65217pmic_reg_read(sc, TPS65217PMIC_DEFSLEW);
831 	val |= TPS65217PMIC_DEFSLEW_GO;
832 	tps65217pmic_reg_write_l2(sc, TPS65217PMIC_DEFSLEW, val);
833 
834 	while (val & TPS65217PMIC_DEFSLEW_GO) {
835 		val = tps65217pmic_reg_read(sc, TPS65217PMIC_DEFSLEW);
836 	}
837 	return 0;
838 }
839