Skip to content

Commit 49a418d

Browse files
committed
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
2 parents 2db767d + 68615eb commit 49a418d

File tree

4 files changed

+37
-10
lines changed

4 files changed

+37
-10
lines changed

Documentation/devicetree/bindings/hwmon/jc42.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ Required properties:
3434

3535
- reg: I2C address
3636

37+
Optional properties:
38+
- smbus-timeout-disable: When set, the smbus timeout function will be disabled.
39+
This is not supported on all chips.
40+
3741
Example:
3842

3943
temp-sensor@1a {

MAINTAINERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6174,7 +6174,6 @@ M: Jean Delvare <jdelvare@suse.com>
61746174
M: Guenter Roeck <linux@roeck-us.net>
61756175
L: linux-hwmon@vger.kernel.org
61766176
W: http://hwmon.wiki.kernel.org/
6177-
T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/
61786177
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
61796178
S: Maintained
61806179
F: Documentation/hwmon/

drivers/hwmon/jc42.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2323
*/
2424

25+
#include <linux/bitops.h>
2526
#include <linux/module.h>
2627
#include <linux/init.h>
2728
#include <linux/slab.h>
@@ -45,6 +46,7 @@ static const unsigned short normal_i2c[] = {
4546
#define JC42_REG_TEMP 0x05
4647
#define JC42_REG_MANID 0x06
4748
#define JC42_REG_DEVICEID 0x07
49+
#define JC42_REG_SMBUS 0x22 /* NXP and Atmel, possibly others? */
4850

4951
/* Status bits in temperature register */
5052
#define JC42_ALARM_CRIT_BIT 15
@@ -75,6 +77,9 @@ static const unsigned short normal_i2c[] = {
7577
#define GT_MANID 0x1c68 /* Giantec */
7678
#define GT_MANID2 0x132d /* Giantec, 2nd mfg ID */
7779

80+
/* SMBUS register */
81+
#define SMBUS_STMOUT BIT(7) /* SMBus time-out, active low */
82+
7883
/* Supported chips */
7984

8085
/* Analog Devices */
@@ -495,6 +500,22 @@ static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
495500

496501
data->extended = !!(cap & JC42_CAP_RANGE);
497502

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+
498519
config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG);
499520
if (config < 0)
500521
return config;

drivers/hwmon/pmbus/pmbus_core.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <linux/debugfs.h>
2323
#include <linux/kernel.h>
24+
#include <linux/math64.h>
2425
#include <linux/module.h>
2526
#include <linux/init.h>
2627
#include <linux/err.h>
@@ -499,8 +500,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
499500
static long pmbus_reg2data_direct(struct pmbus_data *data,
500501
struct pmbus_sensor *sensor)
501502
{
502-
long val = (s16) sensor->data;
503-
long m, b, R;
503+
s64 b, val = (s16)sensor->data;
504+
s32 m, R;
504505

505506
m = data->info->m[sensor->class];
506507
b = data->info->b[sensor->class];
@@ -528,11 +529,12 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
528529
R--;
529530
}
530531
while (R < 0) {
531-
val = DIV_ROUND_CLOSEST(val, 10);
532+
val = div_s64(val + 5LL, 10L); /* round closest */
532533
R++;
533534
}
534535

535-
return (val - b) / m;
536+
val = div_s64(val - b, m);
537+
return clamp_val(val, LONG_MIN, LONG_MAX);
536538
}
537539

538540
/*
@@ -656,7 +658,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
656658
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
657659
struct pmbus_sensor *sensor, long val)
658660
{
659-
long m, b, R;
661+
s64 b, val64 = val;
662+
s32 m, R;
660663

661664
m = data->info->m[sensor->class];
662665
b = data->info->b[sensor->class];
@@ -673,18 +676,18 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
673676
R -= 3; /* Adjust R and b for data in milli-units */
674677
b *= 1000;
675678
}
676-
val = val * m + b;
679+
val64 = val64 * m + b;
677680

678681
while (R > 0) {
679-
val *= 10;
682+
val64 *= 10;
680683
R--;
681684
}
682685
while (R < 0) {
683-
val = DIV_ROUND_CLOSEST(val, 10);
686+
val64 = div_s64(val64 + 5LL, 10L); /* round closest */
684687
R++;
685688
}
686689

687-
return val;
690+
return (u16)clamp_val(val64, S16_MIN, S16_MAX);
688691
}
689692

690693
static u16 pmbus_data2reg_vid(struct pmbus_data *data,

0 commit comments

Comments
 (0)