aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorDavid Bartley <andareed@gmail.com>2013-06-25 01:28:28 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-08-12 01:10:39 -0400
commit578ab5f0e4b13a6f63e9ee108a44d7a20f6ccfce (patch)
treeab7969d3a63070897fedef32935cc95990193b01 /drivers/hwmon
parent30846993047b6611dece427a05b0135d97063153 (diff)
hwmon: (nct6775) Add support for NCT6791D
Signed-off-by: David Bartley <andareed@gmail.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/nct6775.c281
1 files changed, 207 insertions, 74 deletions
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 6386d1b16a23..3a9bb6671f29 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -37,6 +37,7 @@
37 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3 37 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
38 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3 38 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
39 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3 39 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
40 * nct6791d 15 6 6 2+6 0xc800 0xc1 0x5ca3
40 * 41 *
41 * #temp lists the number of monitored temperature sources (first value) plus 42 * #temp lists the number of monitored temperature sources (first value) plus
42 * the number of directly connectable temperature sensors (second value). 43 * the number of directly connectable temperature sensors (second value).
@@ -60,7 +61,7 @@
60 61
61#define USE_ALTERNATE 62#define USE_ALTERNATE
62 63
63enum kinds { nct6106, nct6775, nct6776, nct6779 }; 64enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791 };
64 65
65/* used to set data->name = nct6775_device_names[data->sio_kind] */ 66/* used to set data->name = nct6775_device_names[data->sio_kind] */
66static const char * const nct6775_device_names[] = { 67static const char * const nct6775_device_names[] = {
@@ -68,6 +69,7 @@ static const char * const nct6775_device_names[] = {
68 "nct6775", 69 "nct6775",
69 "nct6776", 70 "nct6776",
70 "nct6779", 71 "nct6779",
72 "nct6791",
71}; 73};
72 74
73static unsigned short force_id; 75static unsigned short force_id;
@@ -97,6 +99,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
97#define SIO_NCT6775_ID 0xb470 99#define SIO_NCT6775_ID 0xb470
98#define SIO_NCT6776_ID 0xc330 100#define SIO_NCT6776_ID 0xc330
99#define SIO_NCT6779_ID 0xc560 101#define SIO_NCT6779_ID 0xc560
102#define SIO_NCT6791_ID 0xc800
100#define SIO_ID_MASK 0xFFF0 103#define SIO_ID_MASK 0xFFF0
101 104
102enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; 105enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -173,6 +176,8 @@ superio_exit(int ioreg)
173#define NUM_REG_ALARM 7 /* Max number of alarm registers */ 176#define NUM_REG_ALARM 7 /* Max number of alarm registers */
174#define NUM_REG_BEEP 5 /* Max number of beep registers */ 177#define NUM_REG_BEEP 5 /* Max number of beep registers */
175 178
179#define NUM_FAN 6
180
176/* Common and NCT6775 specific data */ 181/* Common and NCT6775 specific data */
177 182
178/* Voltage min/max registers for nr=7..14 are in bank 5 */ 183/* Voltage min/max registers for nr=7..14 are in bank 5 */
@@ -239,28 +244,32 @@ static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
239 244
240/* Advanced Fan control, some values are common for all fans */ 245/* Advanced Fan control, some values are common for all fans */
241 246
242static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 }; 247static const u16 NCT6775_REG_TARGET[] = {
243static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; 248 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 };
249static const u16 NCT6775_REG_FAN_MODE[] = {
250 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 };
244static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = { 251static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
245 0x103, 0x203, 0x303, 0x803, 0x903 }; 252 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 };
246static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = { 253static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
247 0x104, 0x204, 0x304, 0x804, 0x904 }; 254 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 };
248static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 255static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
249 0x105, 0x205, 0x305, 0x805, 0x905 }; 256 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 };
250static const u16 NCT6775_REG_FAN_START_OUTPUT[] 257static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
251 = { 0x106, 0x206, 0x306, 0x806, 0x906 }; 258 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 };
252static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a }; 259static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
253static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b }; 260static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
254 261
255static const u16 NCT6775_REG_FAN_STOP_TIME[] = { 262static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
256 0x107, 0x207, 0x307, 0x807, 0x907 }; 263 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 };
257static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 }; 264static const u16 NCT6775_REG_PWM[] = {
258static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 }; 265 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 };
266static const u16 NCT6775_REG_PWM_READ[] = {
267 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 };
259 268
260static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; 269static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
261static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; 270static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
262static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; 271static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
263static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0 }; 272static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
264 273
265static const u16 NCT6775_REG_TEMP[] = { 274static const u16 NCT6775_REG_TEMP[] = {
266 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; 275 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
@@ -276,25 +285,25 @@ static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
276 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 }; 285 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
277 286
278static const u16 NCT6775_REG_TEMP_SEL[] = { 287static const u16 NCT6775_REG_TEMP_SEL[] = {
279 0x100, 0x200, 0x300, 0x800, 0x900 }; 288 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 };
280 289
281static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = { 290static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
282 0x139, 0x239, 0x339, 0x839, 0x939 }; 291 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
283static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = { 292static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
284 0x13a, 0x23a, 0x33a, 0x83a, 0x93a }; 293 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
285static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = { 294static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
286 0x13b, 0x23b, 0x33b, 0x83b, 0x93b }; 295 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
287static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = { 296static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
288 0x13c, 0x23c, 0x33c, 0x83c, 0x93c }; 297 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
289static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = { 298static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
290 0x13d, 0x23d, 0x33d, 0x83d, 0x93d }; 299 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
291 300
292static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; 301static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
293 302
294static const u16 NCT6775_REG_AUTO_TEMP[] = { 303static const u16 NCT6775_REG_AUTO_TEMP[] = {
295 0x121, 0x221, 0x321, 0x821, 0x921 }; 304 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 };
296static const u16 NCT6775_REG_AUTO_PWM[] = { 305static const u16 NCT6775_REG_AUTO_PWM[] = {
297 0x127, 0x227, 0x327, 0x827, 0x927 }; 306 0x127, 0x227, 0x327, 0x827, 0x927, 0xa27 };
298 307
299#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p)) 308#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
300#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p)) 309#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
@@ -302,9 +311,9 @@ static const u16 NCT6775_REG_AUTO_PWM[] = {
302static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 }; 311static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
303 312
304static const u16 NCT6775_REG_CRITICAL_TEMP[] = { 313static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
305 0x135, 0x235, 0x335, 0x835, 0x935 }; 314 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 };
306static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = { 315static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
307 0x138, 0x238, 0x338, 0x838, 0x938 }; 316 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 };
308 317
309static const char *const nct6775_temp_label[] = { 318static const char *const nct6775_temp_label[] = {
310 "", 319 "",
@@ -360,16 +369,16 @@ static const s8 NCT6776_BEEP_BITS[] = {
360 30, 31 }; /* intrusion0, intrusion1 */ 369 30, 31 }; /* intrusion0, intrusion1 */
361 370
362static const u16 NCT6776_REG_TOLERANCE_H[] = { 371static const u16 NCT6776_REG_TOLERANCE_H[] = {
363 0x10c, 0x20c, 0x30c, 0x80c, 0x90c }; 372 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c };
364 373
365static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 }; 374static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
366static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; 375static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
367 376
368static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; 377static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
369static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; 378static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
370 379
371static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = { 380static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
372 0x13e, 0x23e, 0x33e, 0x83e, 0x93e }; 381 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
373 382
374static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { 383static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
375 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A }; 384 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
@@ -433,15 +442,16 @@ static const s8 NCT6779_BEEP_BITS[] = {
433 16, 17, -1, -1, -1, -1, /* temp1..temp6 */ 442 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
434 30, 31 }; /* intrusion0, intrusion1 */ 443 30, 31 }; /* intrusion0, intrusion1 */
435 444
436static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; 445static const u16 NCT6779_REG_FAN[] = {
446 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba };
437static const u16 NCT6779_REG_FAN_PULSES[] = { 447static const u16 NCT6779_REG_FAN_PULSES[] = {
438 0x644, 0x645, 0x646, 0x647, 0x648 }; 448 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
439 449
440static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = { 450static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
441 0x136, 0x236, 0x336, 0x836, 0x936 }; 451 0x136, 0x236, 0x336, 0x836, 0x936, 0xa36 };
442#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01 452#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
443static const u16 NCT6779_REG_CRITICAL_PWM[] = { 453static const u16 NCT6779_REG_CRITICAL_PWM[] = {
444 0x137, 0x237, 0x337, 0x837, 0x937 }; 454 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
445 455
446static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; 456static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
447static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { 457static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
@@ -493,6 +503,23 @@ static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
493static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] 503static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
494 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a }; 504 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
495 505
506/* NCT6791 specific data */
507
508#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
509
510static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
511 0x459, 0x45A, 0x45B, 0x568, 0x45D };
512
513static const s8 NCT6791_ALARM_BITS[] = {
514 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
515 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
516 -1, /* unused */
517 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
518 -1, -1, /* unused */
519 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
520 12, 9 }; /* intrusion0, intrusion1 */
521
522
496/* NCT6102D/NCT6106D specific data */ 523/* NCT6102D/NCT6106D specific data */
497 524
498#define NCT6106_REG_VBAT 0x318 525#define NCT6106_REG_VBAT 0x318
@@ -771,10 +798,10 @@ struct nct6775_data {
771 u8 bank; /* current register bank */ 798 u8 bank; /* current register bank */
772 u8 in_num; /* number of in inputs we have */ 799 u8 in_num; /* number of in inputs we have */
773 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ 800 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
774 unsigned int rpm[5]; 801 unsigned int rpm[NUM_FAN];
775 u16 fan_min[5]; 802 u16 fan_min[NUM_FAN];
776 u8 fan_pulses[5]; 803 u8 fan_pulses[NUM_FAN];
777 u8 fan_div[5]; 804 u8 fan_div[NUM_FAN];
778 u8 has_pwm; 805 u8 has_pwm;
779 u8 has_fan; /* some fan inputs can be disabled */ 806 u8 has_fan; /* some fan inputs can be disabled */
780 u8 has_fan_min; /* some fans don't have min register */ 807 u8 has_fan_min; /* some fans don't have min register */
@@ -791,8 +818,10 @@ struct nct6775_data {
791 u64 beeps; 818 u64 beeps;
792 819
793 u8 pwm_num; /* number of pwm */ 820 u8 pwm_num; /* number of pwm */
794 u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */ 821 u8 pwm_mode[NUM_FAN]; /* 1->DC variable voltage,
795 enum pwm_enable pwm_enable[5]; 822 * 0->PWM variable duty cycle
823 */
824 enum pwm_enable pwm_enable[NUM_FAN];
796 /* 0->off 825 /* 0->off
797 * 1->manual 826 * 1->manual
798 * 2->thermal cruise mode (also called SmartFan I) 827 * 2->thermal cruise mode (also called SmartFan I)
@@ -800,31 +829,31 @@ struct nct6775_data {
800 * 4->SmartFan III 829 * 4->SmartFan III
801 * 5->enhanced variable thermal cruise (SmartFan IV) 830 * 5->enhanced variable thermal cruise (SmartFan IV)
802 */ 831 */
803 u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor, 832 u8 pwm[7][NUM_FAN]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
804 * [3]=pwm_max, [4]=pwm_step, 833 * [3]=pwm_max, [4]=pwm_step,
805 * [5]=weight_duty_step, [6]=weight_duty_base 834 * [5]=weight_duty_step, [6]=weight_duty_base
806 */ 835 */
807 836
808 u8 target_temp[5]; 837 u8 target_temp[NUM_FAN];
809 u8 target_temp_mask; 838 u8 target_temp_mask;
810 u32 target_speed[5]; 839 u32 target_speed[NUM_FAN];
811 u32 target_speed_tolerance[5]; 840 u32 target_speed_tolerance[NUM_FAN];
812 u8 speed_tolerance_limit; 841 u8 speed_tolerance_limit;
813 842
814 u8 temp_tolerance[2][5]; 843 u8 temp_tolerance[2][NUM_FAN];
815 u8 tolerance_mask; 844 u8 tolerance_mask;
816 845
817 u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */ 846 u8 fan_time[3][NUM_FAN]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
818 847
819 /* Automatic fan speed control registers */ 848 /* Automatic fan speed control registers */
820 int auto_pwm_num; 849 int auto_pwm_num;
821 u8 auto_pwm[5][7]; 850 u8 auto_pwm[NUM_FAN][7];
822 u8 auto_temp[5][7]; 851 u8 auto_temp[NUM_FAN][7];
823 u8 pwm_temp_sel[5]; 852 u8 pwm_temp_sel[NUM_FAN];
824 u8 pwm_weight_temp_sel[5]; 853 u8 pwm_weight_temp_sel[NUM_FAN];
825 u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol, 854 u8 weight_temp[3][NUM_FAN]; /* 0->temp_step, 1->temp_step_tol,
826 * 2->temp_base 855 * 2->temp_base
827 */ 856 */
828 857
829 u8 vid; 858 u8 vid;
830 u8 vrm; 859 u8 vrm;
@@ -1009,8 +1038,9 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
1009 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) || 1038 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1010 reg == 0x73 || reg == 0x75 || reg == 0x77; 1039 reg == 0x73 || reg == 0x75 || reg == 0x77;
1011 case nct6779: 1040 case nct6779:
1041 case nct6791:
1012 return reg == 0x150 || reg == 0x153 || reg == 0x155 || 1042 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
1013 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) || 1043 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
1014 reg == 0x402 || 1044 reg == 0x402 ||
1015 reg == 0x63a || reg == 0x63c || reg == 0x63e || 1045 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1016 reg == 0x640 || reg == 0x642 || 1046 reg == 0x640 || reg == 0x642 ||
@@ -1353,6 +1383,7 @@ static void nct6775_update_pwm_limits(struct device *dev)
1353 break; 1383 break;
1354 case nct6106: 1384 case nct6106:
1355 case nct6779: 1385 case nct6779:
1386 case nct6791:
1356 reg = nct6775_read_value(data, 1387 reg = nct6775_read_value(data,
1357 data->REG_CRITICAL_PWM_ENABLE[i]); 1388 data->REG_CRITICAL_PWM_ENABLE[i]);
1358 if (reg & data->CRITICAL_PWM_ENABLE_MASK) 1389 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
@@ -2760,6 +2791,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
2760 break; /* always enabled, nothing to do */ 2791 break; /* always enabled, nothing to do */
2761 case nct6106: 2792 case nct6106:
2762 case nct6779: 2793 case nct6779:
2794 case nct6791:
2763 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], 2795 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
2764 val); 2796 val);
2765 reg = nct6775_read_value(data, 2797 reg = nct6775_read_value(data,
@@ -3135,23 +3167,24 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
3135 struct nct6775_data *data) 3167 struct nct6775_data *data)
3136{ 3168{
3137 int regval; 3169 int regval;
3138 bool fan3pin, fan3min, fan4pin, fan4min, fan5pin; 3170 bool fan3pin, fan4pin, fan4min, fan5pin, fan6pin;
3139 bool pwm3pin, pwm4pin, pwm5pin; 3171 bool pwm3pin, pwm4pin, pwm5pin, pwm6pin;
3140 3172
3141 /* fan4 and fan5 share some pins with the GPIO and serial flash */ 3173 /* fan4 and fan5 share some pins with the GPIO and serial flash */
3142 if (data->kind == nct6775) { 3174 if (data->kind == nct6775) {
3143 regval = superio_inb(sio_data->sioreg, 0x2c); 3175 regval = superio_inb(sio_data->sioreg, 0x2c);
3144 3176
3145 fan3pin = regval & (1 << 6); 3177 fan3pin = regval & (1 << 6);
3146 fan3min = fan3pin;
3147 pwm3pin = regval & (1 << 7); 3178 pwm3pin = regval & (1 << 7);
3148 3179
3149 /* On NCT6775, fan4 shares pins with the fdc interface */ 3180 /* On NCT6775, fan4 shares pins with the fdc interface */
3150 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80); 3181 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
3151 fan4min = 0; 3182 fan4min = false;
3152 fan5pin = 0; 3183 fan5pin = false;
3153 pwm4pin = 0; 3184 fan6pin = false;
3154 pwm5pin = 0; 3185 pwm4pin = false;
3186 pwm5pin = false;
3187 pwm6pin = false;
3155 } else if (data->kind == nct6776) { 3188 } else if (data->kind == nct6776) {
3156 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; 3189 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
3157 3190
@@ -3174,22 +3207,24 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
3174 fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02; 3207 fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
3175 3208
3176 fan4min = fan4pin; 3209 fan4min = fan4pin;
3177 fan3min = fan3pin; 3210 fan6pin = false;
3178 pwm3pin = fan3pin; 3211 pwm3pin = fan3pin;
3179 pwm4pin = 0; 3212 pwm4pin = false;
3180 pwm5pin = 0; 3213 pwm5pin = false;
3214 pwm6pin = false;
3181 } else if (data->kind == nct6106) { 3215 } else if (data->kind == nct6106) {
3182 regval = superio_inb(sio_data->sioreg, 0x24); 3216 regval = superio_inb(sio_data->sioreg, 0x24);
3183 fan3pin = !(regval & 0x80); 3217 fan3pin = !(regval & 0x80);
3184 pwm3pin = regval & 0x08; 3218 pwm3pin = regval & 0x08;
3185 fan3min = fan3pin;
3186 3219
3187 fan4pin = false; 3220 fan4pin = false;
3188 fan4min = false; 3221 fan4min = false;
3189 fan5pin = false; 3222 fan5pin = false;
3223 fan6pin = false;
3190 pwm4pin = false; 3224 pwm4pin = false;
3191 pwm5pin = false; 3225 pwm5pin = false;
3192 } else { /* NCT6779D */ 3226 pwm6pin = false;
3227 } else { /* NCT6779D or NCT6791D */
3193 regval = superio_inb(sio_data->sioreg, 0x1c); 3228 regval = superio_inb(sio_data->sioreg, 0x1c);
3194 3229
3195 fan3pin = !(regval & (1 << 5)); 3230 fan3pin = !(regval & (1 << 5));
@@ -3200,18 +3235,25 @@ nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
3200 pwm4pin = !(regval & (1 << 1)); 3235 pwm4pin = !(regval & (1 << 1));
3201 pwm5pin = !(regval & (1 << 2)); 3236 pwm5pin = !(regval & (1 << 2));
3202 3237
3203 fan3min = fan3pin;
3204 fan4min = fan4pin; 3238 fan4min = fan4pin;
3205 }
3206
3207 data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
3208 data->has_fan |= fan3pin << 2;
3209 data->has_fan_min |= fan3min << 2;
3210 3239
3211 data->has_fan |= (fan4pin << 3) | (fan5pin << 4); 3240 if (data->kind == nct6791) {
3212 data->has_fan_min |= (fan4min << 3) | (fan5pin << 4); 3241 regval = superio_inb(sio_data->sioreg, 0x2d);
3242 fan6pin = (regval & (1 << 1));
3243 pwm6pin = (regval & (1 << 0));
3244 } else { /* NCT6779D */
3245 fan6pin = false;
3246 pwm6pin = false;
3247 }
3248 }
3213 3249
3214 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4); 3250 /* fan 1 and 2 (0x03) are always present */
3251 data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |
3252 (fan5pin << 4) | (fan6pin << 5);
3253 data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |
3254 (fan5pin << 4);
3255 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |
3256 (pwm5pin << 4) | (pwm6pin << 5);
3215} 3257}
3216 3258
3217static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, 3259static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
@@ -3556,6 +3598,80 @@ static int nct6775_probe(struct platform_device *pdev)
3556 reg_temp_crit = NCT6779_REG_TEMP_CRIT; 3598 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3557 3599
3558 break; 3600 break;
3601 case nct6791:
3602 data->in_num = 15;
3603 data->pwm_num = 6;
3604 data->auto_pwm_num = 4;
3605 data->has_fan_div = false;
3606 data->temp_fixed_num = 6;
3607 data->num_temp_alarms = 2;
3608 data->num_temp_beeps = 2;
3609
3610 data->ALARM_BITS = NCT6791_ALARM_BITS;
3611 data->BEEP_BITS = NCT6779_BEEP_BITS;
3612
3613 data->fan_from_reg = fan_from_reg13;
3614 data->fan_from_reg_min = fan_from_reg13;
3615 data->target_temp_mask = 0xff;
3616 data->tolerance_mask = 0x07;
3617 data->speed_tolerance_limit = 63;
3618
3619 data->temp_label = nct6779_temp_label;
3620 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3621
3622 data->REG_CONFIG = NCT6775_REG_CONFIG;
3623 data->REG_VBAT = NCT6775_REG_VBAT;
3624 data->REG_DIODE = NCT6775_REG_DIODE;
3625 data->DIODE_MASK = NCT6775_DIODE_MASK;
3626 data->REG_VIN = NCT6779_REG_IN;
3627 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3628 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3629 data->REG_TARGET = NCT6775_REG_TARGET;
3630 data->REG_FAN = NCT6779_REG_FAN;
3631 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3632 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3633 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3634 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3635 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3636 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3637 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3638 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3639 data->REG_PWM[0] = NCT6775_REG_PWM;
3640 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3641 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3642 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3643 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
3644 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3645 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3646 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3647 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3648 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3649 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3650 data->REG_CRITICAL_TEMP_TOLERANCE
3651 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3652 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3653 data->CRITICAL_PWM_ENABLE_MASK
3654 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3655 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3656 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3657 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3658 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3659 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3660 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3661 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3662 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3663 data->REG_ALARM = NCT6791_REG_ALARM;
3664 data->REG_BEEP = NCT6776_REG_BEEP;
3665
3666 reg_temp = NCT6779_REG_TEMP;
3667 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3668 reg_temp_over = NCT6779_REG_TEMP_OVER;
3669 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3670 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3671 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3672 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3673
3674 break;
3559 default: 3675 default:
3560 return -ENODEV; 3676 return -ENODEV;
3561 } 3677 }
@@ -3702,6 +3818,7 @@ static int nct6775_probe(struct platform_device *pdev)
3702 break; 3818 break;
3703 case nct6106: 3819 case nct6106:
3704 case nct6779: 3820 case nct6779:
3821 case nct6791:
3705 break; 3822 break;
3706 } 3823 }
3707 3824
@@ -3732,6 +3849,9 @@ static int nct6775_probe(struct platform_device *pdev)
3732 case nct6779: 3849 case nct6779:
3733 tmp |= 0x3e; 3850 tmp |= 0x3e;
3734 break; 3851 break;
3852 case nct6791:
3853 tmp |= 0x7e;
3854 break;
3735 } 3855 }
3736 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE, 3856 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3737 tmp); 3857 tmp);
@@ -3900,6 +4020,7 @@ static const char * const nct6775_sio_names[] __initconst = {
3900 "NCT6775F", 4020 "NCT6775F",
3901 "NCT6776D/F", 4021 "NCT6776D/F",
3902 "NCT6779D", 4022 "NCT6779D",
4023 "NCT6791D",
3903}; 4024};
3904 4025
3905/* nct6775_find() looks for a '627 in the Super-I/O config space */ 4026/* nct6775_find() looks for a '627 in the Super-I/O config space */
@@ -3931,6 +4052,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
3931 case SIO_NCT6779_ID: 4052 case SIO_NCT6779_ID:
3932 sio_data->kind = nct6779; 4053 sio_data->kind = nct6779;
3933 break; 4054 break;
4055 case SIO_NCT6791_ID:
4056 sio_data->kind = nct6791;
4057 break;
3934 default: 4058 default:
3935 if (val != 0xffff) 4059 if (val != 0xffff)
3936 pr_debug("unsupported chip ID: 0x%04x\n", val); 4060 pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -3955,6 +4079,15 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
3955 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n"); 4079 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
3956 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); 4080 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
3957 } 4081 }
4082 if (sio_data->kind == nct6791) {
4083 val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
4084 if (val & 0x10) {
4085 pr_info("Enabling hardware monitor logical device mappings.\n");
4086 superio_outb(sioaddr,
4087 NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
4088 val & ~0x10);
4089 }
4090 }
3958 4091
3959 superio_exit(sioaddr); 4092 superio_exit(sioaddr);
3960 pr_info("Found %s or compatible chip at %#x:%#x\n", 4093 pr_info("Found %s or compatible chip at %#x:%#x\n",