diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-01-07 10:37:28 -0500 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-01-07 10:37:28 -0500 |
commit | 498be96834bf88a44db2f4a3115688c882e6f3e3 (patch) | |
tree | 57d7abd32f6fc4edb172a5f47c4d718c973fccce /drivers/hwmon | |
parent | c13548c531ff40501aee1c1dd6f474c3c6adfcd5 (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')
-rw-r--r-- | drivers/hwmon/f71882fg.c | 296 |
1 files changed, 224 insertions, 72 deletions
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 593ed2a0555c..cdd16d4966c3 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 | ||
101 | enum chips { f71862fg, f71882fg }; | ||
102 | |||
103 | static const char *f71882fg_names[] = { | ||
104 | "f71862fg", | ||
105 | "f71882fg", | ||
106 | }; | ||
107 | |||
100 | static struct platform_device *f71882fg_pdev; | 108 | static 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); | |||
106 | static inline void superio_select(int base, int ld); | 114 | static inline void superio_select(int base, int ld); |
107 | static inline void superio_exit(int base); | 115 | static inline void superio_exit(int base); |
108 | 116 | ||
117 | struct f71882fg_sio_data { | ||
118 | enum chips type; | ||
119 | }; | ||
120 | |||
109 | struct f71882fg_data { | 121 | struct 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 | ||
242 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 255 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
243 | 256 | ||
244 | static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { | 257 | static 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 | ||
303 | static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { | 311 | static 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 | |||
319 | static 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 | |||
370 | static 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 | |||
410 | static 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, | |||
1386 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, | 1474 | static 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 | ||
1392 | static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev, | 1481 | static 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, | |||
1405 | static int __devinit f71882fg_probe(struct platform_device *pdev) | 1494 | static 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 | ||
1477 | static int __init f71882fg_find(int sioaddr, unsigned short *address) | 1598 | static 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)); |
1524 | exit: | 1664 | exit: |
1525 | superio_exit(sioaddr); | 1665 | superio_exit(sioaddr); |
1526 | return err; | 1666 | return err; |
1527 | } | 1667 | } |
1528 | 1668 | ||
1529 | static int __init f71882fg_device_add(unsigned short address) | 1669 | static 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 | ||