Skip to content

Commit

Permalink
Merge tag 'hwmon-for-linus-v4.15-rc2' of git://git.kernel.org/pub/scm…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Dec 3, 2017
2 parents 2db767d + 68615eb commit 49a418d
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 10 deletions.
4 changes: 4 additions & 0 deletions Documentation/devicetree/bindings/hwmon/jc42.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ Required properties:

- reg: I2C address

Optional properties:
- smbus-timeout-disable: When set, the smbus timeout function will be disabled.
This is not supported on all chips.

Example:

temp-sensor@1a {
Expand Down
1 change: 0 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -6174,7 +6174,6 @@ M: Jean Delvare <[email protected]>
M: Guenter Roeck <[email protected]>
L: [email protected]
W: http://hwmon.wiki.kernel.org/
T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
S: Maintained
F: Documentation/hwmon/
Expand Down
21 changes: 21 additions & 0 deletions drivers/hwmon/jc42.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

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

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

/* SMBUS register */
#define SMBUS_STMOUT BIT(7) /* SMBus time-out, active low */

/* Supported chips */

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

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

if (device_property_read_bool(dev, "smbus-timeout-disable")) {
int smbus;

/*
* Not all chips support this register, but from a
* quick read of various datasheets no chip appears
* incompatible with the below attempt to disable
* the timeout. And the whole thing is opt-in...
*/
smbus = i2c_smbus_read_word_swapped(client, JC42_REG_SMBUS);
if (smbus < 0)
return smbus;
i2c_smbus_write_word_swapped(client, JC42_REG_SMBUS,
smbus | SMBUS_STMOUT);
}

config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG);
if (config < 0)
return config;
Expand Down
21 changes: 12 additions & 9 deletions drivers/hwmon/pmbus/pmbus_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
Expand Down Expand Up @@ -499,8 +500,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
static long pmbus_reg2data_direct(struct pmbus_data *data,
struct pmbus_sensor *sensor)
{
long val = (s16) sensor->data;
long m, b, R;
s64 b, val = (s16)sensor->data;
s32 m, R;

m = data->info->m[sensor->class];
b = data->info->b[sensor->class];
Expand Down Expand Up @@ -528,11 +529,12 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
R--;
}
while (R < 0) {
val = DIV_ROUND_CLOSEST(val, 10);
val = div_s64(val + 5LL, 10L); /* round closest */
R++;
}

return (val - b) / m;
val = div_s64(val - b, m);
return clamp_val(val, LONG_MIN, LONG_MAX);
}

/*
Expand Down Expand Up @@ -656,7 +658,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
struct pmbus_sensor *sensor, long val)
{
long m, b, R;
s64 b, val64 = val;
s32 m, R;

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

while (R > 0) {
val *= 10;
val64 *= 10;
R--;
}
while (R < 0) {
val = DIV_ROUND_CLOSEST(val, 10);
val64 = div_s64(val64 + 5LL, 10L); /* round closest */
R++;
}

return val;
return (u16)clamp_val(val64, S16_MIN, S16_MAX);
}

static u16 pmbus_data2reg_vid(struct pmbus_data *data,
Expand Down

0 comments on commit 49a418d

Please sign in to comment.