]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
hwmon: (w83627ehf) Add support for temperature offset registers
authorGuenter Roeck <guenter.roeck@ericsson.com>
Wed, 8 Feb 2012 17:29:11 +0000 (09:29 -0800)
committerGuenter Roeck <guenter.roeck@ericsson.com>
Mon, 19 Mar 2012 01:27:54 +0000 (18:27 -0700)
Add support for temperature offset registers for CPUTIN, SYSTIN,
and AUXTIN temperatures.

Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Acked-by: Jean Delvare <khali@linux-fr.org>
drivers/hwmon/w83627ehf.c

index ec595c606ed4608b5c6a604e867eeb05adcfe5f6..a25350cf9554d35cdfaa6131a0c0b2b02b3c9c44 100644 (file)
@@ -240,6 +240,8 @@ static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
 static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[]
                                                = { 0x68, 0x6a, 0x6c };
 
+static const u16 W83627EHF_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
+
 static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301 };
 static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302 };
 static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 0x105, 0x205, 0x305 };
@@ -465,6 +467,7 @@ struct w83627ehf_data {
        u8 has_fan_min;         /* some fans don't have min register */
        bool has_fan_div;
        u8 temp_type[3];
+       s8 temp_offset[3];
        s16 temp[9];
        s16 temp_max[9];
        s16 temp_max_hyst[9];
@@ -496,6 +499,7 @@ struct w83627ehf_data {
        u8 vrm;
 
        u16 have_temp;
+       u16 have_temp_offset;
        u8 in6_skip:1;
        u8 temp3_val_only:1;
 };
@@ -893,6 +897,10 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
                                data->temp_max_hyst[i]
                                  = w83627ehf_read_temp(data,
                                                data->reg_temp_hyst[i]);
+                       if (data->have_temp_offset & (1 << i))
+                               data->temp_offset[i]
+                                 = w83627ehf_read_value(data,
+                                               W83627EHF_REG_TEMP_OFFSET[i]);
                }
 
                data->alarms = w83627ehf_read_value(data,
@@ -1225,6 +1233,39 @@ store_##reg(struct device *dev, struct device_attribute *attr, \
 store_temp_reg(reg_temp_over, temp_max);
 store_temp_reg(reg_temp_hyst, temp_max_hyst);
 
+static ssize_t
+show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct w83627ehf_data *data = w83627ehf_update_device(dev);
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+
+       return sprintf(buf, "%d\n",
+                      data->temp_offset[sensor_attr->index] * 1000);
+}
+
+static ssize_t
+store_temp_offset(struct device *dev, struct device_attribute *attr,
+                 const char *buf, size_t count)
+{
+       struct w83627ehf_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       long val;
+       int err;
+
+       err = kstrtol(buf, 10, &val);
+       if (err < 0)
+               return err;
+
+       val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+
+       mutex_lock(&data->update_lock);
+       data->temp_offset[nr] = val;
+       w83627ehf_write_value(data, W83627EHF_REG_TEMP_OFFSET[nr], val);
+       mutex_unlock(&data->update_lock);
+       return count;
+}
+
 static ssize_t
 show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -1312,6 +1353,15 @@ static struct sensor_device_attribute sda_temp_type[] = {
        SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
 };
 
+static struct sensor_device_attribute sda_temp_offset[] = {
+       SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+                   store_temp_offset, 0),
+       SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+                   store_temp_offset, 1),
+       SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+                   store_temp_offset, 2),
+};
+
 #define show_pwm_reg(reg) \
 static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
                          char *buf) \
@@ -1804,6 +1854,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
                        continue;
                device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
                device_remove_file(dev, &sda_temp_type[i].dev_attr);
+               device_remove_file(dev, &sda_temp_offset[i].dev_attr);
        }
 
        device_remove_file(dev, &sda_caseopen[0].dev_attr);
@@ -2126,6 +2177,11 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                } else {
                        data->temp_label = nct6775_temp_label;
                }
+               data->have_temp_offset = data->have_temp & 0x07;
+               for (i = 0; i < 3; i++) {
+                       if (data->temp_src[i] > 3)
+                               data->have_temp_offset &= ~(1 << i);
+               }
        } else if (sio_data->kind == w83667hg_b) {
                u8 reg;
 
@@ -2168,6 +2224,11 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                        data->in6_skip = 1;
 
                data->temp_label = w83667hg_b_temp_label;
+               data->have_temp_offset = data->have_temp & 0x07;
+               for (i = 0; i < 3; i++) {
+                       if (data->temp_src[i] > 2)
+                               data->have_temp_offset &= ~(1 << i);
+               }
        } else if (sio_data->kind == w83627uhg) {
                u8 reg;
 
@@ -2204,6 +2265,11 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                data->in6_skip = 1;                     /* No VIN3 */
 
                data->temp_label = w83667hg_b_temp_label;
+               data->have_temp_offset = data->have_temp & 0x03;
+               for (i = 0; i < 3; i++) {
+                       if (data->temp_src[i] > 1)
+                               data->have_temp_offset &= ~(1 << i);
+               }
        } else {
                w83627ehf_set_temp_reg_ehf(data, 3);
 
@@ -2223,6 +2289,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                        else
                                data->in6_skip = 1;
                }
+               data->have_temp_offset = data->have_temp & 0x07;
        }
 
        if (sio_data->kind == nct6775) {
@@ -2488,6 +2555,12 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
                        || (err = device_create_file(dev,
                                &sda_temp_type[i].dev_attr)))
                        goto exit_remove;
+               if (data->have_temp_offset & (1 << i)) {
+                       err = device_create_file(dev,
+                                                &sda_temp_offset[i].dev_attr);
+                       if (err)
+                               goto exit_remove;
+               }
        }
 
        err = device_create_file(dev, &sda_caseopen[0].dev_attr);