aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/adm1021.c
diff options
context:
space:
mode:
authorMichael Abbott <michael@araneidae.co.uk>2009-09-21 20:04:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-22 10:17:49 -0400
commitf266889517252bc697e7103bcd6ed46bdf2c1579 (patch)
tree008a9f272f14e1f3b8e6009dc2509d274cf3155a /drivers/hwmon/adm1021.c
parentdc791f8aeeeea4314beede83d6ee74e6af5f627b (diff)
drivers/hwmon/adm1021.c: support high precision ADM1023 remote sensor
The ADM1023 temperature sensor supports higher resolution for its external sensor (sensitivity of 1/8 deg C). This patch makes this higher resolution available through the appropriate temperature sysfs nodes. Curiously, this functionality was available in the 2.4 kernel driver (but formatted in a less helpful manner). Cc: Jean Delvare <khali@linux-fr.org> Signed-off-by: Michael Abbott <michael.abbott@diamond.ac.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/hwmon/adm1021.c')
-rw-r--r--drivers/hwmon/adm1021.c47
1 files changed, 23 insertions, 24 deletions
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index b11e06f644b1..de84398775b6 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -85,14 +85,11 @@ struct adm1021_data {
85 char valid; /* !=0 if following fields are valid */ 85 char valid; /* !=0 if following fields are valid */
86 unsigned long last_updated; /* In jiffies */ 86 unsigned long last_updated; /* In jiffies */
87 87
88 s8 temp_max[2]; /* Register values */ 88 int temp_max[2]; /* Register values */
89 s8 temp_min[2]; 89 int temp_min[2];
90 s8 temp[2]; 90 int temp[2];
91 u8 alarms; 91 u8 alarms;
92 /* Special values for ADM1023 only */ 92 /* Special values for ADM1023 only */
93 u8 remote_temp_prec;
94 u8 remote_temp_os_prec;
95 u8 remote_temp_hyst_prec;
96 u8 remote_temp_offset; 93 u8 remote_temp_offset;
97 u8 remote_temp_offset_prec; 94 u8 remote_temp_offset_prec;
98}; 95};
@@ -141,7 +138,7 @@ static ssize_t show_temp(struct device *dev,
141 int index = to_sensor_dev_attr(devattr)->index; 138 int index = to_sensor_dev_attr(devattr)->index;
142 struct adm1021_data *data = adm1021_update_device(dev); 139 struct adm1021_data *data = adm1021_update_device(dev);
143 140
144 return sprintf(buf, "%d\n", 1000 * data->temp[index]); 141 return sprintf(buf, "%d\n", data->temp[index]);
145} 142}
146 143
147static ssize_t show_temp_max(struct device *dev, 144static ssize_t show_temp_max(struct device *dev,
@@ -150,7 +147,7 @@ static ssize_t show_temp_max(struct device *dev,
150 int index = to_sensor_dev_attr(devattr)->index; 147 int index = to_sensor_dev_attr(devattr)->index;
151 struct adm1021_data *data = adm1021_update_device(dev); 148 struct adm1021_data *data = adm1021_update_device(dev);
152 149
153 return sprintf(buf, "%d\n", 1000 * data->temp_max[index]); 150 return sprintf(buf, "%d\n", data->temp_max[index]);
154} 151}
155 152
156static ssize_t show_temp_min(struct device *dev, 153static ssize_t show_temp_min(struct device *dev,
@@ -159,7 +156,7 @@ static ssize_t show_temp_min(struct device *dev,
159 int index = to_sensor_dev_attr(devattr)->index; 156 int index = to_sensor_dev_attr(devattr)->index;
160 struct adm1021_data *data = adm1021_update_device(dev); 157 struct adm1021_data *data = adm1021_update_device(dev);
161 158
162 return sprintf(buf, "%d\n", 1000 * data->temp_min[index]); 159 return sprintf(buf, "%d\n", data->temp_min[index]);
163} 160}
164 161
165static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, 162static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
@@ -412,25 +409,27 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
412 dev_dbg(&client->dev, "Starting adm1021 update\n"); 409 dev_dbg(&client->dev, "Starting adm1021 update\n");
413 410
414 for (i = 0; i < 2; i++) { 411 for (i = 0; i < 2; i++) {
415 data->temp[i] = i2c_smbus_read_byte_data(client, 412 data->temp[i] = 1000 *
416 ADM1021_REG_TEMP(i)); 413 (s8) i2c_smbus_read_byte_data(
417 data->temp_max[i] = i2c_smbus_read_byte_data(client, 414 client, ADM1021_REG_TEMP(i));
418 ADM1021_REG_TOS_R(i)); 415 data->temp_max[i] = 1000 *
419 data->temp_min[i] = i2c_smbus_read_byte_data(client, 416 (s8) i2c_smbus_read_byte_data(
420 ADM1021_REG_THYST_R(i)); 417 client, ADM1021_REG_TOS_R(i));
418 data->temp_min[i] = 1000 *
419 (s8) i2c_smbus_read_byte_data(
420 client, ADM1021_REG_THYST_R(i));
421 } 421 }
422 data->alarms = i2c_smbus_read_byte_data(client, 422 data->alarms = i2c_smbus_read_byte_data(client,
423 ADM1021_REG_STATUS) & 0x7c; 423 ADM1021_REG_STATUS) & 0x7c;
424 if (data->type == adm1023) { 424 if (data->type == adm1023) {
425 data->remote_temp_prec = 425 /* The ADM1023 provides 3 extra bits of precision for
426 i2c_smbus_read_byte_data(client, 426 * the remote sensor in extra registers. */
427 ADM1023_REG_REM_TEMP_PREC); 427 data->temp[1] += 125 * (i2c_smbus_read_byte_data(
428 data->remote_temp_os_prec = 428 client, ADM1023_REG_REM_TEMP_PREC) >> 5);
429 i2c_smbus_read_byte_data(client, 429 data->temp_max[1] += 125 * (i2c_smbus_read_byte_data(
430 ADM1023_REG_REM_TOS_PREC); 430 client, ADM1023_REG_REM_TOS_PREC) >> 5);
431 data->remote_temp_hyst_prec = 431 data->temp_min[1] += 125 * (i2c_smbus_read_byte_data(
432 i2c_smbus_read_byte_data(client, 432 client, ADM1023_REG_REM_THYST_PREC) >> 5);
433 ADM1023_REG_REM_THYST_PREC);
434 data->remote_temp_offset = 433 data->remote_temp_offset =
435 i2c_smbus_read_byte_data(client, 434 i2c_smbus_read_byte_data(client,
436 ADM1023_REG_REM_OFFSET); 435 ADM1023_REG_REM_OFFSET);