From 9f6ad1ce6484a92ef864e00611a8ef3daf9c986d Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 7 Mar 2011 18:34:50 -0800 Subject: hwmon: (pmbus) Fix LINEAR16 data format LINEAR16 data format is unsigned, not signed. Impact is that affected attributes report negative values in the upper half of the supported value range. Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus_core.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c index 92540c9cd34..6474512f49b 100644 --- a/drivers/hwmon/pmbus_core.c +++ b/drivers/hwmon/pmbus_core.c @@ -359,20 +359,21 @@ static struct pmbus_data *pmbus_update_device(struct device *dev) static int pmbus_reg2data_linear(struct pmbus_data *data, struct pmbus_sensor *sensor) { - s16 exponent, mantissa; + s16 exponent; + s32 mantissa; long val; - if (sensor->class == PSC_VOLTAGE_OUT) { + if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ exponent = data->exponent; - mantissa = (s16) sensor->data; - } else { + mantissa = (u16) sensor->data; + } else { /* LINEAR11 */ exponent = (sensor->data >> 11) & 0x001f; mantissa = sensor->data & 0x07ff; if (exponent > 0x0f) exponent |= 0xffe0; /* sign extend exponent */ if (mantissa > 0x03ff) - mantissa |= 0xf800; /* sign extend mantissa */ + mantissa |= 0xfffff800; /* sign extend mantissa */ } val = mantissa; @@ -454,19 +455,18 @@ static int pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) static u16 pmbus_data2reg_linear(struct pmbus_data *data, enum pmbus_sensor_classes class, long val) { - s16 exponent = 0, mantissa = 0; + s16 exponent = 0, mantissa; bool negative = false; /* simple case */ if (val == 0) return 0; - if (val < 0) { - negative = true; - val = -val; - } - if (class == PSC_VOLTAGE_OUT) { + /* LINEAR16 does not support negative voltages */ + if (val < 0) + return 0; + /* * For a static exponents, we don't have a choice * but to adjust the value to it. @@ -476,9 +476,12 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, else val >>= data->exponent; val = DIV_ROUND_CLOSEST(val, 1000); - if (val > 0x7fff) - val = 0x7fff; - return negative ? -val : val; + return val & 0xffff; + } + + if (val < 0) { + negative = true; + val = -val; } /* Power is in uW. Convert to mW before converting. */ -- cgit v1.2.3