diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-07-01 11:23:15 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-08-12 01:10:39 -0400 |
commit | 6c009501ff20012e80ef997443b49cf121a6e4b0 (patch) | |
tree | 08218967693dca5099f01903639e2c6b7c4277c8 /drivers/hwmon | |
parent | 698a7c24a5447ffd940bfc9f5e6e8448d836a2b4 (diff) |
hwmon: (nct6775) Add support for NCT6102D/6106D
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/nct6775.c | 250 |
1 files changed, 225 insertions, 25 deletions
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index caff72658c1a..bebddbbd3907 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c | |||
@@ -33,6 +33,7 @@ | |||
33 | * Supports the following chips: | 33 | * Supports the following chips: |
34 | * | 34 | * |
35 | * Chip #vin #fan #pwm #temp chip IDs man ID | 35 | * Chip #vin #fan #pwm #temp chip IDs man ID |
36 | * nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3 | ||
36 | * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3 | 37 | * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3 |
37 | * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3 | 38 | * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3 |
38 | * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3 | 39 | * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3 |
@@ -59,10 +60,11 @@ | |||
59 | 60 | ||
60 | #define USE_ALTERNATE | 61 | #define USE_ALTERNATE |
61 | 62 | ||
62 | enum kinds { nct6775, nct6776, nct6779 }; | 63 | enum kinds { nct6106, nct6775, nct6776, nct6779 }; |
63 | 64 | ||
64 | /* used to set data->name = nct6775_device_names[data->sio_kind] */ | 65 | /* used to set data->name = nct6775_device_names[data->sio_kind] */ |
65 | static const char * const nct6775_device_names[] = { | 66 | static const char * const nct6775_device_names[] = { |
67 | "nct6106", | ||
66 | "nct6775", | 68 | "nct6775", |
67 | "nct6776", | 69 | "nct6776", |
68 | "nct6779", | 70 | "nct6779", |
@@ -91,6 +93,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); | |||
91 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ | 93 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ |
92 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ | 94 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ |
93 | 95 | ||
96 | #define SIO_NCT6106_ID 0xc450 | ||
94 | #define SIO_NCT6775_ID 0xb470 | 97 | #define SIO_NCT6775_ID 0xb470 |
95 | #define SIO_NCT6776_ID 0xc330 | 98 | #define SIO_NCT6776_ID 0xc330 |
96 | #define SIO_NCT6779_ID 0xc560 | 99 | #define SIO_NCT6779_ID 0xc560 |
@@ -167,7 +170,7 @@ superio_exit(int ioreg) | |||
167 | #define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/ | 170 | #define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/ |
168 | #define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */ | 171 | #define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */ |
169 | 172 | ||
170 | #define NUM_REG_ALARM 4 /* Max number of alarm registers */ | 173 | #define NUM_REG_ALARM 7 /* Max number of alarm registers */ |
171 | 174 | ||
172 | /* Common and NCT6775 specific data */ | 175 | /* Common and NCT6775 specific data */ |
173 | 176 | ||
@@ -185,6 +188,7 @@ static const u16 NCT6775_REG_IN[] = { | |||
185 | 188 | ||
186 | #define NCT6775_REG_VBAT 0x5D | 189 | #define NCT6775_REG_VBAT 0x5D |
187 | #define NCT6775_REG_DIODE 0x5E | 190 | #define NCT6775_REG_DIODE 0x5E |
191 | #define NCT6775_DIODE_MASK 0x02 | ||
188 | 192 | ||
189 | #define NCT6775_REG_FANDIV1 0x506 | 193 | #define NCT6775_REG_FANDIV1 0x506 |
190 | #define NCT6775_REG_FANDIV2 0x507 | 194 | #define NCT6775_REG_FANDIV2 0x507 |
@@ -238,6 +242,7 @@ static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 }; | |||
238 | static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; | 242 | static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; |
239 | static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; | 243 | static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; |
240 | static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; | 244 | static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; |
245 | static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0 }; | ||
241 | 246 | ||
242 | static const u16 NCT6775_REG_TEMP[] = { | 247 | static const u16 NCT6775_REG_TEMP[] = { |
243 | 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; | 248 | 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; |
@@ -396,6 +401,7 @@ static const u16 NCT6779_REG_FAN_PULSES[] = { | |||
396 | 401 | ||
397 | static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = { | 402 | static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = { |
398 | 0x136, 0x236, 0x336, 0x836, 0x936 }; | 403 | 0x136, 0x236, 0x336, 0x836, 0x936 }; |
404 | #define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01 | ||
399 | static const u16 NCT6779_REG_CRITICAL_PWM[] = { | 405 | static const u16 NCT6779_REG_CRITICAL_PWM[] = { |
400 | 0x137, 0x237, 0x337, 0x837, 0x937 }; | 406 | 0x137, 0x237, 0x337, 0x837, 0x937 }; |
401 | 407 | ||
@@ -449,6 +455,88 @@ static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1] | |||
449 | static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] | 455 | static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] |
450 | = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; | 456 | = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; |
451 | 457 | ||
458 | /* NCT6102D/NCT6106D specific data */ | ||
459 | |||
460 | #define NCT6106_REG_VBAT 0x318 | ||
461 | #define NCT6106_REG_DIODE 0x319 | ||
462 | #define NCT6106_DIODE_MASK 0x01 | ||
463 | |||
464 | static const u16 NCT6106_REG_IN_MAX[] = { | ||
465 | 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 }; | ||
466 | static const u16 NCT6106_REG_IN_MIN[] = { | ||
467 | 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 }; | ||
468 | static const u16 NCT6106_REG_IN[] = { | ||
469 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 }; | ||
470 | |||
471 | static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 }; | ||
472 | static const u16 NCT6106_REG_TEMP_HYST[] = { | ||
473 | 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 }; | ||
474 | static const u16 NCT6106_REG_TEMP_OVER[] = { | ||
475 | 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd4 }; | ||
476 | static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 }; | ||
477 | static const u16 NCT6106_REG_TEMP_CONFIG[] = { | ||
478 | 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc }; | ||
479 | |||
480 | static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 }; | ||
481 | static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 }; | ||
482 | static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 }; | ||
483 | static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 }; | ||
484 | |||
485 | static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 }; | ||
486 | static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 }; | ||
487 | static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 }; | ||
488 | static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c }; | ||
489 | static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 }; | ||
490 | static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 }; | ||
491 | static const u16 NCT6106_REG_TEMP_SOURCE[] = { | ||
492 | 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 }; | ||
493 | |||
494 | static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a }; | ||
495 | static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = { | ||
496 | 0x11b, 0x12b, 0x13b }; | ||
497 | |||
498 | static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c }; | ||
499 | #define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10 | ||
500 | static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d }; | ||
501 | |||
502 | static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 }; | ||
503 | static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 }; | ||
504 | static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 }; | ||
505 | static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 }; | ||
506 | static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 }; | ||
507 | static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 }; | ||
508 | |||
509 | static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 }; | ||
510 | |||
511 | static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 }; | ||
512 | static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 }; | ||
513 | static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a }; | ||
514 | static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c }; | ||
515 | static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c }; | ||
516 | static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d }; | ||
517 | |||
518 | static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 }; | ||
519 | static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 }; | ||
520 | |||
521 | static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = { | ||
522 | 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d }; | ||
523 | |||
524 | static const s8 NCT6106_ALARM_BITS[] = { | ||
525 | 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */ | ||
526 | 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */ | ||
527 | -1, /* unused */ | ||
528 | 32, 33, 34, -1, -1, /* fan1..fan5 */ | ||
529 | -1, -1, -1, /* unused */ | ||
530 | 16, 17, 18, 19, 20, 21, /* temp1..temp6 */ | ||
531 | 48, -1 /* intrusion0, intrusion1 */ | ||
532 | }; | ||
533 | |||
534 | static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1] | ||
535 | = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 }; | ||
536 | |||
537 | static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1] | ||
538 | = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 }; | ||
539 | |||
452 | static enum pwm_enable reg_to_pwm_enable(int pwm, int mode) | 540 | static enum pwm_enable reg_to_pwm_enable(int pwm, int mode) |
453 | { | 541 | { |
454 | if (mode == 0 && pwm == 255) | 542 | if (mode == 0 && pwm == 255) |
@@ -570,6 +658,7 @@ struct nct6775_data { | |||
570 | u16 REG_CONFIG; | 658 | u16 REG_CONFIG; |
571 | u16 REG_VBAT; | 659 | u16 REG_VBAT; |
572 | u16 REG_DIODE; | 660 | u16 REG_DIODE; |
661 | u8 DIODE_MASK; | ||
573 | 662 | ||
574 | const s8 *ALARM_BITS; | 663 | const s8 *ALARM_BITS; |
575 | 664 | ||
@@ -581,6 +670,7 @@ struct nct6775_data { | |||
581 | const u16 *REG_FAN_MODE; | 670 | const u16 *REG_FAN_MODE; |
582 | const u16 *REG_FAN_MIN; | 671 | const u16 *REG_FAN_MIN; |
583 | const u16 *REG_FAN_PULSES; | 672 | const u16 *REG_FAN_PULSES; |
673 | const u16 *FAN_PULSE_SHIFT; | ||
584 | const u16 *REG_FAN_TIME[3]; | 674 | const u16 *REG_FAN_TIME[3]; |
585 | 675 | ||
586 | const u16 *REG_TOLERANCE_H; | 676 | const u16 *REG_TOLERANCE_H; |
@@ -594,6 +684,10 @@ struct nct6775_data { | |||
594 | */ | 684 | */ |
595 | const u16 *REG_PWM_READ; | 685 | const u16 *REG_PWM_READ; |
596 | 686 | ||
687 | const u16 *REG_CRITICAL_PWM_ENABLE; | ||
688 | u8 CRITICAL_PWM_ENABLE_MASK; | ||
689 | const u16 *REG_CRITICAL_PWM; | ||
690 | |||
597 | const u16 *REG_AUTO_TEMP; | 691 | const u16 *REG_AUTO_TEMP; |
598 | const u16 *REG_AUTO_PWM; | 692 | const u16 *REG_AUTO_PWM; |
599 | 693 | ||
@@ -629,7 +723,7 @@ struct nct6775_data { | |||
629 | u8 has_fan_min; /* some fans don't have min register */ | 723 | u8 has_fan_min; /* some fans don't have min register */ |
630 | bool has_fan_div; | 724 | bool has_fan_div; |
631 | 725 | ||
632 | u8 num_temp_alarms; /* 2 or 3 */ | 726 | u8 num_temp_alarms; /* 2, 3, or 6 */ |
633 | u8 temp_fixed_num; /* 3 or 6 */ | 727 | u8 temp_fixed_num; /* 3 or 6 */ |
634 | u8 temp_type[NUM_TEMP_FIXED]; | 728 | u8 temp_type[NUM_TEMP_FIXED]; |
635 | s8 temp_offset[NUM_TEMP_FIXED]; | 729 | s8 temp_offset[NUM_TEMP_FIXED]; |
@@ -829,6 +923,10 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, | |||
829 | static bool is_word_sized(struct nct6775_data *data, u16 reg) | 923 | static bool is_word_sized(struct nct6775_data *data, u16 reg) |
830 | { | 924 | { |
831 | switch (data->kind) { | 925 | switch (data->kind) { |
926 | case nct6106: | ||
927 | return reg == 0x20 || reg == 0x22 || reg == 0x24 || | ||
928 | reg == 0xe0 || reg == 0xe2 || reg == 0xe4 || | ||
929 | reg == 0x111 || reg == 0x121 || reg == 0x131; | ||
832 | case nct6775: | 930 | case nct6775: |
833 | return (((reg & 0xff00) == 0x100 || | 931 | return (((reg & 0xff00) == 0x100 || |
834 | (reg & 0xff00) == 0x200) && | 932 | (reg & 0xff00) == 0x200) && |
@@ -1194,15 +1292,16 @@ static void nct6775_update_pwm_limits(struct device *dev) | |||
1194 | case nct6776: | 1292 | case nct6776: |
1195 | data->auto_pwm[i][data->auto_pwm_num] = 0xff; | 1293 | data->auto_pwm[i][data->auto_pwm_num] = 0xff; |
1196 | break; | 1294 | break; |
1295 | case nct6106: | ||
1197 | case nct6779: | 1296 | case nct6779: |
1198 | reg = nct6775_read_value(data, | 1297 | reg = nct6775_read_value(data, |
1199 | NCT6779_REG_CRITICAL_PWM_ENABLE[i]); | 1298 | data->REG_CRITICAL_PWM_ENABLE[i]); |
1200 | if (reg & 1) | 1299 | if (reg & data->CRITICAL_PWM_ENABLE_MASK) |
1201 | data->auto_pwm[i][data->auto_pwm_num] = | 1300 | reg = nct6775_read_value(data, |
1202 | nct6775_read_value(data, | 1301 | data->REG_CRITICAL_PWM[i]); |
1203 | NCT6779_REG_CRITICAL_PWM[i]); | ||
1204 | else | 1302 | else |
1205 | data->auto_pwm[i][data->auto_pwm_num] = 0xff; | 1303 | reg = 0xff; |
1304 | data->auto_pwm[i][data->auto_pwm_num] = reg; | ||
1206 | break; | 1305 | break; |
1207 | } | 1306 | } |
1208 | } | 1307 | } |
@@ -1248,7 +1347,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) | |||
1248 | data->fan_min[i] = nct6775_read_value(data, | 1347 | data->fan_min[i] = nct6775_read_value(data, |
1249 | data->REG_FAN_MIN[i]); | 1348 | data->REG_FAN_MIN[i]); |
1250 | data->fan_pulses[i] = | 1349 | data->fan_pulses[i] = |
1251 | nct6775_read_value(data, data->REG_FAN_PULSES[i]); | 1350 | (nct6775_read_value(data, data->REG_FAN_PULSES[i]) |
1351 | >> data->FAN_PULSE_SHIFT[i]) & 0x03; | ||
1252 | 1352 | ||
1253 | nct6775_select_fan_div(dev, data, i, reg); | 1353 | nct6775_select_fan_div(dev, data, i, reg); |
1254 | } | 1354 | } |
@@ -1548,6 +1648,7 @@ store_fan_pulses(struct device *dev, struct device_attribute *attr, | |||
1548 | int nr = sattr->index; | 1648 | int nr = sattr->index; |
1549 | unsigned long val; | 1649 | unsigned long val; |
1550 | int err; | 1650 | int err; |
1651 | u8 reg; | ||
1551 | 1652 | ||
1552 | err = kstrtoul(buf, 10, &val); | 1653 | err = kstrtoul(buf, 10, &val); |
1553 | if (err < 0) | 1654 | if (err < 0) |
@@ -1558,7 +1659,10 @@ store_fan_pulses(struct device *dev, struct device_attribute *attr, | |||
1558 | 1659 | ||
1559 | mutex_lock(&data->update_lock); | 1660 | mutex_lock(&data->update_lock); |
1560 | data->fan_pulses[nr] = val & 3; | 1661 | data->fan_pulses[nr] = val & 3; |
1561 | nct6775_write_value(data, data->REG_FAN_PULSES[nr], val & 3); | 1662 | reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]); |
1663 | reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]); | ||
1664 | reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr]; | ||
1665 | nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg); | ||
1562 | mutex_unlock(&data->update_lock); | 1666 | mutex_unlock(&data->update_lock); |
1563 | 1667 | ||
1564 | return count; | 1668 | return count; |
@@ -1708,7 +1812,7 @@ store_temp_type(struct device *dev, struct device_attribute *attr, | |||
1708 | int nr = sattr->index; | 1812 | int nr = sattr->index; |
1709 | unsigned long val; | 1813 | unsigned long val; |
1710 | int err; | 1814 | int err; |
1711 | u8 vbat, diode, bit; | 1815 | u8 vbat, diode, vbit, dbit; |
1712 | 1816 | ||
1713 | err = kstrtoul(buf, 10, &val); | 1817 | err = kstrtoul(buf, 10, &val); |
1714 | if (err < 0) | 1818 | if (err < 0) |
@@ -1720,16 +1824,17 @@ store_temp_type(struct device *dev, struct device_attribute *attr, | |||
1720 | mutex_lock(&data->update_lock); | 1824 | mutex_lock(&data->update_lock); |
1721 | 1825 | ||
1722 | data->temp_type[nr] = val; | 1826 | data->temp_type[nr] = val; |
1723 | vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr); | 1827 | vbit = 0x02 << nr; |
1724 | diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr); | 1828 | dbit = data->DIODE_MASK << nr; |
1725 | bit = 0x02 << nr; | 1829 | vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit; |
1830 | diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit; | ||
1726 | switch (val) { | 1831 | switch (val) { |
1727 | case 1: /* CPU diode (diode, current mode) */ | 1832 | case 1: /* CPU diode (diode, current mode) */ |
1728 | vbat |= bit; | 1833 | vbat |= vbit; |
1729 | diode |= bit; | 1834 | diode |= dbit; |
1730 | break; | 1835 | break; |
1731 | case 3: /* diode, voltage mode */ | 1836 | case 3: /* diode, voltage mode */ |
1732 | vbat |= bit; | 1837 | vbat |= dbit; |
1733 | break; | 1838 | break; |
1734 | case 4: /* thermistor */ | 1839 | case 4: /* thermistor */ |
1735 | break; | 1840 | break; |
@@ -2471,17 +2576,18 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, | |||
2471 | break; | 2576 | break; |
2472 | case nct6776: | 2577 | case nct6776: |
2473 | break; /* always enabled, nothing to do */ | 2578 | break; /* always enabled, nothing to do */ |
2579 | case nct6106: | ||
2474 | case nct6779: | 2580 | case nct6779: |
2475 | nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr], | 2581 | nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], |
2476 | val); | 2582 | val); |
2477 | reg = nct6775_read_value(data, | 2583 | reg = nct6775_read_value(data, |
2478 | NCT6779_REG_CRITICAL_PWM_ENABLE[nr]); | 2584 | data->REG_CRITICAL_PWM_ENABLE[nr]); |
2479 | if (val == 255) | 2585 | if (val == 255) |
2480 | reg &= ~0x01; | 2586 | reg &= ~data->CRITICAL_PWM_ENABLE_MASK; |
2481 | else | 2587 | else |
2482 | reg |= 0x01; | 2588 | reg |= data->CRITICAL_PWM_ENABLE_MASK; |
2483 | nct6775_write_value(data, | 2589 | nct6775_write_value(data, |
2484 | NCT6779_REG_CRITICAL_PWM_ENABLE[nr], | 2590 | data->REG_CRITICAL_PWM_ENABLE[nr], |
2485 | reg); | 2591 | reg); |
2486 | break; | 2592 | break; |
2487 | } | 2593 | } |
@@ -2820,8 +2926,9 @@ static inline void nct6775_init_device(struct nct6775_data *data) | |||
2820 | for (i = 0; i < data->temp_fixed_num; i++) { | 2926 | for (i = 0; i < data->temp_fixed_num; i++) { |
2821 | if (!(data->have_temp_fixed & (1 << i))) | 2927 | if (!(data->have_temp_fixed & (1 << i))) |
2822 | continue; | 2928 | continue; |
2823 | if ((tmp & (0x02 << i))) /* diode */ | 2929 | if ((tmp & (data->DIODE_MASK << i))) /* diode */ |
2824 | data->temp_type[i] = 3 - ((diode >> i) & 0x02); | 2930 | data->temp_type[i] |
2931 | = 3 - ((diode >> i) & data->DIODE_MASK); | ||
2825 | else /* thermistor */ | 2932 | else /* thermistor */ |
2826 | data->temp_type[i] = 4; | 2933 | data->temp_type[i] = 4; |
2827 | } | 2934 | } |
@@ -2875,6 +2982,17 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data, | |||
2875 | pwm3pin = fan3pin; | 2982 | pwm3pin = fan3pin; |
2876 | pwm4pin = 0; | 2983 | pwm4pin = 0; |
2877 | pwm5pin = 0; | 2984 | pwm5pin = 0; |
2985 | } else if (data->kind == nct6106) { | ||
2986 | regval = superio_inb(sio_data->sioreg, 0x24); | ||
2987 | fan3pin = !(regval & 0x80); | ||
2988 | pwm3pin = regval & 0x08; | ||
2989 | fan3min = fan3pin; | ||
2990 | |||
2991 | fan4pin = false; | ||
2992 | fan4min = false; | ||
2993 | fan5pin = false; | ||
2994 | pwm4pin = false; | ||
2995 | pwm5pin = false; | ||
2878 | } else { /* NCT6779D */ | 2996 | } else { /* NCT6779D */ |
2879 | regval = superio_inb(sio_data->sioreg, 0x1c); | 2997 | regval = superio_inb(sio_data->sioreg, 0x1c); |
2880 | 2998 | ||
@@ -2958,6 +3076,70 @@ static int nct6775_probe(struct platform_device *pdev) | |||
2958 | platform_set_drvdata(pdev, data); | 3076 | platform_set_drvdata(pdev, data); |
2959 | 3077 | ||
2960 | switch (data->kind) { | 3078 | switch (data->kind) { |
3079 | case nct6106: | ||
3080 | data->in_num = 9; | ||
3081 | data->pwm_num = 3; | ||
3082 | data->auto_pwm_num = 4; | ||
3083 | data->temp_fixed_num = 3; | ||
3084 | data->num_temp_alarms = 6; | ||
3085 | |||
3086 | data->fan_from_reg = fan_from_reg13; | ||
3087 | data->fan_from_reg_min = fan_from_reg13; | ||
3088 | |||
3089 | data->temp_label = nct6776_temp_label; | ||
3090 | data->temp_label_num = ARRAY_SIZE(nct6776_temp_label); | ||
3091 | |||
3092 | data->REG_VBAT = NCT6106_REG_VBAT; | ||
3093 | data->REG_DIODE = NCT6106_REG_DIODE; | ||
3094 | data->DIODE_MASK = NCT6106_DIODE_MASK; | ||
3095 | data->REG_VIN = NCT6106_REG_IN; | ||
3096 | data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN; | ||
3097 | data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX; | ||
3098 | data->REG_TARGET = NCT6106_REG_TARGET; | ||
3099 | data->REG_FAN = NCT6106_REG_FAN; | ||
3100 | data->REG_FAN_MODE = NCT6106_REG_FAN_MODE; | ||
3101 | data->REG_FAN_MIN = NCT6106_REG_FAN_MIN; | ||
3102 | data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES; | ||
3103 | data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT; | ||
3104 | data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME; | ||
3105 | data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME; | ||
3106 | data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME; | ||
3107 | data->REG_PWM[0] = NCT6106_REG_PWM; | ||
3108 | data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT; | ||
3109 | data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT; | ||
3110 | data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP; | ||
3111 | data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE; | ||
3112 | data->REG_PWM_READ = NCT6106_REG_PWM_READ; | ||
3113 | data->REG_PWM_MODE = NCT6106_REG_PWM_MODE; | ||
3114 | data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK; | ||
3115 | data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP; | ||
3116 | data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM; | ||
3117 | data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP; | ||
3118 | data->REG_CRITICAL_TEMP_TOLERANCE | ||
3119 | = NCT6106_REG_CRITICAL_TEMP_TOLERANCE; | ||
3120 | data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE; | ||
3121 | data->CRITICAL_PWM_ENABLE_MASK | ||
3122 | = NCT6106_CRITICAL_PWM_ENABLE_MASK; | ||
3123 | data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM; | ||
3124 | data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET; | ||
3125 | data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE; | ||
3126 | data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL; | ||
3127 | data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL; | ||
3128 | data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP; | ||
3129 | data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL; | ||
3130 | data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE; | ||
3131 | data->REG_ALARM = NCT6106_REG_ALARM; | ||
3132 | data->ALARM_BITS = NCT6106_ALARM_BITS; | ||
3133 | |||
3134 | reg_temp = NCT6106_REG_TEMP; | ||
3135 | num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP); | ||
3136 | reg_temp_over = NCT6106_REG_TEMP_OVER; | ||
3137 | reg_temp_hyst = NCT6106_REG_TEMP_HYST; | ||
3138 | reg_temp_config = NCT6106_REG_TEMP_CONFIG; | ||
3139 | reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE; | ||
3140 | reg_temp_crit = NCT6106_REG_TEMP_CRIT; | ||
3141 | |||
3142 | break; | ||
2961 | case nct6775: | 3143 | case nct6775: |
2962 | data->in_num = 9; | 3144 | data->in_num = 9; |
2963 | data->pwm_num = 3; | 3145 | data->pwm_num = 3; |
@@ -2980,6 +3162,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
2980 | data->REG_CONFIG = NCT6775_REG_CONFIG; | 3162 | data->REG_CONFIG = NCT6775_REG_CONFIG; |
2981 | data->REG_VBAT = NCT6775_REG_VBAT; | 3163 | data->REG_VBAT = NCT6775_REG_VBAT; |
2982 | data->REG_DIODE = NCT6775_REG_DIODE; | 3164 | data->REG_DIODE = NCT6775_REG_DIODE; |
3165 | data->DIODE_MASK = NCT6775_DIODE_MASK; | ||
2983 | data->REG_VIN = NCT6775_REG_IN; | 3166 | data->REG_VIN = NCT6775_REG_IN; |
2984 | data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; | 3167 | data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; |
2985 | data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; | 3168 | data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; |
@@ -2988,6 +3171,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
2988 | data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; | 3171 | data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; |
2989 | data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; | 3172 | data->REG_FAN_MIN = NCT6775_REG_FAN_MIN; |
2990 | data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; | 3173 | data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES; |
3174 | data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; | ||
2991 | data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; | 3175 | data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; |
2992 | data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; | 3176 | data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; |
2993 | data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; | 3177 | data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; |
@@ -3045,6 +3229,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3045 | data->REG_CONFIG = NCT6775_REG_CONFIG; | 3229 | data->REG_CONFIG = NCT6775_REG_CONFIG; |
3046 | data->REG_VBAT = NCT6775_REG_VBAT; | 3230 | data->REG_VBAT = NCT6775_REG_VBAT; |
3047 | data->REG_DIODE = NCT6775_REG_DIODE; | 3231 | data->REG_DIODE = NCT6775_REG_DIODE; |
3232 | data->DIODE_MASK = NCT6775_DIODE_MASK; | ||
3048 | data->REG_VIN = NCT6775_REG_IN; | 3233 | data->REG_VIN = NCT6775_REG_IN; |
3049 | data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; | 3234 | data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; |
3050 | data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; | 3235 | data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; |
@@ -3053,6 +3238,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3053 | data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; | 3238 | data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; |
3054 | data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; | 3239 | data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; |
3055 | data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; | 3240 | data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; |
3241 | data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; | ||
3056 | data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; | 3242 | data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; |
3057 | data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; | 3243 | data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; |
3058 | data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; | 3244 | data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; |
@@ -3110,6 +3296,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3110 | data->REG_CONFIG = NCT6775_REG_CONFIG; | 3296 | data->REG_CONFIG = NCT6775_REG_CONFIG; |
3111 | data->REG_VBAT = NCT6775_REG_VBAT; | 3297 | data->REG_VBAT = NCT6775_REG_VBAT; |
3112 | data->REG_DIODE = NCT6775_REG_DIODE; | 3298 | data->REG_DIODE = NCT6775_REG_DIODE; |
3299 | data->DIODE_MASK = NCT6775_DIODE_MASK; | ||
3113 | data->REG_VIN = NCT6779_REG_IN; | 3300 | data->REG_VIN = NCT6779_REG_IN; |
3114 | data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; | 3301 | data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; |
3115 | data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; | 3302 | data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; |
@@ -3118,6 +3305,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3118 | data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; | 3305 | data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; |
3119 | data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; | 3306 | data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; |
3120 | data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; | 3307 | data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; |
3308 | data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; | ||
3121 | data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; | 3309 | data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; |
3122 | data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; | 3310 | data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; |
3123 | data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; | 3311 | data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; |
@@ -3135,6 +3323,10 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3135 | data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; | 3323 | data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; |
3136 | data->REG_CRITICAL_TEMP_TOLERANCE | 3324 | data->REG_CRITICAL_TEMP_TOLERANCE |
3137 | = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; | 3325 | = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; |
3326 | data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE; | ||
3327 | data->CRITICAL_PWM_ENABLE_MASK | ||
3328 | = NCT6779_CRITICAL_PWM_ENABLE_MASK; | ||
3329 | data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM; | ||
3138 | data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; | 3330 | data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; |
3139 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; | 3331 | data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE; |
3140 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; | 3332 | data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; |
@@ -3286,6 +3478,7 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3286 | case nct6776: | 3478 | case nct6776: |
3287 | data->have_vid = (cr2a & 0x60) == 0x40; | 3479 | data->have_vid = (cr2a & 0x60) == 0x40; |
3288 | break; | 3480 | break; |
3481 | case nct6106: | ||
3289 | case nct6779: | 3482 | case nct6779: |
3290 | break; | 3483 | break; |
3291 | } | 3484 | } |
@@ -3307,6 +3500,9 @@ static int nct6775_probe(struct platform_device *pdev) | |||
3307 | tmp = superio_inb(sio_data->sioreg, | 3500 | tmp = superio_inb(sio_data->sioreg, |
3308 | NCT6775_REG_CR_FAN_DEBOUNCE); | 3501 | NCT6775_REG_CR_FAN_DEBOUNCE); |
3309 | switch (data->kind) { | 3502 | switch (data->kind) { |
3503 | case nct6106: | ||
3504 | tmp |= 0xe0; | ||
3505 | break; | ||
3310 | case nct6775: | 3506 | case nct6775: |
3311 | tmp |= 0x1e; | 3507 | tmp |= 0x1e; |
3312 | break; | 3508 | break; |
@@ -3478,6 +3674,7 @@ static struct platform_driver nct6775_driver = { | |||
3478 | }; | 3674 | }; |
3479 | 3675 | ||
3480 | static const char * const nct6775_sio_names[] __initconst = { | 3676 | static const char * const nct6775_sio_names[] __initconst = { |
3677 | "NCT6106D", | ||
3481 | "NCT6775F", | 3678 | "NCT6775F", |
3482 | "NCT6776D/F", | 3679 | "NCT6776D/F", |
3483 | "NCT6779D", | 3680 | "NCT6779D", |
@@ -3500,6 +3697,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) | |||
3500 | val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | 3697 | val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) |
3501 | | superio_inb(sioaddr, SIO_REG_DEVID + 1); | 3698 | | superio_inb(sioaddr, SIO_REG_DEVID + 1); |
3502 | switch (val & SIO_ID_MASK) { | 3699 | switch (val & SIO_ID_MASK) { |
3700 | case SIO_NCT6106_ID: | ||
3701 | sio_data->kind = nct6106; | ||
3702 | break; | ||
3503 | case SIO_NCT6775_ID: | 3703 | case SIO_NCT6775_ID: |
3504 | sio_data->kind = nct6775; | 3704 | sio_data->kind = nct6775; |
3505 | break; | 3705 | break; |