diff options
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/f71882fg.c | 353 |
1 files changed, 291 insertions, 62 deletions
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 842592fe5aa9..a833797e96d3 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c | |||
@@ -45,6 +45,7 @@ | |||
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_F71862_ID 0x0601 /* Chipset ID */ |
47 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ | 47 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ |
48 | #define SIO_F8000_ID 0x0581 /* Chipset ID */ | ||
48 | 49 | ||
49 | #define REGION_LENGTH 8 | 50 | #define REGION_LENGTH 8 |
50 | #define ADDR_REG_OFFSET 5 | 51 | #define ADDR_REG_OFFSET 5 |
@@ -90,11 +91,12 @@ static unsigned short force_id; | |||
90 | module_param(force_id, ushort, 0); | 91 | module_param(force_id, ushort, 0); |
91 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | 92 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); |
92 | 93 | ||
93 | enum chips { f71862fg, f71882fg }; | 94 | enum chips { f71862fg, f71882fg, f8000 }; |
94 | 95 | ||
95 | static const char *f71882fg_names[] = { | 96 | static const char *f71882fg_names[] = { |
96 | "f71862fg", | 97 | "f71862fg", |
97 | "f71882fg", | 98 | "f71882fg", |
99 | "f8000", | ||
98 | }; | 100 | }; |
99 | 101 | ||
100 | static struct platform_device *f71882fg_pdev; | 102 | static struct platform_device *f71882fg_pdev; |
@@ -249,6 +251,7 @@ static struct platform_driver f71882fg_driver = { | |||
249 | 251 | ||
250 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 252 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
251 | 253 | ||
254 | /* Temp and in attr common to both the f71862fg and f71882fg */ | ||
252 | static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { | 255 | static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { |
253 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), | 256 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), |
254 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), | 257 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), |
@@ -317,6 +320,7 @@ static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { | |||
317 | SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3), | 320 | SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3), |
318 | }; | 321 | }; |
319 | 322 | ||
323 | /* Temp and in attr found only on the f71882fg */ | ||
320 | static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { | 324 | static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { |
321 | SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, | 325 | SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, |
322 | 0, 1), | 326 | 0, 1), |
@@ -325,27 +329,51 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { | |||
325 | SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), | 329 | SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), |
326 | }; | 330 | }; |
327 | 331 | ||
328 | static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = { | 332 | /* Temp and in attr for the f8000 |
333 | Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max) | ||
334 | is used as hysteresis value to clear alarms | ||
335 | */ | ||
336 | static struct sensor_device_attribute_2 f8000_in_temp_attr[] = { | ||
337 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), | ||
338 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), | ||
339 | SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), | ||
340 | SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), | ||
341 | SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit, | ||
342 | store_temp_crit, 0, 0), | ||
343 | SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, | ||
344 | store_temp_max, 0, 0), | ||
345 | SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4), | ||
346 | SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1), | ||
347 | SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit, | ||
348 | store_temp_crit, 0, 1), | ||
349 | SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, | ||
350 | store_temp_max, 0, 1), | ||
351 | SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), | ||
352 | SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1), | ||
353 | SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2), | ||
354 | SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit, | ||
355 | store_temp_crit, 0, 2), | ||
356 | SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, | ||
357 | store_temp_max, 0, 2), | ||
358 | SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), | ||
359 | }; | ||
360 | |||
361 | /* Fan / PWM attr common to all models */ | ||
362 | static struct sensor_device_attribute_2 fxxxx_fan_attr[] = { | ||
329 | SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), | 363 | SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), |
330 | SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, | 364 | SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, |
331 | show_fan_full_speed, | 365 | show_fan_full_speed, |
332 | store_fan_full_speed, 0, 0), | 366 | store_fan_full_speed, 0, 0), |
333 | SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
334 | store_fan_beep, 0, 0), | ||
335 | SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), | 367 | SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), |
336 | SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), | 368 | SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), |
337 | SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, | 369 | SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, |
338 | show_fan_full_speed, | 370 | show_fan_full_speed, |
339 | store_fan_full_speed, 0, 1), | 371 | store_fan_full_speed, 0, 1), |
340 | SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
341 | store_fan_beep, 0, 1), | ||
342 | SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), | 372 | SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), |
343 | SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), | 373 | SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), |
344 | SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, | 374 | SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, |
345 | show_fan_full_speed, | 375 | show_fan_full_speed, |
346 | store_fan_full_speed, 0, 2), | 376 | store_fan_full_speed, 0, 2), |
347 | SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
348 | store_fan_beep, 0, 2), | ||
349 | SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), | 377 | SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), |
350 | 378 | ||
351 | SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), | 379 | SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), |
@@ -366,9 +394,6 @@ static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = { | |||
366 | show_pwm_auto_point_channel, | 394 | show_pwm_auto_point_channel, |
367 | store_pwm_auto_point_channel, 0, 1), | 395 | store_pwm_auto_point_channel, 0, 1), |
368 | 396 | ||
369 | SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), | ||
370 | SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
371 | store_pwm_enable, 0, 2), | ||
372 | SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, | 397 | SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, |
373 | show_pwm_interpolate, store_pwm_interpolate, 0, 2), | 398 | show_pwm_interpolate, store_pwm_interpolate, 0, 2), |
374 | SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, | 399 | SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, |
@@ -376,7 +401,16 @@ static struct sensor_device_attribute_2 f718x2fg_fan_attr[] = { | |||
376 | store_pwm_auto_point_channel, 0, 2), | 401 | store_pwm_auto_point_channel, 0, 2), |
377 | }; | 402 | }; |
378 | 403 | ||
404 | /* Fan / PWM attr for the f71862fg, less pwms and less zones per pwm than the | ||
405 | f71882fg */ | ||
379 | static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { | 406 | static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { |
407 | SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
408 | store_fan_beep, 0, 0), | ||
409 | SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
410 | store_fan_beep, 0, 1), | ||
411 | SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
412 | store_fan_beep, 0, 2), | ||
413 | |||
380 | SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, | 414 | SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, |
381 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | 415 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
382 | 1, 0), | 416 | 1, 0), |
@@ -416,7 +450,14 @@ static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { | |||
416 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), | 450 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), |
417 | }; | 451 | }; |
418 | 452 | ||
453 | /* Fan / PWM attr for the f71882fg */ | ||
419 | static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { | 454 | static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { |
455 | SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
456 | store_fan_beep, 0, 0), | ||
457 | SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
458 | store_fan_beep, 0, 1), | ||
459 | SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, | ||
460 | store_fan_beep, 0, 2), | ||
420 | SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), | 461 | SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), |
421 | SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, | 462 | SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, |
422 | show_fan_full_speed, | 463 | show_fan_full_speed, |
@@ -501,6 +542,9 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { | |||
501 | SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, | 542 | SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, |
502 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), | 543 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), |
503 | 544 | ||
545 | SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), | ||
546 | SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
547 | store_pwm_enable, 0, 2), | ||
504 | SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, | 548 | SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, |
505 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | 549 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
506 | 0, 2), | 550 | 0, 2), |
@@ -586,6 +630,128 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { | |||
586 | show_pwm_auto_point_temp_hyst, NULL, 3, 3), | 630 | show_pwm_auto_point_temp_hyst, NULL, 3, 3), |
587 | }; | 631 | }; |
588 | 632 | ||
633 | /* Fan / PWM attr for the f8000, zones mapped to temp instead of to pwm! | ||
634 | Also the register block at offset A0 maps to TEMP1 (so our temp2, as the | ||
635 | F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */ | ||
636 | static struct sensor_device_attribute_2 f8000_fan_attr[] = { | ||
637 | SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), | ||
638 | |||
639 | SENSOR_ATTR_2(pwm3, S_IRUGO, show_pwm, NULL, 0, 2), | ||
640 | |||
641 | SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
642 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
643 | 0, 2), | ||
644 | SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
645 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
646 | 1, 2), | ||
647 | SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
648 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
649 | 2, 2), | ||
650 | SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
651 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
652 | 3, 2), | ||
653 | SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
654 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
655 | 4, 2), | ||
656 | SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
657 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
658 | 0, 2), | ||
659 | SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
660 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
661 | 1, 2), | ||
662 | SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
663 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
664 | 2, 2), | ||
665 | SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
666 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
667 | 3, 2), | ||
668 | SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
669 | show_pwm_auto_point_temp_hyst, | ||
670 | store_pwm_auto_point_temp_hyst, | ||
671 | 0, 2), | ||
672 | SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO, | ||
673 | show_pwm_auto_point_temp_hyst, NULL, 1, 2), | ||
674 | SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO, | ||
675 | show_pwm_auto_point_temp_hyst, NULL, 2, 2), | ||
676 | SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO, | ||
677 | show_pwm_auto_point_temp_hyst, NULL, 3, 2), | ||
678 | |||
679 | SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
680 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
681 | 0, 0), | ||
682 | SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
683 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
684 | 1, 0), | ||
685 | SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
686 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
687 | 2, 0), | ||
688 | SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
689 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
690 | 3, 0), | ||
691 | SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
692 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
693 | 4, 0), | ||
694 | SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
695 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
696 | 0, 0), | ||
697 | SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
698 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
699 | 1, 0), | ||
700 | SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
701 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
702 | 2, 0), | ||
703 | SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
704 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
705 | 3, 0), | ||
706 | SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
707 | show_pwm_auto_point_temp_hyst, | ||
708 | store_pwm_auto_point_temp_hyst, | ||
709 | 0, 0), | ||
710 | SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO, | ||
711 | show_pwm_auto_point_temp_hyst, NULL, 1, 0), | ||
712 | SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO, | ||
713 | show_pwm_auto_point_temp_hyst, NULL, 2, 0), | ||
714 | SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO, | ||
715 | show_pwm_auto_point_temp_hyst, NULL, 3, 0), | ||
716 | |||
717 | SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
718 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
719 | 0, 1), | ||
720 | SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
721 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
722 | 1, 1), | ||
723 | SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
724 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
725 | 2, 1), | ||
726 | SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
727 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
728 | 3, 1), | ||
729 | SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
730 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
731 | 4, 1), | ||
732 | SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
733 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
734 | 0, 1), | ||
735 | SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
736 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
737 | 1, 1), | ||
738 | SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
739 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
740 | 2, 1), | ||
741 | SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
742 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
743 | 3, 1), | ||
744 | SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
745 | show_pwm_auto_point_temp_hyst, | ||
746 | store_pwm_auto_point_temp_hyst, | ||
747 | 0, 1), | ||
748 | SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO, | ||
749 | show_pwm_auto_point_temp_hyst, NULL, 1, 1), | ||
750 | SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO, | ||
751 | show_pwm_auto_point_temp_hyst, NULL, 2, 1), | ||
752 | SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO, | ||
753 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), | ||
754 | }; | ||
589 | 755 | ||
590 | /* Super I/O functions */ | 756 | /* Super I/O functions */ |
591 | static inline int superio_inb(int base, int reg) | 757 | static inline int superio_inb(int base, int reg) |
@@ -671,8 +837,10 @@ static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) | |||
671 | static struct f71882fg_data *f71882fg_update_device(struct device *dev) | 837 | static struct f71882fg_data *f71882fg_update_device(struct device *dev) |
672 | { | 838 | { |
673 | struct f71882fg_data *data = dev_get_drvdata(dev); | 839 | struct f71882fg_data *data = dev_get_drvdata(dev); |
674 | int nr, reg, reg2; | 840 | int nr, reg = 0, reg2; |
675 | int nr_fans = (data->type == f71862fg) ? 3 : 4; | 841 | int nr_fans = (data->type == f71882fg) ? 4 : 3; |
842 | int nr_ins = (data->type == f8000) ? 3 : 9; | ||
843 | int temp_start = (data->type == f8000) ? 0 : 1; | ||
676 | 844 | ||
677 | mutex_lock(&data->update_lock); | 845 | mutex_lock(&data->update_lock); |
678 | 846 | ||
@@ -687,35 +855,36 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
687 | } | 855 | } |
688 | 856 | ||
689 | /* Get High & boundary temps*/ | 857 | /* Get High & boundary temps*/ |
690 | for (nr = 1; nr < 4; nr++) { | 858 | for (nr = temp_start; nr < 3 + temp_start; nr++) { |
691 | data->temp_ovt[nr] = f71882fg_read8(data, | 859 | data->temp_ovt[nr] = f71882fg_read8(data, |
692 | F71882FG_REG_TEMP_OVT(nr)); | 860 | F71882FG_REG_TEMP_OVT(nr)); |
693 | data->temp_high[nr] = f71882fg_read8(data, | 861 | data->temp_high[nr] = f71882fg_read8(data, |
694 | F71882FG_REG_TEMP_HIGH(nr)); | 862 | F71882FG_REG_TEMP_HIGH(nr)); |
695 | } | 863 | } |
696 | 864 | ||
697 | /* hyst */ | 865 | if (data->type != f8000) { |
698 | data->temp_hyst[0] = | 866 | data->fan_beep = f71882fg_read8(data, |
699 | f71882fg_read8(data, F71882FG_REG_TEMP_HYST(0)); | 867 | F71882FG_REG_FAN_BEEP); |
700 | data->temp_hyst[1] = | 868 | data->temp_beep = f71882fg_read8(data, |
701 | f71882fg_read8(data, F71882FG_REG_TEMP_HYST(1)); | 869 | F71882FG_REG_TEMP_BEEP); |
702 | 870 | data->temp_hyst[0] = f71882fg_read8(data, | |
703 | /* Have to hardcode type, because temp1 is special */ | 871 | F71882FG_REG_TEMP_HYST(0)); |
704 | reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); | 872 | data->temp_hyst[1] = f71882fg_read8(data, |
873 | F71882FG_REG_TEMP_HYST(1)); | ||
874 | /* Have to hardcode type, because temp1 is special */ | ||
875 | reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); | ||
876 | data->temp_type[2] = (reg & 0x04) ? 2 : 4; | ||
877 | data->temp_type[3] = (reg & 0x08) ? 2 : 4; | ||
878 | } | ||
705 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); | 879 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); |
706 | if ((reg2 & 0x03) == 0x01) | 880 | if ((reg2 & 0x03) == 0x01) |
707 | data->temp_type[1] = 6 /* PECI */; | 881 | data->temp_type[1] = 6 /* PECI */; |
708 | else if ((reg2 & 0x03) == 0x02) | 882 | else if ((reg2 & 0x03) == 0x02) |
709 | data->temp_type[1] = 5 /* AMDSI */; | 883 | data->temp_type[1] = 5 /* AMDSI */; |
710 | else | 884 | else if (data->type != f8000) |
711 | data->temp_type[1] = (reg & 0x02) ? 2 : 4; | 885 | data->temp_type[1] = (reg & 0x02) ? 2 : 4; |
712 | 886 | else | |
713 | data->temp_type[2] = (reg & 0x04) ? 2 : 4; | 887 | data->temp_type[1] = 2; /* F8000 only supports BJT */ |
714 | data->temp_type[3] = (reg & 0x08) ? 2 : 4; | ||
715 | |||
716 | data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); | ||
717 | |||
718 | data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); | ||
719 | 888 | ||
720 | data->pwm_enable = f71882fg_read8(data, | 889 | data->pwm_enable = f71882fg_read8(data, |
721 | F71882FG_REG_PWM_ENABLE); | 890 | F71882FG_REG_PWM_ENABLE); |
@@ -729,7 +898,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
729 | f71882fg_read8(data, | 898 | f71882fg_read8(data, |
730 | F71882FG_REG_POINT_MAPPING(nr)); | 899 | F71882FG_REG_POINT_MAPPING(nr)); |
731 | 900 | ||
732 | if (data->type == f71882fg) { | 901 | if (data->type != f71862fg) { |
733 | int point; | 902 | int point; |
734 | for (point = 0; point < 5; point++) { | 903 | for (point = 0; point < 5; point++) { |
735 | data->pwm_auto_point_pwm[nr][point] = | 904 | data->pwm_auto_point_pwm[nr][point] = |
@@ -771,7 +940,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
771 | F71882FG_REG_TEMP_STATUS); | 940 | F71882FG_REG_TEMP_STATUS); |
772 | data->temp_diode_open = f71882fg_read8(data, | 941 | data->temp_diode_open = f71882fg_read8(data, |
773 | F71882FG_REG_TEMP_DIODE_OPEN); | 942 | F71882FG_REG_TEMP_DIODE_OPEN); |
774 | for (nr = 1; nr < 4; nr++) | 943 | for (nr = temp_start; nr < 3 + temp_start; nr++) |
775 | data->temp[nr] = f71882fg_read8(data, | 944 | data->temp[nr] = f71882fg_read8(data, |
776 | F71882FG_REG_TEMP(nr)); | 945 | F71882FG_REG_TEMP(nr)); |
777 | 946 | ||
@@ -789,10 +958,14 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
789 | f71882fg_read8(data, F71882FG_REG_PWM(nr)); | 958 | f71882fg_read8(data, F71882FG_REG_PWM(nr)); |
790 | } | 959 | } |
791 | 960 | ||
961 | /* The f8000 can monitor 1 more fan, but has no pwm for it */ | ||
962 | if (data->type == f8000) | ||
963 | data->fan[3] = f71882fg_read16(data, | ||
964 | F71882FG_REG_FAN(3)); | ||
792 | if (data->type == f71882fg) | 965 | if (data->type == f71882fg) |
793 | data->in_status = f71882fg_read8(data, | 966 | data->in_status = f71882fg_read8(data, |
794 | F71882FG_REG_IN_STATUS); | 967 | F71882FG_REG_IN_STATUS); |
795 | for (nr = 0; nr < 9; nr++) | 968 | for (nr = 0; nr < nr_ins; nr++) |
796 | data->in[nr] = f71882fg_read8(data, | 969 | data->in[nr] = f71882fg_read8(data, |
797 | F71882FG_REG_IN(nr)); | 970 | F71882FG_REG_IN(nr)); |
798 | 971 | ||
@@ -1186,6 +1359,11 @@ static ssize_t store_pwm(struct device *dev, | |||
1186 | 1359 | ||
1187 | mutex_lock(&data->update_lock); | 1360 | mutex_lock(&data->update_lock); |
1188 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); | 1361 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); |
1362 | if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) || | ||
1363 | (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) { | ||
1364 | count = -EROFS; | ||
1365 | goto leave; | ||
1366 | } | ||
1189 | if (data->pwm_enable & (1 << (2 * nr))) { | 1367 | if (data->pwm_enable & (1 << (2 * nr))) { |
1190 | /* PWM mode */ | 1368 | /* PWM mode */ |
1191 | f71882fg_write8(data, F71882FG_REG_PWM(nr), val); | 1369 | f71882fg_write8(data, F71882FG_REG_PWM(nr), val); |
@@ -1200,6 +1378,7 @@ static ssize_t store_pwm(struct device *dev, | |||
1200 | data->fan_target[nr] = target; | 1378 | data->fan_target[nr] = target; |
1201 | data->fan_full_speed[nr] = full_speed; | 1379 | data->fan_full_speed[nr] = full_speed; |
1202 | } | 1380 | } |
1381 | leave: | ||
1203 | mutex_unlock(&data->update_lock); | 1382 | mutex_unlock(&data->update_lock); |
1204 | 1383 | ||
1205 | return count; | 1384 | return count; |
@@ -1208,14 +1387,25 @@ static ssize_t store_pwm(struct device *dev, | |||
1208 | static ssize_t show_pwm_enable(struct device *dev, | 1387 | static ssize_t show_pwm_enable(struct device *dev, |
1209 | struct device_attribute *devattr, char *buf) | 1388 | struct device_attribute *devattr, char *buf) |
1210 | { | 1389 | { |
1211 | int result; | 1390 | int result = 0; |
1212 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1391 | struct f71882fg_data *data = f71882fg_update_device(dev); |
1213 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1392 | int nr = to_sensor_dev_attr_2(devattr)->index; |
1214 | 1393 | ||
1215 | if (data->pwm_enable & (2 << (2 * nr))) | 1394 | switch ((data->pwm_enable >> 2 * nr) & 3) { |
1216 | result = 1; | 1395 | case 0: |
1217 | else | 1396 | case 1: |
1218 | result = 2; | 1397 | result = 2; /* Normal auto mode */ |
1398 | break; | ||
1399 | case 2: | ||
1400 | result = 1; /* Manual mode */ | ||
1401 | break; | ||
1402 | case 3: | ||
1403 | if (data->type == f8000) | ||
1404 | result = 3; /* Thermostat mode */ | ||
1405 | else | ||
1406 | result = 1; /* Manual mode */ | ||
1407 | break; | ||
1408 | } | ||
1219 | 1409 | ||
1220 | return sprintf(buf, "%d\n", result); | 1410 | return sprintf(buf, "%d\n", result); |
1221 | } | 1411 | } |
@@ -1226,20 +1416,37 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute | |||
1226 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1416 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1227 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1417 | int nr = to_sensor_dev_attr_2(devattr)->index; |
1228 | long val = simple_strtol(buf, NULL, 10); | 1418 | long val = simple_strtol(buf, NULL, 10); |
1229 | if (val < 1 || val > 2) | ||
1230 | return -EINVAL; | ||
1231 | 1419 | ||
1232 | mutex_lock(&data->update_lock); | 1420 | mutex_lock(&data->update_lock); |
1233 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); | 1421 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); |
1234 | switch (val) { | 1422 | /* Special case for F8000 auto PWM mode / Thermostat mode */ |
1235 | case 1: | 1423 | if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) { |
1236 | data->pwm_enable |= 2 << (2 * nr); | 1424 | switch (val) { |
1237 | break; /* Manual */ | 1425 | case 2: |
1238 | case 2: | 1426 | data->pwm_enable &= ~(2 << (2 * nr)); |
1239 | data->pwm_enable &= ~(2 << (2 * nr)); | 1427 | break; /* Normal auto mode */ |
1240 | break; /* Temperature ctrl */ | 1428 | case 3: |
1429 | data->pwm_enable |= 2 << (2 * nr); | ||
1430 | break; /* Thermostat mode */ | ||
1431 | default: | ||
1432 | count = -EINVAL; | ||
1433 | goto leave; | ||
1434 | } | ||
1435 | } else { | ||
1436 | switch (val) { | ||
1437 | case 1: | ||
1438 | data->pwm_enable |= 2 << (2 * nr); | ||
1439 | break; /* Manual */ | ||
1440 | case 2: | ||
1441 | data->pwm_enable &= ~(2 << (2 * nr)); | ||
1442 | break; /* Normal auto mode */ | ||
1443 | default: | ||
1444 | count = -EINVAL; | ||
1445 | goto leave; | ||
1446 | } | ||
1241 | } | 1447 | } |
1242 | f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); | 1448 | f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); |
1449 | leave: | ||
1243 | mutex_unlock(&data->update_lock); | 1450 | mutex_unlock(&data->update_lock); |
1244 | 1451 | ||
1245 | return count; | 1452 | return count; |
@@ -1521,34 +1728,51 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) | |||
1521 | goto exit_unregister_sysfs; | 1728 | goto exit_unregister_sysfs; |
1522 | 1729 | ||
1523 | if (start_reg & 0x01) { | 1730 | if (start_reg & 0x01) { |
1524 | err = f71882fg_create_sysfs_files(pdev, f718x2fg_in_temp_attr, | 1731 | switch (data->type) { |
1525 | ARRAY_SIZE(f718x2fg_in_temp_attr)); | 1732 | case f71882fg: |
1526 | if (err) | ||
1527 | goto exit_unregister_sysfs; | ||
1528 | |||
1529 | if (data->type == f71882fg) { | ||
1530 | err = f71882fg_create_sysfs_files(pdev, | 1733 | err = f71882fg_create_sysfs_files(pdev, |
1531 | f71882fg_in_temp_attr, | 1734 | f71882fg_in_temp_attr, |
1532 | ARRAY_SIZE(f71882fg_in_temp_attr)); | 1735 | ARRAY_SIZE(f71882fg_in_temp_attr)); |
1533 | if (err) | 1736 | if (err) |
1534 | goto exit_unregister_sysfs; | 1737 | goto exit_unregister_sysfs; |
1738 | /* fall through! */ | ||
1739 | case f71862fg: | ||
1740 | err = f71882fg_create_sysfs_files(pdev, | ||
1741 | f718x2fg_in_temp_attr, | ||
1742 | ARRAY_SIZE(f718x2fg_in_temp_attr)); | ||
1743 | break; | ||
1744 | case f8000: | ||
1745 | err = f71882fg_create_sysfs_files(pdev, | ||
1746 | f8000_in_temp_attr, | ||
1747 | ARRAY_SIZE(f8000_in_temp_attr)); | ||
1748 | break; | ||
1535 | } | 1749 | } |
1750 | if (err) | ||
1751 | goto exit_unregister_sysfs; | ||
1536 | } | 1752 | } |
1537 | 1753 | ||
1538 | if (start_reg & 0x02) { | 1754 | if (start_reg & 0x02) { |
1539 | err = f71882fg_create_sysfs_files(pdev, f718x2fg_fan_attr, | 1755 | err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr, |
1540 | ARRAY_SIZE(f718x2fg_fan_attr)); | 1756 | ARRAY_SIZE(fxxxx_fan_attr)); |
1541 | if (err) | 1757 | if (err) |
1542 | goto exit_unregister_sysfs; | 1758 | goto exit_unregister_sysfs; |
1543 | 1759 | ||
1544 | if (data->type == f71862fg) { | 1760 | switch (data->type) { |
1761 | case f71862fg: | ||
1545 | err = f71882fg_create_sysfs_files(pdev, | 1762 | err = f71882fg_create_sysfs_files(pdev, |
1546 | f71862fg_fan_attr, | 1763 | f71862fg_fan_attr, |
1547 | ARRAY_SIZE(f71862fg_fan_attr)); | 1764 | ARRAY_SIZE(f71862fg_fan_attr)); |
1548 | } else { | 1765 | break; |
1766 | case f71882fg: | ||
1549 | err = f71882fg_create_sysfs_files(pdev, | 1767 | err = f71882fg_create_sysfs_files(pdev, |
1550 | f71882fg_fan_attr, | 1768 | f71882fg_fan_attr, |
1551 | ARRAY_SIZE(f71882fg_fan_attr)); | 1769 | ARRAY_SIZE(f71882fg_fan_attr)); |
1770 | break; | ||
1771 | case f8000: | ||
1772 | err = f71882fg_create_sysfs_files(pdev, | ||
1773 | f8000_fan_attr, | ||
1774 | ARRAY_SIZE(f8000_fan_attr)); | ||
1775 | break; | ||
1552 | } | 1776 | } |
1553 | if (err) | 1777 | if (err) |
1554 | goto exit_unregister_sysfs; | 1778 | goto exit_unregister_sysfs; |
@@ -1580,6 +1804,8 @@ static int f71882fg_remove(struct platform_device *pdev) | |||
1580 | if (data->hwmon_dev) | 1804 | if (data->hwmon_dev) |
1581 | hwmon_device_unregister(data->hwmon_dev); | 1805 | hwmon_device_unregister(data->hwmon_dev); |
1582 | 1806 | ||
1807 | /* Note we are not looping over all attr arrays we have as the ones | ||
1808 | below are supersets of the ones skipped. */ | ||
1583 | device_remove_file(&pdev->dev, &dev_attr_name); | 1809 | device_remove_file(&pdev->dev, &dev_attr_name); |
1584 | 1810 | ||
1585 | for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++) | 1811 | for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++) |
@@ -1590,15 +1816,15 @@ static int f71882fg_remove(struct platform_device *pdev) | |||
1590 | device_remove_file(&pdev->dev, | 1816 | device_remove_file(&pdev->dev, |
1591 | &f71882fg_in_temp_attr[i].dev_attr); | 1817 | &f71882fg_in_temp_attr[i].dev_attr); |
1592 | 1818 | ||
1593 | for (i = 0; i < ARRAY_SIZE(f718x2fg_fan_attr); i++) | 1819 | for (i = 0; i < ARRAY_SIZE(fxxxx_fan_attr); i++) |
1594 | device_remove_file(&pdev->dev, &f718x2fg_fan_attr[i].dev_attr); | 1820 | device_remove_file(&pdev->dev, &fxxxx_fan_attr[i].dev_attr); |
1595 | |||
1596 | for (i = 0; i < ARRAY_SIZE(f71862fg_fan_attr); i++) | ||
1597 | device_remove_file(&pdev->dev, &f71862fg_fan_attr[i].dev_attr); | ||
1598 | 1821 | ||
1599 | for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) | 1822 | for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) |
1600 | device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); | 1823 | device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); |
1601 | 1824 | ||
1825 | for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++) | ||
1826 | device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr); | ||
1827 | |||
1602 | kfree(data); | 1828 | kfree(data); |
1603 | 1829 | ||
1604 | return 0; | 1830 | return 0; |
@@ -1626,6 +1852,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, | |||
1626 | case SIO_F71882_ID: | 1852 | case SIO_F71882_ID: |
1627 | sio_data->type = f71882fg; | 1853 | sio_data->type = f71882fg; |
1628 | break; | 1854 | break; |
1855 | case SIO_F8000_ID: | ||
1856 | sio_data->type = f8000; | ||
1857 | break; | ||
1629 | default: | 1858 | default: |
1630 | printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); | 1859 | printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); |
1631 | goto exit; | 1860 | goto exit; |