]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
hwmon: (it87) Introduce support for tempX_offset sysfs attribute
authorGuenter Roeck <linux@roeck-us.net>
Tue, 13 Nov 2012 23:31:29 +0000 (10:31 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Tue, 13 Nov 2012 23:31:29 +0000 (10:31 +1100)
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Documentation/hwmon/it87
drivers/hwmon/it87.c

index 87850d86c55995fe895524cf9550c38f8fd90bb0..e1f38287fbb30ccfb45cddc6169debcaa73f4581 100644 (file)
@@ -209,3 +209,12 @@ doesn't use CPU cycles.
 Trip points must be set properly before switching to automatic fan speed
 control mode. The driver will perform basic integrity checks before
 actually switching to automatic control mode.
+
+
+Temperature offset attributes
+-----------------------------
+
+The driver supports temp[1-3]_offset sysfs attributes to adjust the reported
+temperature for thermal diodes or diode-connected thermal transistors.
+If a temperature sensor is configured for thermistors, the attribute values
+are ignored.
index b6d72534d4d653342f4f1e33db68be6f9e3d949d..7e4f4183285c0f073a6da0236f69df8e9b0cf865 100644 (file)
@@ -203,6 +203,8 @@ static const u8 IT87_REG_FAN[]              = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
 static const u8 IT87_REG_FAN_MIN[]     = { 0x10, 0x11, 0x12, 0x84, 0x86 };
 static const u8 IT87_REG_FANX[]                = { 0x18, 0x19, 0x1a, 0x81, 0x83 };
 static const u8 IT87_REG_FANX_MIN[]    = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
+static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 };
+
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
@@ -263,7 +265,7 @@ struct it87_data {
        u16 fan[5];             /* Register values, possibly combined */
        u16 fan_min[5];         /* Register values, possibly combined */
        u8 has_temp;            /* Bitfield, temp sensors enabled */
-       s8 temp[3][3];          /* [nr][0]=temp, [1]=min, [2]=max */
+       s8 temp[3][4];          /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
        u8 sensor;              /* Register value */
        u8 fan_div[3];          /* Register encoding, shifted right */
        u8 vid;                 /* Register encoding, combined */
@@ -312,6 +314,17 @@ static inline int has_newer_autopwm(const struct it87_data *data)
            || data->type == it8728;
 }
 
+static inline int has_temp_offset(const struct it87_data *data)
+{
+       return data->type == it8716
+           || data->type == it8718
+           || data->type == it8720
+           || data->type == it8721
+           || data->type == it8728
+           || data->type == it8782
+           || data->type == it8783;
+}
+
 static int adc_lsb(const struct it87_data *data, int nr)
 {
        int lsb = has_12mv_adc(data) ? 12 : 16;
@@ -546,16 +559,34 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
        int index = sattr->index;
        struct it87_data *data = dev_get_drvdata(dev);
        long val;
+       u8 reg, regval;
 
        if (kstrtol(buf, 10, &val) < 0)
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
+
+       switch (index) {
+       default:
+       case 1:
+               reg = IT87_REG_TEMP_LOW(nr);
+               break;
+       case 2:
+               reg = IT87_REG_TEMP_HIGH(nr);
+               break;
+       case 3:
+               regval = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+               if (!(regval & 0x80)) {
+                       regval |= 0x80;
+                       it87_write_value(data, IT87_REG_BEEP_ENABLE, regval);
+               }
+               data->valid = 0;
+               reg = IT87_REG_TEMP_OFFSET[nr];
+               break;
+       }
+
        data->temp[nr][index] = TEMP_TO_REG(val);
-       it87_write_value(data,
-                        index == 1 ? IT87_REG_TEMP_LOW(nr)
-                                   : IT87_REG_TEMP_HIGH(nr),
-                        data->temp[nr][index]);
+       it87_write_value(data, reg, data->temp[nr][index]);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -565,16 +596,22 @@ static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
                            0, 1);
 static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
                            0, 2);
+static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp,
+                           set_temp, 0, 3);
 static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
                            1, 1);
 static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
                            1, 2);
+static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp,
+                           set_temp, 1, 3);
 static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0);
 static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
                            2, 1);
 static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
                            2, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp,
+                           set_temp, 2, 3);
 
 static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
                              char *buf)
@@ -1429,6 +1466,12 @@ static const struct attribute_group it87_group_temp[3] = {
        { .attrs = it87_attributes_temp[2] },
 };
 
+static struct attribute *it87_attributes_temp_offset[] = {
+       &sensor_dev_attr_temp1_offset.dev_attr.attr,
+       &sensor_dev_attr_temp2_offset.dev_attr.attr,
+       &sensor_dev_attr_temp3_offset.dev_attr.attr,
+};
+
 static struct attribute *it87_attributes[] = {
        &dev_attr_alarms.attr,
        &sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
@@ -1899,6 +1942,9 @@ static void it87_remove_files(struct device *dev)
                if (!(data->has_temp & (1 << i)))
                        continue;
                sysfs_remove_group(&dev->kobj, &it87_group_temp[i]);
+               if (has_temp_offset(data))
+                       sysfs_remove_file(&dev->kobj,
+                                         it87_attributes_temp_offset[i]);
                if (sio_data->beep_pin)
                        sysfs_remove_file(&dev->kobj,
                                          it87_attributes_temp_beep[i]);
@@ -2026,6 +2072,12 @@ static int __devinit it87_probe(struct platform_device *pdev)
                err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]);
                if (err)
                        goto error;
+               if (has_temp_offset(data)) {
+                       err = sysfs_create_file(&dev->kobj,
+                                               it87_attributes_temp_offset[i]);
+                       if (err)
+                               goto error;
+               }
                if (sio_data->beep_pin) {
                        err = sysfs_create_file(&dev->kobj,
                                                it87_attributes_temp_beep[i]);
@@ -2383,6 +2435,10 @@ static struct it87_data *it87_update_device(struct device *dev)
                                it87_read_value(data, IT87_REG_TEMP_LOW(i));
                        data->temp[i][2] =
                                it87_read_value(data, IT87_REG_TEMP_HIGH(i));
+                       if (has_temp_offset(data))
+                               data->temp[i][3] =
+                                 it87_read_value(data,
+                                                 IT87_REG_TEMP_OFFSET[i]);
                }
 
                /* Newer chips don't have clock dividers */