hwmon: (lm75) Prepare to support per-chip resolution and sample time
authorJean Delvare <khali@linux-fr.org>
Sat, 4 May 2013 12:49:36 +0000 (14:49 +0200)
committerJean Delvare <khali@endymion.delvare>
Sat, 4 May 2013 12:49:36 +0000 (14:49 +0200)
Prepare the lm75 driver to support per-chip resolution and sample
time. For now we only make the code generic enough to support it, but
we still use the same, unchanged resolution (9-bit) and sample time
(1.5 s) for all chips.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/lm75.c

index 4670fbef6a9c84d9b1ee3fa34dcbc11e2bbe4da5..559e675db3c879e9b9b018fb3366bc369bbcaefc 100644 (file)
@@ -71,9 +71,12 @@ struct lm75_data {
        struct device           *hwmon_dev;
        struct mutex            update_lock;
        u8                      orig_conf;
+       u8                      resolution;     /* In bits, between 9 and 12 */
+       u8                      resolution_limits;
        char                    valid;          /* !=0 if registers are valid */
        unsigned long           last_updated;   /* In jiffies */
-       u16                     temp[3];        /* Register values,
+       unsigned long           sample_time;    /* In jiffies */
+       s16                     temp[3];        /* Register values,
                                                   0 = input
                                                   1 = max
                                                   2 = hyst */
@@ -93,12 +96,15 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct lm75_data *data = lm75_update_device(dev);
+       long temp;
 
        if (IS_ERR(data))
                return PTR_ERR(data);
 
-       return sprintf(buf, "%d\n",
-                      LM75_TEMP_FROM_REG(data->temp[attr->index]));
+       temp = ((data->temp[attr->index] >> (16 - data->resolution)) * 1000)
+              >> (data->resolution - 8);
+
+       return sprintf(buf, "%ld\n", temp);
 }
 
 static ssize_t set_temp(struct device *dev, struct device_attribute *da,
@@ -110,13 +116,25 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
        int nr = attr->index;
        long temp;
        int error;
+       u8 resolution;
 
        error = kstrtol(buf, 10, &temp);
        if (error)
                return error;
 
+       /*
+        * Resolution of limit registers is assumed to be the same as the
+        * temperature input register resolution unless given explicitly.
+        */
+       if (attr->index && data->resolution_limits)
+               resolution = data->resolution_limits;
+       else
+               resolution = data->resolution;
+
        mutex_lock(&data->update_lock);
-       data->temp[nr] = LM75_TEMP_TO_REG(temp);
+       temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
+       data->temp[nr] = DIV_ROUND_CLOSEST(temp  << (resolution - 8),
+                                          1000) << (16 - resolution);
        lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]);
        mutex_unlock(&data->update_lock);
        return count;
@@ -190,6 +208,9 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                break;
        }
 
+       data->resolution = 9;
+       data->sample_time = HZ + HZ / 2;
+
        /* configure as specified */
        status = lm75_read_value(client, LM75_REG_CONF);
        if (status < 0) {
@@ -427,7 +448,7 @@ static struct lm75_data *lm75_update_device(struct device *dev)
 
        mutex_lock(&data->update_lock);
 
-       if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+       if (time_after(jiffies, data->last_updated + data->sample_time)
            || !data->valid) {
                int i;
                dev_dbg(&client->dev, "Starting lm75 update\n");