Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / ic / nslm7x.c
blob5303c036372a2cbbc57d8d1ea16b63765652761b
1 /* $NetBSD: nslm7x.c,v 1.48 2008/10/12 13:17:28 pgoyette Exp $ */
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Bill Squier.
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.48 2008/10/12 13:17:28 pgoyette Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/proc.h>
39 #include <sys/device.h>
40 #include <sys/conf.h>
41 #include <sys/time.h>
43 #include <sys/bus.h>
45 #include <dev/isa/isareg.h>
46 #include <dev/isa/isavar.h>
48 #include <dev/sysmon/sysmonvar.h>
50 #include <dev/ic/nslm7xvar.h>
52 #include <sys/intr.h>
54 #if defined(LMDEBUG)
55 #define DPRINTF(x) do { printf x; } while (0)
56 #else
57 #define DPRINTF(x)
58 #endif
61 * LM78-compatible chips can typically measure voltages up to 4.096 V.
62 * To measure higher voltages the input is attenuated with (external)
63 * resistors. Negative voltages are measured using inverting op amps
64 * and resistors. So we have to convert the sensor values back to
65 * real voltages by applying the appropriate resistor factor.
67 #define RFACT_NONE 10000
68 #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
69 #define NRFACT(x, y) (-RFACT_NONE * (x) / (y))
71 #define LM_REFRESH_TIMO (2 * hz) /* 2 seconds */
73 static int lm_match(struct lm_softc *);
74 static int wb_match(struct lm_softc *);
75 static int def_match(struct lm_softc *);
77 static void lm_refresh(void *);
79 static void lm_generic_banksel(struct lm_softc *, int);
80 static void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
81 static void lm_refresh_sensor_data(struct lm_softc *);
82 static void lm_refresh_volt(struct lm_softc *, int);
83 static void lm_refresh_temp(struct lm_softc *, int);
84 static void lm_refresh_fanrpm(struct lm_softc *, int);
86 static void wb_refresh_sensor_data(struct lm_softc *);
87 static void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
88 static void wb_refresh_nvolt(struct lm_softc *, int);
89 static void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
90 static void wb_refresh_temp(struct lm_softc *, int);
91 static void wb_refresh_fanrpm(struct lm_softc *, int);
92 static void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
94 static void as_refresh_temp(struct lm_softc *, int);
96 struct lm_chip {
97 int (*chip_match)(struct lm_softc *);
100 static struct lm_chip lm_chips[] = {
101 { wb_match },
102 { lm_match },
103 { def_match } /* Must be last */
106 /* LM78/78J/79/81 */
107 static struct lm_sensor lm78_sensors[] = {
108 /* Voltage */
110 .desc = "VCore A",
111 .type = ENVSYS_SVOLTS_DC,
112 .bank = 0,
113 .reg = 0x20,
114 .refresh = lm_refresh_volt,
115 .rfact = RFACT_NONE
118 .desc = "VCore B",
119 .type = ENVSYS_SVOLTS_DC,
120 .bank = 0,
121 .reg = 0x21,
122 .refresh = lm_refresh_volt,
123 .rfact = RFACT_NONE
126 .desc = "+3.3V",
127 .type = ENVSYS_SVOLTS_DC,
128 .bank = 0,
129 .reg = 0x22,
130 .refresh = lm_refresh_volt,
131 .rfact = RFACT_NONE
134 .desc = "+5V",
135 .type = ENVSYS_SVOLTS_DC,
136 .bank = 0,
137 .reg = 0x23,
138 .refresh = lm_refresh_volt,
139 .rfact = RFACT(68, 100)
142 .desc = "+12V",
143 .type = ENVSYS_SVOLTS_DC,
144 .bank = 0,
145 .reg = 0x24,
146 .refresh = lm_refresh_volt,
147 .rfact = RFACT(30, 10)
150 .desc = "-12V",
151 .type = ENVSYS_SVOLTS_DC,
152 .bank = 0,
153 .reg = 0x25,
154 .refresh = lm_refresh_volt,
155 .rfact = NRFACT(240, 60)
158 .desc = "-5V",
159 .type = ENVSYS_SVOLTS_DC,
160 .bank = 0,
161 .reg = 0x26,
162 .refresh = lm_refresh_volt,
163 .rfact = NRFACT(100, 60)
166 /* Temperature */
168 .desc = "Temp0",
169 .type = ENVSYS_STEMP,
170 .bank = 0,
171 .reg = 0x27,
172 .refresh = lm_refresh_temp,
173 .rfact = 0
176 /* Fans */
178 .desc = "Fan0",
179 .type = ENVSYS_SFANRPM,
180 .bank = 0,
181 .reg = 0x28,
182 .refresh = lm_refresh_fanrpm,
183 .rfact = 0
186 .desc = "Fan1",
187 .type = ENVSYS_SFANRPM,
188 .bank = 0,
189 .reg = 0x29,
190 .refresh = lm_refresh_fanrpm,
191 .rfact = 0
194 .desc = "Fan2",
195 .type = ENVSYS_SFANRPM,
196 .bank = 0,
197 .reg = 0x2a,
198 .refresh = lm_refresh_fanrpm,
199 .rfact = 0
202 { .desc = NULL }
205 /* W83627HF */
206 static struct lm_sensor w83627hf_sensors[] = {
207 /* Voltage */
209 .desc = "VCore A",
210 .type = ENVSYS_SVOLTS_DC,
211 .bank = 0,
212 .reg = 0x20,
213 .refresh = lm_refresh_volt,
214 .rfact = RFACT_NONE
217 .desc = "VCore B",
218 .type = ENVSYS_SVOLTS_DC,
219 .bank = 0,
220 .reg = 0x21,
221 .refresh = lm_refresh_volt,
222 .rfact = RFACT_NONE
225 .desc = "+3.3V",
226 .type = ENVSYS_SVOLTS_DC,
227 .bank = 0,
228 .reg = 0x22,
229 .refresh = lm_refresh_volt,
230 .rfact = RFACT_NONE
233 .desc = "+5V",
234 .type = ENVSYS_SVOLTS_DC,
235 .bank = 0,
236 .reg = 0x23,
237 .refresh = lm_refresh_volt,
238 .rfact = RFACT(34, 50)
241 .desc = "+12V",
242 .type = ENVSYS_SVOLTS_DC,
243 .bank = 0,
244 .reg = 0x24,
245 .refresh = lm_refresh_volt,
246 .rfact = RFACT(28, 10)
249 .desc = "-12V",
250 .type = ENVSYS_SVOLTS_DC,
251 .bank = 0,
252 .reg = 0x25,
253 .refresh = wb_refresh_nvolt,
254 .rfact = RFACT(232, 56)
257 .desc = "-5V",
258 .type = ENVSYS_SVOLTS_DC,
259 .bank = 0,
260 .reg = 0x26,
261 .refresh = wb_refresh_nvolt,
262 .rfact = RFACT(120, 56)
265 .desc = "5VSB",
266 .type = ENVSYS_SVOLTS_DC,
267 .bank = 5,
268 .reg = 0x50,
269 .refresh = lm_refresh_volt,
270 .rfact = RFACT(17, 33)
273 .desc = "VBAT",
274 .type = ENVSYS_SVOLTS_DC,
275 .bank = 5,
276 .reg = 0x51,
277 .refresh = lm_refresh_volt,
278 .rfact = RFACT_NONE
281 /* Temperature */
283 .desc = "Temp0",
284 .type = ENVSYS_STEMP,
285 .bank = 0,
286 .reg = 0x27,
287 .refresh = lm_refresh_temp,
288 .rfact = 0
291 .desc = "Temp1",
292 .type = ENVSYS_STEMP,
293 .bank = 1,
294 .reg = 0x50,
295 .refresh = wb_refresh_temp,
296 .rfact = 0
299 .desc = "Temp2",
300 .type = ENVSYS_STEMP,
301 .bank = 2,
302 .reg = 0x50,
303 .refresh = wb_refresh_temp,
304 .rfact = 0
307 /* Fans */
309 .desc = "Fan0",
310 .type = ENVSYS_SFANRPM,
311 .bank = 0,
312 .reg = 0x28,
313 .refresh = wb_refresh_fanrpm,
314 .rfact = 0
317 .desc = "Fan1",
318 .type = ENVSYS_SFANRPM,
319 .bank = 0,
320 .reg = 0x29,
321 .refresh = wb_refresh_fanrpm,
322 .rfact = 0
325 .desc = "Fan2",
326 .type = ENVSYS_SFANRPM,
327 .bank = 0,
328 .reg = 0x2a,
329 .refresh = wb_refresh_fanrpm,
330 .rfact = 0
333 { .desc = NULL }
336 /* W8627EHF */
339 * The W83627EHF can measure voltages up to 2.048 V instead of the
340 * traditional 4.096 V. For measuring positive voltages, this can be
341 * accounted for by halving the resistor factor. Negative voltages
342 * need special treatment, also because the reference voltage is 2.048 V
343 * instead of the traditional 3.6 V.
345 static struct lm_sensor w83627ehf_sensors[] = {
346 /* Voltage */
348 .desc = "VCore",
349 .type = ENVSYS_SVOLTS_DC,
350 .bank = 0,
351 .reg = 0x20,
352 .refresh = lm_refresh_volt,
353 .rfact = RFACT_NONE / 2
356 .desc = "+12V",
357 .type = ENVSYS_SVOLTS_DC,
358 .bank = 0,
359 .reg = 0x21,
360 .refresh = lm_refresh_volt,
361 .rfact = RFACT(56, 10) / 2
364 .desc = "+3.3V",
365 .type = ENVSYS_SVOLTS_DC,
366 .bank = 0,
367 .reg = 0x22,
368 .refresh = lm_refresh_volt,
369 .rfact = RFACT(34, 34) / 2
372 .desc = "VIN3",
373 .type = ENVSYS_SVOLTS_DC,
374 .bank = 0,
375 .reg = 0x23,
376 .refresh = lm_refresh_volt,
377 .rfact = RFACT(34, 34) / 2
380 .desc = "-12V",
381 .type = ENVSYS_SVOLTS_DC,
382 .bank = 0,
383 .reg = 0x24,
384 .refresh = wb_w83627ehf_refresh_nvolt,
385 .rfact = 0
388 .desc = "VIN5",
389 .type = ENVSYS_SVOLTS_DC,
390 .bank = 0,
391 .reg = 0x25,
392 .refresh = lm_refresh_volt,
393 .rfact = RFACT_NONE / 2
396 .desc = "VIN6",
397 .type = ENVSYS_SVOLTS_DC,
398 .bank = 0,
399 .reg = 0x26,
400 .refresh = lm_refresh_volt,
401 .rfact = RFACT_NONE / 2
404 .desc = "3.3VSB",
405 .type = ENVSYS_SVOLTS_DC,
406 .bank = 5,
407 .reg = 0x50,
408 .refresh = lm_refresh_volt,
409 .rfact = RFACT(34, 34) / 2
412 .desc = "VBAT",
413 .type = ENVSYS_SVOLTS_DC,
414 .bank = 5,
415 .reg = 0x51,
416 .refresh = lm_refresh_volt,
417 .rfact = RFACT_NONE / 2
420 .desc = "VIN8",
421 .type = ENVSYS_SVOLTS_DC,
422 .bank = 5,
423 .reg = 0x52,
424 .refresh = lm_refresh_volt,
425 .rfact = RFACT_NONE / 2
428 /* Temperature */
430 .desc = "Temp0",
431 .type = ENVSYS_STEMP,
432 .bank = 0,
433 .reg = 0x27,
434 .refresh = lm_refresh_temp,
435 .rfact = 0
438 .desc = "Temp1",
439 .type = ENVSYS_STEMP,
440 .bank = 1,
441 .reg = 0x50,
442 .refresh = wb_refresh_temp,
443 .rfact = 0
446 .desc = "Temp2",
447 .type = ENVSYS_STEMP,
448 .bank = 2,
449 .reg = 0x50,
450 .refresh = wb_refresh_temp,
451 .rfact = 0
454 /* Fans */
456 .desc = "Fan0",
457 .type = ENVSYS_SFANRPM,
458 .bank = 0,
459 .reg = 0x28,
460 .refresh = wb_refresh_fanrpm,
461 .rfact = 0
464 .desc = "Fan1",
465 .type = ENVSYS_SFANRPM,
466 .bank = 0,
467 .reg = 0x29,
468 .refresh = wb_refresh_fanrpm,
469 .rfact = 0
472 .desc = "Fan2",
473 .type = ENVSYS_SFANRPM,
474 .bank = 0,
475 .reg = 0x2a,
476 .refresh = wb_refresh_fanrpm,
477 .rfact = 0
480 { .desc = NULL }
483 /* W83627DHG */
484 static struct lm_sensor w83627dhg_sensors[] = {
485 /* Voltage */
487 .desc = "VCore",
488 .type = ENVSYS_SVOLTS_DC,
489 .bank = 0,
490 .reg = 0x20,
491 .refresh = lm_refresh_volt,
492 .rfact = RFACT_NONE / 2
495 .desc = "+12V",
496 .type = ENVSYS_SVOLTS_DC,
497 .bank = 0,
498 .reg = 0x21,
499 .refresh = lm_refresh_volt,
500 .rfact = RFACT(56, 10) / 2
503 .desc = "AVCC",
504 .type = ENVSYS_SVOLTS_DC,
505 .bank = 0,
506 .reg = 0x22,
507 .refresh = lm_refresh_volt,
508 .rfact = RFACT(34, 34) / 2
511 .desc = "+3.3V",
512 .type = ENVSYS_SVOLTS_DC,
513 .bank = 0,
514 .reg = 0x23,
515 .refresh = lm_refresh_volt,
516 .rfact = RFACT(34, 34) / 2
519 .desc = "-12V",
520 .type = ENVSYS_SVOLTS_DC,
521 .bank = 0,
522 .reg = 0x24,
523 .refresh = wb_w83627ehf_refresh_nvolt,
524 .rfact = 0
527 .desc = "+5V",
528 .type = ENVSYS_SVOLTS_DC,
529 .bank = 0,
530 .reg = 0x25,
531 .refresh = lm_refresh_volt,
532 .rfact = 16000
535 .desc = "VIN3",
536 .type = ENVSYS_SVOLTS_DC,
537 .bank = 0,
538 .reg = 0x26,
539 .refresh = lm_refresh_volt,
540 .rfact = RFACT_NONE
543 .desc = "+3.3VSB",
544 .type = ENVSYS_SVOLTS_DC,
545 .bank = 5,
546 .reg = 0x50,
547 .refresh = lm_refresh_volt,
548 .rfact = RFACT(34, 34) / 2
551 .desc = "VBAT",
552 .type = ENVSYS_SVOLTS_DC,
553 .bank = 5,
554 .reg = 0x51,
555 .refresh = lm_refresh_volt,
556 .rfact = RFACT(34, 34) / 2
559 /* Temperature */
561 .desc = "MB Temperature",
562 .type = ENVSYS_STEMP,
563 .bank = 0,
564 .reg = 0x27,
565 .refresh = lm_refresh_temp,
566 .rfact = 0
569 .desc = "CPU Temperature",
570 .type = ENVSYS_STEMP,
571 .bank = 1,
572 .reg = 0x50,
573 .refresh = lm_refresh_temp,
574 .rfact = 0
577 .desc = "Aux Temp",
578 .type = ENVSYS_STEMP,
579 .bank = 2,
580 .reg = 0x50,
581 .refresh = lm_refresh_temp,
582 .rfact = 0
585 /* Fans */
587 .desc = "System Fan",
588 .type = ENVSYS_SFANRPM,
589 .bank = 0,
590 .reg = 0x28,
591 .refresh = wb_refresh_fanrpm,
592 .rfact = 0
595 .desc = "CPU Fan",
596 .type = ENVSYS_SFANRPM,
597 .bank = 0,
598 .reg = 0x29,
599 .refresh = wb_refresh_fanrpm,
600 .rfact = 0
603 .desc = "Aux Fan",
604 .type = ENVSYS_SFANRPM,
605 .bank = 0,
606 .reg = 0x2a,
607 .refresh = wb_refresh_fanrpm,
608 .rfact = 0
611 { .desc = NULL }
614 /* W83637HF */
615 static struct lm_sensor w83637hf_sensors[] = {
616 /* Voltage */
618 .desc = "VCore",
619 .type = ENVSYS_SVOLTS_DC,
620 .bank = 0,
621 .reg = 0x20,
622 .refresh = wb_w83637hf_refresh_vcore,
623 .rfact = 0
626 .desc = "+12V",
627 .type = ENVSYS_SVOLTS_DC,
628 .bank = 0,
629 .reg = 0x21,
630 .refresh = lm_refresh_volt,
631 .rfact = RFACT(28, 10)
634 .desc = "+3.3V",
635 .type = ENVSYS_SVOLTS_DC,
636 .bank = 0,
637 .reg = 0x22,
638 .refresh = lm_refresh_volt,
639 .rfact = RFACT_NONE
642 .desc = "+5V",
643 .type = ENVSYS_SVOLTS_DC,
644 .bank = 0,
645 .reg = 0x23,
646 .refresh = lm_refresh_volt,
647 .rfact = RFACT(34, 51)
650 .desc = "-12V",
651 .type = ENVSYS_SVOLTS_DC,
652 .bank = 0,
653 .reg = 0x24,
654 .refresh = wb_refresh_nvolt,
655 .rfact = RFACT(232, 56)
658 .desc = "5VSB",
659 .type = ENVSYS_SVOLTS_DC,
660 .bank = 5,
661 .reg = 0x50,
662 .refresh = lm_refresh_volt,
663 .rfact = RFACT(34, 51)
666 .desc = "VBAT",
667 .type = ENVSYS_SVOLTS_DC,
668 .bank = 5,
669 .reg = 0x51,
670 .refresh = lm_refresh_volt,
671 .rfact = RFACT_NONE
674 /* Temperature */
676 .desc = "Temp0",
677 .type = ENVSYS_STEMP,
678 .bank = 0,
679 .reg = 0x27,
680 .refresh = lm_refresh_temp,
681 .rfact = 0
684 .desc = "Temp1",
685 .type = ENVSYS_STEMP,
686 .bank = 1,
687 .reg = 0x50,
688 .refresh = wb_refresh_temp,
689 .rfact = 0
692 .desc = "Temp2",
693 .type = ENVSYS_STEMP,
694 .bank = 2,
695 .reg = 0x50,
696 .refresh = wb_refresh_temp,
697 .rfact = 0
700 /* Fans */
702 .desc = "Fan0",
703 .type = ENVSYS_SFANRPM,
704 .bank = 0,
705 .reg = 0x28,
706 .refresh = wb_refresh_fanrpm,
707 .rfact = 0
710 .desc = "Fan1",
711 .type = ENVSYS_SFANRPM,
712 .bank = 0,
713 .reg = 0x29,
714 .refresh = wb_refresh_fanrpm,
715 .rfact = 0
718 .desc = "Fan2",
719 .type = ENVSYS_SFANRPM,
720 .bank = 0,
721 .reg = 0x2a,
722 .refresh = wb_refresh_fanrpm,
723 .rfact = 0
726 { .desc = NULL }
729 /* W83697HF */
730 static struct lm_sensor w83697hf_sensors[] = {
731 /* Voltage */
733 .desc = "VCore",
734 .type = ENVSYS_SVOLTS_DC,
735 .bank = 0,
736 .reg = 0x20,
737 .refresh = lm_refresh_volt,
738 .rfact = RFACT_NONE
741 .desc = "+3.3V",
742 .type = ENVSYS_SVOLTS_DC,
743 .bank = 0,
744 .reg = 0x22,
745 .refresh = lm_refresh_volt,
746 .rfact = RFACT_NONE
749 .desc = "+5V",
750 .type = ENVSYS_SVOLTS_DC,
751 .bank = 0,
752 .reg = 0x23,
753 .refresh = lm_refresh_volt,
754 .rfact = RFACT(34, 50)
757 .desc = "+12V",
758 .type = ENVSYS_SVOLTS_DC,
759 .bank = 0,
760 .reg = 0x24,
761 .refresh = lm_refresh_volt,
762 .rfact = RFACT(28, 10)
765 .desc = "-12V",
766 .type = ENVSYS_SVOLTS_DC,
767 .bank = 0,
768 .reg = 0x25,
769 .refresh = wb_refresh_nvolt,
770 .rfact = RFACT(232, 56)
773 .desc = "-5V",
774 .type = ENVSYS_SVOLTS_DC,
775 .bank = 0,
776 .reg = 0x26,
777 .refresh = wb_refresh_nvolt,
778 .rfact = RFACT(120, 56)
781 .desc = "5VSB",
782 .type = ENVSYS_SVOLTS_DC,
783 .bank = 5,
784 .reg = 0x50,
785 .refresh = lm_refresh_volt,
786 .rfact = RFACT(17, 33)
789 .desc = "VBAT",
790 .type = ENVSYS_SVOLTS_DC,
791 .bank = 5,
792 .reg = 0x51,
793 .refresh = lm_refresh_volt,
794 .rfact = RFACT_NONE
797 /* Temperature */
799 .desc = "Temp0",
800 .type = ENVSYS_STEMP,
801 .bank = 0,
802 .reg = 0x27,
803 .refresh = lm_refresh_temp,
804 .rfact = 0
807 .desc = "Temp1",
808 .type = ENVSYS_STEMP,
809 .bank = 1,
810 .reg = 0x50,
811 .refresh = wb_refresh_temp,
812 .rfact = 0
815 /* Fans */
817 .desc = "Fan0",
818 .type = ENVSYS_SFANRPM,
819 .bank = 0,
820 .reg = 0x28,
821 .refresh = wb_refresh_fanrpm,
822 .rfact = 0
825 .desc = "Fan1",
826 .type = ENVSYS_SFANRPM,
827 .bank = 0,
828 .reg = 0x29,
829 .refresh = wb_refresh_fanrpm,
830 .rfact = 0
833 { .desc = NULL }
836 /* W83781D */
839 * The datasheet doesn't mention the (internal) resistors used for the
840 * +5V, but using the values from the W83782D datasheets seems to
841 * provide sensible results.
843 static struct lm_sensor w83781d_sensors[] = {
844 /* Voltage */
846 .desc = "VCore A",
847 .type = ENVSYS_SVOLTS_DC,
848 .bank = 0,
849 .reg = 0x20,
850 .refresh = lm_refresh_volt,
851 .rfact = RFACT_NONE
854 .desc = "VCore B",
855 .type = ENVSYS_SVOLTS_DC,
856 .bank = 0,
857 .reg = 0x21,
858 .refresh = lm_refresh_volt,
859 .rfact = RFACT_NONE
862 .desc = "+3.3V",
863 .type = ENVSYS_SVOLTS_DC,
864 .bank = 0,
865 .reg = 0x22,
866 .refresh = lm_refresh_volt,
867 .rfact = RFACT_NONE
870 .desc = "+5V",
871 .type = ENVSYS_SVOLTS_DC,
872 .bank = 0,
873 .reg = 0x23,
874 .refresh = lm_refresh_volt,
875 .rfact = RFACT(34, 50)
878 .desc = "+12V",
879 .type = ENVSYS_SVOLTS_DC,
880 .bank = 0,
881 .reg = 0x24,
882 .refresh = lm_refresh_volt,
883 .rfact = RFACT(28, 10)
886 .desc = "-12V",
887 .type = ENVSYS_SVOLTS_DC,
888 .bank = 0,
889 .reg = 0x25,
890 .refresh = lm_refresh_volt,
891 .rfact = NRFACT(2100, 604)
894 .desc = "-5V",
895 .type = ENVSYS_SVOLTS_DC,
896 .bank = 0,
897 .reg = 0x26,
898 .refresh = lm_refresh_volt,
899 .rfact = NRFACT(909, 604)
902 /* Temperature */
904 .desc = "Temp0",
905 .type = ENVSYS_STEMP,
906 .bank = 0,
907 .reg = 0x27,
908 .refresh = lm_refresh_temp,
909 .rfact = 0
912 .desc = "Temp1",
913 .type = ENVSYS_STEMP,
914 .bank = 1,
915 .reg = 0x50,
916 .refresh = wb_refresh_temp,
917 .rfact = 0
920 .desc = "Temp2",
921 .type = ENVSYS_STEMP,
922 .bank = 2,
923 .reg = 0x50,
924 .refresh = wb_refresh_temp,
925 .rfact = 0
928 /* Fans */
930 .desc = "Fan0",
931 .type = ENVSYS_SFANRPM,
932 .bank = 0,
933 .reg = 0x28,
934 .refresh = lm_refresh_fanrpm,
935 .rfact = 0
938 .desc = "Fan1",
939 .type = ENVSYS_SFANRPM,
940 .bank = 0,
941 .reg = 0x29,
942 .refresh = lm_refresh_fanrpm,
943 .rfact = 0
946 .desc = "Fan2",
947 .type = ENVSYS_SFANRPM,
948 .bank = 0,
949 .reg = 0x2a,
950 .refresh = lm_refresh_fanrpm,
951 .rfact = 0
954 { .desc = NULL }
957 /* W83782D */
958 static struct lm_sensor w83782d_sensors[] = {
959 /* Voltage */
961 .desc = "VCore",
962 .type = ENVSYS_SVOLTS_DC,
963 .bank = 0,
964 .reg = 0x20,
965 .refresh = lm_refresh_volt,
966 .rfact = RFACT_NONE
969 .desc = "VINR0",
970 .type = ENVSYS_SVOLTS_DC,
971 .bank = 0,
972 .reg = 0x21,
973 .refresh = lm_refresh_volt,
974 .rfact = RFACT_NONE
977 .desc = "+3.3V",
978 .type = ENVSYS_SVOLTS_DC,
979 .bank = 0,
980 .reg = 0x22,
981 .refresh = lm_refresh_volt,
982 .rfact = RFACT_NONE
985 .desc = "+5V",
986 .type = ENVSYS_SVOLTS_DC,
987 .bank = 0,
988 .reg = 0x23,
989 .refresh = lm_refresh_volt,
990 .rfact = RFACT(34, 50)
993 .desc = "+12V",
994 .type = ENVSYS_SVOLTS_DC,
995 .bank = 0,
996 .reg = 0x24,
997 .refresh = lm_refresh_volt,
998 .rfact = RFACT(28, 10)
1001 .desc = "-12V",
1002 .type = ENVSYS_SVOLTS_DC,
1003 .bank = 0,
1004 .reg = 0x25,
1005 .refresh = wb_refresh_nvolt,
1006 .rfact = RFACT(232, 56)
1009 .desc = "-5V",
1010 .type = ENVSYS_SVOLTS_DC,
1011 .bank = 0,
1012 .reg = 0x26,
1013 .refresh = wb_refresh_nvolt,
1014 .rfact = RFACT(120, 56)
1017 .desc = "5VSB",
1018 .type = ENVSYS_SVOLTS_DC,
1019 .bank = 5,
1020 .reg = 0x50,
1021 .refresh = lm_refresh_volt,
1022 .rfact = RFACT(17, 33)
1025 .desc = "VBAT",
1026 .type = ENVSYS_SVOLTS_DC,
1027 .bank = 5,
1028 .reg = 0x51,
1029 .refresh = lm_refresh_volt,
1030 .rfact = RFACT_NONE
1033 /* Temperature */
1035 .desc = "Temp0",
1036 .type = ENVSYS_STEMP,
1037 .bank = 0,
1038 .reg = 0x27,
1039 .refresh = lm_refresh_temp,
1040 .rfact = 0
1043 .desc = "Temp1",
1044 .type = ENVSYS_STEMP,
1045 .bank = 1,
1046 .reg = 0x50,
1047 .refresh = wb_refresh_temp,
1048 .rfact = 0
1051 .desc = "Temp2",
1052 .type = ENVSYS_STEMP,
1053 .bank = 2,
1054 .reg = 0x50,
1055 .refresh = wb_refresh_temp,
1056 .rfact = 0
1059 /* Fans */
1061 .desc = "Fan0",
1062 .type = ENVSYS_SFANRPM,
1063 .bank = 0,
1064 .reg = 0x28,
1065 .refresh = wb_refresh_fanrpm,
1066 .rfact = 0
1069 .desc = "Fan1",
1070 .type = ENVSYS_SFANRPM,
1071 .bank = 0,
1072 .reg = 0x29,
1073 .refresh = wb_refresh_fanrpm,
1074 .rfact = 0
1077 .desc = "Fan2",
1078 .type = ENVSYS_SFANRPM,
1079 .bank = 0,
1080 .reg = 0x2a,
1081 .refresh = wb_refresh_fanrpm,
1082 .rfact = 0
1085 { .desc = NULL }
1088 /* W83783S */
1089 static struct lm_sensor w83783s_sensors[] = {
1090 /* Voltage */
1092 .desc = "VCore",
1093 .type = ENVSYS_SVOLTS_DC,
1094 .bank = 0,
1095 .reg = 0x20,
1096 .refresh = lm_refresh_volt,
1097 .rfact = RFACT_NONE
1100 .desc = "+3.3V",
1101 .type = ENVSYS_SVOLTS_DC,
1102 .bank = 0,
1103 .reg = 0x22,
1104 .refresh = lm_refresh_volt,
1105 .rfact = RFACT_NONE
1108 .desc = "+5V",
1109 .type = ENVSYS_SVOLTS_DC,
1110 .bank = 0,
1111 .reg = 0x23,
1112 .refresh = lm_refresh_volt,
1113 .rfact = RFACT(34, 50)
1116 .desc = "+12V",
1117 .type = ENVSYS_SVOLTS_DC,
1118 .bank = 0,
1119 .reg = 0x24,
1120 .refresh = lm_refresh_volt,
1121 .rfact = RFACT(28, 10)
1124 .desc = "-12V",
1125 .type = ENVSYS_SVOLTS_DC,
1126 .bank = 0,
1127 .reg = 0x25,
1128 .refresh = wb_refresh_nvolt,
1129 .rfact = RFACT(232, 56)
1132 .desc = "-5V",
1133 .type = ENVSYS_SVOLTS_DC,
1134 .bank = 0,
1135 .reg = 0x26,
1136 .refresh = wb_refresh_nvolt,
1137 .rfact = RFACT(120, 56)
1140 /* Temperature */
1142 .desc = "Temp0",
1143 .type = ENVSYS_STEMP,
1144 .bank = 0,
1145 .reg = 0x27,
1146 .refresh = lm_refresh_temp,
1147 .rfact = 0
1150 .desc = "Temp1",
1151 .type = ENVSYS_STEMP,
1152 .bank = 1,
1153 .reg = 0x50,
1154 .refresh = wb_refresh_temp,
1155 .rfact = 0
1158 /* Fans */
1160 .desc = "Fan0",
1161 .type = ENVSYS_SFANRPM,
1162 .bank = 0,
1163 .reg = 0x28,
1164 .refresh = wb_refresh_fanrpm,
1165 .rfact = 0
1168 .desc = "Fan1",
1169 .type = ENVSYS_SFANRPM,
1170 .bank = 0,
1171 .reg = 0x29,
1172 .refresh = wb_refresh_fanrpm,
1173 .rfact = 0
1176 .desc = "Fan2",
1177 .type = ENVSYS_SFANRPM,
1178 .bank = 0,
1179 .reg = 0x2a,
1180 .refresh = wb_refresh_fanrpm,
1181 .rfact = 0
1184 { .desc = NULL }
1187 /* W83791D */
1188 static struct lm_sensor w83791d_sensors[] = {
1189 /* Voltage */
1191 .desc = "VCore",
1192 .type = ENVSYS_SVOLTS_DC,
1193 .bank = 0,
1194 .reg = 0x20,
1195 .refresh = lm_refresh_volt,
1196 .rfact = 10000
1199 .desc = "VINR0",
1200 .type = ENVSYS_SVOLTS_DC,
1201 .bank = 0,
1202 .reg = 0x21,
1203 .refresh = lm_refresh_volt,
1204 .rfact = 10000
1207 .desc = "+3.3V",
1208 .type = ENVSYS_SVOLTS_DC,
1209 .bank = 0,
1210 .reg = 0x22,
1211 .refresh = lm_refresh_volt,
1212 .rfact = 10000
1215 .desc = "+5V",
1216 .type = ENVSYS_SVOLTS_DC,
1217 .bank = 0,
1218 .reg = 0x23,
1219 .refresh = lm_refresh_volt,
1220 .rfact = RFACT(34, 50)
1223 .desc = "+12V",
1224 .type = ENVSYS_SVOLTS_DC,
1225 .bank = 0,
1226 .reg = 0x24,
1227 .refresh = lm_refresh_volt,
1228 .rfact = RFACT(28, 10)
1231 .desc = "-12V",
1232 .type = ENVSYS_SVOLTS_DC,
1233 .bank = 0,
1234 .reg = 0x25,
1235 .refresh = wb_refresh_nvolt,
1236 .rfact = RFACT(232, 56)
1239 .desc = "-5V",
1240 .type = ENVSYS_SVOLTS_DC,
1241 .bank = 0,
1242 .reg = 0x26,
1243 .refresh = wb_refresh_nvolt,
1244 .rfact = RFACT(120, 56)
1247 .desc = "5VSB",
1248 .type = ENVSYS_SVOLTS_DC,
1249 .bank = 0,
1250 .reg = 0xb0,
1251 .refresh = lm_refresh_volt,
1252 .rfact = RFACT(17, 33)
1255 .desc = "VBAT",
1256 .type = ENVSYS_SVOLTS_DC,
1257 .bank = 0,
1258 .reg = 0xb1,
1259 .refresh = lm_refresh_volt,
1260 .rfact = RFACT_NONE
1263 .desc = "VINR1",
1264 .type = ENVSYS_SVOLTS_DC,
1265 .bank = 0,
1266 .reg = 0xb2,
1267 .refresh = lm_refresh_volt,
1268 .rfact = RFACT_NONE
1271 /* Temperature */
1273 .desc = "Temp0",
1274 .type = ENVSYS_STEMP,
1275 .bank = 0,
1276 .reg = 0x27,
1277 .refresh = lm_refresh_temp,
1278 .rfact = 0
1281 .desc = "Temp1",
1282 .type = ENVSYS_STEMP,
1283 .bank = 0,
1284 .reg = 0xc0,
1285 .refresh = wb_refresh_temp,
1286 .rfact = 0
1289 .desc = "Temp2",
1290 .type = ENVSYS_STEMP,
1291 .bank = 0,
1292 .reg = 0xc8,
1293 .refresh = wb_refresh_temp,
1294 .rfact = 0
1297 /* Fans */
1299 .desc = "Fan0",
1300 .type = ENVSYS_SFANRPM,
1301 .bank = 0,
1302 .reg = 0x28,
1303 .refresh = wb_refresh_fanrpm,
1304 .rfact = 0
1307 .desc = "Fan1",
1308 .type = ENVSYS_SFANRPM,
1309 .bank = 0,
1310 .reg = 0x29,
1311 .refresh = wb_refresh_fanrpm,
1312 .rfact = 0
1315 .desc = "Fan2",
1316 .type = ENVSYS_SFANRPM,
1317 .bank = 0,
1318 .reg = 0x2a,
1319 .refresh = wb_refresh_fanrpm,
1320 .rfact = 0
1323 .desc = "Fan3",
1324 .type = ENVSYS_SFANRPM,
1325 .bank = 0,
1326 .reg = 0xba,
1327 .refresh = wb_refresh_fanrpm,
1328 .rfact = 0
1331 .desc = "Fan4",
1332 .type = ENVSYS_SFANRPM,
1333 .bank = 0,
1334 .reg = 0xbb,
1335 .refresh = wb_refresh_fanrpm,
1336 .rfact = 0
1339 { .desc = NULL }
1342 /* W83792D */
1343 static struct lm_sensor w83792d_sensors[] = {
1344 /* Voltage */
1346 .desc = "VCore A",
1347 .type = ENVSYS_SVOLTS_DC,
1348 .bank = 0,
1349 .reg = 0x20,
1350 .refresh = lm_refresh_volt,
1351 .rfact = RFACT_NONE
1354 .desc = "VCore B",
1355 .type = ENVSYS_SVOLTS_DC,
1356 .bank = 0,
1357 .reg = 0x21,
1358 .refresh = lm_refresh_volt,
1359 .rfact = RFACT_NONE
1362 .desc = "+3.3V",
1363 .type = ENVSYS_SVOLTS_DC,
1364 .bank = 0,
1365 .reg = 0x22,
1366 .refresh = lm_refresh_volt,
1367 .rfact = RFACT_NONE
1370 .desc = "-5V",
1371 .type = ENVSYS_SVOLTS_DC,
1372 .bank = 0,
1373 .reg = 0x23,
1374 .refresh = wb_refresh_nvolt,
1375 .rfact = RFACT(120, 56)
1378 .desc = "+12V",
1379 .type = ENVSYS_SVOLTS_DC,
1380 .bank = 0,
1381 .reg = 0x24,
1382 .refresh = lm_refresh_volt,
1383 .rfact = RFACT(28, 10)
1386 .desc = "-12V",
1387 .type = ENVSYS_SVOLTS_DC,
1388 .bank = 0,
1389 .reg = 0x25,
1390 .refresh = wb_refresh_nvolt,
1391 .rfact = RFACT(232, 56)
1394 .desc = "+5V",
1395 .type = ENVSYS_SVOLTS_DC,
1396 .bank = 0,
1397 .reg = 0x26,
1398 .refresh = lm_refresh_volt,
1399 .rfact = RFACT(34, 50)
1402 .desc = "5VSB",
1403 .type = ENVSYS_SVOLTS_DC,
1404 .bank = 0,
1405 .reg = 0xb0,
1406 .refresh = lm_refresh_volt,
1407 .rfact = RFACT(17, 33)
1410 .desc = "VBAT",
1411 .type = ENVSYS_SVOLTS_DC,
1412 .bank = 0,
1413 .reg = 0xb1,
1414 .refresh = lm_refresh_volt,
1415 .rfact = RFACT_NONE
1418 /* Temperature */
1420 .desc = "Temp0",
1421 .type = ENVSYS_STEMP,
1422 .bank = 0,
1423 .reg = 0x27,
1424 .refresh = lm_refresh_temp,
1425 .rfact = 0
1428 .desc = "Temp1",
1429 .type = ENVSYS_STEMP,
1430 .bank = 0,
1431 .reg = 0xc0,
1432 .refresh = wb_refresh_temp,
1433 .rfact = 0
1436 .desc = "Temp2",
1437 .type = ENVSYS_STEMP,
1438 .bank = 0,
1439 .reg = 0xc8,
1440 .refresh = wb_refresh_temp,
1441 .rfact = 0
1444 /* Fans */
1446 .desc = "Fan0",
1447 .type = ENVSYS_SFANRPM,
1448 .bank = 0,
1449 .reg = 0x28,
1450 .refresh = wb_w83792d_refresh_fanrpm,
1451 .rfact = 0
1454 .desc = "Fan1",
1455 .type = ENVSYS_SFANRPM,
1456 .bank = 0,
1457 .reg = 0x29,
1458 .refresh = wb_w83792d_refresh_fanrpm,
1459 .rfact = 0
1462 .desc = "Fan2",
1463 .type = ENVSYS_SFANRPM,
1464 .bank = 0,
1465 .reg = 0x2a,
1466 .refresh = wb_w83792d_refresh_fanrpm,
1467 .rfact = 0
1470 .desc = "Fan3",
1471 .type = ENVSYS_SFANRPM,
1472 .bank = 0,
1473 .reg = 0xb8,
1474 .refresh = wb_w83792d_refresh_fanrpm,
1475 .rfact = 0
1478 .desc = "Fan4",
1479 .type = ENVSYS_SFANRPM,
1480 .bank = 0,
1481 .reg = 0xb9,
1482 .refresh = wb_w83792d_refresh_fanrpm,
1483 .rfact = 0
1486 .desc = "Fan5",
1487 .type = ENVSYS_SFANRPM,
1488 .bank = 0,
1489 .reg = 0xba,
1490 .refresh = wb_w83792d_refresh_fanrpm,
1491 .rfact = 0
1494 .desc = "Fan6",
1495 .type = ENVSYS_SFANRPM,
1496 .bank = 0,
1497 .reg = 0xbe,
1498 .refresh = wb_w83792d_refresh_fanrpm,
1499 .rfact = 0
1502 { .desc = NULL }
1505 /* AS99127F */
1506 static struct lm_sensor as99127f_sensors[] = {
1507 /* Voltage */
1509 .desc = "VCore A",
1510 .type = ENVSYS_SVOLTS_DC,
1511 .bank = 0,
1512 .reg = 0x20,
1513 .refresh = lm_refresh_volt,
1514 .rfact = RFACT_NONE
1517 .desc = "VCore B",
1518 .type = ENVSYS_SVOLTS_DC,
1519 .bank = 0,
1520 .reg = 0x21,
1521 .refresh = lm_refresh_volt,
1522 .rfact = RFACT_NONE
1525 .desc = "+3.3V",
1526 .type = ENVSYS_SVOLTS_DC,
1527 .bank = 0,
1528 .reg = 0x22,
1529 .refresh = lm_refresh_volt,
1530 .rfact = RFACT_NONE
1533 .desc = "+5V",
1534 .type = ENVSYS_SVOLTS_DC,
1535 .bank = 0,
1536 .reg = 0x23,
1537 .refresh = lm_refresh_volt,
1538 .rfact = RFACT(34, 50)
1541 .desc = "+12V",
1542 .type = ENVSYS_SVOLTS_DC,
1543 .bank = 0,
1544 .reg = 0x24,
1545 .refresh = lm_refresh_volt,
1546 .rfact = RFACT(28, 10)
1549 .desc = "-12V",
1550 .type = ENVSYS_SVOLTS_DC,
1551 .bank = 0,
1552 .reg = 0x25,
1553 .refresh = wb_refresh_nvolt,
1554 .rfact = RFACT(232, 56)
1557 .desc = "-5V",
1558 .type = ENVSYS_SVOLTS_DC,
1559 .bank = 0,
1560 .reg = 0x26,
1561 .refresh = wb_refresh_nvolt,
1562 .rfact = RFACT(120, 56)
1565 /* Temperature */
1567 .desc = "Temp0",
1568 .type = ENVSYS_STEMP,
1569 .bank = 0,
1570 .reg = 0x27,
1571 .refresh = lm_refresh_temp,
1572 .rfact = 0
1575 .desc = "Temp1",
1576 .type = ENVSYS_STEMP,
1577 .bank = 1,
1578 .reg = 0x50,
1579 .refresh = as_refresh_temp,
1580 .rfact = 0
1583 .desc = "Temp2",
1584 .type = ENVSYS_STEMP,
1585 .bank = 2,
1586 .reg = 0x50,
1587 .refresh = as_refresh_temp,
1588 .rfact = 0
1591 /* Fans */
1593 .desc = "Fan0",
1594 .type = ENVSYS_SFANRPM,
1595 .bank = 0,
1596 .reg = 0x28,
1597 .refresh = lm_refresh_fanrpm,
1598 .rfact = 0
1601 .desc = "Fan1",
1602 .type = ENVSYS_SFANRPM,
1603 .bank = 0,
1604 .reg = 0x29,
1605 .refresh = lm_refresh_fanrpm,
1606 .rfact = 0
1609 .desc = "Fan2",
1610 .type = ENVSYS_SFANRPM,
1611 .bank = 0,
1612 .reg = 0x2a,
1613 .refresh = lm_refresh_fanrpm,
1614 .rfact = 0
1617 { .desc = NULL }
1620 static void
1621 lm_generic_banksel(struct lm_softc *lmsc, int bank)
1623 (*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank);
1627 * bus independent probe
1629 * prerequisites: lmsc contains valid lm_{read,write}reg() routines
1630 * and associated bus access data is present in attachment's softc
1633 lm_probe(struct lm_softc *lmsc)
1635 uint8_t cr;
1636 int rv;
1638 /* Perform LM78 reset */
1639 /*(*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x80); */
1641 cr = (*lmsc->lm_readreg)(lmsc, LMD_CONFIG);
1643 /* XXX - spec says *only* 0x08! */
1644 if ((cr == 0x08) || (cr == 0x01) || (cr == 0x03) || (cr == 0x06))
1645 rv = 1;
1646 else
1647 rv = 0;
1649 DPRINTF(("%s: rv = %d, cr = %x\n", __func__, rv, cr));
1651 return rv;
1654 void
1655 lm_attach(struct lm_softc *lmsc)
1657 uint32_t i;
1659 for (i = 0; i < __arraycount(lm_chips); i++)
1660 if (lm_chips[i].chip_match(lmsc))
1661 break;
1663 /* Start the monitoring loop */
1664 (*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x01);
1666 lmsc->sc_sme = sysmon_envsys_create();
1667 /* Initialize sensors */
1668 for (i = 0; i < lmsc->numsensors; i++) {
1669 if (sysmon_envsys_sensor_attach(lmsc->sc_sme,
1670 &lmsc->sensors[i])) {
1671 sysmon_envsys_destroy(lmsc->sc_sme);
1672 return;
1677 * Setup the callout to refresh sensor data every 2 seconds.
1679 callout_init(&lmsc->sc_callout, 0);
1680 callout_setfunc(&lmsc->sc_callout, lm_refresh, lmsc);
1681 callout_schedule(&lmsc->sc_callout, LM_REFRESH_TIMO);
1684 * Hook into the System Monitor.
1686 lmsc->sc_sme->sme_name = device_xname(lmsc->sc_dev);
1687 lmsc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
1689 if (sysmon_envsys_register(lmsc->sc_sme)) {
1690 aprint_error_dev(lmsc->sc_dev,
1691 "unable to register with sysmon\n");
1692 sysmon_envsys_destroy(lmsc->sc_sme);
1697 * Stop, destroy the callout and unregister the driver with the
1698 * sysmon_envsys(9) framework.
1700 void
1701 lm_detach(struct lm_softc *lmsc)
1703 callout_stop(&lmsc->sc_callout);
1704 callout_destroy(&lmsc->sc_callout);
1705 sysmon_envsys_unregister(lmsc->sc_sme);
1708 static void
1709 lm_refresh(void *arg)
1711 struct lm_softc *lmsc = arg;
1713 lmsc->refresh_sensor_data(lmsc);
1714 callout_schedule(&lmsc->sc_callout, LM_REFRESH_TIMO);
1717 static int
1718 lm_match(struct lm_softc *sc)
1720 const char *model = NULL;
1721 int chipid;
1723 /* See if we have an LM78/LM78J/LM79 or LM81 */
1724 chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
1725 switch(chipid) {
1726 case LM_ID_LM78:
1727 model = "LM78";
1728 break;
1729 case LM_ID_LM78J:
1730 model = "LM78J";
1731 break;
1732 case LM_ID_LM79:
1733 model = "LM79";
1734 break;
1735 case LM_ID_LM81:
1736 model = "LM81";
1737 break;
1738 default:
1739 return 0;
1742 aprint_normal("\n");
1743 aprint_normal_dev(sc->sc_dev,
1744 "National Semiconductor %s Hardware monitor\n", model);
1746 lm_setup_sensors(sc, lm78_sensors);
1747 sc->refresh_sensor_data = lm_refresh_sensor_data;
1748 return 1;
1751 static int
1752 def_match(struct lm_softc *sc)
1754 int chipid;
1756 chipid = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
1757 aprint_normal("\n");
1758 aprint_error_dev(sc->sc_dev, "Unknown chip (ID %d)\n", chipid);
1760 lm_setup_sensors(sc, lm78_sensors);
1761 sc->refresh_sensor_data = lm_refresh_sensor_data;
1762 return 1;
1765 static int
1766 wb_match(struct lm_softc *sc)
1768 const char *model = NULL;
1769 int banksel, vendid, devid;
1771 aprint_normal("\n");
1772 /* Read vendor ID */
1773 banksel = (*sc->lm_readreg)(sc, WB_BANKSEL);
1774 lm_generic_banksel(sc, WB_BANKSEL_HBAC);
1775 vendid = (*sc->lm_readreg)(sc, WB_VENDID) << 8;
1776 lm_generic_banksel(sc, 0);
1777 vendid |= (*sc->lm_readreg)(sc, WB_VENDID);
1778 DPRINTF(("%s: winbond vend id 0x%x\n", __func__, vendid));
1779 if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
1780 return 0;
1782 /* Read device/chip ID */
1783 lm_generic_banksel(sc, WB_BANKSEL_B0);
1784 devid = (*sc->lm_readreg)(sc, LMD_CHIPID);
1785 sc->chipid = (*sc->lm_readreg)(sc, WB_BANK0_CHIPID);
1786 lm_generic_banksel(sc, banksel);
1787 DPRINTF(("%s: winbond chip id 0x%x\n", __func__, sc->chipid));
1789 switch(sc->chipid) {
1790 case WB_CHIPID_W83627HF:
1791 model = "W83627HF";
1792 lm_setup_sensors(sc, w83627hf_sensors);
1793 break;
1794 case WB_CHIPID_W83627THF:
1795 model = "W83627THF";
1796 lm_setup_sensors(sc, w83637hf_sensors);
1797 break;
1798 case WB_CHIPID_W83627EHF_A:
1799 model = "W83627EHF-A";
1800 lm_setup_sensors(sc, w83627ehf_sensors);
1801 break;
1802 case WB_CHIPID_W83627EHF:
1803 model = "W83627EHF";
1804 lm_setup_sensors(sc, w83627ehf_sensors);
1805 break;
1806 case WB_CHIPID_W83627DHG:
1807 model = "W83627DHG";
1808 lm_setup_sensors(sc, w83627dhg_sensors);
1809 break;
1810 case WB_CHIPID_W83637HF:
1811 model = "W83637HF";
1812 lm_generic_banksel(sc, WB_BANKSEL_B0);
1813 if ((*sc->lm_readreg)(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
1814 sc->vrm9 = 1;
1815 lm_generic_banksel(sc, banksel);
1816 lm_setup_sensors(sc, w83637hf_sensors);
1817 break;
1818 case WB_CHIPID_W83697HF:
1819 model = "W83697HF";
1820 lm_setup_sensors(sc, w83697hf_sensors);
1821 break;
1822 case WB_CHIPID_W83781D:
1823 case WB_CHIPID_W83781D_2:
1824 model = "W83781D";
1825 lm_setup_sensors(sc, w83781d_sensors);
1826 break;
1827 case WB_CHIPID_W83782D:
1828 model = "W83782D";
1829 lm_setup_sensors(sc, w83782d_sensors);
1830 break;
1831 case WB_CHIPID_W83783S:
1832 model = "W83783S";
1833 lm_setup_sensors(sc, w83783s_sensors);
1834 break;
1835 case WB_CHIPID_W83791D:
1836 model = "W83791D";
1837 lm_setup_sensors(sc, w83791d_sensors);
1838 break;
1839 case WB_CHIPID_W83791SD:
1840 model = "W83791SD";
1841 break;
1842 case WB_CHIPID_W83792D:
1843 model = "W83792D";
1844 lm_setup_sensors(sc, w83792d_sensors);
1845 break;
1846 case WB_CHIPID_AS99127F:
1847 if (vendid == WB_VENDID_ASUS) {
1848 model = "AS99127F";
1849 lm_setup_sensors(sc, w83781d_sensors);
1850 } else {
1851 model = "AS99127F rev 2";
1852 lm_setup_sensors(sc, as99127f_sensors);
1854 break;
1855 default:
1856 aprint_normal_dev(sc->sc_dev,
1857 "unknown Winbond chip (ID 0x%x)\n", sc->chipid);
1858 /* Handle as a standard LM78. */
1859 lm_setup_sensors(sc, lm78_sensors);
1860 sc->refresh_sensor_data = lm_refresh_sensor_data;
1861 return 1;
1864 aprint_normal_dev(sc->sc_dev, "Winbond %s Hardware monitor\n", model);
1866 sc->refresh_sensor_data = wb_refresh_sensor_data;
1867 return 1;
1870 static void
1871 lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
1873 int i;
1875 for (i = 0; sensors[i].desc; i++) {
1876 sc->sensors[i].units = sensors[i].type;
1877 strlcpy(sc->sensors[i].desc, sensors[i].desc,
1878 sizeof(sc->sensors[i].desc));
1879 sc->numsensors++;
1881 sc->lm_sensors = sensors;
1884 static void
1885 lm_refresh_sensor_data(struct lm_softc *sc)
1887 int i;
1889 for (i = 0; i < sc->numsensors; i++)
1890 sc->lm_sensors[i].refresh(sc, i);
1893 static void
1894 lm_refresh_volt(struct lm_softc *sc, int n)
1896 int data;
1898 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1899 if (data == 0xff) {
1900 sc->sensors[n].state = ENVSYS_SINVALID;
1901 } else {
1902 sc->sensors[n].flags = ENVSYS_FCHANGERFACT;
1903 sc->sensors[n].value_cur = (data << 4);
1904 if (sc->sensors[n].rfact) {
1905 sc->sensors[n].value_cur *= sc->sensors[n].rfact;
1906 sc->sensors[n].value_cur /= 10;
1907 } else {
1908 sc->sensors[n].value_cur *= sc->lm_sensors[n].rfact;
1909 sc->sensors[n].value_cur /= 10;
1910 sc->sensors[n].rfact = sc->lm_sensors[n].rfact;
1912 sc->sensors[n].state = ENVSYS_SVALID;
1915 DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
1916 __func__, n, data, sc->sensors[n].value_cur));
1919 static void
1920 lm_refresh_temp(struct lm_softc *sc, int n)
1922 int data;
1925 * The data sheet suggests that the range of the temperature
1926 * sensor is between -55 degC and +125 degC.
1928 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1929 if (data > 0x7d && data < 0xc9)
1930 sc->sensors[n].state = ENVSYS_SINVALID;
1931 else {
1932 if (data & 0x80)
1933 data -= 0x100;
1934 sc->sensors[n].state = ENVSYS_SVALID;
1935 sc->sensors[n].value_cur = data * 1000000 + 273150000;
1937 DPRINTF(("%s: temp[%d] data=0x%x value_cur=%d\n",
1938 __func__, n, data, sc->sensors[n].value_cur));
1941 static void
1942 lm_refresh_fanrpm(struct lm_softc *sc, int n)
1944 int data, divisor = 1;
1947 * We might get more accurate fan readings by adjusting the
1948 * divisor, but that might interfere with APM or other SMM
1949 * BIOS code reading the fan speeds.
1952 /* FAN3 has a fixed fan divisor. */
1953 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
1954 sc->lm_sensors[n].reg == LMD_FAN2) {
1955 data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
1956 if (sc->lm_sensors[n].reg == LMD_FAN1)
1957 divisor = (data >> 4) & 0x03;
1958 else
1959 divisor = (data >> 6) & 0x03;
1962 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1963 if (data == 0xff || data == 0x00)
1964 sc->sensors[n].state = ENVSYS_SINVALID;
1965 else {
1966 sc->sensors[n].state = ENVSYS_SVALID;
1967 sc->sensors[n].value_cur = 1350000 / (data << divisor);
1969 DPRINTF(("%s: fan[%d] data=0x%x value_cur=%d\n",
1970 __func__, n, data, sc->sensors[n].value_cur));
1973 static void
1974 wb_refresh_sensor_data(struct lm_softc *sc)
1976 int banksel, bank, i;
1979 * Properly save and restore bank selection register.
1981 banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
1982 for (i = 0; i < sc->numsensors; i++) {
1983 if (bank != sc->lm_sensors[i].bank) {
1984 bank = sc->lm_sensors[i].bank;
1985 lm_generic_banksel(sc, bank);
1987 sc->lm_sensors[i].refresh(sc, i);
1989 lm_generic_banksel(sc, banksel);
1992 static void
1993 wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
1995 int data;
1997 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
1999 * Depending on the voltage detection method,
2000 * one of the following formulas is used:
2001 * VRM8 method: value = raw * 0.016V
2002 * VRM9 method: value = raw * 0.00488V + 0.70V
2004 if (sc->vrm9)
2005 sc->sensors[n].value_cur = (data * 4880) + 700000;
2006 else
2007 sc->sensors[n].value_cur = (data * 16000);
2008 DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
2009 __func__, n, data, sc->sensors[n].value_cur));
2012 static void
2013 wb_refresh_nvolt(struct lm_softc *sc, int n)
2015 int data;
2017 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2018 sc->sensors[n].flags = ENVSYS_FCHANGERFACT;
2019 sc->sensors[n].value_cur = ((data << 4) - WB_VREF);
2020 if (sc->sensors[n].rfact)
2021 sc->sensors[n].value_cur *= sc->sensors[n].rfact;
2022 else
2023 sc->sensors[n].value_cur *= sc->lm_sensors[n].rfact;
2025 sc->sensors[n].value_cur /= 10;
2026 sc->sensors[n].value_cur += WB_VREF * 1000;
2027 DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
2028 __func__, n , data, sc->sensors[n].value_cur));
2031 static void
2032 wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
2034 int data;
2036 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2037 sc->sensors[n].value_cur = ((data << 3) - WB_W83627EHF_VREF);
2038 sc->sensors[n].flags = ENVSYS_FCHANGERFACT;
2039 if (sc->sensors[n].rfact)
2040 sc->sensors[n].value_cur *= sc->sensors[n].rfact;
2041 else
2042 sc->sensors[n].value_cur *= RFACT(232, 10);
2044 sc->sensors[n].value_cur /= 10;
2045 sc->sensors[n].value_cur += WB_W83627EHF_VREF * 1000;
2046 DPRINTF(("%s: volt[%d] data=0x%x value_cur=%d\n",
2047 __func__, n , data, sc->sensors[n].value_cur));
2050 static void
2051 wb_refresh_temp(struct lm_softc *sc, int n)
2053 int data;
2056 * The data sheet suggests that the range of the temperature
2057 * sensor is between -55 degC and +125 degC. However, values
2058 * around -48 degC seem to be a very common bogus values.
2059 * Since such values are unreasonably low, we use -45 degC for
2060 * the lower limit instead.
2062 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
2063 data += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
2064 if (data > 0xfffffff || (data > 0x0fa && data < 0x1a6)) {
2065 sc->sensors[n].state = ENVSYS_SINVALID;
2066 } else {
2067 if (data & 0x100)
2068 data -= 0x200;
2069 sc->sensors[n].state = ENVSYS_SVALID;
2070 sc->sensors[n].value_cur = data * 500000 + 273150000;
2072 DPRINTF(("%s: temp[%d] data=0x%x value_cur=%d\n",
2073 __func__, n , data, sc->sensors[n].value_cur));
2076 static void
2077 wb_refresh_fanrpm(struct lm_softc *sc, int n)
2079 int fan, data, divisor = 0;
2082 * This is madness; the fan divisor bits are scattered all
2083 * over the place.
2086 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
2087 sc->lm_sensors[n].reg == LMD_FAN2 ||
2088 sc->lm_sensors[n].reg == LMD_FAN3) {
2089 data = (*sc->lm_readreg)(sc, WB_BANK0_VBAT);
2090 fan = (sc->lm_sensors[n].reg - LMD_FAN1);
2091 if ((data >> 5) & (1 << fan))
2092 divisor |= 0x04;
2095 if (sc->lm_sensors[n].reg == LMD_FAN1 ||
2096 sc->lm_sensors[n].reg == LMD_FAN2) {
2097 data = (*sc->lm_readreg)(sc, LMD_VIDFAN);
2098 if (sc->lm_sensors[n].reg == LMD_FAN1)
2099 divisor |= (data >> 4) & 0x03;
2100 else
2101 divisor |= (data >> 6) & 0x03;
2102 } else if (sc->lm_sensors[n].reg == LMD_FAN3) {
2103 data = (*sc->lm_readreg)(sc, WB_PIN);
2104 divisor |= (data >> 6) & 0x03;
2105 } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
2106 sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
2107 data = (*sc->lm_readreg)(sc, WB_BANK0_FAN45);
2108 if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
2109 divisor |= (data >> 0) & 0x07;
2110 else
2111 divisor |= (data >> 4) & 0x07;
2114 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2115 if (data >= 0xff || data == 0x00)
2116 sc->sensors[n].state = ENVSYS_SINVALID;
2117 else {
2118 sc->sensors[n].state = ENVSYS_SVALID;
2119 sc->sensors[n].value_cur = 1350000 / (data << divisor);
2121 DPRINTF(("%s: fan[%d] data=0x%x value_cur=%d\n",
2122 __func__, n , data, sc->sensors[n].value_cur));
2125 static void
2126 wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
2128 int reg, shift, data, divisor = 1;
2130 shift = 0;
2132 switch (sc->lm_sensors[n].reg) {
2133 case 0x28:
2134 reg = 0x47; shift = 0;
2135 break;
2136 case 0x29:
2137 reg = 0x47; shift = 4;
2138 break;
2139 case 0x2a:
2140 reg = 0x5b; shift = 0;
2141 break;
2142 case 0xb8:
2143 reg = 0x5b; shift = 4;
2144 break;
2145 case 0xb9:
2146 reg = 0x5c; shift = 0;
2147 break;
2148 case 0xba:
2149 reg = 0x5c; shift = 4;
2150 break;
2151 case 0xbe:
2152 reg = 0x9e; shift = 0;
2153 break;
2154 default:
2155 reg = 0;
2156 break;
2159 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg);
2160 if (data == 0xff || data == 0x00)
2161 sc->sensors[n].state = ENVSYS_SINVALID;
2162 else {
2163 if (reg != 0)
2164 divisor = ((*sc->lm_readreg)(sc, reg) >> shift) & 0x7;
2165 sc->sensors[n].state = ENVSYS_SVALID;
2166 sc->sensors[n].value_cur = 1350000 / (data << divisor);
2168 DPRINTF(("%s: fan[%d] data=0x%x value_cur=%d\n",
2169 __func__, n , data, sc->sensors[n].value_cur));
2172 static void
2173 as_refresh_temp(struct lm_softc *sc, int n)
2175 int data;
2178 * It seems a shorted temperature diode produces an all-ones
2179 * bit pattern.
2181 data = (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg) << 1;
2182 data += (*sc->lm_readreg)(sc, sc->lm_sensors[n].reg + 1) >> 7;
2183 if (data == 0x1ff)
2184 sc->sensors[n].state = ENVSYS_SINVALID;
2185 else {
2186 if (data & 0x100)
2187 data -= 0x200;
2188 sc->sensors[n].state = ENVSYS_SVALID;
2189 sc->sensors[n].value_cur = data * 500000 + 273150000;
2191 DPRINTF(("%s: temp[%d] data=0x%x value_cur=%d\n",
2192 __func__, n, data, sc->sensors[n].value_cur));