hwmon: (f75375s) Properly map the F75387 automatic modes to pwm_enable
[firefly-linux-kernel-4.4.55.git] / drivers / hwmon / f75375s.c
index eb648d9c91d6890f5335dc3ffc31e548beaf2955..9ab034a1b4c1ff059cdd5388760751d76261bd03 100644 (file)
@@ -264,6 +264,21 @@ static inline u16 rpm_to_reg(int rpm)
        return 1500000 / rpm;
 }
 
+static bool duty_mode_enabled(u8 pwm_enable)
+{
+       switch (pwm_enable) {
+       case 0: /* Manual, duty mode (full speed) */
+       case 1: /* Manual, duty mode */
+       case 4: /* Auto, duty mode */
+               return true;
+       case 2: /* Auto, speed mode */
+       case 3: /* Manual, speed mode */
+               return false;
+       default:
+               BUG();
+       }
+}
+
 static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
@@ -337,11 +352,15 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
        struct f75375_data *data = i2c_get_clientdata(client);
        u8 fanmode;
 
-       if (val < 0 || val > 3)
+       if (val < 0 || val > 4)
                return -EINVAL;
 
        fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
        if (data->kind == f75387) {
+               /* For now, deny dangerous toggling of duty mode */
+               if (duty_mode_enabled(data->pwm_enable[nr]) !=
+                               duty_mode_enabled(val))
+                       return -EOPNOTSUPP;
                /* clear each fanX_mode bit before setting them properly */
                fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr));
                fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr));
@@ -355,12 +374,14 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
                        fanmode  |= (1 << F75387_FAN_MANU_MODE(nr));
                        fanmode  |= (1 << F75387_FAN_DUTY_MODE(nr));
                        break;
-               case 2: /* AUTOMATIC*/
-                       fanmode  |=  (1 << F75387_FAN_DUTY_MODE(nr));
+               case 2: /* Automatic, speed mode */
                        break;
                case 3: /* fan speed */
                        fanmode |= (1 << F75387_FAN_MANU_MODE(nr));
                        break;
+               case 4: /* Automatic, pwm */
+                       fanmode |= (1 << F75387_FAN_DUTY_MODE(nr));
+                       break;
                }
        } else {
                /* clear each fanX_mode bit before setting them properly */
@@ -378,6 +399,8 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
                        break;
                case 3: /* fan speed */
                        break;
+               case 4: /* Automatic pwm */
+                       return -EINVAL;
                }
        }
 
@@ -735,14 +758,17 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
 
                                manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1);
                                duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1);
-                               if (manu && duty)
-                                       /* speed */
+                               if (!manu && duty)
+                                       /* auto, pwm */
+                                       data->pwm_enable[nr] = 4;
+                               else if (manu && !duty)
+                                       /* manual, speed */
                                        data->pwm_enable[nr] = 3;
-                               else if (!manu && duty)
-                                       /* automatic */
+                               else if (!manu && !duty)
+                                       /* automatic, speed */
                                        data->pwm_enable[nr] = 2;
                                else
-                                       /* manual */
+                                       /* manual, pwm */
                                        data->pwm_enable[nr] = 1;
                        } else {
                                if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr))))