aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-11-13 15:46:20 -0500
committerGuenter Roeck <linux@roeck-us.net>2013-11-18 17:08:05 -0500
commitd1a284b7ed8124599e3b747fb2b86311761fb609 (patch)
treeddfeb2aa9433881516d15442d9843404ebee5717
parentc98d6c65e6e6bd24a12174fff6ca4990d346de5d (diff)
hwmon: (nct6775) Monitor additional temperature registers
The number of SMIOVT registers on NCT6779 and NCT6791 is limited to 2. As result, the driver may not report some of the temperatures used for fan control. This can result in some of the pwmX_temp_sel or pwm2_weight_temp_sel attributes to wrongly return 0. Fortunately, the chip has registers to monitor those temperatures. Add them to the list of temperatures to report. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/nct6775.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index d17325db0ea3..3f4ef21010d5 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -274,6 +274,8 @@ static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0, 0 };
274static const u16 NCT6775_REG_TEMP[] = { 274static const u16 NCT6775_REG_TEMP[] = {
275 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d }; 275 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
276 276
277static const u16 NCT6775_REG_TEMP_MON[] = { 0x73, 0x75, 0x77 };
278
277static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = { 279static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
278 0, 0x152, 0x252, 0x628, 0x629, 0x62A }; 280 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
279static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = { 281static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
@@ -454,6 +456,7 @@ static const u16 NCT6779_REG_CRITICAL_PWM[] = {
454 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 }; 456 0x137, 0x237, 0x337, 0x837, 0x937, 0xa37 };
455 457
456static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 }; 458static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
459static const u16 NCT6779_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
457static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = { 460static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
458 0x18, 0x152 }; 461 0x18, 0x152 };
459static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = { 462static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
@@ -534,6 +537,7 @@ static const u16 NCT6106_REG_IN[] = {
534 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 }; 537 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
535 538
536static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 }; 539static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
540static const u16 NCT6106_REG_TEMP_MON[] = { 0x18, 0x19, 0x1a };
537static const u16 NCT6106_REG_TEMP_HYST[] = { 541static const u16 NCT6106_REG_TEMP_HYST[] = {
538 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 }; 542 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
539static const u16 NCT6106_REG_TEMP_OVER[] = { 543static const u16 NCT6106_REG_TEMP_OVER[] = {
@@ -3253,9 +3257,9 @@ static int nct6775_probe(struct platform_device *pdev)
3253 int i, s, err = 0; 3257 int i, s, err = 0;
3254 int src, mask, available; 3258 int src, mask, available;
3255 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config; 3259 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3256 const u16 *reg_temp_alternate, *reg_temp_crit; 3260 const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit;
3257 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL; 3261 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
3258 int num_reg_temp; 3262 int num_reg_temp, num_reg_temp_mon;
3259 u8 cr2a; 3263 u8 cr2a;
3260 struct attribute_group *group; 3264 struct attribute_group *group;
3261 struct device *hwmon_dev; 3265 struct device *hwmon_dev;
@@ -3338,7 +3342,9 @@ static int nct6775_probe(struct platform_device *pdev)
3338 data->BEEP_BITS = NCT6106_BEEP_BITS; 3342 data->BEEP_BITS = NCT6106_BEEP_BITS;
3339 3343
3340 reg_temp = NCT6106_REG_TEMP; 3344 reg_temp = NCT6106_REG_TEMP;
3345 reg_temp_mon = NCT6106_REG_TEMP_MON;
3341 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP); 3346 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3347 num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
3342 reg_temp_over = NCT6106_REG_TEMP_OVER; 3348 reg_temp_over = NCT6106_REG_TEMP_OVER;
3343 reg_temp_hyst = NCT6106_REG_TEMP_HYST; 3349 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3344 reg_temp_config = NCT6106_REG_TEMP_CONFIG; 3350 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
@@ -3410,7 +3416,9 @@ static int nct6775_probe(struct platform_device *pdev)
3410 data->REG_BEEP = NCT6775_REG_BEEP; 3416 data->REG_BEEP = NCT6775_REG_BEEP;
3411 3417
3412 reg_temp = NCT6775_REG_TEMP; 3418 reg_temp = NCT6775_REG_TEMP;
3419 reg_temp_mon = NCT6775_REG_TEMP_MON;
3413 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP); 3420 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3421 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
3414 reg_temp_over = NCT6775_REG_TEMP_OVER; 3422 reg_temp_over = NCT6775_REG_TEMP_OVER;
3415 reg_temp_hyst = NCT6775_REG_TEMP_HYST; 3423 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3416 reg_temp_config = NCT6775_REG_TEMP_CONFIG; 3424 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
@@ -3480,7 +3488,9 @@ static int nct6775_probe(struct platform_device *pdev)
3480 data->REG_BEEP = NCT6776_REG_BEEP; 3488 data->REG_BEEP = NCT6776_REG_BEEP;
3481 3489
3482 reg_temp = NCT6775_REG_TEMP; 3490 reg_temp = NCT6775_REG_TEMP;
3491 reg_temp_mon = NCT6775_REG_TEMP_MON;
3483 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP); 3492 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3493 num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
3484 reg_temp_over = NCT6775_REG_TEMP_OVER; 3494 reg_temp_over = NCT6775_REG_TEMP_OVER;
3485 reg_temp_hyst = NCT6775_REG_TEMP_HYST; 3495 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3486 reg_temp_config = NCT6776_REG_TEMP_CONFIG; 3496 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
@@ -3554,7 +3564,9 @@ static int nct6775_probe(struct platform_device *pdev)
3554 data->REG_BEEP = NCT6776_REG_BEEP; 3564 data->REG_BEEP = NCT6776_REG_BEEP;
3555 3565
3556 reg_temp = NCT6779_REG_TEMP; 3566 reg_temp = NCT6779_REG_TEMP;
3567 reg_temp_mon = NCT6779_REG_TEMP_MON;
3557 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP); 3568 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3569 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
3558 reg_temp_over = NCT6779_REG_TEMP_OVER; 3570 reg_temp_over = NCT6779_REG_TEMP_OVER;
3559 reg_temp_hyst = NCT6779_REG_TEMP_HYST; 3571 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3560 reg_temp_config = NCT6779_REG_TEMP_CONFIG; 3572 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
@@ -3628,7 +3640,9 @@ static int nct6775_probe(struct platform_device *pdev)
3628 data->REG_BEEP = NCT6776_REG_BEEP; 3640 data->REG_BEEP = NCT6776_REG_BEEP;
3629 3641
3630 reg_temp = NCT6779_REG_TEMP; 3642 reg_temp = NCT6779_REG_TEMP;
3643 reg_temp_mon = NCT6779_REG_TEMP_MON;
3631 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP); 3644 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3645 num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
3632 reg_temp_over = NCT6779_REG_TEMP_OVER; 3646 reg_temp_over = NCT6779_REG_TEMP_OVER;
3633 reg_temp_hyst = NCT6779_REG_TEMP_HYST; 3647 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3634 reg_temp_config = NCT6779_REG_TEMP_CONFIG; 3648 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
@@ -3729,6 +3743,50 @@ static int nct6775_probe(struct platform_device *pdev)
3729 s++; 3743 s++;
3730 } 3744 }
3731 3745
3746 /*
3747 * Repeat with temperatures used for fan control.
3748 * This set of registers does not support limits.
3749 */
3750 for (i = 0; i < num_reg_temp_mon; i++) {
3751 if (reg_temp_mon[i] == 0)
3752 continue;
3753
3754 src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f;
3755 if (!src || (mask & (1 << src)))
3756 continue;
3757
3758 if (src >= data->temp_label_num ||
3759 !strlen(data->temp_label[src])) {
3760 dev_info(dev,
3761 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3762 src, i, data->REG_TEMP_SEL[i],
3763 reg_temp_mon[i]);
3764 continue;
3765 }
3766
3767 mask |= 1 << src;
3768
3769 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3770 if (src <= data->temp_fixed_num) {
3771 if (data->have_temp & (1 << (src - 1)))
3772 continue;
3773 data->have_temp |= 1 << (src - 1);
3774 data->have_temp_fixed |= 1 << (src - 1);
3775 data->reg_temp[0][src - 1] = reg_temp_mon[i];
3776 data->temp_src[src - 1] = src;
3777 continue;
3778 }
3779
3780 if (s >= NUM_TEMP)
3781 continue;
3782
3783 /* Use dynamic index for other sources */
3784 data->have_temp |= 1 << s;
3785 data->reg_temp[0][s] = reg_temp_mon[i];
3786 data->temp_src[s] = src;
3787 s++;
3788 }
3789
3732#ifdef USE_ALTERNATE 3790#ifdef USE_ALTERNATE
3733 /* 3791 /*
3734 * Go through the list of alternate temp registers and enable 3792 * Go through the list of alternate temp registers and enable