]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/hwmon/adt7470.c
adt7470: fix pwm at a certain level during temperature sensor scan
[karo-tx-linux.git] / drivers / hwmon / adt7470.c
index 1311a595147e17a136fbe5dbe1b81ebaa635acfe..b7a442a80bded32d865c467b19fdd827e429fb3f 100644 (file)
@@ -74,6 +74,7 @@ I2C_CLIENT_INSMOD_1(adt7470);
 #define ADT7470_REG_PWM12_CFG                  0x68
 #define                ADT7470_PWM2_AUTO_MASK          0x40
 #define                ADT7470_PWM1_AUTO_MASK          0x80
+#define                ADT7470_PWM_AUTO_MASK           0xC0
 #define ADT7470_REG_PWM34_CFG                  0x69
 #define                ADT7470_PWM3_AUTO_MASK          0x40
 #define                ADT7470_PWM4_AUTO_MASK          0x80
@@ -137,8 +138,6 @@ I2C_CLIENT_INSMOD_1(adt7470);
 #define FAN_PERIOD_INVALID     65535
 #define FAN_DATA_VALID(x)      ((x) && (x) != FAN_PERIOD_INVALID)
 
-#define ROUND_DIV(x, divisor)  (((x) + ((divisor) / 2)) / (divisor))
-
 struct adt7470_data {
        struct device           *hwmon_dev;
        struct attribute_group  attrs;
@@ -225,7 +224,7 @@ static struct adt7470_data *adt7470_update_device(struct device *dev)
        struct i2c_client *client = to_i2c_client(dev);
        struct adt7470_data *data = i2c_get_clientdata(client);
        unsigned long local_jiffies = jiffies;
-       u8 cfg;
+       u8 cfg, pwm[4], pwm_cfg[2];
        int i;
 
        mutex_lock(&data->lock);
@@ -234,6 +233,24 @@ static struct adt7470_data *adt7470_update_device(struct device *dev)
                && data->sensors_valid)
                goto no_sensor_update;
 
+       /* save pwm[1-4] config register */
+       pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0));
+       pwm_cfg[1] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(2));
+
+       /* set manual pwm to whatever it is set to now */
+       for (i = 0; i < ADT7470_FAN_COUNT; i++)
+               pwm[i] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM(i));
+
+       /* put pwm in manual mode */
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0),
+               pwm_cfg[0] & ~(ADT7470_PWM_AUTO_MASK));
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2),
+               pwm_cfg[1] & ~(ADT7470_PWM_AUTO_MASK));
+
+       /* write pwm control to whatever it was */
+       for (i = 0; i < ADT7470_FAN_COUNT; i++)
+               i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(i), pwm[i]);
+
        /* start reading temperature sensors */
        cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
        cfg |= 0x80;
@@ -251,6 +268,10 @@ static struct adt7470_data *adt7470_update_device(struct device *dev)
        cfg &= ~0x80;
        i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);
 
+       /* restore pwm[1-4] config registers */
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]);
+       i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
+
        for (i = 0; i < ADT7470_TEMP_COUNT; i++)
                data->temp[i] = i2c_smbus_read_byte_data(client,
                                                ADT7470_TEMP_REG(i));
@@ -360,7 +381,7 @@ static ssize_t set_temp_min(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -394,7 +415,7 @@ static ssize_t set_temp_max(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);
@@ -671,7 +692,7 @@ static ssize_t set_pwm_tmin(struct device *dev,
        if (strict_strtol(buf, 10, &temp))
                return -EINVAL;
 
-       temp = ROUND_DIV(temp, 1000);
+       temp = DIV_ROUND_CLOSEST(temp, 1000);
        temp = SENSORS_LIMIT(temp, 0, 255);
 
        mutex_lock(&data->lock);