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