aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Rosin <peda@axentia.se>2017-11-27 11:31:00 -0500
committerGuenter Roeck <linux@roeck-us.net>2017-11-30 16:12:44 -0500
commit68615eb01f82256c19e41967bfb3eef902f77033 (patch)
treefc7dc12e54f6468fc0fa657efdf36a602f9304db
parentbd467e4eababe4c04272c1e646f066db02734c79 (diff)
hwmon: (jc42) optionally try to disable the SMBUS timeout
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>
-rw-r--r--Documentation/devicetree/bindings/hwmon/jc42.txt4
-rw-r--r--drivers/hwmon/jc42.c21
2 files changed, 25 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/jc42.txt b/Documentation/devicetree/bindings/hwmon/jc42.txt
index 07a250498fbb..f569db58f64a 100644
--- a/Documentation/devicetree/bindings/hwmon/jc42.txt
+++ b/Documentation/devicetree/bindings/hwmon/jc42.txt
@@ -34,6 +34,10 @@ Required properties:
34 34
35- reg: I2C address 35- reg: I2C address
36 36
37Optional properties:
38- smbus-timeout-disable: When set, the smbus timeout function will be disabled.
39 This is not supported on all chips.
40
37Example: 41Example:
38 42
39temp-sensor@1a { 43temp-sensor@1a {
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;