Skip to content

Commit

Permalink
hwmon: (jc42) optionally try to disable the SMBUS timeout
Browse files Browse the repository at this point in the history
With a nxp,se97 chip on an atmel sama5d31 board, the I2C adapter driver
is not always capable of avoiding the 25-35 ms timeout as specified by
the SMBUS protocol. This may cause silent corruption of the last bit of
any transfer, e.g. a one is read instead of a zero if the sensor chip
times out. This also affects the eeprom half of the nxp-se97 chip, where
this silent corruption was originally noticed. Other I2C adapters probably
suffer similar issues, e.g. bit-banging comes to mind as risky...

The SMBUS register in the nxp chip is not a standard Jedec register, but
it is not special to the nxp chips either, at least the atmel chips
have the same mechanism. Therefore, do not special case this on the
manufacturer, it is opt-in via the device property anyway.

Cc: stable@vger.kernel.org # 4.9+
Signed-off-by: Peter Rosin <peda@axentia.se>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
  • Loading branch information
Peter Rosin authored and Guenter Roeck committed Nov 30, 2017
1 parent bd467e4 commit 68615eb
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 0 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
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

0 comments on commit 68615eb

Please sign in to comment.