aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 52a58b8b6e1b..a139940cd991 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -21,6 +21,7 @@
21 21
22#include <linux/debugfs.h> 22#include <linux/debugfs.h>
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/math64.h>
24#include <linux/module.h> 25#include <linux/module.h>
25#include <linux/init.h> 26#include <linux/init.h>
26#include <linux/err.h> 27#include <linux/err.h>
@@ -499,8 +500,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
499static long pmbus_reg2data_direct(struct pmbus_data *data, 500static long pmbus_reg2data_direct(struct pmbus_data *data,
500 struct pmbus_sensor *sensor) 501 struct pmbus_sensor *sensor)
501{ 502{
502 long val = (s16) sensor->data; 503 s64 b, val = (s16)sensor->data;
503 long m, b, R; 504 s32 m, R;
504 505
505 m = data->info->m[sensor->class]; 506 m = data->info->m[sensor->class];
506 b = data->info->b[sensor->class]; 507 b = data->info->b[sensor->class];
@@ -528,11 +529,12 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
528 R--; 529 R--;
529 } 530 }
530 while (R < 0) { 531 while (R < 0) {
531 val = DIV_ROUND_CLOSEST(val, 10); 532 val = div_s64(val + 5LL, 10L); /* round closest */
532 R++; 533 R++;
533 } 534 }
534 535
535 return (val - b) / m; 536 val = div_s64(val - b, m);
537 return clamp_val(val, LONG_MIN, LONG_MAX);
536} 538}
537 539
538/* 540/*
@@ -656,7 +658,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
656static u16 pmbus_data2reg_direct(struct pmbus_data *data, 658static u16 pmbus_data2reg_direct(struct pmbus_data *data,
657 struct pmbus_sensor *sensor, long val) 659 struct pmbus_sensor *sensor, long val)
658{ 660{
659 long m, b, R; 661 s64 b, val64 = val;
662 s32 m, R;
660 663
661 m = data->info->m[sensor->class]; 664 m = data->info->m[sensor->class];
662 b = data->info->b[sensor->class]; 665 b = data->info->b[sensor->class];
@@ -673,18 +676,18 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
673 R -= 3; /* Adjust R and b for data in milli-units */ 676 R -= 3; /* Adjust R and b for data in milli-units */
674 b *= 1000; 677 b *= 1000;
675 } 678 }
676 val = val * m + b; 679 val64 = val64 * m + b;
677 680
678 while (R > 0) { 681 while (R > 0) {
679 val *= 10; 682 val64 *= 10;
680 R--; 683 R--;
681 } 684 }
682 while (R < 0) { 685 while (R < 0) {
683 val = DIV_ROUND_CLOSEST(val, 10); 686 val64 = div_s64(val64 + 5LL, 10L); /* round closest */
684 R++; 687 R++;
685 } 688 }
686 689
687 return val; 690 return (u16)clamp_val(val64, S16_MIN, S16_MAX);
688} 691}
689 692
690static u16 pmbus_data2reg_vid(struct pmbus_data *data, 693static u16 pmbus_data2reg_vid(struct pmbus_data *data,