Commit 161d898a authored by Guenter Roeck's avatar Guenter Roeck Committed by Jean Delvare

hwmon: (it87) Introduce support for tempX_offset sysfs attribute

Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 2cece01f
...@@ -209,3 +209,12 @@ doesn't use CPU cycles. ...@@ -209,3 +209,12 @@ doesn't use CPU cycles.
Trip points must be set properly before switching to automatic fan speed Trip points must be set properly before switching to automatic fan speed
control mode. The driver will perform basic integrity checks before control mode. The driver will perform basic integrity checks before
actually switching to automatic control mode. 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.
...@@ -203,6 +203,8 @@ static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 }; ...@@ -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_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 };
static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; 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_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_MAIN_CTRL 0x13
#define IT87_REG_FAN_CTL 0x14 #define IT87_REG_FAN_CTL 0x14
#define IT87_REG_PWM(nr) (0x15 + (nr)) #define IT87_REG_PWM(nr) (0x15 + (nr))
...@@ -263,7 +265,7 @@ struct it87_data { ...@@ -263,7 +265,7 @@ struct it87_data {
u16 fan[5]; /* Register values, possibly combined */ u16 fan[5]; /* Register values, possibly combined */
u16 fan_min[5]; /* Register values, possibly combined */ u16 fan_min[5]; /* Register values, possibly combined */
u8 has_temp; /* Bitfield, temp sensors enabled */ 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 sensor; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */ u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */ u8 vid; /* Register encoding, combined */
...@@ -312,6 +314,17 @@ static inline int has_newer_autopwm(const struct it87_data *data) ...@@ -312,6 +314,17 @@ static inline int has_newer_autopwm(const struct it87_data *data)
|| data->type == it8728; || 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) static int adc_lsb(const struct it87_data *data, int nr)
{ {
int lsb = has_12mv_adc(data) ? 12 : 16; int lsb = has_12mv_adc(data) ? 12 : 16;
...@@ -546,16 +559,34 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, ...@@ -546,16 +559,34 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
int index = sattr->index; int index = sattr->index;
struct it87_data *data = dev_get_drvdata(dev); struct it87_data *data = dev_get_drvdata(dev);
long val; long val;
u8 reg, regval;
if (kstrtol(buf, 10, &val) < 0) if (kstrtol(buf, 10, &val) < 0)
return -EINVAL; return -EINVAL;
mutex_lock(&data->update_lock); 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); data->temp[nr][index] = TEMP_TO_REG(val);
it87_write_value(data, it87_write_value(data, reg, data->temp[nr][index]);
index == 1 ? IT87_REG_TEMP_LOW(nr)
: IT87_REG_TEMP_HIGH(nr),
data->temp[nr][index]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -565,16 +596,22 @@ static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp, ...@@ -565,16 +596,22 @@ static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
0, 1); 0, 1);
static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
0, 2); 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_input, S_IRUGO, show_temp, NULL, 1, 0);
static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
1, 1); 1, 1);
static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
1, 2); 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_input, S_IRUGO, show_temp, NULL, 2, 0);
static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
2, 1); 2, 1);
static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
2, 2); 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, static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -1429,6 +1466,12 @@ static const struct attribute_group it87_group_temp[3] = { ...@@ -1429,6 +1466,12 @@ static const struct attribute_group it87_group_temp[3] = {
{ .attrs = it87_attributes_temp[2] }, { .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[] = { static struct attribute *it87_attributes[] = {
&dev_attr_alarms.attr, &dev_attr_alarms.attr,
&sensor_dev_attr_intrusion0_alarm.dev_attr.attr, &sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
...@@ -1899,6 +1942,9 @@ static void it87_remove_files(struct device *dev) ...@@ -1899,6 +1942,9 @@ static void it87_remove_files(struct device *dev)
if (!(data->has_temp & (1 << i))) if (!(data->has_temp & (1 << i)))
continue; continue;
sysfs_remove_group(&dev->kobj, &it87_group_temp[i]); 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) if (sio_data->beep_pin)
sysfs_remove_file(&dev->kobj, sysfs_remove_file(&dev->kobj,
it87_attributes_temp_beep[i]); it87_attributes_temp_beep[i]);
...@@ -2026,6 +2072,12 @@ static int it87_probe(struct platform_device *pdev) ...@@ -2026,6 +2072,12 @@ static int it87_probe(struct platform_device *pdev)
err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]); err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]);
if (err) if (err)
goto error; 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) { if (sio_data->beep_pin) {
err = sysfs_create_file(&dev->kobj, err = sysfs_create_file(&dev->kobj,
it87_attributes_temp_beep[i]); it87_attributes_temp_beep[i]);
...@@ -2383,6 +2435,10 @@ static struct it87_data *it87_update_device(struct device *dev) ...@@ -2383,6 +2435,10 @@ static struct it87_data *it87_update_device(struct device *dev)
it87_read_value(data, IT87_REG_TEMP_LOW(i)); it87_read_value(data, IT87_REG_TEMP_LOW(i));
data->temp[i][2] = data->temp[i][2] =
it87_read_value(data, IT87_REG_TEMP_HIGH(i)); 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 */ /* Newer chips don't have clock dividers */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment