Annotation of sys/dev/ic/lm78.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: lm78.c,v 1.20 2007/06/25 22:50:18 cnst Exp $ */
2:
3: /*
4: * Copyright (c) 2005, 2006 Mark Kettenis
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21: #include <sys/device.h>
22: #include <sys/kernel.h>
23: #include <sys/queue.h>
24: #include <sys/sensors.h>
25: #include <machine/bus.h>
26:
27: #include <dev/ic/lm78var.h>
28:
29: #if defined(LMDEBUG)
30: #define DPRINTF(x) do { printf x; } while (0)
31: #else
32: #define DPRINTF(x)
33: #endif
34:
35: /*
36: * LM78-compatible chips can typically measure voltages up to 4.096 V.
37: * To measure higher voltages the input is attenuated with (external)
38: * resistors. Negative voltages are measured using inverting op amps
39: * and resistors. So we have to convert the sensor values back to
40: * real voltages by applying the appropriate resistor factor.
41: */
42: #define RFACT_NONE 10000
43: #define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
44: #define NRFACT(x, y) (-RFACT_NONE * (x) / (y))
45:
46: struct cfdriver lm_cd = {
47: NULL, "lm", DV_DULL
48: };
49:
50: int lm_match(struct lm_softc *);
51: int wb_match(struct lm_softc *);
52: int def_match(struct lm_softc *);
53:
54: void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
55: void lm_refresh(void *);
56:
57: void lm_refresh_sensor_data(struct lm_softc *);
58: void lm_refresh_volt(struct lm_softc *, int);
59: void lm_refresh_temp(struct lm_softc *, int);
60: void lm_refresh_fanrpm(struct lm_softc *, int);
61:
62: void wb_refresh_sensor_data(struct lm_softc *);
63: void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
64: void wb_refresh_nvolt(struct lm_softc *, int);
65: void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
66: void wb_refresh_temp(struct lm_softc *, int);
67: void wb_refresh_fanrpm(struct lm_softc *, int);
68: void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
69:
70: void as_refresh_temp(struct lm_softc *, int);
71:
72: struct lm_chip {
73: int (*chip_match)(struct lm_softc *);
74: };
75:
76: struct lm_chip lm_chips[] = {
77: { wb_match },
78: { lm_match },
79: { def_match } /* Must be last */
80: };
81:
82: struct lm_sensor lm78_sensors[] = {
83: /* Voltage */
84: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
85: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
86: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
87: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(68, 100) },
88: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(30, 10) },
89: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(240, 60) },
90: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(100, 60) },
91:
92: /* Temperature */
93: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
94:
95: /* Fans */
96: { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
97: { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
98: { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
99:
100: { NULL }
101: };
102:
103: struct lm_sensor w83627hf_sensors[] = {
104: /* Voltage */
105: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
106: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
107: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
108: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
109: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
110: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
111: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
112: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
113: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
114:
115: /* Temperature */
116: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
117: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
118: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
119:
120: /* Fans */
121: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
122: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
123: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
124:
125: { NULL }
126: };
127:
128: /*
129: * The W83627EHF can measure voltages up to 2.048 V instead of the
130: * traditional 4.096 V. For measuring positive voltages, this can be
131: * accounted for by halving the resistor factor. Negative voltages
132: * need special treatment, also because the reference voltage is 2.048 V
133: * instead of the traditional 3.6 V.
134: */
135: struct lm_sensor w83627ehf_sensors[] = {
136: /* Voltage */
137: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
138: { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
139: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
140: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
141: { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
142: { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
143: { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
144: { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
145: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
146: { "", SENSOR_VOLTS_DC, 5, 0x52, lm_refresh_volt, RFACT_NONE / 2 },
147:
148: /* Temperature */
149: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
150: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
151: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
152:
153: /* Fans */
154: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
155: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
156: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
157:
158: { NULL }
159: };
160:
161: /*
162: * w83627dhg is almost identical to w83627ehf, except that
163: * it has 9 instead of 10 voltage sensors
164: */
165: struct lm_sensor w83627dhg_sensors[] = {
166: /* Voltage */
167: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
168: { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
169: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
170: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
171: { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
172: { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
173: { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
174: { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
175: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
176:
177: /* Temperature */
178: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
179: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
180: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
181:
182: /* Fans */
183: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
184: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
185: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
186:
187: { NULL }
188: };
189:
190: struct lm_sensor w83637hf_sensors[] = {
191: /* Voltage */
192: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
193: { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) },
194: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
195: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) },
196: { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) },
197: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) },
198: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
199:
200: /* Temperature */
201: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
202: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
203: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
204:
205: /* Fans */
206: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
207: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
208: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
209:
210: { NULL }
211: };
212:
213: struct lm_sensor w83697hf_sensors[] = {
214: /* Voltage */
215: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
216: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
217: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
218: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
219: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
220: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
221: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
222: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
223:
224: /* Temperature */
225: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
226: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
227:
228: /* Fans */
229: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
230: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
231:
232: { NULL }
233: };
234:
235: /*
236: * The datasheet doesn't mention the (internal) resistors used for the
237: * +5V, but using the values from the W83782D datasheets seems to
238: * provide sensible results.
239: */
240: struct lm_sensor w83781d_sensors[] = {
241: /* Voltage */
242: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
243: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
244: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
245: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
246: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
247: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) },
248: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) },
249:
250: /* Temperature */
251: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
252: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
253: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
254:
255: /* Fans */
256: { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
257: { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
258: { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
259:
260: { NULL }
261: };
262:
263: struct lm_sensor w83782d_sensors[] = {
264: /* Voltage */
265: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
266: { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
267: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
268: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
269: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
270: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
271: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
272: { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
273: { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
274:
275: /* Temperature */
276: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
277: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
278: { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
279:
280: /* Fans */
281: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
282: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
283: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
284:
285: { NULL }
286: };
287:
288: struct lm_sensor w83783s_sensors[] = {
289: /* Voltage */
290: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
291: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
292: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
293: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
294: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
295: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
296:
297: /* Temperature */
298: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
299: { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
300:
301: /* Fans */
302: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
303: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
304: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
305:
306: { NULL }
307: };
308:
309: struct lm_sensor w83791d_sensors[] = {
310: /* Voltage */
311: { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, 10000 },
312: { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, 10000 },
313: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, 10000 },
314: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
315: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
316: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
317: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
318: { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
319: { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
320: { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE },
321:
322: /* Temperature */
323: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
324: { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
325: { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
326:
327: /* Fans */
328: { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
329: { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
330: { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
331: { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm },
332: { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm },
333:
334: { NULL }
335: };
336:
337: struct lm_sensor w83792d_sensors[] = {
338: /* Voltage */
339: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
340: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
341: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
342: { "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) },
343: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
344: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
345: { "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) },
346: { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
347: { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
348:
349: /* Temperature */
350: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
351: { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
352: { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
353:
354: /* Fans */
355: { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm },
356: { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm },
357: { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm },
358: { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm },
359: { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm },
360: { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm },
361: { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm },
362:
363: { NULL }
364: };
365:
366: struct lm_sensor as99127f_sensors[] = {
367: /* Voltage */
368: { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
369: { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
370: { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
371: { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
372: { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
373: { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
374: { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
375:
376: /* Temperature */
377: { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
378: { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp },
379: { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp },
380:
381: /* Fans */
382: { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
383: { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
384: { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
385:
386: { NULL }
387: };
388:
389: void
390: lm_attach(struct lm_softc *sc)
391: {
392: u_int i, config;
393:
394: for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
395: if (lm_chips[i].chip_match(sc))
396: break;
397:
398: /* No point in doing anything if we don't have any sensors. */
399: if (sc->numsensors == 0)
400: return;
401:
402: sc->sensortask = sensor_task_register(sc, lm_refresh, 5);
403: if (sc->sensortask == NULL) {
404: printf("%s: unable to register update task\n",
405: sc->sc_dev.dv_xname);
406: return;
407: }
408:
409: /* Start the monitoring loop */
410: config = sc->lm_readreg(sc, LM_CONFIG);
411: sc->lm_writereg(sc, LM_CONFIG, config | 0x01);
412:
413: /* Add sensors */
414: for (i = 0; i < sc->numsensors; ++i)
415: sensor_attach(&sc->sensordev, &sc->sensors[i]);
416: sensordev_install(&sc->sensordev);
417: }
418:
419: int
420: lm_detach(struct lm_softc *sc)
421: {
422: int i;
423:
424: /* Remove sensors */
425: sensordev_deinstall(&sc->sensordev);
426: for (i = 0; i < sc->numsensors; i++)
427: sensor_detach(&sc->sensordev, &sc->sensors[i]);
428:
429: if (sc->sensortask != NULL)
430: sensor_task_unregister(sc->sensortask);
431:
432: return 0;
433: }
434:
435: int
436: lm_match(struct lm_softc *sc)
437: {
438: int chipid;
439:
440: /* See if we have an LM78 or LM79. */
441: chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
442: switch(chipid) {
443: case LM_CHIPID_LM78:
444: printf(": LM78\n");
445: break;
446: case LM_CHIPID_LM78J:
447: printf(": LM78J\n");
448: break;
449: case LM_CHIPID_LM79:
450: printf(": LM79\n");
451: break;
452: case LM_CHIPID_LM81:
453: printf(": LM81\n");
454: break;
455: default:
456: return 0;
457: }
458:
459: lm_setup_sensors(sc, lm78_sensors);
460: sc->refresh_sensor_data = lm_refresh_sensor_data;
461: return 1;
462: }
463:
464: int
465: def_match(struct lm_softc *sc)
466: {
467: int chipid;
468:
469: chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
470: printf(": unknown chip (ID %d)\n", chipid);
471:
472: lm_setup_sensors(sc, lm78_sensors);
473: sc->refresh_sensor_data = lm_refresh_sensor_data;
474: return 1;
475: }
476:
477: int
478: wb_match(struct lm_softc *sc)
479: {
480: int banksel, vendid, devid;
481:
482: /* Read vendor ID */
483: banksel = sc->lm_readreg(sc, WB_BANKSEL);
484: sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
485: vendid = sc->lm_readreg(sc, WB_VENDID) << 8;
486: sc->lm_writereg(sc, WB_BANKSEL, 0);
487: vendid |= sc->lm_readreg(sc, WB_VENDID);
488: sc->lm_writereg(sc, WB_BANKSEL, banksel);
489: DPRINTF((" winbond vend id 0x%x\n", vendid));
490: if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
491: return 0;
492:
493: /* Read device/chip ID */
494: sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
495: devid = sc->lm_readreg(sc, LM_CHIPID);
496: sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID);
497: sc->lm_writereg(sc, WB_BANKSEL, banksel);
498: DPRINTF((" winbond chip id 0x%x\n", sc->chipid));
499: switch(sc->chipid) {
500: case WB_CHIPID_W83627HF:
501: printf(": W83627HF\n");
502: lm_setup_sensors(sc, w83627hf_sensors);
503: break;
504: case WB_CHIPID_W83627THF:
505: printf(": W83627THF\n");
506: lm_setup_sensors(sc, w83637hf_sensors);
507: break;
508: case WB_CHIPID_W83627EHF_A:
509: printf(": W83627EHF-A\n");
510: lm_setup_sensors(sc, w83627ehf_sensors);
511: break;
512: case WB_CHIPID_W83627EHF:
513: printf(": W83627EHF\n");
514: lm_setup_sensors(sc, w83627ehf_sensors);
515: break;
516: case WB_CHIPID_W83627DHG:
517: printf(": W83627DHG\n");
518: lm_setup_sensors(sc, w83627dhg_sensors);
519: break;
520: case WB_CHIPID_W83637HF:
521: printf(": W83637HF\n");
522: sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
523: if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
524: sc->vrm9 = 1;
525: sc->lm_writereg(sc, WB_BANKSEL, banksel);
526: lm_setup_sensors(sc, w83637hf_sensors);
527: break;
528: case WB_CHIPID_W83697HF:
529: printf(": W83697HF\n");
530: lm_setup_sensors(sc, w83697hf_sensors);
531: break;
532: case WB_CHIPID_W83781D:
533: case WB_CHIPID_W83781D_2:
534: printf(": W83781D\n");
535: lm_setup_sensors(sc, w83781d_sensors);
536: break;
537: case WB_CHIPID_W83782D:
538: printf(": W83782D\n");
539: lm_setup_sensors(sc, w83782d_sensors);
540: break;
541: case WB_CHIPID_W83783S:
542: printf(": W83783S\n");
543: lm_setup_sensors(sc, w83783s_sensors);
544: break;
545: case WB_CHIPID_W83791D:
546: printf(": W83791D\n");
547: lm_setup_sensors(sc, w83791d_sensors);
548: break;
549: case WB_CHIPID_W83791SD:
550: printf(": W83791SD\n");
551: break;
552: case WB_CHIPID_W83792D:
553: if (devid >= 0x10 && devid <= 0x29)
554: printf(": W83792D rev %c\n", 'A' + devid - 0x10);
555: else
556: printf(": W83792D rev 0x%x\n", devid);
557: lm_setup_sensors(sc, w83792d_sensors);
558: break;
559: case WB_CHIPID_AS99127F:
560: if (vendid == WB_VENDID_ASUS) {
561: printf(": AS99127F\n");
562: lm_setup_sensors(sc, w83781d_sensors);
563: } else {
564: printf(": AS99127F rev 2\n");
565: lm_setup_sensors(sc, as99127f_sensors);
566: }
567: break;
568: default:
569: printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid);
570: /* Handle as a standard LM78. */
571: lm_setup_sensors(sc, lm78_sensors);
572: sc->refresh_sensor_data = lm_refresh_sensor_data;
573: return 1;
574: }
575:
576: sc->refresh_sensor_data = wb_refresh_sensor_data;
577: return 1;
578: }
579:
580: void
581: lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
582: {
583: int i;
584:
585: strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
586: sizeof(sc->sensordev.xname));
587:
588: for (i = 0; sensors[i].desc; i++) {
589: sc->sensors[i].type = sensors[i].type;
590: strlcpy(sc->sensors[i].desc, sensors[i].desc,
591: sizeof(sc->sensors[i].desc));
592: sc->numsensors++;
593: }
594: sc->lm_sensors = sensors;
595: }
596:
597: void
598: lm_refresh(void *arg)
599: {
600: struct lm_softc *sc = arg;
601:
602: sc->refresh_sensor_data(sc);
603: }
604:
605: void
606: lm_refresh_sensor_data(struct lm_softc *sc)
607: {
608: int i;
609:
610: for (i = 0; i < sc->numsensors; i++)
611: sc->lm_sensors[i].refresh(sc, i);
612: }
613:
614: void
615: lm_refresh_volt(struct lm_softc *sc, int n)
616: {
617: struct ksensor *sensor = &sc->sensors[n];
618: int data;
619:
620: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
621: sensor->value = (data << 4);
622: sensor->value *= sc->lm_sensors[n].rfact;
623: sensor->value /= 10;
624: }
625:
626: void
627: lm_refresh_temp(struct lm_softc *sc, int n)
628: {
629: struct ksensor *sensor = &sc->sensors[n];
630: int sdata;
631:
632: /*
633: * The data sheet suggests that the range of the temperature
634: * sensor is between -55 degC and +125 degC.
635: */
636: sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
637: if (sdata > 0x7d && sdata < 0xc9) {
638: sensor->flags |= SENSOR_FINVALID;
639: sensor->value = 0;
640: } else {
641: if (sdata & 0x80)
642: sdata -= 0x100;
643: sensor->flags &= ~SENSOR_FINVALID;
644: sensor->value = sdata * 1000000 + 273150000;
645: }
646: }
647:
648: void
649: lm_refresh_fanrpm(struct lm_softc *sc, int n)
650: {
651: struct ksensor *sensor = &sc->sensors[n];
652: int data, divisor = 1;
653:
654: /*
655: * We might get more accurate fan readings by adjusting the
656: * divisor, but that might interfere with APM or other SMM
657: * BIOS code reading the fan speeds.
658: */
659:
660: /* FAN3 has a fixed fan divisor. */
661: if (sc->lm_sensors[n].reg == LM_FAN1 ||
662: sc->lm_sensors[n].reg == LM_FAN2) {
663: data = sc->lm_readreg(sc, LM_VIDFAN);
664: if (sc->lm_sensors[n].reg == LM_FAN1)
665: divisor = (data >> 4) & 0x03;
666: else
667: divisor = (data >> 6) & 0x03;
668: }
669:
670: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
671: if (data == 0xff || data == 0x00) {
672: sensor->flags |= SENSOR_FINVALID;
673: sensor->value = 0;
674: } else {
675: sensor->flags &= ~SENSOR_FINVALID;
676: sensor->value = 1350000 / (data << divisor);
677: }
678: }
679:
680: void
681: wb_refresh_sensor_data(struct lm_softc *sc)
682: {
683: int banksel, bank, i;
684:
685: /*
686: * Properly save and restore bank selection register.
687: */
688:
689: banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
690: for (i = 0; i < sc->numsensors; i++) {
691: if (bank != sc->lm_sensors[i].bank) {
692: bank = sc->lm_sensors[i].bank;
693: sc->lm_writereg(sc, WB_BANKSEL, bank);
694: }
695: sc->lm_sensors[i].refresh(sc, i);
696: }
697: sc->lm_writereg(sc, WB_BANKSEL, banksel);
698: }
699:
700: void
701: wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
702: {
703: struct ksensor *sensor = &sc->sensors[n];
704: int data;
705:
706: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
707:
708: /*
709: * Depending on the voltage detection method,
710: * one of the following formulas is used:
711: * VRM8 method: value = raw * 0.016V
712: * VRM9 method: value = raw * 0.00488V + 0.70V
713: */
714: if (sc->vrm9)
715: sensor->value = (data * 4880) + 700000;
716: else
717: sensor->value = (data * 16000);
718: }
719:
720: void
721: wb_refresh_nvolt(struct lm_softc *sc, int n)
722: {
723: struct ksensor *sensor = &sc->sensors[n];
724: int data;
725:
726: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
727: sensor->value = ((data << 4) - WB_VREF);
728: sensor->value *= sc->lm_sensors[n].rfact;
729: sensor->value /= 10;
730: sensor->value += WB_VREF * 1000;
731: }
732:
733: void
734: wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
735: {
736: struct ksensor *sensor = &sc->sensors[n];
737: int data;
738:
739: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
740: sensor->value = ((data << 3) - WB_W83627EHF_VREF);
741: sensor->value *= RFACT(232, 10);
742: sensor->value /= 10;
743: sensor->value += WB_W83627EHF_VREF * 1000;
744: }
745:
746: void
747: wb_refresh_temp(struct lm_softc *sc, int n)
748: {
749: struct ksensor *sensor = &sc->sensors[n];
750: int sdata;
751:
752: /*
753: * The data sheet suggests that the range of the temperature
754: * sensor is between -55 degC and +125 degC. However, values
755: * around -48 degC seem to be a very common bogus values.
756: * Since such values are unreasonably low, we use -45 degC for
757: * the lower limit instead.
758: */
759: sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
760: sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
761: if (sdata > 0x0fa && sdata < 0x1a6) {
762: sensor->flags |= SENSOR_FINVALID;
763: sensor->value = 0;
764: } else {
765: if (sdata & 0x100)
766: sdata -= 0x200;
767: sensor->flags &= ~SENSOR_FINVALID;
768: sensor->value = sdata * 500000 + 273150000;
769: }
770: }
771:
772: void
773: wb_refresh_fanrpm(struct lm_softc *sc, int n)
774: {
775: struct ksensor *sensor = &sc->sensors[n];
776: int fan, data, divisor = 0;
777:
778: /*
779: * This is madness; the fan divisor bits are scattered all
780: * over the place.
781: */
782:
783: if (sc->lm_sensors[n].reg == LM_FAN1 ||
784: sc->lm_sensors[n].reg == LM_FAN2 ||
785: sc->lm_sensors[n].reg == LM_FAN3) {
786: data = sc->lm_readreg(sc, WB_BANK0_VBAT);
787: fan = (sc->lm_sensors[n].reg - LM_FAN1);
788: if ((data >> 5) & (1 << fan))
789: divisor |= 0x04;
790: }
791:
792: if (sc->lm_sensors[n].reg == LM_FAN1 ||
793: sc->lm_sensors[n].reg == LM_FAN2) {
794: data = sc->lm_readreg(sc, LM_VIDFAN);
795: if (sc->lm_sensors[n].reg == LM_FAN1)
796: divisor |= (data >> 4) & 0x03;
797: else
798: divisor |= (data >> 6) & 0x03;
799: } else if (sc->lm_sensors[n].reg == LM_FAN3) {
800: data = sc->lm_readreg(sc, WB_PIN);
801: divisor |= (data >> 6) & 0x03;
802: } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
803: sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
804: data = sc->lm_readreg(sc, WB_BANK0_FAN45);
805: if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
806: divisor |= (data >> 0) & 0x07;
807: else
808: divisor |= (data >> 4) & 0x07;
809: }
810:
811: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
812: if (data == 0xff || data == 0x00) {
813: sensor->flags |= SENSOR_FINVALID;
814: sensor->value = 0;
815: } else {
816: sensor->flags &= ~SENSOR_FINVALID;
817: sensor->value = 1350000 / (data << divisor);
818: }
819: }
820:
821: void
822: wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
823: {
824: struct ksensor *sensor = &sc->sensors[n];
825: int reg, shift, data, divisor = 1;
826:
827: switch (sc->lm_sensors[n].reg) {
828: case 0x28:
829: reg = 0x47; shift = 0;
830: break;
831: case 0x29:
832: reg = 0x47; shift = 4;
833: break;
834: case 0x2a:
835: reg = 0x5b; shift = 0;
836: break;
837: case 0xb8:
838: reg = 0x5b; shift = 4;
839: break;
840: case 0xb9:
841: reg = 0x5c; shift = 0;
842: break;
843: case 0xba:
844: reg = 0x5c; shift = 4;
845: break;
846: case 0xbe:
847: reg = 0x9e; shift = 0;
848: break;
849: default:
850: reg = 0;
851: break;
852: }
853:
854: data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
855: if (data == 0xff || data == 0x00) {
856: sensor->flags |= SENSOR_FINVALID;
857: sensor->value = 0;
858: } else {
859: if (reg != 0)
860: divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7;
861: sensor->flags &= ~SENSOR_FINVALID;
862: sensor->value = 1350000 / (data << divisor);
863: }
864: }
865:
866: void
867: as_refresh_temp(struct lm_softc *sc, int n)
868: {
869: struct ksensor *sensor = &sc->sensors[n];
870: int sdata;
871:
872: /*
873: * It seems a shorted temperature diode produces an all-ones
874: * bit pattern.
875: */
876: sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
877: sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
878: if (sdata == 0x1ff) {
879: sensor->flags |= SENSOR_FINVALID;
880: sensor->value = 0;
881: } else {
882: if (sdata & 0x100)
883: sdata -= 0x200;
884: sensor->flags &= ~SENSOR_FINVALID;
885: sensor->value = sdata * 500000 + 273150000;
886: }
887: }
CVSweb