diff options
author | David Bartley <andareed@gmail.com> | 2013-06-25 01:28:28 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-08-12 01:10:39 -0400 |
commit | 578ab5f0e4b13a6f63e9ee108a44d7a20f6ccfce (patch) | |
tree | ab7969d3a63070897fedef32935cc95990193b01 /drivers/hwmon | |
parent | 30846993047b6611dece427a05b0135d97063153 (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.c | 281 |
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 | ||
63 | enum kinds { nct6106, nct6775, nct6776, nct6779 }; | 64 | enum 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] */ |
66 | static const char * const nct6775_device_names[] = { | 67 | static 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 | ||
73 | static unsigned short force_id; | 75 | static 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 | ||
102 | enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; | 105 | enum 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 | ||
242 | static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 }; | 247 | static const u16 NCT6775_REG_TARGET[] = { |
243 | static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 }; | 248 | 0x101, 0x201, 0x301, 0x801, 0x901, 0xa01 }; |
249 | static const u16 NCT6775_REG_FAN_MODE[] = { | ||
250 | 0x102, 0x202, 0x302, 0x802, 0x902, 0xa02 }; | ||
244 | static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = { | 251 | static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = { |
245 | 0x103, 0x203, 0x303, 0x803, 0x903 }; | 252 | 0x103, 0x203, 0x303, 0x803, 0x903, 0xa03 }; |
246 | static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = { | 253 | static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = { |
247 | 0x104, 0x204, 0x304, 0x804, 0x904 }; | 254 | 0x104, 0x204, 0x304, 0x804, 0x904, 0xa04 }; |
248 | static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { | 255 | static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { |
249 | 0x105, 0x205, 0x305, 0x805, 0x905 }; | 256 | 0x105, 0x205, 0x305, 0x805, 0x905, 0xa05 }; |
250 | static const u16 NCT6775_REG_FAN_START_OUTPUT[] | 257 | static const u16 NCT6775_REG_FAN_START_OUTPUT[] = { |
251 | = { 0x106, 0x206, 0x306, 0x806, 0x906 }; | 258 | 0x106, 0x206, 0x306, 0x806, 0x906, 0xa06 }; |
252 | static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a }; | 259 | static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a }; |
253 | static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b }; | 260 | static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b }; |
254 | 261 | ||
255 | static const u16 NCT6775_REG_FAN_STOP_TIME[] = { | 262 | static const u16 NCT6775_REG_FAN_STOP_TIME[] = { |
256 | 0x107, 0x207, 0x307, 0x807, 0x907 }; | 263 | 0x107, 0x207, 0x307, 0x807, 0x907, 0xa07 }; |
257 | static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 }; | 264 | static const u16 NCT6775_REG_PWM[] = { |
258 | static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 }; | 265 | 0x109, 0x209, 0x309, 0x809, 0x909, 0xa09 }; |
266 | static const u16 NCT6775_REG_PWM_READ[] = { | ||
267 | 0x01, 0x03, 0x11, 0x13, 0x15, 0xa09 }; | ||
259 | 268 | ||
260 | static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; | 269 | static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; |
261 | static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; | 270 | static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d }; |
262 | static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; | 271 | static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 }; |
263 | static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0 }; | 272 | static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 }; |
264 | 273 | ||
265 | static const u16 NCT6775_REG_TEMP[] = { | 274 | static 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 | ||
278 | static const u16 NCT6775_REG_TEMP_SEL[] = { | 287 | static const u16 NCT6775_REG_TEMP_SEL[] = { |
279 | 0x100, 0x200, 0x300, 0x800, 0x900 }; | 288 | 0x100, 0x200, 0x300, 0x800, 0x900, 0xa00 }; |
280 | 289 | ||
281 | static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = { | 290 | static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = { |
282 | 0x139, 0x239, 0x339, 0x839, 0x939 }; | 291 | 0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 }; |
283 | static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = { | 292 | static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = { |
284 | 0x13a, 0x23a, 0x33a, 0x83a, 0x93a }; | 293 | 0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a }; |
285 | static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = { | 294 | static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = { |
286 | 0x13b, 0x23b, 0x33b, 0x83b, 0x93b }; | 295 | 0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b }; |
287 | static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = { | 296 | static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = { |
288 | 0x13c, 0x23c, 0x33c, 0x83c, 0x93c }; | 297 | 0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c }; |
289 | static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = { | 298 | static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = { |
290 | 0x13d, 0x23d, 0x33d, 0x83d, 0x93d }; | 299 | 0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d }; |
291 | 300 | ||
292 | static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; | 301 | static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; |
293 | 302 | ||
294 | static const u16 NCT6775_REG_AUTO_TEMP[] = { | 303 | static const u16 NCT6775_REG_AUTO_TEMP[] = { |
295 | 0x121, 0x221, 0x321, 0x821, 0x921 }; | 304 | 0x121, 0x221, 0x321, 0x821, 0x921, 0xa21 }; |
296 | static const u16 NCT6775_REG_AUTO_PWM[] = { | 305 | static 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[] = { | |||
302 | static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 }; | 311 | static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 }; |
303 | 312 | ||
304 | static const u16 NCT6775_REG_CRITICAL_TEMP[] = { | 313 | static const u16 NCT6775_REG_CRITICAL_TEMP[] = { |
305 | 0x135, 0x235, 0x335, 0x835, 0x935 }; | 314 | 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35 }; |
306 | static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = { | 315 | static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = { |
307 | 0x138, 0x238, 0x338, 0x838, 0x938 }; | 316 | 0x138, 0x238, 0x338, 0x838, 0x938, 0xa38 }; |
308 | 317 | ||
309 | static const char *const nct6775_temp_label[] = { | 318 | static 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 | ||
362 | static const u16 NCT6776_REG_TOLERANCE_H[] = { | 371 | static const u16 NCT6776_REG_TOLERANCE_H[] = { |
363 | 0x10c, 0x20c, 0x30c, 0x80c, 0x90c }; | 372 | 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c }; |
364 | 373 | ||
365 | static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 }; | 374 | static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 }; |
366 | static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 }; | 375 | static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 }; |
367 | 376 | ||
368 | static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; | 377 | static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 }; |
369 | static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; | 378 | static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 }; |
370 | 379 | ||
371 | static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = { | 380 | static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = { |
372 | 0x13e, 0x23e, 0x33e, 0x83e, 0x93e }; | 381 | 0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e }; |
373 | 382 | ||
374 | static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { | 383 | static 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 | ||
436 | static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 }; | 445 | static const u16 NCT6779_REG_FAN[] = { |
446 | 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba }; | ||
437 | static const u16 NCT6779_REG_FAN_PULSES[] = { | 447 | static const u16 NCT6779_REG_FAN_PULSES[] = { |
438 | 0x644, 0x645, 0x646, 0x647, 0x648 }; | 448 | 0x644, 0x645, 0x646, 0x647, 0x648, 0x649 }; |
439 | 449 | ||
440 | static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = { | 450 | static 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 |
443 | static const u16 NCT6779_REG_CRITICAL_PWM[] = { | 453 | static const u16 NCT6779_REG_CRITICAL_PWM[] = { |
444 | 0x137, 0x237, 0x337, 0x837, 0x937 }; | 454 | 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 }; |
445 | 455 | ||
446 | static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; | 456 | static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; |
447 | static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { | 457 | static 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] | |||
493 | static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1] | 503 | static 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 | |||
510 | static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = { | ||
511 | 0x459, 0x45A, 0x45B, 0x568, 0x45D }; | ||
512 | |||
513 | static 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 | ||
3217 | static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, | 3259 | static 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", |