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