1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34
35#include <linux/module.h>
36#include <linux/slab.h>
37#include <linux/pci.h>
38#include <linux/jiffies.h>
39#include <linux/platform_device.h>
40#include <linux/hwmon.h>
41#include <linux/hwmon-sysfs.h>
42#include <linux/err.h>
43#include <linux/init.h>
44#include <linux/mutex.h>
45#include <linux/sysfs.h>
46#include <linux/acpi.h>
47#include <linux/io.h>
48
49
50
51
52static unsigned short force_addr;
53module_param(force_addr, ushort, 0);
54MODULE_PARM_DESC(force_addr,
55 "Initialize the base address of the sensors");
56
57static struct platform_device *pdev;
58
59
60
61
62
63
64
65
66
67#define VIA686A_EXTENT 0x80
68#define VIA686A_BASE_REG 0x70
69#define VIA686A_ENABLE_REG 0x74
70
71
72
73#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
74#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
75#define VIA686A_REG_IN(nr) (0x22 + (nr))
76
77
78#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
79#define VIA686A_REG_FAN(nr) (0x28 + (nr))
80
81
82static const u8 VIA686A_REG_TEMP[] = { 0x20, 0x21, 0x1f };
83static const u8 VIA686A_REG_TEMP_OVER[] = { 0x39, 0x3d, 0x1d };
84static const u8 VIA686A_REG_TEMP_HYST[] = { 0x3a, 0x3e, 0x1e };
85
86#define VIA686A_REG_TEMP_LOW1 0x4b
87
88#define VIA686A_REG_TEMP_LOW23 0x49
89
90#define VIA686A_REG_ALARM1 0x41
91#define VIA686A_REG_ALARM2 0x42
92#define VIA686A_REG_FANDIV 0x47
93#define VIA686A_REG_CONFIG 0x40
94
95
96
97
98
99
100#define VIA686A_REG_TEMP_MODE 0x4b
101
102#define VIA686A_TEMP_MODE_MASK 0x3F
103#define VIA686A_TEMP_MODE_CONTINUOUS 0x00
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121static inline u8 IN_TO_REG(long val, int inNum)
122{
123
124
125
126
127
128 if (inNum <= 1)
129 return (u8)
130 SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255);
131 else if (inNum == 2)
132 return (u8)
133 SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255);
134 else if (inNum == 3)
135 return (u8)
136 SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255);
137 else
138 return (u8)
139 SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255);
140}
141
142static inline long IN_FROM_REG(u8 val, int inNum)
143{
144
145
146
147 if (inNum <= 1)
148 return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024);
149 else if (inNum == 2)
150 return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737);
151 else if (inNum == 3)
152 return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108);
153 else
154 return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714);
155}
156
157
158
159
160
161static inline u8 FAN_TO_REG(long rpm, int div)
162{
163 if (rpm == 0)
164 return 0;
165 rpm = SENSORS_LIMIT(rpm, 1, 1000000);
166 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
167}
168
169#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203static const s16 tempLUT[] =
204{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
205 -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
206 -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
207 -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
208 -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
209 -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
210 -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
211 20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
212 88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
213 142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
214 193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
215 245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
216 299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
217 353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
218 409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
219 469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
220 538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
221 621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
222 728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
223 870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
224 1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
225 1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
226};
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249static const u8 viaLUT[] =
250{ 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
251 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
252 41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
253 69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
254 103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
255 131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
256 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
257 182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
258 200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
259 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
260 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
261 233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
262 239, 240
263};
264
265
266
267
268static inline u8 TEMP_TO_REG(long val)
269{
270 return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
271 (val < 0 ? val - 500 : val + 500) / 1000 + 50];
272}
273
274
275#define TEMP_FROM_REG(val) ((long)tempLUT[val] * 100)
276
277
278static inline long TEMP_FROM_REG10(u16 val)
279{
280 u16 eightBits = val >> 2;
281 u16 twoBits = val & 3;
282
283
284 if (twoBits == 0 || eightBits == 255)
285 return TEMP_FROM_REG(eightBits);
286
287
288 return (tempLUT[eightBits] * (4 - twoBits) +
289 tempLUT[eightBits + 1] * twoBits) * 25;
290}
291
292#define DIV_FROM_REG(val) (1 << (val))
293#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
294
295
296
297struct via686a_data {
298 unsigned short addr;
299 const char *name;
300 struct device *hwmon_dev;
301 struct mutex update_lock;
302 char valid;
303 unsigned long last_updated;
304
305 u8 in[5];
306 u8 in_max[5];
307 u8 in_min[5];
308 u8 fan[2];
309 u8 fan_min[2];
310 u16 temp[3];
311 u8 temp_over[3];
312 u8 temp_hyst[3];
313 u8 fan_div[2];
314 u16 alarms;
315};
316
317static struct pci_dev *s_bridge;
318
319static int via686a_probe(struct platform_device *pdev);
320static int __devexit via686a_remove(struct platform_device *pdev);
321
322static inline int via686a_read_value(struct via686a_data *data, u8 reg)
323{
324 return inb_p(data->addr + reg);
325}
326
327static inline void via686a_write_value(struct via686a_data *data, u8 reg,
328 u8 value)
329{
330 outb_p(value, data->addr + reg);
331}
332
333static struct via686a_data *via686a_update_device(struct device *dev);
334static void via686a_init_device(struct via686a_data *data);
335
336
337
338
339static ssize_t show_in(struct device *dev, struct device_attribute *da,
340 char *buf) {
341 struct via686a_data *data = via686a_update_device(dev);
342 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
343 int nr = attr->index;
344 return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr));
345}
346
347static ssize_t show_in_min(struct device *dev, struct device_attribute *da,
348 char *buf) {
349 struct via686a_data *data = via686a_update_device(dev);
350 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
351 int nr = attr->index;
352 return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr));
353}
354
355static ssize_t show_in_max(struct device *dev, struct device_attribute *da,
356 char *buf) {
357 struct via686a_data *data = via686a_update_device(dev);
358 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
359 int nr = attr->index;
360 return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
361}
362
363static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
364 const char *buf, size_t count) {
365 struct via686a_data *data = dev_get_drvdata(dev);
366 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
367 int nr = attr->index;
368 unsigned long val = simple_strtoul(buf, NULL, 10);
369
370 mutex_lock(&data->update_lock);
371 data->in_min[nr] = IN_TO_REG(val, nr);
372 via686a_write_value(data, VIA686A_REG_IN_MIN(nr),
373 data->in_min[nr]);
374 mutex_unlock(&data->update_lock);
375 return count;
376}
377static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
378 const char *buf, size_t count) {
379 struct via686a_data *data = dev_get_drvdata(dev);
380 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
381 int nr = attr->index;
382 unsigned long val = simple_strtoul(buf, NULL, 10);
383
384 mutex_lock(&data->update_lock);
385 data->in_max[nr] = IN_TO_REG(val, nr);
386 via686a_write_value(data, VIA686A_REG_IN_MAX(nr),
387 data->in_max[nr]);
388 mutex_unlock(&data->update_lock);
389 return count;
390}
391#define show_in_offset(offset) \
392static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
393 show_in, NULL, offset); \
394static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
395 show_in_min, set_in_min, offset); \
396static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
397 show_in_max, set_in_max, offset);
398
399show_in_offset(0);
400show_in_offset(1);
401show_in_offset(2);
402show_in_offset(3);
403show_in_offset(4);
404
405
406static ssize_t show_temp(struct device *dev, struct device_attribute *da,
407 char *buf) {
408 struct via686a_data *data = via686a_update_device(dev);
409 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
410 int nr = attr->index;
411 return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr]));
412}
413static ssize_t show_temp_over(struct device *dev, struct device_attribute *da,
414 char *buf) {
415 struct via686a_data *data = via686a_update_device(dev);
416 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
417 int nr = attr->index;
418 return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr]));
419}
420static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da,
421 char *buf) {
422 struct via686a_data *data = via686a_update_device(dev);
423 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
424 int nr = attr->index;
425 return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
426}
427static ssize_t set_temp_over(struct device *dev, struct device_attribute *da,
428 const char *buf, size_t count) {
429 struct via686a_data *data = dev_get_drvdata(dev);
430 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
431 int nr = attr->index;
432 int val = simple_strtol(buf, NULL, 10);
433
434 mutex_lock(&data->update_lock);
435 data->temp_over[nr] = TEMP_TO_REG(val);
436 via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr],
437 data->temp_over[nr]);
438 mutex_unlock(&data->update_lock);
439 return count;
440}
441static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da,
442 const char *buf, size_t count) {
443 struct via686a_data *data = dev_get_drvdata(dev);
444 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
445 int nr = attr->index;
446 int val = simple_strtol(buf, NULL, 10);
447
448 mutex_lock(&data->update_lock);
449 data->temp_hyst[nr] = TEMP_TO_REG(val);
450 via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr],
451 data->temp_hyst[nr]);
452 mutex_unlock(&data->update_lock);
453 return count;
454}
455#define show_temp_offset(offset) \
456static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
457 show_temp, NULL, offset - 1); \
458static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
459 show_temp_over, set_temp_over, offset - 1); \
460static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
461 show_temp_hyst, set_temp_hyst, offset - 1);
462
463show_temp_offset(1);
464show_temp_offset(2);
465show_temp_offset(3);
466
467
468static ssize_t show_fan(struct device *dev, struct device_attribute *da,
469 char *buf) {
470 struct via686a_data *data = via686a_update_device(dev);
471 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
472 int nr = attr->index;
473 return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
474 DIV_FROM_REG(data->fan_div[nr])) );
475}
476static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
477 char *buf) {
478 struct via686a_data *data = via686a_update_device(dev);
479 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
480 int nr = attr->index;
481 return sprintf(buf, "%d\n",
482 FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
483}
484static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
485 char *buf) {
486 struct via686a_data *data = via686a_update_device(dev);
487 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
488 int nr = attr->index;
489 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
490}
491static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
492 const char *buf, size_t count) {
493 struct via686a_data *data = dev_get_drvdata(dev);
494 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
495 int nr = attr->index;
496 int val = simple_strtol(buf, NULL, 10);
497
498 mutex_lock(&data->update_lock);
499 data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
500 via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
501 mutex_unlock(&data->update_lock);
502 return count;
503}
504static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
505 const char *buf, size_t count) {
506 struct via686a_data *data = dev_get_drvdata(dev);
507 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
508 int nr = attr->index;
509 int val = simple_strtol(buf, NULL, 10);
510 int old;
511
512 mutex_lock(&data->update_lock);
513 old = via686a_read_value(data, VIA686A_REG_FANDIV);
514 data->fan_div[nr] = DIV_TO_REG(val);
515 old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
516 via686a_write_value(data, VIA686A_REG_FANDIV, old);
517 mutex_unlock(&data->update_lock);
518 return count;
519}
520
521#define show_fan_offset(offset) \
522static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
523 show_fan, NULL, offset - 1); \
524static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
525 show_fan_min, set_fan_min, offset - 1); \
526static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
527 show_fan_div, set_fan_div, offset - 1);
528
529show_fan_offset(1);
530show_fan_offset(2);
531
532
533static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) {
534 struct via686a_data *data = via686a_update_device(dev);
535 return sprintf(buf, "%u\n", data->alarms);
536}
537static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
538
539static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
540 char *buf)
541{
542 int bitnr = to_sensor_dev_attr(attr)->index;
543 struct via686a_data *data = via686a_update_device(dev);
544 return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
545}
546static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
547static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
548static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
549static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
550static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8);
551static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
552static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 11);
553static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 15);
554static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
555static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
556
557static ssize_t show_name(struct device *dev, struct device_attribute
558 *devattr, char *buf)
559{
560 struct via686a_data *data = dev_get_drvdata(dev);
561 return sprintf(buf, "%s\n", data->name);
562}
563static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
564
565static struct attribute *via686a_attributes[] = {
566 &sensor_dev_attr_in0_input.dev_attr.attr,
567 &sensor_dev_attr_in1_input.dev_attr.attr,
568 &sensor_dev_attr_in2_input.dev_attr.attr,
569 &sensor_dev_attr_in3_input.dev_attr.attr,
570 &sensor_dev_attr_in4_input.dev_attr.attr,
571 &sensor_dev_attr_in0_min.dev_attr.attr,
572 &sensor_dev_attr_in1_min.dev_attr.attr,
573 &sensor_dev_attr_in2_min.dev_attr.attr,
574 &sensor_dev_attr_in3_min.dev_attr.attr,
575 &sensor_dev_attr_in4_min.dev_attr.attr,
576 &sensor_dev_attr_in0_max.dev_attr.attr,
577 &sensor_dev_attr_in1_max.dev_attr.attr,
578 &sensor_dev_attr_in2_max.dev_attr.attr,
579 &sensor_dev_attr_in3_max.dev_attr.attr,
580 &sensor_dev_attr_in4_max.dev_attr.attr,
581 &sensor_dev_attr_in0_alarm.dev_attr.attr,
582 &sensor_dev_attr_in1_alarm.dev_attr.attr,
583 &sensor_dev_attr_in2_alarm.dev_attr.attr,
584 &sensor_dev_attr_in3_alarm.dev_attr.attr,
585 &sensor_dev_attr_in4_alarm.dev_attr.attr,
586
587 &sensor_dev_attr_temp1_input.dev_attr.attr,
588 &sensor_dev_attr_temp2_input.dev_attr.attr,
589 &sensor_dev_attr_temp3_input.dev_attr.attr,
590 &sensor_dev_attr_temp1_max.dev_attr.attr,
591 &sensor_dev_attr_temp2_max.dev_attr.attr,
592 &sensor_dev_attr_temp3_max.dev_attr.attr,
593 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
594 &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
595 &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
596 &sensor_dev_attr_temp1_alarm.dev_attr.attr,
597 &sensor_dev_attr_temp2_alarm.dev_attr.attr,
598 &sensor_dev_attr_temp3_alarm.dev_attr.attr,
599
600 &sensor_dev_attr_fan1_input.dev_attr.attr,
601 &sensor_dev_attr_fan2_input.dev_attr.attr,
602 &sensor_dev_attr_fan1_min.dev_attr.attr,
603 &sensor_dev_attr_fan2_min.dev_attr.attr,
604 &sensor_dev_attr_fan1_div.dev_attr.attr,
605 &sensor_dev_attr_fan2_div.dev_attr.attr,
606 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
607 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
608
609 &dev_attr_alarms.attr,
610 &dev_attr_name.attr,
611 NULL
612};
613
614static const struct attribute_group via686a_group = {
615 .attrs = via686a_attributes,
616};
617
618static struct platform_driver via686a_driver = {
619 .driver = {
620 .owner = THIS_MODULE,
621 .name = "via686a",
622 },
623 .probe = via686a_probe,
624 .remove = __devexit_p(via686a_remove),
625};
626
627
628
629static int __devinit via686a_probe(struct platform_device *pdev)
630{
631 struct via686a_data *data;
632 struct resource *res;
633 int err;
634
635
636 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
637 if (!request_region(res->start, VIA686A_EXTENT,
638 via686a_driver.driver.name)) {
639 dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n",
640 (unsigned long)res->start, (unsigned long)res->end);
641 return -ENODEV;
642 }
643
644 if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
645 err = -ENOMEM;
646 goto exit_release;
647 }
648
649 platform_set_drvdata(pdev, data);
650 data->addr = res->start;
651 data->name = "via686a";
652 mutex_init(&data->update_lock);
653
654
655 via686a_init_device(data);
656
657
658 if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group)))
659 goto exit_free;
660
661 data->hwmon_dev = hwmon_device_register(&pdev->dev);
662 if (IS_ERR(data->hwmon_dev)) {
663 err = PTR_ERR(data->hwmon_dev);
664 goto exit_remove_files;
665 }
666
667 return 0;
668
669exit_remove_files:
670 sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
671exit_free:
672 kfree(data);
673exit_release:
674 release_region(res->start, VIA686A_EXTENT);
675 return err;
676}
677
678static int __devexit via686a_remove(struct platform_device *pdev)
679{
680 struct via686a_data *data = platform_get_drvdata(pdev);
681
682 hwmon_device_unregister(data->hwmon_dev);
683 sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
684
685 release_region(data->addr, VIA686A_EXTENT);
686 platform_set_drvdata(pdev, NULL);
687 kfree(data);
688
689 return 0;
690}
691
692static void via686a_update_fan_div(struct via686a_data *data)
693{
694 int reg = via686a_read_value(data, VIA686A_REG_FANDIV);
695 data->fan_div[0] = (reg >> 4) & 0x03;
696 data->fan_div[1] = reg >> 6;
697}
698
699static void __devinit via686a_init_device(struct via686a_data *data)
700{
701 u8 reg;
702
703
704 reg = via686a_read_value(data, VIA686A_REG_CONFIG);
705 via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F);
706
707
708 reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE);
709 via686a_write_value(data, VIA686A_REG_TEMP_MODE,
710 (reg & ~VIA686A_TEMP_MODE_MASK)
711 | VIA686A_TEMP_MODE_CONTINUOUS);
712
713
714 via686a_update_fan_div(data);
715}
716
717static struct via686a_data *via686a_update_device(struct device *dev)
718{
719 struct via686a_data *data = dev_get_drvdata(dev);
720 int i;
721
722 mutex_lock(&data->update_lock);
723
724 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
725 || !data->valid) {
726 for (i = 0; i <= 4; i++) {
727 data->in[i] =
728 via686a_read_value(data, VIA686A_REG_IN(i));
729 data->in_min[i] = via686a_read_value(data,
730 VIA686A_REG_IN_MIN
731 (i));
732 data->in_max[i] =
733 via686a_read_value(data, VIA686A_REG_IN_MAX(i));
734 }
735 for (i = 1; i <= 2; i++) {
736 data->fan[i - 1] =
737 via686a_read_value(data, VIA686A_REG_FAN(i));
738 data->fan_min[i - 1] = via686a_read_value(data,
739 VIA686A_REG_FAN_MIN(i));
740 }
741 for (i = 0; i <= 2; i++) {
742 data->temp[i] = via686a_read_value(data,
743 VIA686A_REG_TEMP[i]) << 2;
744 data->temp_over[i] =
745 via686a_read_value(data,
746 VIA686A_REG_TEMP_OVER[i]);
747 data->temp_hyst[i] =
748 via686a_read_value(data,
749 VIA686A_REG_TEMP_HYST[i]);
750 }
751
752
753
754
755
756 data->temp[0] |= (via686a_read_value(data,
757 VIA686A_REG_TEMP_LOW1)
758 & 0xc0) >> 6;
759 data->temp[1] |=
760 (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
761 0x30) >> 4;
762 data->temp[2] |=
763 (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
764 0xc0) >> 6;
765
766 via686a_update_fan_div(data);
767 data->alarms =
768 via686a_read_value(data,
769 VIA686A_REG_ALARM1) |
770 (via686a_read_value(data, VIA686A_REG_ALARM2) << 8);
771 data->last_updated = jiffies;
772 data->valid = 1;
773 }
774
775 mutex_unlock(&data->update_lock);
776
777 return data;
778}
779
780static const struct pci_device_id via686a_pci_ids[] = {
781 { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
782 { 0, }
783};
784
785MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
786
787static int __devinit via686a_device_add(unsigned short address)
788{
789 struct resource res = {
790 .start = address,
791 .end = address + VIA686A_EXTENT - 1,
792 .name = "via686a",
793 .flags = IORESOURCE_IO,
794 };
795 int err;
796
797 err = acpi_check_resource_conflict(&res);
798 if (err)
799 goto exit;
800
801 pdev = platform_device_alloc("via686a", address);
802 if (!pdev) {
803 err = -ENOMEM;
804 pr_err("Device allocation failed\n");
805 goto exit;
806 }
807
808 err = platform_device_add_resources(pdev, &res, 1);
809 if (err) {
810 pr_err("Device resource addition failed (%d)\n", err);
811 goto exit_device_put;
812 }
813
814 err = platform_device_add(pdev);
815 if (err) {
816 pr_err("Device addition failed (%d)\n", err);
817 goto exit_device_put;
818 }
819
820 return 0;
821
822exit_device_put:
823 platform_device_put(pdev);
824exit:
825 return err;
826}
827
828static int __devinit via686a_pci_probe(struct pci_dev *dev,
829 const struct pci_device_id *id)
830{
831 u16 address, val;
832
833 if (force_addr) {
834 address = force_addr & ~(VIA686A_EXTENT - 1);
835 dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address);
836 if (PCIBIOS_SUCCESSFUL !=
837 pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
838 return -ENODEV;
839 }
840 if (PCIBIOS_SUCCESSFUL !=
841 pci_read_config_word(dev, VIA686A_BASE_REG, &val))
842 return -ENODEV;
843
844 address = val & ~(VIA686A_EXTENT - 1);
845 if (address == 0) {
846 dev_err(&dev->dev, "base address not set - upgrade BIOS "
847 "or use force_addr=0xaddr\n");
848 return -ENODEV;
849 }
850
851 if (PCIBIOS_SUCCESSFUL !=
852 pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
853 return -ENODEV;
854 if (!(val & 0x0001)) {
855 if (!force_addr) {
856 dev_warn(&dev->dev, "Sensors disabled, enable "
857 "with force_addr=0x%x\n", address);
858 return -ENODEV;
859 }
860
861 dev_warn(&dev->dev, "Enabling sensors\n");
862 if (PCIBIOS_SUCCESSFUL !=
863 pci_write_config_word(dev, VIA686A_ENABLE_REG,
864 val | 0x0001))
865 return -ENODEV;
866 }
867
868 if (platform_driver_register(&via686a_driver))
869 goto exit;
870
871
872 if (via686a_device_add(address))
873 goto exit_unregister;
874
875
876
877
878
879 s_bridge = pci_dev_get(dev);
880 return -ENODEV;
881
882exit_unregister:
883 platform_driver_unregister(&via686a_driver);
884exit:
885 return -ENODEV;
886}
887
888static struct pci_driver via686a_pci_driver = {
889 .name = "via686a",
890 .id_table = via686a_pci_ids,
891 .probe = via686a_pci_probe,
892};
893
894static int __init sm_via686a_init(void)
895{
896 return pci_register_driver(&via686a_pci_driver);
897}
898
899static void __exit sm_via686a_exit(void)
900{
901 pci_unregister_driver(&via686a_pci_driver);
902 if (s_bridge != NULL) {
903 platform_device_unregister(pdev);
904 platform_driver_unregister(&via686a_driver);
905 pci_dev_put(s_bridge);
906 s_bridge = NULL;
907 }
908}
909
910MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
911 "Mark Studebaker <mdsxyz123@yahoo.com> "
912 "and Bob Dougherty <bobd@stanford.edu>");
913MODULE_DESCRIPTION("VIA 686A Sensor device");
914MODULE_LICENSE("GPL");
915
916module_init(sm_via686a_init);
917module_exit(sm_via686a_exit);
918