diff options
author | Guenter Roeck <guenter.roeck@ericsson.com> | 2011-03-07 21:34:50 -0500 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2011-03-15 01:39:11 -0400 |
commit | 9f6ad1ce6484a92ef864e00611a8ef3daf9c986d (patch) | |
tree | 8aabd7f60d7a6ccfc62beb37356180c37f7b64e0 /drivers/hwmon | |
parent | 8677011a5d8e0358ce5ae26d82dfcddcad073c47 (diff) |
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 <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/pmbus_core.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c index 92540c9cd34e..6474512f49b0 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) | |||
359 | static int pmbus_reg2data_linear(struct pmbus_data *data, | 359 | static int pmbus_reg2data_linear(struct pmbus_data *data, |
360 | struct pmbus_sensor *sensor) | 360 | struct pmbus_sensor *sensor) |
361 | { | 361 | { |
362 | s16 exponent, mantissa; | 362 | s16 exponent; |
363 | s32 mantissa; | ||
363 | long val; | 364 | long val; |
364 | 365 | ||
365 | if (sensor->class == PSC_VOLTAGE_OUT) { | 366 | if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ |
366 | exponent = data->exponent; | 367 | exponent = data->exponent; |
367 | mantissa = (s16) sensor->data; | 368 | mantissa = (u16) sensor->data; |
368 | } else { | 369 | } else { /* LINEAR11 */ |
369 | exponent = (sensor->data >> 11) & 0x001f; | 370 | exponent = (sensor->data >> 11) & 0x001f; |
370 | mantissa = sensor->data & 0x07ff; | 371 | mantissa = sensor->data & 0x07ff; |
371 | 372 | ||
372 | if (exponent > 0x0f) | 373 | if (exponent > 0x0f) |
373 | exponent |= 0xffe0; /* sign extend exponent */ | 374 | exponent |= 0xffe0; /* sign extend exponent */ |
374 | if (mantissa > 0x03ff) | 375 | if (mantissa > 0x03ff) |
375 | mantissa |= 0xf800; /* sign extend mantissa */ | 376 | mantissa |= 0xfffff800; /* sign extend mantissa */ |
376 | } | 377 | } |
377 | 378 | ||
378 | val = mantissa; | 379 | val = mantissa; |
@@ -454,19 +455,18 @@ static int pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) | |||
454 | static u16 pmbus_data2reg_linear(struct pmbus_data *data, | 455 | static u16 pmbus_data2reg_linear(struct pmbus_data *data, |
455 | enum pmbus_sensor_classes class, long val) | 456 | enum pmbus_sensor_classes class, long val) |
456 | { | 457 | { |
457 | s16 exponent = 0, mantissa = 0; | 458 | s16 exponent = 0, mantissa; |
458 | bool negative = false; | 459 | bool negative = false; |
459 | 460 | ||
460 | /* simple case */ | 461 | /* simple case */ |
461 | if (val == 0) | 462 | if (val == 0) |
462 | return 0; | 463 | return 0; |
463 | 464 | ||
464 | if (val < 0) { | ||
465 | negative = true; | ||
466 | val = -val; | ||
467 | } | ||
468 | |||
469 | if (class == PSC_VOLTAGE_OUT) { | 465 | if (class == PSC_VOLTAGE_OUT) { |
466 | /* LINEAR16 does not support negative voltages */ | ||
467 | if (val < 0) | ||
468 | return 0; | ||
469 | |||
470 | /* | 470 | /* |
471 | * For a static exponents, we don't have a choice | 471 | * For a static exponents, we don't have a choice |
472 | * but to adjust the value to it. | 472 | * but to adjust the value to it. |
@@ -476,9 +476,12 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, | |||
476 | else | 476 | else |
477 | val >>= data->exponent; | 477 | val >>= data->exponent; |
478 | val = DIV_ROUND_CLOSEST(val, 1000); | 478 | val = DIV_ROUND_CLOSEST(val, 1000); |
479 | if (val > 0x7fff) | 479 | return val & 0xffff; |
480 | val = 0x7fff; | 480 | } |
481 | return negative ? -val : val; | 481 | |
482 | if (val < 0) { | ||
483 | negative = true; | ||
484 | val = -val; | ||
482 | } | 485 | } |
483 | 486 | ||
484 | /* Power is in uW. Convert to mW before converting. */ | 487 | /* Power is in uW. Convert to mW before converting. */ |