aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/f71882fg.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2009-01-07 10:37:28 -0500
committerJean Delvare <khali@linux-fr.org>2009-01-07 10:37:28 -0500
commit498be96834bf88a44db2f4a3115688c882e6f3e3 (patch)
tree57d7abd32f6fc4edb172a5f47c4d718c973fccce /drivers/hwmon/f71882fg.c
parentc13548c531ff40501aee1c1dd6f474c3c6adfcd5 (diff)
hwmon: (f71882fg) Add support for the F71862FG superio sensors
This patch adds support for the Fintek f71862fg superio monitoring functions to the f71882fg driver. This support has been tested without problems on a Jetway J9F2 by Tony McConnell. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/f71882fg.c')
-rw-r--r--drivers/hwmon/f71882fg.c296
1 files changed, 224 insertions, 72 deletions
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 593ed2a0555..cdd16d4966c 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -43,6 +43,7 @@
43#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ 43#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
44 44
45#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ 45#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
46#define SIO_F71862_ID 0x0601 /* Chipset ID */
46#define SIO_F71882_ID 0x0541 /* Chipset ID */ 47#define SIO_F71882_ID 0x0541 /* Chipset ID */
47 48
48#define REGION_LENGTH 8 49#define REGION_LENGTH 8
@@ -51,10 +52,10 @@
51 52
52#define F71882FG_REG_PECI 0x0A 53#define F71882FG_REG_PECI 0x0A
53 54
54#define F71882FG_REG_IN_STATUS 0x12 55#define F71882FG_REG_IN_STATUS 0x12 /* f71882fg only */
55#define F71882FG_REG_IN_BEEP 0x13 56#define F71882FG_REG_IN_BEEP 0x13 /* f71882fg only */
56#define F71882FG_REG_IN(nr) (0x20 + (nr)) 57#define F71882FG_REG_IN(nr) (0x20 + (nr))
57#define F71882FG_REG_IN1_HIGH 0x32 58#define F71882FG_REG_IN1_HIGH 0x32 /* f71882fg only */
58 59
59#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) 60#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
60#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr))) 61#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
@@ -97,6 +98,13 @@ MODULE_PARM_DESC(fan_mode, "List of fan control modes (f71882fg only) "
97 "(0=don't change, 1=pwm, 2=rpm)\n" 98 "(0=don't change, 1=pwm, 2=rpm)\n"
98 "Note: this needs a write to pwm#_enable to take effect"); 99 "Note: this needs a write to pwm#_enable to take effect");
99 100
101enum chips { f71862fg, f71882fg };
102
103static const char *f71882fg_names[] = {
104 "f71862fg",
105 "f71882fg",
106};
107
100static struct platform_device *f71882fg_pdev; 108static struct platform_device *f71882fg_pdev;
101 109
102/* Super-I/O Function prototypes */ 110/* Super-I/O Function prototypes */
@@ -106,8 +114,13 @@ static inline void superio_enter(int base);
106static inline void superio_select(int base, int ld); 114static inline void superio_select(int base, int ld);
107static inline void superio_exit(int base); 115static inline void superio_exit(int base);
108 116
117struct f71882fg_sio_data {
118 enum chips type;
119};
120
109struct f71882fg_data { 121struct f71882fg_data {
110 unsigned short addr; 122 unsigned short addr;
123 enum chips type;
111 struct device *hwmon_dev; 124 struct device *hwmon_dev;
112 125
113 struct mutex update_lock; 126 struct mutex update_lock;
@@ -241,14 +254,9 @@ static struct platform_driver f71882fg_driver = {
241 254
242static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 255static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
243 256
244static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { 257static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = {
245 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), 258 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
246 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), 259 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
247 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
248 0, 1),
249 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
250 0, 1),
251 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
252 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), 260 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
253 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), 261 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
254 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), 262 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
@@ -300,7 +308,15 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
300 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), 308 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
301}; 309};
302 310
303static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { 311static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
312 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
313 0, 1),
314 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
315 0, 1),
316 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
317};
318
319static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = {
304 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), 320 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
305 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, 321 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
306 show_fan_full_speed, 322 show_fan_full_speed,
@@ -322,13 +338,6 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
322 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, 338 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
323 store_fan_beep, 0, 2), 339 store_fan_beep, 0, 2),
324 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), 340 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
325 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
326 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
327 show_fan_full_speed,
328 store_fan_full_speed, 0, 3),
329 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
330 store_fan_beep, 0, 3),
331 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
332 341
333 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), 342 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
334 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, 343 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
@@ -338,6 +347,75 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
338 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, 347 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
339 show_pwm_auto_point_channel, 348 show_pwm_auto_point_channel,
340 store_pwm_auto_point_channel, 0, 0), 349 store_pwm_auto_point_channel, 0, 0),
350
351 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
352 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
353 store_pwm_enable, 0, 1),
354 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
355 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
356 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
357 show_pwm_auto_point_channel,
358 store_pwm_auto_point_channel, 0, 1),
359
360 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
361 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
362 store_pwm_enable, 0, 2),
363 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
364 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
365 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
366 show_pwm_auto_point_channel,
367 store_pwm_auto_point_channel, 0, 2),
368};
369
370static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
371 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
372 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
373 1, 0),
374 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
375 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
376 4, 0),
377 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
378 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
379 0, 0),
380 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
381 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
382 3, 0),
383 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
384 show_pwm_auto_point_temp_hyst,
385 store_pwm_auto_point_temp_hyst,
386 0, 0),
387 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
388 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
389
390 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
391 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
392 1, 1),
393 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
394 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
395 4, 1),
396 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
397 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
398 0, 1),
399 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
400 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
401 3, 1),
402 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
403 show_pwm_auto_point_temp_hyst,
404 store_pwm_auto_point_temp_hyst,
405 0, 1),
406 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
407 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
408};
409
410static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
411 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
412 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
413 show_fan_full_speed,
414 store_fan_full_speed, 0, 3),
415 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
416 store_fan_beep, 0, 3),
417 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
418
341 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, 419 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
342 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 420 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
343 0, 0), 421 0, 0),
@@ -376,14 +454,6 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
376 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO, 454 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
377 show_pwm_auto_point_temp_hyst, NULL, 3, 0), 455 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
378 456
379 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
380 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
381 store_pwm_enable, 0, 1),
382 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
383 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
384 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
385 show_pwm_auto_point_channel,
386 store_pwm_auto_point_channel, 0, 1),
387 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, 457 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
388 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 458 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
389 0, 1), 459 0, 1),
@@ -422,14 +492,6 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
422 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, 492 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
423 show_pwm_auto_point_temp_hyst, NULL, 3, 1), 493 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
424 494
425 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
426 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
427 store_pwm_enable, 0, 2),
428 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
429 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
430 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
431 show_pwm_auto_point_channel,
432 store_pwm_auto_point_channel, 0, 2),
433 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, 495 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
434 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, 496 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
435 0, 2), 497 0, 2),
@@ -601,14 +663,19 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
601{ 663{
602 struct f71882fg_data *data = dev_get_drvdata(dev); 664 struct f71882fg_data *data = dev_get_drvdata(dev);
603 int nr, reg, reg2; 665 int nr, reg, reg2;
666 int nr_fans = (data->type == f71862fg) ? 3 : 4;
604 667
605 mutex_lock(&data->update_lock); 668 mutex_lock(&data->update_lock);
606 669
607 /* Update once every 60 seconds */ 670 /* Update once every 60 seconds */
608 if ( time_after(jiffies, data->last_limits + 60 * HZ ) || 671 if ( time_after(jiffies, data->last_limits + 60 * HZ ) ||
609 !data->valid) { 672 !data->valid) {
610 data->in1_max = f71882fg_read8(data, F71882FG_REG_IN1_HIGH); 673 if (data->type == f71882fg) {
611 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); 674 data->in1_max =
675 f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
676 data->in_beep =
677 f71882fg_read8(data, F71882FG_REG_IN_BEEP);
678 }
612 679
613 /* Get High & boundary temps*/ 680 /* Get High & boundary temps*/
614 for (nr = 0; nr < 3; nr++) { 681 for (nr = 0; nr < 3; nr++) {
@@ -649,24 +716,42 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
649 F71882FG_REG_FAN_HYST0); 716 F71882FG_REG_FAN_HYST0);
650 data->pwm_auto_point_hyst[1] = f71882fg_read8(data, 717 data->pwm_auto_point_hyst[1] = f71882fg_read8(data,
651 F71882FG_REG_FAN_HYST1); 718 F71882FG_REG_FAN_HYST1);
652 for (nr = 0; nr < 4; nr++) { 719 for (nr = 0; nr < nr_fans; nr++) {
653 int point;
654
655 data->pwm_auto_point_mapping[nr] = 720 data->pwm_auto_point_mapping[nr] =
656 f71882fg_read8(data, 721 f71882fg_read8(data,
657 F71882FG_REG_POINT_MAPPING(nr)); 722 F71882FG_REG_POINT_MAPPING(nr));
658 723
659 for (point = 0; point < 5; point++) { 724 if (data->type == f71882fg) {
660 data->pwm_auto_point_pwm[nr][point] = 725 int point;
661 f71882fg_read8(data, 726 for (point = 0; point < 5; point++) {
662 F71882FG_REG_POINT_PWM 727 data->pwm_auto_point_pwm[nr][point] =
663 (nr, point)); 728 f71882fg_read8(data,
664 } 729 F71882FG_REG_POINT_PWM
665 for (point = 0; point < 4; point++) { 730 (nr, point));
666 data->pwm_auto_point_temp[nr][point] = 731 }
667 f71882fg_read8(data, 732 for (point = 0; point < 4; point++) {
668 F71882FG_REG_POINT_TEMP 733 data->pwm_auto_point_temp[nr][point] =
669 (nr, point)); 734 f71882fg_read8(data,
735 F71882FG_REG_POINT_TEMP
736 (nr, point));
737 }
738 } else {
739 data->pwm_auto_point_pwm[nr][1] =
740 f71882fg_read8(data,
741 F71882FG_REG_POINT_PWM
742 (nr, 1));
743 data->pwm_auto_point_pwm[nr][4] =
744 f71882fg_read8(data,
745 F71882FG_REG_POINT_PWM
746 (nr, 4));
747 data->pwm_auto_point_temp[nr][0] =
748 f71882fg_read8(data,
749 F71882FG_REG_POINT_TEMP
750 (nr, 0));
751 data->pwm_auto_point_temp[nr][3] =
752 f71882fg_read8(data,
753 F71882FG_REG_POINT_TEMP
754 (nr, 3));
670 } 755 }
671 } 756 }
672 data->last_limits = jiffies; 757 data->last_limits = jiffies;
@@ -684,7 +769,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
684 769
685 data->fan_status = f71882fg_read8(data, 770 data->fan_status = f71882fg_read8(data,
686 F71882FG_REG_FAN_STATUS); 771 F71882FG_REG_FAN_STATUS);
687 for (nr = 0; nr < 4; nr++) { 772 for (nr = 0; nr < nr_fans; nr++) {
688 data->fan[nr] = f71882fg_read16(data, 773 data->fan[nr] = f71882fg_read16(data,
689 F71882FG_REG_FAN(nr)); 774 F71882FG_REG_FAN(nr));
690 data->fan_target[nr] = 775 data->fan_target[nr] =
@@ -696,7 +781,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
696 f71882fg_read8(data, F71882FG_REG_PWM(nr)); 781 f71882fg_read8(data, F71882FG_REG_PWM(nr));
697 } 782 }
698 783
699 data->in_status = f71882fg_read8(data, 784 if (data->type == f71882fg)
785 data->in_status = f71882fg_read8(data,
700 F71882FG_REG_IN_STATUS); 786 F71882FG_REG_IN_STATUS);
701 for (nr = 0; nr < 9; nr++) 787 for (nr = 0; nr < 9; nr++)
702 data->in[nr] = f71882fg_read8(data, 788 data->in[nr] = f71882fg_read8(data,
@@ -1144,13 +1230,15 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1144 data->pwm_enable &= ~(2 << (2 * nr)); 1230 data->pwm_enable &= ~(2 << (2 * nr));
1145 break; /* Temperature ctrl */ 1231 break; /* Temperature ctrl */
1146 } 1232 }
1147 switch (fan_mode[nr]) { 1233 if (data->type == f71882fg) {
1148 case 1: 1234 switch (fan_mode[nr]) {
1149 data->pwm_enable |= 1 << (2 * nr); 1235 case 1:
1150 break; /* Duty cycle mode */ 1236 data->pwm_enable |= 1 << (2 * nr);
1151 case 2: 1237 break; /* Duty cycle mode */
1152 data->pwm_enable &= ~(1 << (2 * nr)); 1238 case 2:
1153 break; /* RPM mode */ 1239 data->pwm_enable &= ~(1 << (2 * nr));
1240 break; /* RPM mode */
1241 }
1154 } 1242 }
1155 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); 1243 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
1156 mutex_unlock(&data->update_lock); 1244 mutex_unlock(&data->update_lock);
@@ -1386,7 +1474,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
1386static ssize_t show_name(struct device *dev, struct device_attribute *devattr, 1474static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
1387 char *buf) 1475 char *buf)
1388{ 1476{
1389 return sprintf(buf, DRVNAME "\n"); 1477 struct f71882fg_data *data = dev_get_drvdata(dev);
1478 return sprintf(buf, "%s\n", f71882fg_names[data->type]);
1390} 1479}
1391 1480
1392static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev, 1481static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
@@ -1405,6 +1494,7 @@ static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
1405static int __devinit f71882fg_probe(struct platform_device *pdev) 1494static int __devinit f71882fg_probe(struct platform_device *pdev)
1406{ 1495{
1407 struct f71882fg_data *data; 1496 struct f71882fg_data *data;
1497 struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
1408 int err; 1498 int err;
1409 u8 start_reg; 1499 u8 start_reg;
1410 1500
@@ -1413,6 +1503,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
1413 return -ENOMEM; 1503 return -ENOMEM;
1414 1504
1415 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; 1505 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
1506 data->type = sio_data->type;
1416 mutex_init(&data->update_lock); 1507 mutex_init(&data->update_lock);
1417 platform_set_drvdata(pdev, data); 1508 platform_set_drvdata(pdev, data);
1418 1509
@@ -1423,15 +1514,35 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
1423 1514
1424 start_reg = f71882fg_read8(data, F71882FG_REG_START); 1515 start_reg = f71882fg_read8(data, F71882FG_REG_START);
1425 if (start_reg & 0x01) { 1516 if (start_reg & 0x01) {
1426 err = f71882fg_create_sysfs_files(pdev, f71882fg_in_temp_attr, 1517 err = f71882fg_create_sysfs_files(pdev, f718x2fg_in_temp_attr,
1427 ARRAY_SIZE(f71882fg_in_temp_attr)); 1518 ARRAY_SIZE(f718x2fg_in_temp_attr));
1428 if (err) 1519 if (err)
1429 goto exit_unregister_sysfs; 1520 goto exit_unregister_sysfs;
1521
1522 if (data->type == f71882fg) {
1523 err = f71882fg_create_sysfs_files(pdev,
1524 f71882fg_in_temp_attr,
1525 ARRAY_SIZE(f71882fg_in_temp_attr));
1526 if (err)
1527 goto exit_unregister_sysfs;
1528 }
1430 } 1529 }
1431 1530
1432 if (start_reg & 0x02) { 1531 if (start_reg & 0x02) {
1433 err = f71882fg_create_sysfs_files(pdev, f71882fg_fan_attr, 1532 err = f71882fg_create_sysfs_files(pdev, f718x2fg_fan_attr,
1533 ARRAY_SIZE(f718x2fg_fan_attr));
1534 if (err)
1535 goto exit_unregister_sysfs;
1536
1537 if (data->type == f71862fg) {
1538 err = f71882fg_create_sysfs_files(pdev,
1539 f71862fg_fan_attr,
1540 ARRAY_SIZE(f71862fg_fan_attr));
1541 } else {
1542 err = f71882fg_create_sysfs_files(pdev,
1543 f71882fg_fan_attr,
1434 ARRAY_SIZE(f71882fg_fan_attr)); 1544 ARRAY_SIZE(f71882fg_fan_attr));
1545 }
1435 if (err) 1546 if (err)
1436 goto exit_unregister_sysfs; 1547 goto exit_unregister_sysfs;
1437 } 1548 }
@@ -1462,10 +1573,20 @@ static int f71882fg_remove(struct platform_device *pdev)
1462 1573
1463 device_remove_file(&pdev->dev, &dev_attr_name); 1574 device_remove_file(&pdev->dev, &dev_attr_name);
1464 1575
1576 for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++)
1577 device_remove_file(&pdev->dev,
1578 &f718x2fg_in_temp_attr[i].dev_attr);
1579
1465 for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) 1580 for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++)
1466 device_remove_file(&pdev->dev, 1581 device_remove_file(&pdev->dev,
1467 &f71882fg_in_temp_attr[i].dev_attr); 1582 &f71882fg_in_temp_attr[i].dev_attr);
1468 1583
1584 for (i = 0; i < ARRAY_SIZE(f718x2fg_fan_attr); i++)
1585 device_remove_file(&pdev->dev, &f718x2fg_fan_attr[i].dev_attr);
1586
1587 for (i = 0; i < ARRAY_SIZE(f71862fg_fan_attr); i++)
1588 device_remove_file(&pdev->dev, &f71862fg_fan_attr[i].dev_attr);
1589
1469 for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) 1590 for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++)
1470 device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); 1591 device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr);
1471 1592
@@ -1474,11 +1595,12 @@ static int f71882fg_remove(struct platform_device *pdev)
1474 return 0; 1595 return 0;
1475} 1596}
1476 1597
1477static int __init f71882fg_find(int sioaddr, unsigned short *address) 1598static int __init f71882fg_find(int sioaddr, unsigned short *address,
1599 struct f71882fg_sio_data *sio_data)
1478{ 1600{
1479 int err = -ENODEV; 1601 int err = -ENODEV;
1480 u16 devid; 1602 u16 devid;
1481 u8 start_reg; 1603 u8 reg;
1482 struct f71882fg_data data; 1604 struct f71882fg_data data;
1483 1605
1484 superio_enter(sioaddr); 1606 superio_enter(sioaddr);
@@ -1490,7 +1612,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address)
1490 } 1612 }
1491 1613
1492 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); 1614 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
1493 if (devid != SIO_F71882_ID) { 1615 switch (devid) {
1616 case SIO_F71862_ID:
1617 sio_data->type = f71862fg;
1618 break;
1619 case SIO_F71882_ID:
1620 sio_data->type = f71882fg;
1621 break;
1622 default:
1494 printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); 1623 printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n");
1495 goto exit; 1624 goto exit;
1496 } 1625 }
@@ -1510,23 +1639,35 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address)
1510 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ 1639 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
1511 1640
1512 data.addr = *address; 1641 data.addr = *address;
1513 start_reg = f71882fg_read8(&data, F71882FG_REG_START); 1642 reg = f71882fg_read8(&data, F71882FG_REG_START);
1514 if (!(start_reg & 0x03)) { 1643 if (!(reg & 0x03)) {
1515 printk(KERN_WARNING DRVNAME 1644 printk(KERN_WARNING DRVNAME
1516 ": Hardware monitoring not activated\n"); 1645 ": Hardware monitoring not activated\n");
1517 goto exit; 1646 goto exit;
1518 } 1647 }
1519 1648
1649 /* If it is a 71862 and the fan / pwm part is enabled sanity check
1650 the pwm settings */
1651 if (sio_data->type == f71862fg && (reg & 0x02)) {
1652 reg = f71882fg_read8(&data, F71882FG_REG_PWM_ENABLE);
1653 if ((reg & 0x15) != 0x15) {
1654 printk(KERN_ERR DRVNAME
1655 ": Invalid (reserved) pwm settings: 0x%02x\n",
1656 (unsigned int)reg);
1657 goto exit;
1658 }
1659 }
1520 err = 0; 1660 err = 0;
1521 printk(KERN_INFO DRVNAME ": Found F71882FG chip at %#x, revision %d\n", 1661 printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n",
1522 (unsigned int)*address, 1662 f71882fg_names[sio_data->type], (unsigned int)*address,
1523 (int)superio_inb(sioaddr, SIO_REG_DEVREV)); 1663 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
1524exit: 1664exit:
1525 superio_exit(sioaddr); 1665 superio_exit(sioaddr);
1526 return err; 1666 return err;
1527} 1667}
1528 1668
1529static int __init f71882fg_device_add(unsigned short address) 1669static int __init f71882fg_device_add(unsigned short address,
1670 const struct f71882fg_sio_data *sio_data)
1530{ 1671{
1531 struct resource res = { 1672 struct resource res = {
1532 .start = address, 1673 .start = address,
@@ -1546,6 +1687,13 @@ static int __init f71882fg_device_add(unsigned short address)
1546 goto exit_device_put; 1687 goto exit_device_put;
1547 } 1688 }
1548 1689
1690 err = platform_device_add_data(f71882fg_pdev, sio_data,
1691 sizeof(struct f71882fg_sio_data));
1692 if (err) {
1693 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1694 goto exit_device_put;
1695 }
1696
1549 err = platform_device_add(f71882fg_pdev); 1697 err = platform_device_add(f71882fg_pdev);
1550 if (err) { 1698 if (err) {
1551 printk(KERN_ERR DRVNAME ": Device addition failed\n"); 1699 printk(KERN_ERR DRVNAME ": Device addition failed\n");
@@ -1564,15 +1712,19 @@ static int __init f71882fg_init(void)
1564{ 1712{
1565 int err = -ENODEV; 1713 int err = -ENODEV;
1566 unsigned short address; 1714 unsigned short address;
1715 struct f71882fg_sio_data sio_data;
1716
1717 memset(&sio_data, 0, sizeof(sio_data));
1567 1718
1568 if (f71882fg_find(0x2e, &address) && f71882fg_find(0x4e, &address)) 1719 if (f71882fg_find(0x2e, &address, &sio_data) &&
1720 f71882fg_find(0x4e, &address, &sio_data))
1569 goto exit; 1721 goto exit;
1570 1722
1571 err = platform_driver_register(&f71882fg_driver); 1723 err = platform_driver_register(&f71882fg_driver);
1572 if (err) 1724 if (err)
1573 goto exit; 1725 goto exit;
1574 1726
1575 err = f71882fg_device_add(address); 1727 err = f71882fg_device_add(address, &sio_data);
1576 if (err) 1728 if (err)
1577 goto exit_driver; 1729 goto exit_driver;
1578 1730