nslm7x.c revision 1.35 1 /* $NetBSD: nslm7x.c,v 1.35 2007/04/19 20:24:47 xtraeme Exp $ */
2
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Bill Squier.
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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.35 2007/04/19 20:24:47 xtraeme Exp $");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/proc.h>
46 #include <sys/device.h>
47 #include <sys/conf.h>
48 #include <sys/time.h>
49
50 #include <machine/bus.h>
51
52 #include <dev/isa/isareg.h>
53 #include <dev/isa/isavar.h>
54
55 #include <dev/sysmon/sysmonvar.h>
56
57 #include <dev/ic/nslm7xvar.h>
58
59 #include <machine/intr.h>
60
61 #if defined(LMDEBUG)
62 #define DPRINTF(x) do { printf x; } while (0)
63 #else
64 #define DPRINTF(x)
65 #endif
66
67 /*
68 * LM78-compatible chips can typically measure voltages up to 4.096 V.
69 * To measure higher voltages the input is attenuated with (external)
70 * resistors. Negative voltages are measured using inverting op amps
71 * and resistors. So we have to convert the sensor values back to
72 * real voltages by applying the appropriate resistor factor.
73 */
74 #define RFACT_NONE 10000
75 #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
76 #define NRFACT(x, y) (-RFACT_NONE * (x) / (y))
77
78 const struct envsys_range lm_ranges[] = { /* sc->sensors sub-intervals */
79 /* for each unit type */
80 { 7, 7, ENVSYS_STEMP },
81 { 8, 10, ENVSYS_SFANRPM },
82 { 1, 0, ENVSYS_SVOLTS_AC }, /* None */
83 { 0, 6, ENVSYS_SVOLTS_DC },
84 { 1, 0, ENVSYS_SOHMS }, /* None */
85 { 1, 0, ENVSYS_SWATTS }, /* None */
86 { 1, 0, ENVSYS_SAMPS } /* None */
87 };
88
89 static int lm_match(struct lm_softc *);
90 static int wb_match(struct lm_softc *);
91 static int def_match(struct lm_softc *);
92
93 static void lm_generic_banksel(struct lm_softc *, int);
94 static void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
95
96 static void lm_refresh_sensor_data(struct lm_softc *);
97 static void lm_refresh_volt(struct lm_softc *, int);
98 static void lm_refresh_temp(struct lm_softc *, int);
99 static void lm_refresh_fanrpm(struct lm_softc *, int);
100
101 static void wb_refresh_sensor_data(struct lm_softc *);
102 static void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
103 static void wb_refresh_nvolt(struct lm_softc *, int);
104 static void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
105 static void wb_refresh_temp(struct lm_softc *, int);
106 static void wb_refresh_fanrpm(struct lm_softc *, int);
107 static void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
108
109 static void as_refresh_temp(struct lm_softc *, int);
110
111 static int lm_gtredata(struct sysmon_envsys *, struct envsys_tre_data *);
112 static int generic_streinfo_fan(struct lm_softc *, struct envsys_basic_info *,
113 int, struct envsys_basic_info *);
114 static int lm_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
115 static int wb781_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
116 static int wb782_streinfo(struct sysmon_envsys *, struct envsys_basic_info *);
117
118 struct lm_chip {
119 int (*chip_match)(struct lm_softc *);
120 };
121
122 static struct lm_chip lm_chips[] = {
123 { wb_match },
124 { lm_match },
125 { def_match } /* Must be last */
126 };
127
128 /* LM78/78J/79/81 */
129 static struct lm_sensor lm78_sensors[] = {
130 /* Voltage */
131 {
132 .desc = "VCore A",
133 .type = ENVSYS_SVOLTS_DC,
134 .bank = 0,
135 .reg = 0x20,
136 .refresh = lm_refresh_volt,
137 .rfact = RFACT_NONE
138 },
139 {
140 .desc = "VCore B",
141 .type = ENVSYS_SVOLTS_DC,
142 .bank = 0,
143 .reg = 0x21,
144 .refresh = lm_refresh_volt,
145 .rfact = RFACT_NONE
146 },
147 {
148 .desc = "+3.3V",
149 .type = ENVSYS_SVOLTS_DC,
150 .bank = 0,
151 .reg = 0x22,
152 .refresh = lm_refresh_volt,
153 .rfact = RFACT_NONE
154 },
155 {
156 .desc = "+5V",
157 .type = ENVSYS_SVOLTS_DC,
158 .bank = 0,
159 .reg = 0x23,
160 .refresh = lm_refresh_volt,
161 .rfact = RFACT(68, 100)
162 },
163 {
164 .desc = "+12V",
165 .type = ENVSYS_SVOLTS_DC,
166 .bank = 0,
167 .reg = 0x24,
168 .refresh = lm_refresh_volt,
169 .rfact = RFACT(30, 10)
170 },
171 {
172 .desc = "-12V",
173 .type = ENVSYS_SVOLTS_DC,
174 .bank = 0,
175 .reg = 0x25,
176 .refresh = lm_refresh_volt,
177 .rfact = NRFACT(240, 60)
178 },
179 {
180 .desc = "-5V",
181 .type = ENVSYS_SVOLTS_DC,
182 .bank = 0,
183 .reg = 0x26,
184 .refresh = lm_refresh_volt,
185 .rfact = NRFACT(100, 60)
186 },
187
188 /* Temperature */
189 {
190 .desc = "Temp0",
191 .type = ENVSYS_STEMP,
192 .bank = 0,
193 .reg = 0x27,
194 .refresh = lm_refresh_temp,
195 .rfact = 0
196 },
197
198 /* Fans */
199 {
200 .desc = "Fan0",
201 .type = ENVSYS_SFANRPM,
202 .bank = 0,
203 .reg = 0x28,
204 .refresh = lm_refresh_fanrpm,
205 .rfact = 0
206 },
207 {
208 .desc = "Fan1",
209 .type = ENVSYS_SFANRPM,
210 .bank = 0,
211 .reg = 0x29,
212 .refresh = lm_refresh_fanrpm,
213 .rfact = 0
214 },
215 {
216 .desc = "Fan2",
217 .type = ENVSYS_SFANRPM,
218 .bank = 0,
219 .reg = 0x2a,
220 .refresh = lm_refresh_fanrpm,
221 .rfact = 0
222 },
223
224 { .desc = NULL }
225 };
226
227 /* W83627HF */
228 static struct lm_sensor w83627hf_sensors[] = {
229 /* Voltage */
230 {
231 .desc = "VCore A",
232 .type = ENVSYS_SVOLTS_DC,
233 .bank = 0,
234 .reg = 0x20,
235 .refresh = lm_refresh_volt,
236 .rfact = RFACT_NONE
237 },
238 {
239 .desc = "VCore B",
240 .type = ENVSYS_SVOLTS_DC,
241 .bank = 0,
242 .reg = 0x21,
243 .refresh = lm_refresh_volt,
244 .rfact = RFACT_NONE
245 },
246 {
247 .desc = "+3.3V",
248 .type = ENVSYS_SVOLTS_DC,
249 .bank = 0,
250 .reg = 0x22,
251 .refresh = lm_refresh_volt,
252 .rfact = RFACT_NONE
253 },
254 {
255 .desc = "+5V",
256 .type = ENVSYS_SVOLTS_DC,
257 .bank = 0,
258 .reg = 0x23,
259 .refresh = lm_refresh_volt,
260 .rfact = RFACT(34, 50)
261 },
262 {
263 .desc = "+12V",
264 .type = ENVSYS_SVOLTS_DC,
265 .bank = 0,
266 .reg = 0x24,
267 .refresh = lm_refresh_volt,
268 .rfact = RFACT(28, 10)
269 },
270 {
271 .desc = "-12V",
272 .type = ENVSYS_SVOLTS_DC,
273 .bank = 0,
274 .reg = 0x25,
275 .refresh = wb_refresh_nvolt,
276 .rfact = RFACT(232, 56)
277 },
278 {
279 .desc = "-5V",
280 .type = ENVSYS_SVOLTS_DC,
281 .bank = 0,
282 .reg = 0x26,
283 .refresh = wb_refresh_nvolt,
284 .rfact = RFACT(120, 56)
285 },
286 {
287 .desc = "5VSB",
288 .type = ENVSYS_SVOLTS_DC,
289 .bank = 5,
290 .reg = 0x50,
291 .refresh = lm_refresh_volt,
292 .rfact = RFACT(17, 33)
293 },
294 {
295 .desc = "VBAT",
296 .type = ENVSYS_SVOLTS_DC,
297 .bank = 5,
298 .reg = 0x51,
299 .refresh = lm_refresh_volt,
300 .rfact = RFACT_NONE
301 },
302
303 /* Temperature */
304 {
305 .desc = "Temp0",
306 .type = ENVSYS_STEMP,
307 .bank = 0,
308 .reg = 0x27,
309 .refresh = lm_refresh_temp,
310 .rfact = 0
311 },
312 {
313 .desc = "Temp1",
314 .type = ENVSYS_STEMP,
315 .bank = 1,
316 .reg = 0x50,
317 .refresh = wb_refresh_temp,
318 .rfact = 0
319 },
320 {
321 .desc = "Temp2",
322 .type = ENVSYS_STEMP,
323 .bank = 2,
324 .reg = 0x50,
325 .refresh = wb_refresh_temp,
326 .rfact = 0
327 },
328
329 /* Fans */
330 {
331 .desc = "Fan0",
332 .type = ENVSYS_SFANRPM,
333 .bank = 0,
334 .reg = 0x28,
335 .refresh = wb_refresh_fanrpm,
336 .rfact = 0
337 },
338 {
339 .desc = "Fan1",
340 .type = ENVSYS_SFANRPM,
341 .bank = 0,
342 .reg = 0x29,
343 .refresh = wb_refresh_fanrpm,
344 .rfact = 0
345 },
346 {
347 .desc = "Fan2",
348 .type = ENVSYS_SFANRPM,
349 .bank = 0,
350 .reg = 0x2a,
351 .refresh = wb_refresh_fanrpm,
352 .rfact = 0
353 },
354
355 { .desc = NULL }
356 };
357
358 /* W8627EHF */
359
360 /*
361 * The W83627EHF can measure voltages up to 2.048 V instead of the
362 * traditional 4.096 V. For measuring positive voltages, this can be
363 * accounted for by halving the resistor factor. Negative voltages
364 * need special treatment, also because the reference voltage is 2.048 V
365 * instead of the traditional 3.6 V.
366 */
367 static struct lm_sensor w83627ehf_sensors[] = {
368 /* Voltage */
369 {
370 .desc = "VCore",
371 .type = ENVSYS_SVOLTS_DC,
372 .bank = 0,
373 .reg = 0x20,
374 .refresh = lm_refresh_volt,
375 .rfact = RFACT_NONE / 2
376 },
377 {
378 .desc = "+12V",
379 .type = ENVSYS_SVOLTS_DC,
380 .bank = 0,
381 .reg = 0x21,
382 .refresh = lm_refresh_volt,
383 .rfact = RFACT(56, 10) / 2
384 },
385 {
386 .desc = "+3.3V",
387 .type = ENVSYS_SVOLTS_DC,
388 .bank = 0,
389 .reg = 0x22,
390 .refresh = lm_refresh_volt,
391 .rfact = RFACT(34, 34) / 2
392 },
393 {
394 .desc = "+3.3V",
395 .type = ENVSYS_SVOLTS_DC,
396 .bank = 0,
397 .reg = 0x23,
398 .refresh = lm_refresh_volt,
399 .rfact = RFACT(34, 24) / 2
400 },
401 {
402 .desc = "-12V",
403 .type = ENVSYS_SVOLTS_DC,
404 .bank = 0,
405 .reg = 0x24,
406 .refresh = wb_w83627ehf_refresh_nvolt,
407 .rfact = 0
408 },
409 {
410 .desc = "Unknown",
411 .type = ENVSYS_SVOLTS_DC,
412 .bank = 0,
413 .reg = 0x25,
414 .refresh = lm_refresh_volt,
415 .rfact = RFACT_NONE / 2
416 },
417 {
418 .desc = "Unknown",
419 .type = ENVSYS_SVOLTS_DC,
420 .bank = 0,
421 .reg = 0x26,
422 .refresh = lm_refresh_volt,
423 .rfact = RFACT_NONE / 2
424 },
425 {
426 .desc = "3.3VSB",
427 .type = ENVSYS_SVOLTS_DC,
428 .bank = 5,
429 .reg = 0x50,
430 .refresh = lm_refresh_volt,
431 .rfact = RFACT(34, 34) / 2
432 },
433 {
434 .desc = "VBAT",
435 .type = ENVSYS_SVOLTS_DC,
436 .bank = 5,
437 .reg = 0x51,
438 .refresh = lm_refresh_volt,
439 .rfact = RFACT_NONE / 2
440 },
441 {
442 .desc = "Unknown",
443 .type = ENVSYS_SVOLTS_DC,
444 .bank = 5,
445 .reg = 0x52,
446 .refresh = lm_refresh_volt,
447 .rfact = RFACT_NONE / 2
448 },
449
450 /* Temperature */
451 {
452 .desc = "Temp0",
453 .type = ENVSYS_STEMP,
454 .bank = 0,
455 .reg = 0x27,
456 .refresh = lm_refresh_temp,
457 .rfact = 0
458 },
459 {
460 .desc = "Temp1",
461 .type = ENVSYS_STEMP,
462 .bank = 1,
463 .reg = 0x50,
464 .refresh = wb_refresh_temp,
465 .rfact = 0
466 },
467 {
468 .desc = "Temp2",
469 .type = ENVSYS_STEMP,
470 .bank = 2,
471 .reg = 0x50,
472 .refresh = wb_refresh_temp,
473 .rfact = 0
474 },
475
476 /* Fans */
477 {
478 .desc = "Fan0",
479 .type = ENVSYS_SFANRPM,
480 .bank = 0,
481 .reg = 0x28,
482 .refresh = wb_refresh_fanrpm,
483 .rfact = 0
484 },
485 {
486 .desc = "Fan1",
487 .type = ENVSYS_SFANRPM,
488 .bank = 0,
489 .reg = 0x29,
490 .refresh = wb_refresh_fanrpm,
491 .rfact = 0
492 },
493 {
494 .desc = "Fan2",
495 .type = ENVSYS_SFANRPM,
496 .bank = 0,
497 .reg = 0x2a,
498 .refresh = wb_refresh_fanrpm,
499 .rfact = 0
500 },
501
502 { .desc = NULL }
503 };
504
505 /* W83627DHG */
506 static struct lm_sensor w83627dhg_sensors[] = {
507 /* Voltage */
508 {
509 .desc = "VCore",
510 .type = ENVSYS_SVOLTS_DC,
511 .bank = 0,
512 .reg = 0x20,
513 .refresh = lm_refresh_volt,
514 .rfact = RFACT_NONE / 2
515 },
516 {
517 .desc = "+12V",
518 .type = ENVSYS_SVOLTS_DC,
519 .bank = 0,
520 .reg = 0x21,
521 .refresh = lm_refresh_volt,
522 .rfact = RFACT(56, 10) / 2
523 },
524 {
525 .desc = "+3.3V",
526 .type = ENVSYS_SVOLTS_DC,
527 .bank = 0,
528 .reg = 0x22,
529 .refresh = lm_refresh_volt,
530 .rfact = RFACT_NONE
531 },
532 {
533 .desc = "AVCC",
534 .type = ENVSYS_SVOLTS_DC,
535 .bank = 0,
536 .reg = 0x23,
537 .refresh = lm_refresh_volt,
538 .rfact = RFACT_NONE
539 },
540 {
541 .desc = "+5V",
542 .type = ENVSYS_SVOLTS_DC,
543 .bank = 0,
544 .reg = 0x25,
545 .refresh = lm_refresh_volt,
546 .rfact = RFACT(32, 56)
547 },
548 /*
549 * I'm not sure about which one is -12V or -5V.
550 */
551 #if 0
552 {
553 .desc = "-12V",
554 .type = ENVSYS_SVOLTS_DC,
555 .bank = 0,
556 .reg = 0x24,
557 .refresh = wb_refresh_nvolt,
558 .rfact = RFACT(232, 60)
559 },
560 {
561 .desc = "-5V",
562 .type = ENVSYS_SVOLTS_DC,
563 .bank = 0,
564 .reg = 0x26,
565 .refresh = wb_w83627ehf_refresh_nvolt
566 .rfact = 0
567 },
568 #endif
569 {
570 .desc = "+3.3VSB",
571 .type = ENVSYS_SVOLTS_DC,
572 .bank = 5,
573 .reg = 0x50,
574 .refresh = lm_refresh_volt,
575 .rfact = RFACT_NONE
576 },
577 {
578 .desc = "VBAT",
579 .type = ENVSYS_SVOLTS_DC,
580 .bank = 5,
581 .reg = 0x51,
582 .refresh = lm_refresh_volt,
583 .rfact = RFACT_NONE
584 },
585
586 /* Temperature */
587 {
588 .desc = "System Temp",
589 .type = ENVSYS_STEMP,
590 .bank = 0,
591 .reg = 0x27,
592 .refresh = lm_refresh_temp,
593 .rfact = 0
594 },
595 {
596 .desc = "CPU Temp",
597 .type = ENVSYS_STEMP,
598 .bank = 1,
599 .reg = 0x50,
600 .refresh = wb_refresh_temp,
601 .rfact = 0
602 },
603 {
604 .desc = "Aux Temp",
605 .type = ENVSYS_STEMP,
606 .bank = 2,
607 .reg = 0x50,
608 .refresh = wb_refresh_temp,
609 .rfact = 0
610 },
611
612 /* Fans */
613 {
614 .desc = "System Fan",
615 .type = ENVSYS_SFANRPM,
616 .bank = 0,
617 .reg = 0x28,
618 .refresh = wb_refresh_fanrpm,
619 .rfact = 0
620 },
621 {
622 .desc = "CPU Fan",
623 .type = ENVSYS_SFANRPM,
624 .bank = 0,
625 .reg = 0x29,
626 .refresh = wb_refresh_fanrpm,
627 .rfact = 0
628 },
629 {
630 .desc = "Aux Fan",
631 .type = ENVSYS_SFANRPM,
632 .bank = 0,
633 .reg = 0x2a,
634 .refresh = wb_refresh_fanrpm,
635 .rfact = 0
636 },
637
638 { .desc = NULL }
639 };
640
641 /* W83637HF */
642 static struct lm_sensor w83637hf_sensors[] = {
643 /* Voltage */
644 {
645 .desc = "VCore",
646 .type = ENVSYS_SVOLTS_DC,
647 .bank = 0,
648 .reg = 0x20,
649 .refresh = wb_w83637hf_refresh_vcore,
650 .rfact = 0
651 },
652 {
653 .desc = "+12V",
654 .type = ENVSYS_SVOLTS_DC,
655 .bank = 0,
656 .reg = 0x21,
657 .refresh = lm_refresh_volt,
658 .rfact = RFACT(28, 10)
659 },
660 {
661 .desc = "+3.3V",
662 .type = ENVSYS_SVOLTS_DC,
663 .bank = 0,
664 .reg = 0x22,
665 .refresh = lm_refresh_volt,
666 .rfact = RFACT_NONE
667 },
668 {
669 .desc = "+5V",
670 .type = ENVSYS_SVOLTS_DC,
671 .bank = 0,
672 .reg = 0x23,
673 .refresh = lm_refresh_volt,
674 .rfact = RFACT(34, 51)
675 },
676 {
677 .desc = "-12V",
678 .type = ENVSYS_SVOLTS_DC,
679 .bank = 0,
680 .reg = 0x24,
681 .refresh = wb_refresh_nvolt,
682 .rfact = RFACT(232, 56)
683 },
684 {
685 .desc = "5VSB",
686 .type = ENVSYS_SVOLTS_DC,
687 .bank = 5,
688 .reg = 0x50,
689 .refresh = lm_refresh_volt,
690 .rfact = RFACT(34, 51)
691 },
692 {
693 .desc = "VBAT",
694 .type = ENVSYS_SVOLTS_DC,
695 .bank = 5,
696 .reg = 0x51,
697 .refresh = lm_refresh_volt,
698 .rfact = RFACT_NONE
699 },
700
701 /* Temperature */
702 {
703 .desc = "Temp0",
704 .type = ENVSYS_STEMP,
705 .bank = 0,
706 .reg = 0x27,
707 .refresh = lm_refresh_temp,
708 .rfact = 0
709 },
710 {
711 .desc = "Temp1",
712 .type = ENVSYS_STEMP,
713 .bank = 1,
714 .reg = 0x50,
715 .refresh = wb_refresh_temp,
716 .rfact = 0
717 },
718 {
719 .desc = "Temp2",
720 .type = ENVSYS_STEMP,
721 .bank = 2,
722 .reg = 0x50,
723 .refresh = wb_refresh_temp,
724 .rfact = 0
725 },
726
727 /* Fans */
728 {
729 .desc = "Fan0",
730 .type = ENVSYS_SFANRPM,
731 .bank = 0,
732 .reg = 0x28,
733 .refresh = wb_refresh_fanrpm,
734 .rfact = 0
735 },
736 {
737 .desc = "Fan1",
738 .type = ENVSYS_SFANRPM,
739 .bank = 0,
740 .reg = 0x29,
741 .refresh = wb_refresh_fanrpm,
742 .rfact = 0
743 },
744 {
745 .desc = "Fan2",
746 .type = ENVSYS_SFANRPM,
747 .bank = 0,
748 .reg = 0x2a,
749 .refresh = wb_refresh_fanrpm,
750 .rfact = 0
751 },
752
753 { .desc = NULL }
754 };
755
756 /* W83697HF */
757 static struct lm_sensor w83697hf_sensors[] = {
758 /* Voltage */
759 {
760 .desc = "VCore",
761 .type = ENVSYS_SVOLTS_DC,
762 .bank = 0,
763 .reg = 0x20,
764 .refresh = lm_refresh_volt,
765 .rfact = RFACT_NONE
766 },
767 {
768 .desc = "+3.3V",
769 .type = ENVSYS_SVOLTS_DC,
770 .bank = 0,
771 .reg = 0x22,
772 .refresh = lm_refresh_volt,
773 .rfact = RFACT_NONE
774 },
775 {
776 .desc = "+5V",
777 .type = ENVSYS_SVOLTS_DC,
778 .bank = 0,
779 .reg = 0x23,
780 .refresh = lm_refresh_volt,
781 .rfact = RFACT(34, 50)
782 },
783 {
784 .desc = "+12V",
785 .type = ENVSYS_SVOLTS_DC,
786 .bank = 0,
787 .reg = 0x24,
788 .refresh = lm_refresh_volt,
789 .rfact = RFACT(28, 10)
790 },
791 {
792 .desc = "-12V",
793 .type = ENVSYS_SVOLTS_DC,
794 .bank = 0,
795 .reg = 0x25,
796 .refresh = wb_refresh_nvolt,
797 .rfact = RFACT(232, 56)
798 },
799 {
800 .desc = "-5V",
801 .type = ENVSYS_SVOLTS_DC,
802 .bank = 0,
803 .reg = 0x26,
804 .refresh = wb_refresh_nvolt,
805 .rfact = RFACT(120, 56)
806 },
807 {
808 .desc = "5VSB",
809 .type = ENVSYS_SVOLTS_DC,
810 .bank = 5,
811 .reg = 0x50,
812 .refresh = lm_refresh_volt,
813 .rfact = RFACT(17, 33)
814 },
815 {
816 .desc = "VBAT",
817 .type = ENVSYS_SVOLTS_DC,
818 .bank = 5,
819 .reg = 0x51,
820 .refresh = lm_refresh_volt,
821 .rfact = RFACT_NONE
822 },
823
824 /* Temperature */
825 {
826 .desc = "Temp0",
827 .type = ENVSYS_STEMP,
828 .bank = 0,
829 .reg = 0x27,
830 .refresh = lm_refresh_temp,
831 .rfact = 0
832 },
833 {
834 .desc = "Temp1",
835 .type = ENVSYS_STEMP,
836 .bank = 1,
837 .reg = 0x50,
838 .refresh = wb_refresh_temp,
839 .rfact = 0
840 },
841
842 /* Fans */
843 {
844 .desc = "Fan0",
845 .type = ENVSYS_SFANRPM,
846 .bank = 0,
847 .reg = 0x28,
848 .refresh = wb_refresh_fanrpm,
849 .rfact = 0
850 },
851 {
852 .desc = "Fan1",
853 .type = ENVSYS_SFANRPM,
854 .bank = 0,
855 .reg = 0x29,
856 .refresh = wb_refresh_fanrpm,
857 .rfact = 0
858 },
859
860 { .desc = NULL }
861 };
862
863 /* W83781D */
864
865 /*
866 * The datasheet doesn't mention the (internal) resistors used for the
867 * +5V, but using the values from the W83782D datasheets seems to
868 * provide sensible results.
869 */
870 static struct lm_sensor w83781d_sensors[] = {
871 /* Voltage */
872 {
873 .desc = "VCore A",
874 .type = ENVSYS_SVOLTS_DC,
875 .bank = 0,
876 .reg = 0x20,
877 .refresh = lm_refresh_volt,
878 .rfact = RFACT_NONE
879 },
880 {
881 .desc = "VCore B",
882 .type = ENVSYS_SVOLTS_DC,
883 .bank = 0,
884 .reg = 0x21,
885 .refresh = lm_refresh_volt,
886 .rfact = RFACT_NONE
887 },
888 {
889 .desc = "+3.3V",
890 .type = ENVSYS_SVOLTS_DC,
891 .bank = 0,
892 .reg = 0x22,
893 .refresh = lm_refresh_volt,
894 .rfact = RFACT_NONE
895 },
896 {
897 .desc = "+5V",
898 .type = ENVSYS_SVOLTS_DC,
899 .bank = 0,
900 .reg = 0x23,
901 .refresh = lm_refresh_volt,
902 .rfact = RFACT(34, 50)
903 },
904 {
905 .desc = "+12V",
906 .type = ENVSYS_SVOLTS_DC,
907 .bank = 0,
908 .reg = 0x24,
909 .refresh = lm_refresh_volt,
910 .rfact = RFACT(28, 10)
911 },
912 {
913 .desc = "-12V",
914 .type = ENVSYS_SVOLTS_DC,
915 .bank = 0,
916 .reg = 0x25,
917 .refresh = lm_refresh_volt,
918 .rfact = NRFACT(2100, 604)
919 },
920 {
921 .desc = "-5V",
922 .type = ENVSYS_SVOLTS_DC,
923 .bank = 0,
924 .reg = 0x26,
925 .refresh = lm_refresh_volt,
926 .rfact = NRFACT(909, 604)
927 },
928
929 /* Temperature */
930 {
931 .desc = "Temp0",
932 .type = ENVSYS_STEMP,
933 .bank = 0,
934 .reg = 0x27,
935 .refresh = lm_refresh_temp,
936 .rfact = 0
937 },
938 {
939 .desc = "Temp1",
940 .type = ENVSYS_STEMP,
941 .bank = 1,
942 .reg = 0x50,
943 .refresh = wb_refresh_temp,
944 .rfact = 0
945 },
946 {
947 .desc = "Temp2",
948 .type = ENVSYS_STEMP,
949 .bank = 2,
950 .reg = 0x50,
951 .refresh = wb_refresh_temp,
952 .rfact = 0
953 },
954
955 /* Fans */
956 {
957 .desc = "Fan0",
958 .type = ENVSYS_SFANRPM,
959 .bank = 0,
960 .reg = 0x28,
961 .refresh = lm_refresh_fanrpm,
962 .rfact = 0
963 },
964 {
965 .desc = "Fan1",
966 .type = ENVSYS_SFANRPM,
967 .bank = 0,
968 .reg = 0x29,
969 .refresh = lm_refresh_fanrpm,
970 .rfact = 0
971 },
972 {
973 .desc = "Fan2",
974 .type = ENVSYS_SFANRPM,
975 .bank = 0,
976 .reg = 0x2a,
977 .refresh = lm_refresh_fanrpm,
978 .rfact = 0
979 },
980
981 { .desc = NULL }
982 };
983
984 /* W83782D */
985 static struct lm_sensor w83782d_sensors[] = {
986 /* Voltage */
987 {
988 .desc = "VCore",
989 .type = ENVSYS_SVOLTS_DC,
990 .bank = 0,
991 .reg = 0x20,
992 .refresh = lm_refresh_volt,
993 .rfact = RFACT_NONE
994 },
995 {
996 .desc = "VINR0",
997 .type = ENVSYS_SVOLTS_DC,
998 .bank = 0,
999 .reg = 0x21,
1000 .refresh = lm_refresh_volt,
1001 .rfact = RFACT_NONE
1002 },
1003 {
1004 .desc = "+3.3V",
1005 .type = ENVSYS_SVOLTS_DC,
1006 .bank = 0,
1007 .reg = 0x22,
1008 .refresh = lm_refresh_volt,
1009 .rfact = RFACT_NONE
1010 },
1011 {
1012 .desc = "+5V",
1013 .type = ENVSYS_SVOLTS_DC,
1014 .bank = 0,
1015 .reg = 0x23,
1016 .refresh = lm_refresh_volt,
1017 .rfact = RFACT(34, 50)
1018 },
1019 {
1020 .desc = "+12V",
1021 .type = ENVSYS_SVOLTS_DC,
1022 .bank = 0,
1023 .reg = 0x24,
1024 .refresh = lm_refresh_volt,
1025 .rfact = RFACT(28, 10)
1026 },
1027 {
1028 .desc = "-12V",
1029 .type = ENVSYS_SVOLTS_DC,
1030 .bank = 0,
1031 .reg = 0x25,
1032 .refresh = wb_refresh_nvolt,
1033 .rfact = RFACT(232, 56)
1034 },
1035 {
1036 .desc = "-5V",
1037 .type = ENVSYS_SVOLTS_DC,
1038 .bank = 0,
1039 .reg = 0x26,
1040 .refresh = wb_refresh_nvolt,
1041 .rfact = RFACT(120, 56)
1042 },
1043 {
1044 .desc = "5VSB",
1045 .type = ENVSYS_SVOLTS_DC,
1046 .bank = 5,
1047 .reg = 0x50,
1048 .refresh = lm_refresh_volt,
1049 .rfact = RFACT(17, 33)
1050 },
1051 {
1052 .desc = "VBAT",
1053 .type = ENVSYS_SVOLTS_DC,
1054 .bank = 5,
1055 .reg = 0x51,
1056 .refresh = lm_refresh_volt,
1057 .rfact = RFACT_NONE
1058 },
1059
1060 /* Temperature */
1061 {
1062 .desc = "Temp0",
1063 .type = ENVSYS_STEMP,
1064 .bank = 0,
1065 .reg = 0x27,
1066 .refresh = lm_refresh_temp,
1067 .rfact = 0
1068 },
1069 {
1070 .desc = "Temp1",
1071 .type = ENVSYS_STEMP,
1072 .bank = 1,
1073 .reg = 0x50,
1074 .refresh = wb_refresh_temp,
1075 .rfact = 0
1076 },
1077 {
1078 .desc = "Temp2",
1079 .type = ENVSYS_STEMP,
1080 .bank = 2,
1081 .reg = 0x50,
1082 .refresh = wb_refresh_temp,
1083 .rfact = 0
1084 },
1085
1086 /* Fans */
1087 {
1088 .desc = "Fan0",
1089 .type = ENVSYS_SFANRPM,
1090 .bank = 0,
1091 .reg = 0x28,
1092 .refresh = wb_refresh_fanrpm,
1093 .rfact = 0
1094 },
1095 {
1096 .desc = "Fan1",
1097 .type = ENVSYS_SFANRPM,
1098 .bank = 0,
1099 .reg = 0x29,
1100 .refresh = wb_refresh_fanrpm,
1101 .rfact = 0
1102 },
1103 {
1104 .desc = "Fan2",
1105 .type = ENVSYS_SFANRPM,
1106 .bank = 0,
1107 .reg = 0x2a,
1108 .refresh = wb_refresh_fanrpm,
1109 .rfact = 0
1110 },
1111
1112 { .desc = NULL }
1113 };
1114
1115 /* W83783S */
1116 static struct lm_sensor w83783s_sensors[] = {
1117 /* Voltage */
1118 {
1119 .desc = "VCore",
1120 .type = ENVSYS_SVOLTS_DC,
1121 .bank = 0,
1122 .reg = 0x20,
1123 .refresh = lm_refresh_volt,
1124 .rfact = RFACT_NONE
1125 },
1126 {
1127 .desc = "+3.3V",
1128 .type = ENVSYS_SVOLTS_DC,
1129 .bank = 0,
1130 .reg = 0x22,
1131 .refresh = lm_refresh_volt,
1132 .rfact = RFACT_NONE
1133 },
1134 {
1135 .desc = "+5V",
1136 .type = ENVSYS_SVOLTS_DC,
1137 .bank = 0,
1138 .reg = 0x23,
1139 .refresh = lm_refresh_volt,
1140 .rfact = RFACT(34, 50)
1141 },
1142 {
1143 .desc = "+12V",
1144 .type = ENVSYS_SVOLTS_DC,
1145 .bank = 0,
1146 .reg = 0x24,
1147 .refresh = lm_refresh_volt,
1148 .rfact = RFACT(28, 10)
1149 },
1150 {
1151 .desc = "-12V",
1152 .type = ENVSYS_SVOLTS_DC,
1153 .bank = 0,
1154 .reg = 0x25,
1155 .refresh = wb_refresh_nvolt,
1156 .rfact = RFACT(232, 56)
1157 },
1158 {
1159 .desc = "-5V",
1160 .type = ENVSYS_SVOLTS_DC,
1161 .bank = 0,
1162 .reg = 0x26,
1163 .refresh = wb_refresh_nvolt,
1164 .rfact = RFACT(120, 56)
1165 },
1166
1167 /* Temperature */
1168 {
1169 .desc = "Temp0",
1170 .type = ENVSYS_STEMP,
1171 .bank = 0,
1172 .reg = 0x27,
1173 .refresh = lm_refresh_temp,
1174 .rfact = 0
1175 },
1176 {
1177 .desc = "Temp1",
1178 .type = ENVSYS_STEMP,
1179 .bank = 1,
1180 .reg = 0x50,
1181 .refresh = wb_refresh_temp,
1182 .rfact = 0
1183 },
1184
1185 /* Fans */
1186 {
1187 .desc = "Fan0",
1188 .type = ENVSYS_SFANRPM,
1189 .bank = 0,
1190 .reg = 0x28,
1191 .refresh = wb_refresh_fanrpm,
1192 .rfact = 0
1193 },
1194 {
1195 .desc = "Fan1",
1196 .type = ENVSYS_SFANRPM,
1197 .bank = 0,
1198 .reg = 0x29,
1199 .refresh = wb_refresh_fanrpm,
1200 .rfact = 0
1201 },
1202 {
1203 .desc = "Fan2",
1204 .type = ENVSYS_SFANRPM,
1205 .bank = 0,
1206 .reg = 0x2a,
1207 .refresh = wb_refresh_fanrpm,
1208 .rfact = 0
1209 },
1210
1211 { .desc = NULL }
1212 };
1213
1214 /* W83791D */
1215 static struct lm_sensor w83791d_sensors[] = {
1216 /* Voltage */
1217 {
1218 .desc = "VCore",
1219 .type = ENVSYS_SVOLTS_DC,
1220 .bank = 0,
1221 .reg = 0x20,
1222 .refresh = lm_refresh_volt,
1223 .rfact = 10000
1224 },
1225 {
1226 .desc = "VINR0",
1227 .type = ENVSYS_SVOLTS_DC,
1228 .bank = 0,
1229 .reg = 0x21,
1230 .refresh = lm_refresh_volt,
1231 .rfact = 10000
1232 },
1233 {
1234 .desc = "+3.3V",
1235 .type = ENVSYS_SVOLTS_DC,
1236 .bank = 0,
1237 .reg = 0x22,
1238 .refresh = lm_refresh_volt,
1239 .rfact = 10000
1240 },
1241 {
1242 .desc = "+5V",
1243 .type = ENVSYS_SVOLTS_DC,
1244 .bank = 0,
1245 .reg = 0x23,
1246 .refresh = lm_refresh_volt,
1247 .rfact = RFACT(34, 50)
1248 },
1249 {
1250 .desc = "+12V",
1251 .type = ENVSYS_SVOLTS_DC,
1252 .bank = 0,
1253 .reg = 0x24,
1254 .refresh = lm_refresh_volt,
1255 .rfact = RFACT(28, 10)
1256 },
1257 {
1258 .desc = "-12V",
1259 .type = ENVSYS_SVOLTS_DC,
1260 .bank = 0,
1261 .reg = 0x25,
1262 .refresh = wb_refresh_nvolt,
1263 .rfact = RFACT(232, 56)
1264 },
1265 {
1266 .desc = "-5V",
1267 .type = ENVSYS_SVOLTS_DC,
1268 .bank = 0,
1269 .reg = 0x26,
1270 .refresh = wb_refresh_nvolt,
1271 .rfact = RFACT(120, 56)
1272 },
1273 {
1274 .desc = "5VSB",
1275 .type = ENVSYS_SVOLTS_DC,
1276 .bank = 0,
1277 .reg = 0xb0,
1278 .refresh = lm_refresh_volt,
1279 .rfact = RFACT(17, 33)
1280 },
1281 {
1282 .desc = "VBAT",
1283 .type = ENVSYS_SVOLTS_DC,
1284 .bank = 0,
1285 .reg = 0xb1,
1286 .refresh = lm_refresh_volt,
1287 .rfact = RFACT_NONE
1288 },
1289 {
1290 .desc = "VINR1",
1291 .type = ENVSYS_SVOLTS_DC,
1292 .bank = 0,
1293 .reg = 0xb2,
1294 .refresh = lm_refresh_volt,
1295 .rfact = RFACT_NONE
1296 },
1297
1298 /* Temperature */
1299 {
1300 .desc = "Temp0",
1301 .type = ENVSYS_STEMP,
1302 .bank = 0,
1303 .reg = 0x27,
1304 .refresh = lm_refresh_temp,
1305 .rfact = 0
1306 },
1307 {
1308 .desc = "Temp1",
1309 .type = ENVSYS_STEMP,
1310 .bank = 0,
1311 .reg = 0xc0,
1312 .refresh = wb_refresh_temp,
1313 .rfact = 0
1314 },
1315 {
1316 .desc = "Temp2",
1317 .type = ENVSYS_STEMP,
1318 .bank = 0,
1319 .reg = 0xc8,
1320 .refresh = wb_refresh_temp,
1321 .rfact = 0
1322 },
1323
1324 /* Fans */
1325 {
1326 .desc = "Fan0",
1327 .type = ENVSYS_SFANRPM,
1328 .bank = 0,
1329 .reg = 0x28,
1330 .refresh = wb_refresh_fanrpm,
1331 .rfact = 0
1332 },
1333 {
1334 .desc = "Fan1",
1335 .type = ENVSYS_SFANRPM,
1336 .bank = 0,
1337 .reg = 0x29,
1338 .refresh = wb_refresh_fanrpm,
1339 .rfact = 0
1340 },
1341 {
1342 .desc = "Fan2",
1343 .type = ENVSYS_SFANRPM,
1344 .bank = 0,
1345 .reg = 0x2a,
1346 .refresh = wb_refresh_fanrpm,
1347 .rfact = 0
1348 },
1349 {
1350 .desc = "Fan3",
1351 .type = ENVSYS_SFANRPM,
1352 .bank = 0,
1353 .reg = 0xba,
1354 .refresh = wb_refresh_fanrpm,
1355 .rfact = 0
1356 },
1357 {
1358 .desc = "Fan4",
1359 .type = ENVSYS_SFANRPM,
1360 .bank = 0,
1361 .reg = 0xbb,
1362 .refresh = wb_refresh_fanrpm,
1363 .rfact = 0
1364 },
1365
1366 { .desc = NULL }
1367 };
1368
1369 /* W83792D */
1370 static struct lm_sensor w83792d_sensors[] = {
1371 /* Voltage */
1372 {
1373 .desc = "VCore A",
1374 .type = ENVSYS_SVOLTS_DC,
1375 .bank = 0,
1376 .reg = 0x20,
1377 .refresh = lm_refresh_volt,
1378 .rfact = RFACT_NONE
1379 },
1380 {
1381 .desc = "VCore B",
1382 .type = ENVSYS_SVOLTS_DC,
1383 .bank = 0,
1384 .reg = 0x21,
1385 .refresh = lm_refresh_volt,
1386 .rfact = RFACT_NONE
1387 },
1388 {
1389 .desc = "+3.3V",
1390 .type = ENVSYS_SVOLTS_DC,
1391 .bank = 0,
1392 .reg = 0x22,
1393 .refresh = lm_refresh_volt,
1394 .rfact = RFACT_NONE
1395 },
1396 {
1397 .desc = "-5V",
1398 .type = ENVSYS_SVOLTS_DC,
1399 .bank = 0,
1400 .reg = 0x23,
1401 .refresh = wb_refresh_nvolt,
1402 .rfact = RFACT(120, 56)
1403 },
1404 {
1405 .desc = "+12V",
1406 .type = ENVSYS_SVOLTS_DC,
1407 .bank = 0,
1408 .reg = 0x24,
1409 .refresh = lm_refresh_volt,
1410 .rfact = RFACT(28, 10)
1411 },
1412 {
1413 .desc = "-12V",
1414 .type = ENVSYS_SVOLTS_DC,
1415 .bank = 0,
1416 .reg = 0x25,
1417 .refresh = wb_refresh_nvolt,
1418 .rfact = RFACT(232, 56)
1419 },
1420 {
1421 .desc = "+5V",
1422 .type = ENVSYS_SVOLTS_DC,
1423 .bank = 0,
1424 .reg = 0x26,
1425 .refresh = lm_refresh_volt,
1426 .rfact = RFACT(34, 50)
1427 },
1428 {
1429 .desc = "5VSB",
1430 .type = ENVSYS_SVOLTS_DC,
1431 .bank = 0,
1432 .reg = 0xb0,
1433 .refresh = lm_refresh_volt,
1434 .rfact = RFACT(17, 33)
1435 },
1436 {
1437 .desc = "VBAT",
1438 .type = ENVSYS_SVOLTS_DC,
1439 .bank = 0,
1440 .reg = 0xb1,
1441 .refresh = lm_refresh_volt,
1442 .rfact = RFACT_NONE
1443 },
1444
1445 /* Temperature */
1446 {
1447 .desc = "Temp0",
1448 .type = ENVSYS_STEMP,
1449 .bank = 0,
1450 .reg = 0x27,
1451 .refresh = lm_refresh_temp,
1452 .rfact = 0
1453 },
1454 {
1455 .desc = "Temp1",
1456 .type = ENVSYS_STEMP,
1457 .bank = 0,
1458 .reg = 0xc0,
1459 .refresh = wb_refresh_temp,
1460 .rfact = 0
1461 },
1462 {
1463 .desc = "Temp2",
1464 .type = ENVSYS_STEMP,
1465 .bank = 0,
1466 .reg = 0xc8,
1467 .refresh = wb_refresh_temp,
1468 .rfact = 0
1469 },
1470
1471 /* Fans */
1472 {
1473 .desc = "Fan0",
1474 .type = ENVSYS_SFANRPM,
1475 .bank = 0,
1476 .reg = 0x28,
1477 .refresh = wb_w83792d_refresh_fanrpm,
1478 .rfact = 0
1479 },
1480 {
1481 .desc = "Fan1",
1482 .type = ENVSYS_SFANRPM,
1483 .bank = 0,
1484 .reg = 0x29,
1485 .refresh = wb_w83792d_refresh_fanrpm,
1486 .rfact = 0
1487 },
1488 {
1489 .desc = "Fan2",
1490 .type = ENVSYS_SFANRPM,
1491 .bank = 0,
1492 .reg = 0x2a,
1493 .refresh = wb_w83792d_refresh_fanrpm,
1494 .rfact = 0
1495 },
1496 {
1497 .desc = "Fan3",
1498 .type = ENVSYS_SFANRPM,
1499 .bank = 0,
1500 .reg = 0xb8,
1501 .refresh = wb_w83792d_refresh_fanrpm,
1502 .rfact = 0
1503 },
1504 {
1505 .desc = "Fan4",
1506 .type = ENVSYS_SFANRPM,
1507 .bank = 0,
1508 .reg = 0xb9,
1509 .refresh = wb_w83792d_refresh_fanrpm,
1510 .rfact = 0
1511 },
1512 {
1513 .desc = "Fan5",
1514 .type = ENVSYS_SFANRPM,
1515 .bank = 0,
1516 .reg = 0xba,
1517 .refresh = wb_w83792d_refresh_fanrpm,
1518 .rfact = 0
1519 },
1520 {
1521 .desc = "Fan6",
1522 .type = ENVSYS_SFANRPM,
1523 .bank = 0,
1524 .reg = 0xbe,
1525 .refresh = wb_w83792d_refresh_fanrpm,
1526 .rfact = 0
1527 },
1528
1529 { .desc = NULL }
1530 };
1531
1532 /* AS99127F */
1533 static struct lm_sensor as99127f_sensors[] = {
1534 /* Voltage */
1535 {
1536 .desc = "VCore A",
1537 .type = ENVSYS_SVOLTS_DC,
1538 .bank = 0,
1539 .reg = 0x20,
1540 .refresh = lm_refresh_volt,
1541 .rfact = RFACT_NONE
1542 },
1543 {
1544 .desc = "VCore B",
1545 .type = ENVSYS_SVOLTS_DC,
1546 .bank = 0,
1547 .reg = 0x21,
1548 .refresh = lm_refresh_volt,
1549 .rfact = RFACT_NONE
1550 },
1551 {
1552 .desc = "+3.3V",
1553 .type = ENVSYS_SVOLTS_DC,
1554 .bank = 0,
1555 .reg = 0x22,
1556 .refresh = lm_refresh_volt,
1557 .rfact = RFACT_NONE
1558 },
1559 {
1560 .desc = "+5V",
1561 .type = ENVSYS_SVOLTS_DC,
1562 .bank = 0,
1563 .reg = 0x23,
1564 .refresh = lm_refresh_volt,
1565 .rfact = RFACT(34, 50)
1566 },
1567 {
1568 .desc = "+12V",
1569 .type = ENVSYS_SVOLTS_DC,
1570 .bank = 0,
1571 .reg = 0x24,
1572 .refresh = lm_refresh_volt,
1573 .rfact = RFACT(28, 10)
1574 },
1575 {
1576 .desc = "-12V",
1577 .type = ENVSYS_SVOLTS_DC,
1578 .bank = 0,
1579 .reg = 0x25,
1580 .refresh = wb_refresh_nvolt,
1581 .rfact = RFACT(232, 56)
1582 },
1583 {
1584 .desc = "-5V",
1585 .type = ENVSYS_SVOLTS_DC,
1586 .bank = 0,
1587 .reg = 0x26,
1588 .refresh = wb_refresh_nvolt,
1589 .rfact = RFACT(120, 56)
1590 },
1591
1592 /* Temperature */
1593 {
1594 .desc = "Temp0",
1595 .type = ENVSYS_STEMP,
1596 .bank = 0,
1597 .reg = 0x27,
1598 .refresh = lm_refresh_temp,
1599 .rfact = 0
1600 },
1601 {
1602 .desc = "Temp1",
1603 .type = ENVSYS_STEMP,
1604 .bank = 1,
1605 .reg = 0x50,
1606 .refresh = as_refresh_temp,
1607 .rfact = 0
1608 },
1609 {
1610 .desc = "Temp2",
1611 .type = ENVSYS_STEMP,
1612 .bank = 2,
1613 .reg = 0x50,
1614 .refresh = as_refresh_temp,
1615 .rfact = 0
1616 },
1617
1618 /* Fans */
1619 {
1620 .desc = "Fan0",
1621 .type = ENVSYS_SFANRPM,
1622 .bank = 0,
1623 .reg = 0x28,
1624 .refresh = lm_refresh_fanrpm,
1625 .rfact = 0
1626 },
1627 {
1628 .desc = "Fan1",
1629 .type = ENVSYS_SFANRPM,
1630 .bank = 0,
1631 .reg = 0x29,
1632 .refresh = lm_refresh_fanrpm,
1633 .rfact = 0
1634 },
1635 {
1636 .desc = "Fan2",
1637 .type = ENVSYS_SFANRPM,
1638 .bank = 0,
1639 .reg = 0x2a,
1640 .refresh = lm_refresh_fanrpm,
1641 .rfact = 0
1642 },
1643
1644 { .desc = NULL }
1645 };
1646
1647 static void
1648 lm_generic_banksel(struct lm_softc *lmsc, int bank)
1649 {
1650 (*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank);
1651 }
1652
1653 /*
1654 * bus independent probe
1655 */
1656 int
1657 lm_probe(bus_space_tag_t iot, bus_space_handle_t ioh)
1658 {
1659 uint8_t cr;
1660 int rv;
1661
1662 /* Check for some power-on defaults */
1663 bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
1664
1665 /* Perform LM78 reset */
1666 bus_space_write_1(iot, ioh, LMC_DATA, 0x80);
1667
1668 /* XXX - Why do I have to reselect the register? */
1669 bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
1670 cr = bus_space_read_1(iot, ioh, LMC_DATA);
1671
1672 /* XXX - spec says *only* 0x08! */
1673 if ((cr == 0x08) || (cr == 0x01) || (cr == 0x03))
1674 rv = 1;
1675 else
1676 rv = 0;
1677
1678 DPRINTF(("lm: rv = %d, cr = %x\n", rv, cr));
1679
1680 return rv;
1681 }
1682
1683
1684 /*
1685 * pre: lmsc contains valid busspace tag and handle
1686 */
1687 void
1688 lm_attach(struct lm_softc *lmsc)
1689 {
1690 uint32_t i;
1691
1692 for (i = 0; i < __arraycount(lm_chips); i++)
1693 if (lm_chips[i].chip_match(lmsc))
1694 break;
1695
1696 /* Start the monitoring loop */
1697 (*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x01);
1698
1699 /* Indicate we have never read the registers */
1700 timerclear(&lmsc->lastread);
1701
1702 /* Initialize sensors */
1703 for (i = 0; i < lmsc->numsensors; ++i) {
1704 lmsc->sensors[i].sensor = lmsc->info[i].sensor = i;
1705 lmsc->sensors[i].validflags = (ENVSYS_FVALID|ENVSYS_FCURVALID);
1706 lmsc->info[i].validflags = ENVSYS_FVALID;
1707 lmsc->sensors[i].warnflags = ENVSYS_WARN_OK;
1708 }
1709 /*
1710 * Hook into the System Monitor.
1711 */
1712 lmsc->sc_sysmon.sme_ranges = lm_ranges;
1713 lmsc->sc_sysmon.sme_sensor_info = lmsc->info;
1714 lmsc->sc_sysmon.sme_sensor_data = lmsc->sensors;
1715 lmsc->sc_sysmon.sme_cookie = lmsc;
1716
1717 lmsc->sc_sysmon.sme_gtredata = lm_gtredata;
1718 /* sme_streinfo set in chip-specific attach */
1719
1720 lmsc->sc_sysmon.sme_nsensors = lmsc->numsensors;
1721 lmsc->sc_sysmon.sme_envsys_version = 1000;
1722
1723 if (sysmon_envsys_register(&lmsc->sc_sysmon))
1724 aprint_error("%s: unable to register with sysmon\n",
1725 lmsc->sc_dev.dv_xname);
1726 }
1727
1728 static int
1729 lm_match(struct lm_softc *sc)
1730 {
1731 const char *model = NULL;
1732 int chipid;
1733
1734 /* See if we have an LM78/LM78J/LM79 or LM81 */
1735 chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
1736 switch(chipid) {
1737 case LM_ID_LM78:
1738 model = "LM78";
1739 break;
1740 case LM_ID_LM78J:
1741 model = "LM78J";
1742 break;
1743 case LM_ID_LM79:
1744 model = "LM79";
1745 break;
1746 case LM_ID_LM81:
1747 model = "LM81";
1748 break;
1749 default:
1750 return 0;
1751 }
1752
1753 aprint_normal(": National Semiconductor %s Hardware monitor\n", model);
1754
1755 lm_setup_sensors(sc, lm78_sensors);
1756 sc->sc_sysmon.sme_streinfo = lm_streinfo;
1757 sc->refresh_sensor_data = lm_refresh_sensor_data;
1758 return 1;
1759 }
1760
1761 static int
1762 def_match(struct lm_softc *sc)
1763 {
1764 int chipid;
1765
1766 chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
1767 aprint_error(": Unknown chip (ID %d)\n", chipid);
1768
1769 lm_setup_sensors(sc, lm78_sensors);
1770 sc->sc_sysmon.sme_streinfo = lm_streinfo;
1771 sc->refresh_sensor_data = lm_refresh_sensor_data;
1772 return 1;
1773 }
1774
1775 static int
1776 wb_match(struct lm_softc *sc)
1777 {
1778 const char *model;
1779 int banksel, vendid, devid;
1780
1781 model = NULL;
1782
1783 /* Read vendor ID */
1784 banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
1785 lm_generic_banksel(sc, WB_BANKSEL_HBAC);
1786
1787 vendid = (*sc->lm_readreg)(sc, WB_VENDID) << 8;
1788 lm_generic_banksel(sc, 0);
1789 vendid |= (*sc->lm_readreg)(sc, WB_VENDID);
1790 DPRINTF(("winbond vend id 0x%x\n", vendid));
1791 if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
1792 return 0;
1793
1794 /* Read device/chip ID */
1795 lm_generic_banksel(sc, WB_BANKSEL_B0);
1796 devid = (*sc->lm_readreg)(sc, LMD_CHIPID);
1797 sc->chipid = (*sc->lm_readreg)(sc, WB_BANK0_CHIPID);
1798 lm_generic_banksel(sc, banksel);
1799 DPRINTF(("winbond chip id 0x%x\n", sc->chipid));
1800
1801 switch(sc->chipid) {
1802 case WB_CHIPID_W83627HF:
1803 model = "W83627HF";
1804 lm_setup_sensors(sc, w83627hf_sensors);
1805 break;
1806 case WB_CHIPID_W83627THF:
1807 model = "W83627THF";
1808 lm_setup_sensors(sc, w83637hf_sensors);
1809 break;
1810 case WB_CHIPID_W83627EHF:
1811 model = "W83627EHF";
1812 lm_setup_sensors(sc, w83627ehf_sensors);
1813 break;
1814 case WB_CHIPID_W83627DHG:
1815 model = "W83627DHG";
1816 lm_setup_sensors(sc, w83627dhg_sensors);
1817 break;
1818 case WB_CHIPID_W83637HF:
1819 model = "W83637HF";
1820 lm_generic_banksel(sc, WB_BANKSEL_B0);
1821 if ((*sc->lm_readreg)(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
1822 sc->vrm9 = 1;
1823 lm_generic_banksel(sc, banksel);
1824 lm_setup_sensors(sc, w83637hf_sensors);
1825 break;
1826 case WB_CHIPID_W83697HF:
1827 model = "W83697HF";
1828 lm_setup_sensors(sc, w83697hf_sensors);
1829 break;
1830 case WB_CHIPID_W83781D:
1831 case WB_CHIPID_W83781D_2:
1832 model = "W83781D";
1833 lm_setup_sensors(sc, w83781d_sensors);
1834 sc->sc_sysmon.sme_streinfo = wb781_streinfo;
1835 break;
1836 case WB_CHIPID_W83782D:
1837 model = "W83782D";
1838 lm_setup_sensors(sc, w83782d_sensors);
1839 sc->sc_sysmon.sme_streinfo = wb782_streinfo;
1840 break;
1841 case WB_CHIPID_W83783S:
1842 model = "W83783S";
1843 lm_setup_sensors(sc, w83783s_sensors);
1844 break;
1845 case WB_CHIPID_W83791D:
1846 model = "W83791D";
1847 lm_setup_sensors(sc, w83791d_sensors);
1848 break;
1849 case WB_CHIPID_W83791SD:
1850 model = "W83791SD";
1851 break;
1852 case WB_CHIPID_W83792D:
1853 model = "W83792D";
1854 lm_setup_sensors(sc, w83792d_sensors);
1855 break;
1856 case WB_CHIPID_AS99127F:
1857 if (vendid == WB_VENDID_ASUS) {
1858 model = "AS99127F";
1859 lm_setup_sensors(sc, w83781d_sensors);
1860 } else {
1861 model = "AS99127F rev 2";
1862 lm_setup_sensors(sc, as99127f_sensors);
1863 }
1864 break;
1865 default:
1866 aprint_normal(": unknown Winbond chip (ID 0x%x)\n",
1867 sc->chipid);
1868 /* Handle as a standard LM78. */
1869 lm_setup_sensors(sc, lm78_sensors);
1870 sc->refresh_sensor_data = lm_refresh_sensor_data;
1871 return 1;
1872 }
1873
1874 aprint_normal(": Winbond %s Hardware monitor\n", model);
1875
1876 sc->sc_sysmon.sme_streinfo = lm_streinfo;
1877 sc->refresh_sensor_data = wb_refresh_sensor_data;
1878 return 1;
1879 }
1880
1881 static void
1882 lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
1883 {
1884 int i;
1885
1886 for (i = 0; sensors[i].desc; i++) {
1887 sc->sensors[i].units = sc->info[i].units = sensors[i].type;
1888 strlcpy(sc->info[i].desc, sensors[i].desc,
1889 sizeof(sc->info[i].desc));
1890 sc->numsensors++;
1891 }
1892 sc->lm_sensors = sensors;
1893 }
1894
1895 static void
1896 lm_refresh_sensor_data(struct lm_softc *sc)
1897 {
1898 int i;
1899
1900 /* Refresh our stored data for every sensor */
1901 for (i = 0; i < sc->numsensors; i++)
1902 sc->lm_sensors[i].refresh(sc, i);
1903 }
1904
1905 static void
1906 lm_refresh_volt(struct lm_softc *sc, int n)
1907 {
1908 int data;
1909
1910 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1911 DPRINTF(("%s: volt[%d] 0x%x\n", __func__, n, data));
1912 sc->sensors[n].cur.data_s = (data << 4);
1913 sc->sensors[n].cur.data_s *= sc->lm_sensors[n].rfact;
1914 sc->sensors[n].cur.data_s /= 10;
1915 sc->info[n].rfact = sc->lm_sensors[n].rfact;
1916 }
1917
1918 #define INVALIDATE_SENSOR(x) \
1919 do { \
1920 sc->sensors[(x)].validflags &= ~ENVSYS_FCURVALID; \
1921 sc->sensors[(x)].cur.data_us = 0; \
1922 } while (/* CONSTCOND */ 0)
1923
1924 static void
1925 lm_refresh_temp(struct lm_softc *sc, int n)
1926 {
1927 int sdata;
1928
1929 /*
1930 * The data sheet suggests that the range of the temperature
1931 * sensor is between -55 degC and +125 degC.
1932 */
1933 sdata = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1934 DPRINTF(("%s: temp[%d] 0x%x\n", __func__, n, sdata));
1935 if (sdata > 0x7d && sdata < 0xc9) {
1936 INVALIDATE_SENSOR(n);
1937 } else {
1938 if (sdata & 0x80)
1939 sdata -= 0x100;
1940 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
1941 sc->sensors[n].cur.data_us = sdata * 1000000 + 273150000;
1942 }
1943 }
1944
1945 static void
1946 lm_refresh_fanrpm(struct lm_softc *sc, int n)
1947 {
1948 int data, divisor = 1;
1949
1950 /*
1951 * We might get more accurate fan readings by adjusting the
1952 * divisor, but that might interfere with APM or other SMM
1953 * BIOS code reading the fan speeds.
1954 */
1955
1956 /* FAN3 has a fixed fan divisor. */
1957 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
1958 sc->lm_sensors[n].reg == LMD_FAN2) {
1959 data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
1960 if (sc->lm_sensors[n].reg == LMD_FAN1)
1961 divisor = (data >> 4) & 0x03;
1962 else
1963 divisor = (data >> 6) & 0x03;
1964 }
1965
1966 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1967 DPRINTF(("%s: fan[%d] 0x%x\n", __func__, n, data));
1968 if (data == 0xff || data == 0x00) {
1969 INVALIDATE_SENSOR(n);
1970 } else {
1971 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
1972 sc->sensors[n].cur.data_us = 1350000 / (data << divisor);
1973 }
1974 }
1975
1976 static void
1977 wb_refresh_sensor_data(struct lm_softc *sc)
1978 {
1979 int banksel, bank, i;
1980
1981 /*
1982 * Properly save and restore bank selection register.
1983 */
1984
1985 banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
1986 for (i = 0; i < sc->numsensors; i++) {
1987 if (bank != sc->lm_sensors[i].bank) {
1988 bank = sc->lm_sensors[i].bank;
1989 lm_generic_banksel(sc, bank);
1990 }
1991 sc->lm_sensors[i].refresh(sc, i);
1992 }
1993 lm_generic_banksel(sc, banksel);
1994 }
1995
1996 static void
1997 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
1998 {
1999 int data;
2000
2001 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2002 DPRINTF(("%s: volt[%d] 0x%x\n", __func__, n, data));
2003 /*
2004 * Depending on the voltage detection method,
2005 * one of the following formulas is used:
2006 * VRM8 method: value = raw * 0.016V
2007 * VRM9 method: value = raw * 0.00488V + 0.70V
2008 */
2009 if (sc->vrm9)
2010 sc->sensors[n].cur.data_s = (data * 4880) + 700000;
2011 else
2012 sc->sensors[n].cur.data_s = (data * 16000);
2013 }
2014
2015 static void
2016 wb_refresh_nvolt(struct lm_softc *sc, int n)
2017 {
2018 int data;
2019
2020 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2021 DPRINTF(("%s: volt[%d] 0x%x\n", __func__, n , data));
2022 sc->sensors[n].cur.data_s = ((data << 4) - WB_VREF);
2023 sc->sensors[n].cur.data_s *= sc->lm_sensors[n].rfact;
2024 sc->sensors[n].cur.data_s /= 10;
2025 sc->sensors[n].cur.data_s += WB_VREF * 1000;
2026 }
2027
2028 static void
2029 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
2030 {
2031 int data;
2032
2033 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2034 DPRINTF(("%s: volt[%d] 0x%x\n", __func__, n , data));
2035 sc->sensors[n].cur.data_s = ((data << 3) - WB_W83627EHF_VREF);
2036 sc->sensors[n].cur.data_s *= RFACT(232, 10);
2037 sc->sensors[n].cur.data_s /= 10;
2038 sc->sensors[n].cur.data_s += WB_W83627EHF_VREF * 1000;
2039 }
2040
2041 static void
2042 wb_refresh_temp(struct lm_softc *sc, int n)
2043 {
2044 int sdata;
2045
2046 /*
2047 * The data sheet suggests that the range of the temperature
2048 * sensor is between -55 degC and +125 degC. However, values
2049 * around -48 degC seem to be a very common bogus values.
2050 * Since such values are unreasonably low, we use -45 degC for
2051 * the lower limit instead.
2052 */
2053 sdata = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
2054 sdata += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
2055 DPRINTF(("%s: temp[%d] 0x%x\n", __func__, n , sdata));
2056 if (sdata > 0x0fa && sdata < 0x1a6) {
2057 INVALIDATE_SENSOR(n);
2058 } else {
2059 if (sdata & 0x100)
2060 sdata -= 0x200;
2061 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2062 sc->sensors[n].cur.data_us = sdata * 500000 + 273150000;
2063 }
2064 }
2065
2066 static void
2067 wb_refresh_fanrpm(struct lm_softc *sc, int n)
2068 {
2069 int fan, data, divisor = 0;
2070
2071 /*
2072 * This is madness; the fan divisor bits are scattered all
2073 * over the place.
2074 */
2075
2076 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
2077 sc->lm_sensors[n].reg == LMD_FAN2 ||
2078 sc->lm_sensors[n].reg == LMD_FAN3) {
2079 data = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
2080 fan = (sc->lm_sensors[n].reg - LMD_FAN1);
2081 if ((data >> 5) & (1 << fan))
2082 divisor |= 0x04;
2083 }
2084
2085 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
2086 sc->lm_sensors[n].reg == LMD_FAN2) {
2087 data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2088 if (sc->lm_sensors[n].reg == LMD_FAN1)
2089 divisor |= (data >> 4) & 0x03;
2090 else
2091 divisor |= (data >> 6) & 0x03;
2092 } else if (sc->lm_sensors[n].reg == LMD_FAN3) {
2093 data = (*sc->lm_readreg)(sc, WB_PIN);
2094 divisor |= (data >> 6) & 0x03;
2095 } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
2096 sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
2097 data = (*sc->lm_readreg)(sc, WB_BANK0_FAN45);
2098 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
2099 divisor |= (data >> 0) & 0x07;
2100 else
2101 divisor |= (data >> 4) & 0x07;
2102 }
2103
2104 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2105 DPRINTF(("%s: fan[%d] 0x%x\n", __func__, n , data));
2106 if (data == 0xff || data == 0x00) {
2107 INVALIDATE_SENSOR(n);
2108 } else {
2109 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2110 sc->sensors[n].cur.data_us = 1350000 / (data << divisor);
2111 }
2112 }
2113
2114 static void
2115 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
2116 {
2117 int reg, shift, data, divisor = 1;
2118
2119 shift = 0;
2120
2121 switch (sc->lm_sensors[n].reg) {
2122 case 0x28:
2123 reg = 0x47; shift = 0;
2124 break;
2125 case 0x29:
2126 reg = 0x47; shift = 4;
2127 break;
2128 case 0x2a:
2129 reg = 0x5b; shift = 0;
2130 break;
2131 case 0xb8:
2132 reg = 0x5b; shift = 4;
2133 break;
2134 case 0xb9:
2135 reg = 0x5c; shift = 0;
2136 break;
2137 case 0xba:
2138 reg = 0x5c; shift = 4;
2139 break;
2140 case 0xbe:
2141 reg = 0x9e; shift = 0;
2142 break;
2143 default:
2144 reg = 0;
2145 break;
2146 }
2147
2148 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2149 DPRINTF(("%s: fan[%d] 0x%x\n", __func__, n , data));
2150 if (data == 0xff || data == 0x00) {
2151 INVALIDATE_SENSOR(n);
2152 } else {
2153 if (reg != 0)
2154 divisor = ((*sc->lm_readreg)(sc, reg) >> shift) & 0x7;
2155 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2156 sc->sensors[n].cur.data_us = 1350000 / (data << divisor);
2157 }
2158 }
2159
2160 static void
2161 as_refresh_temp(struct lm_softc *sc, int n)
2162 {
2163 int sdata;
2164
2165 /*
2166 * It seems a shorted temperature diode produces an all-ones
2167 * bit pattern.
2168 */
2169 sdata = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
2170 sdata += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
2171 DPRINTF(("%s: temp[%d] 0x%x\n", __func__, n , data));
2172 if (sdata == 0x1ff) {
2173 INVALIDATE_SENSOR(n);
2174 } else {
2175 if (sdata & 0x100)
2176 sdata -= 0x200;
2177 sc->sensors[n].validflags |= (ENVSYS_FVALID|ENVSYS_FCURVALID);
2178 sc->sensors[n].cur.data_us = sdata * 500000 + 273150000;
2179 }
2180 }
2181
2182 #undef INVALIDATE_SENSOR
2183
2184 static int
2185 lm_gtredata(struct sysmon_envsys *sme, envsys_tre_data_t *tred)
2186 {
2187 static const struct timeval onepointfive = { 1, 500000 };
2188 struct timeval t, utv;
2189 struct lm_softc *sc = sme->sme_cookie;
2190
2191 /* read new values at most once every 1.5 seconds */
2192 getmicrouptime(&utv);
2193 timeradd(&sc->lastread, &onepointfive, &t);
2194 if (timercmp(&utv, &t, >)) {
2195 sc->lastread = utv;
2196 sc->refresh_sensor_data(sc);
2197 }
2198
2199 *tred = sc->sensors[tred->sensor];
2200
2201 return 0;
2202 }
2203
2204 static int
2205 generic_streinfo_fan(struct lm_softc *sc, envsys_basic_info_t *info, int n,
2206 envsys_basic_info_t *binfo)
2207 {
2208 uint8_t sdata;
2209 int divisor;
2210
2211 /* FAN1 and FAN2 can have divisors set, but not FAN3 */
2212 if ((sc->info[binfo->sensor].units == ENVSYS_SFANRPM)
2213 && (n < 2)) {
2214 if (binfo->rpms == 0) {
2215 binfo->validflags = 0;
2216 return 0;
2217 }
2218
2219 /* write back the nominal FAN speed */
2220 info->rpms = binfo->rpms;
2221
2222 /* 153 is the nominal FAN speed value */
2223 divisor = 1350000 / (binfo->rpms * 153);
2224
2225 /* ...but we need lg(divisor) */
2226 if (divisor <= 1)
2227 divisor = 0;
2228 else if (divisor <= 2)
2229 divisor = 1;
2230 else if (divisor <= 4)
2231 divisor = 2;
2232 else
2233 divisor = 3;
2234
2235 /*
2236 * FAN1 div is in bits <5:4>, FAN2 div is
2237 * in <7:6>
2238 */
2239 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2240 if ( n == 0 ) { /* FAN1 */
2241 divisor <<= 4;
2242 sdata = (sdata & 0xCF) | divisor;
2243 } else { /* FAN2 */
2244 divisor <<= 6;
2245 sdata = (sdata & 0x3F) | divisor;
2246 }
2247
2248 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
2249 }
2250 return 0;
2251
2252 }
2253
2254 static int
2255 lm_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
2256 {
2257 struct lm_softc *sc = sme->sme_cookie;
2258
2259 if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
2260 sc->info[binfo->sensor].rfact = binfo->rfact;
2261 else {
2262 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
2263 generic_streinfo_fan(sc, &sc->info[binfo->sensor],
2264 binfo->sensor - 8, binfo);
2265 }
2266 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
2267 sizeof(sc->info[binfo->sensor].desc));
2268 binfo->validflags = ENVSYS_FVALID;
2269 }
2270 return 0;
2271 }
2272
2273 static int
2274 wb781_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
2275 {
2276 struct lm_softc *sc = sme->sme_cookie;
2277 int divisor;
2278 uint8_t sdata;
2279 int i;
2280
2281 if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
2282 sc->info[binfo->sensor].rfact = binfo->rfact;
2283 else {
2284 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
2285 if (binfo->rpms == 0) {
2286 binfo->validflags = 0;
2287 return 0;
2288 }
2289
2290 /* write back the nominal FAN speed */
2291 sc->info[binfo->sensor].rpms = binfo->rpms;
2292
2293 /* 153 is the nominal FAN speed value */
2294 divisor = 1350000 / (binfo->rpms * 153);
2295
2296 /* ...but we need lg(divisor) */
2297 for (i = 0; i < 7; i++) {
2298 if (divisor <= (1 << i))
2299 break;
2300 }
2301 divisor = i;
2302
2303 if (binfo->sensor == 10 || binfo->sensor == 11) {
2304 /*
2305 * FAN1 div is in bits <5:4>, FAN2 div
2306 * is in <7:6>
2307 */
2308 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2309 if ( binfo->sensor == 10 ) { /* FAN1 */
2310 sdata = (sdata & 0xCF) |
2311 ((divisor & 0x3) << 4);
2312 } else { /* FAN2 */
2313 sdata = (sdata & 0x3F) |
2314 ((divisor & 0x3) << 6);
2315 }
2316 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
2317 } else {
2318 /* FAN3 is in WB_PIN <7:6> */
2319 sdata = (*sc->lm_readreg)(sc, WB_PIN);
2320 sdata = (sdata & 0x3F) |
2321 ((divisor & 0x3) << 6);
2322 (*sc->lm_writereg)(sc, WB_PIN, sdata);
2323 }
2324 }
2325 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
2326 sizeof(sc->info[binfo->sensor].desc));
2327 binfo->validflags = ENVSYS_FVALID;
2328 }
2329 return 0;
2330 }
2331
2332 static int
2333 wb782_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
2334 {
2335 struct lm_softc *sc = sme->sme_cookie;
2336 int divisor;
2337 uint8_t sdata;
2338 int i;
2339
2340 if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
2341 sc->info[binfo->sensor].rfact = binfo->rfact;
2342 else {
2343 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
2344 if (binfo->rpms == 0) {
2345 binfo->validflags = 0;
2346 return 0;
2347 }
2348
2349 /* write back the nominal FAN speed */
2350 sc->info[binfo->sensor].rpms = binfo->rpms;
2351
2352 /* 153 is the nominal FAN speed value */
2353 divisor = 1350000 / (binfo->rpms * 153);
2354
2355 /* ...but we need lg(divisor) */
2356 for (i = 0; i < 7; i++) {
2357 if (divisor <= (1 << i))
2358 break;
2359 }
2360 divisor = i;
2361
2362 if (binfo->sensor == 12 || binfo->sensor == 13) {
2363 /*
2364 * FAN1 div is in bits <5:4>, FAN2 div
2365 * is in <7:6>
2366 */
2367 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2368 if ( binfo->sensor == 12 ) { /* FAN1 */
2369 sdata = (sdata & 0xCF) |
2370 ((divisor & 0x3) << 4);
2371 } else { /* FAN2 */
2372 sdata = (sdata & 0x3F) |
2373 ((divisor & 0x3) << 6);
2374 }
2375 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
2376 } else {
2377 /* FAN3 is in WB_PIN <7:6> */
2378 sdata = (*sc->lm_readreg)(sc, WB_PIN);
2379 sdata = (sdata & 0x3F) |
2380 ((divisor & 0x3) << 6);
2381 (*sc->lm_writereg)(sc, WB_PIN, sdata);
2382 }
2383 /* Bit 2 of divisor is in WB_BANK0_VBAT */
2384 lm_generic_banksel(sc, WB_BANKSEL_B0);
2385 sdata = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
2386 sdata &= ~(0x20 << (binfo->sensor - 12));
2387 sdata |= (divisor & 0x4) << (binfo->sensor - 9);
2388 (*sc->lm_writereg)(sc, WB_BANK0_VBAT, sdata);
2389 }
2390
2391 strlcpy(sc->info[binfo->sensor].desc, binfo->desc,
2392 sizeof(sc->info[binfo->sensor].desc));
2393 binfo->validflags = ENVSYS_FVALID;
2394 }
2395 return 0;
2396 }
2397