summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2011-06-30 02:09:37 -0700
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-07-10 08:54:15 -0700
commit0c2a40e2fe4f4af0410f57e84b95b817ec15aa70 (patch)
treeca3d7268acc38bf2549dc53be8c96df98560cfd4
parent27739e694a3c34b5e371575d74e500d60111c689 (diff)
downloadlinux-0c2a40e2fe4f4af0410f57e84b95b817ec15aa70.tar.bz2
hwmon: (lm95241) Fix negative temperature results
Negative temperatures were returned in degrees C instead of milli-Degrees C. Also, negative temperatures were reported for remote temperature sensors even if the chip was configured for positive-only results. Fix by detecting temperature modes, and by treating negative temperatures similar to positive temperatures, with appropriate sign extension. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Acked-by: Jean Delvare <khali@linux-fr.org> Cc: stable@kernel.org # 2.6.30+
-rw-r--r--drivers/hwmon/lm95241.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
index 01c638e31e07..d3b464b74ced 100644
--- a/drivers/hwmon/lm95241.c
+++ b/drivers/hwmon/lm95241.c
@@ -98,11 +98,16 @@ struct lm95241_data {
};
/* Conversions */
-static int TempFromReg(u8 val_h, u8 val_l)
+static int temp_from_reg_signed(u8 val_h, u8 val_l)
{
- if (val_h & 0x80)
- return val_h - 0x100;
- return val_h * 1000 + val_l * 1000 / 256;
+ s16 val_hl = (val_h << 8) | val_l;
+ return val_hl * 1000 / 256;
+}
+
+static int temp_from_reg_unsigned(u8 val_h, u8 val_l)
+{
+ u16 val_hl = (val_h << 8) | val_l;
+ return val_hl * 1000 / 256;
}
static struct lm95241_data *lm95241_update_device(struct device *dev)
@@ -135,10 +140,13 @@ static ssize_t show_input(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct lm95241_data *data = lm95241_update_device(dev);
+ int index = to_sensor_dev_attr(attr)->index;
return snprintf(buf, PAGE_SIZE - 1, "%d\n",
- TempFromReg(data->temp[to_sensor_dev_attr(attr)->index],
- data->temp[to_sensor_dev_attr(attr)->index + 1]));
+ index == 0 || (data->config & (1 << (index / 2))) ?
+ temp_from_reg_signed(data->temp[index], data->temp[index + 1]) :
+ temp_from_reg_unsigned(data->temp[index],
+ data->temp[index + 1]));
}
static ssize_t show_type(struct device *dev, struct device_attribute *attr,