OSDN Git Service

hwmon: (it87) Do not overwrite bit 2..6 of pwm control registers
authorGuenter Roeck <linux@roeck-us.net>
Wed, 8 Feb 2017 22:07:42 +0000 (14:07 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 12 Mar 2017 05:41:42 +0000 (06:41 +0100)
commit 4c7b8ca1ae5ed9e27014732c8a918ba11a86cf09 upstream.

In IT8620E, after setting pwm control to manual, it was observed that
pwm values for fan 4..6 have reversed results (writing 0 results in fans
running at full speed, writing 255 results in fans turned off).

With the new PWM control, pwm polarity for pwm control 4..6 is specified
in its pwm control registers. Those registers are overwritten when setting
the pwm mode or the temperature mapping. Do not touch bit 2..6 of pwm
control registers on register writes to fix the problem.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/hwmon/it87.c

index ad82cb2..991e0fc 100644 (file)
@@ -1300,25 +1300,35 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
                        it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
                                         data->fan_main_ctrl);
                } else {
+                       u8 ctrl;
+
                        /* No on/off mode, set maximum pwm value */
                        data->pwm_duty[nr] = pwm_to_reg(data, 0xff);
                        it87_write_value(data, IT87_REG_PWM_DUTY[nr],
                                         data->pwm_duty[nr]);
                        /* and set manual mode */
-                       data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
-                                            data->pwm_temp_map[nr] :
-                                            data->pwm_duty[nr];
-                       it87_write_value(data, IT87_REG_PWM[nr],
-                                        data->pwm_ctrl[nr]);
+                       if (has_newer_autopwm(data)) {
+                               ctrl = (data->pwm_ctrl[nr] & 0x7c) |
+                                       data->pwm_temp_map[nr];
+                       } else {
+                               ctrl = data->pwm_duty[nr];
+                       }
+                       data->pwm_ctrl[nr] = ctrl;
+                       it87_write_value(data, IT87_REG_PWM[nr], ctrl);
                }
        } else {
-               if (val == 1)                           /* Manual mode */
-                       data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
-                                            data->pwm_temp_map[nr] :
-                                            data->pwm_duty[nr];
-               else                                    /* Automatic mode */
-                       data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
-               it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]);
+               u8 ctrl;
+
+               if (has_newer_autopwm(data)) {
+                       ctrl = (data->pwm_ctrl[nr] & 0x7c) |
+                               data->pwm_temp_map[nr];
+                       if (val != 1)
+                               ctrl |= 0x80;
+               } else {
+                       ctrl = (val == 1 ? data->pwm_duty[nr] : 0x80);
+               }
+               data->pwm_ctrl[nr] = ctrl;
+               it87_write_value(data, IT87_REG_PWM[nr], ctrl);
 
                if (data->type != it8603 && nr < 3) {
                        /* set SmartGuardian mode */
@@ -1462,7 +1472,8 @@ static ssize_t set_pwm_temp_map(struct device *dev,
         * otherwise, just store it for later use.
         */
        if (data->pwm_ctrl[nr] & 0x80) {
-               data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
+               data->pwm_ctrl[nr] = (data->pwm_ctrl[nr] & 0xfc) |
+                                               data->pwm_temp_map[nr];
                it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]);
        }
        mutex_unlock(&data->update_lock);