hwmon: (it87) Introduce support for tempX_offset sysfs attribute

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
Guenter Roeck 2012-12-19 22:17:01 +01:00 committed by Jean Delvare
parent 2cece01ffd
commit 161d898ac9
2 changed files with 70 additions and 5 deletions

View 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.

View 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 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 */