aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-12-03 10:46:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-12-03 10:46:16 -0500
commit49a418d78378769cf78b8c645f7e469f4dae2bbd (patch)
tree2291eb5fa0dcd3ee227e7a477628c53829fea2d3 /drivers
parent2db767d9889cef087149a5eaa35c1497671fa40f (diff)
parent68615eb01f82256c19e41967bfb3eef902f77033 (diff)
Merge tag 'hwmon-for-linus-v4.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon fixes from Guenter Roeck: "Fixes: - Drop reference to obsolete maintainer tree - Fix overflow bug in pmbus driver - Fix SMBUS timeout problem in jc42 driver For the SMBUS timeout handling, we had a brief discussion if this should be considered a bug fix or a feature. Peter says "it fixes real problems where the application misbehave due to faulty content when reading from an eeprom", and he needs the patch in his company's v4.14 images. This is good enough for me and warrants backport to stable kernels" * tag 'hwmon-for-linus-v4.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: hwmon: (jc42) optionally try to disable the SMBUS timeout hwmon: (pmbus) Use 64bit math for DIRECT format values hwmon: Drop reference to Jean's tree
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/jc42.c21
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c21
2 files changed, 33 insertions, 9 deletions
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index 5f11dc014ed6..e5234f953a6d 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -22,6 +22,7 @@
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */ 23 */
24 24
25#include <linux/bitops.h>
25#include <linux/module.h> 26#include <linux/module.h>
26#include <linux/init.h> 27#include <linux/init.h>
27#include <linux/slab.h> 28#include <linux/slab.h>
@@ -45,6 +46,7 @@ static const unsigned short normal_i2c[] = {
45#define JC42_REG_TEMP 0x05 46#define JC42_REG_TEMP 0x05
46#define JC42_REG_MANID 0x06 47#define JC42_REG_MANID 0x06
47#define JC42_REG_DEVICEID 0x07 48#define JC42_REG_DEVICEID 0x07
49#define JC42_REG_SMBUS 0x22 /* NXP and Atmel, possibly others? */
48 50
49/* Status bits in temperature register */ 51/* Status bits in temperature register */
50#define JC42_ALARM_CRIT_BIT 15 52#define JC42_ALARM_CRIT_BIT 15
@@ -75,6 +77,9 @@ static const unsigned short normal_i2c[] = {
75#define GT_MANID 0x1c68 /* Giantec */ 77#define GT_MANID 0x1c68 /* Giantec */
76#define GT_MANID2 0x132d /* Giantec, 2nd mfg ID */ 78#define GT_MANID2 0x132d /* Giantec, 2nd mfg ID */
77 79
80/* SMBUS register */
81#define SMBUS_STMOUT BIT(7) /* SMBus time-out, active low */
82
78/* Supported chips */ 83/* Supported chips */
79 84
80/* Analog Devices */ 85/* Analog Devices */
@@ -495,6 +500,22 @@ static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
495 500
496 data->extended = !!(cap & JC42_CAP_RANGE); 501 data->extended = !!(cap & JC42_CAP_RANGE);
497 502
503 if (device_property_read_bool(dev, "smbus-timeout-disable")) {
504 int smbus;
505
506 /*
507 * Not all chips support this register, but from a
508 * quick read of various datasheets no chip appears
509 * incompatible with the below attempt to disable
510 * the timeout. And the whole thing is opt-in...
511 */
512 smbus = i2c_smbus_read_word_swapped(client, JC42_REG_SMBUS);
513 if (smbus < 0)
514 return smbus;
515 i2c_smbus_write_word_swapped(client, JC42_REG_SMBUS,
516 smbus | SMBUS_STMOUT);
517 }
518
498 config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG); 519 config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG);
499 if (config < 0) 520 if (config < 0)
500 return config; 521 return config;
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,