Skip to content

Commit 066ed42

Browse files
Thomas VanSelusgregkh
authored andcommitted
misc: ds1682: Ignore update-in-progress ETC reads
The Elapsed Time Counter (ETC) registers are not buffered for reading. If a 250ms tick occurs while data is being read out, the result can be a combination of old and new values. This can occur at the byte level (giving a time in the future) or the individual bit level (giving a time in the past). We catch both these cases by reading until we get two equal or consecutive values. After five unsuccessful attempts we give up. Signed-off-by: Thomas VanSelus <[email protected]> Signed-off-by: Aaron Sierra <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2fa065f commit 066ed42

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

drivers/misc/ds1682.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr,
5959
{
6060
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
6161
struct i2c_client *client = to_i2c_client(dev);
62-
unsigned long long val;
62+
unsigned long long val, check;
6363
__le32 val_le = 0;
6464
int rc;
6565

@@ -73,6 +73,23 @@ static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr,
7373

7474
val = le32_to_cpu(val_le);
7575

76+
if (sattr->index == DS1682_REG_ELAPSED) {
77+
int retries = 5;
78+
79+
/* Detect and retry when a tick occurs mid-read */
80+
do {
81+
rc = i2c_smbus_read_i2c_block_data(client, sattr->index,
82+
sattr->nr,
83+
(u8 *)&val_le);
84+
if (rc < 0 || retries <= 0)
85+
return -EIO;
86+
87+
check = val;
88+
val = le32_to_cpu(val_le);
89+
retries--;
90+
} while (val != check && val != (check + 1));
91+
}
92+
7693
/* Format the output string and return # of bytes
7794
* Special case: the 32 bit regs are time values with 1/4s
7895
* resolution, scale them up to milliseconds

0 commit comments

Comments
 (0)