aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-21 10:58:38 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-24 21:38:59 -0400
commit85062c9b990b1dc8bbb8971ee7d3044a999cf25f (patch)
treed801d95e05e74855464d708de925a2716c5779f9 /drivers/rtc
parent7f8a58925b4c0198c12344025b6ffd5dd7d9f1f5 (diff)
rtc: rv8803: workaround i2c HW issue
The rv8803 has a 60µs window where it will not answer on the i2c bus. It also means there will be no ack for the communication. Make sure communication is tried multiple times when this happens (the i2c subsystem mandates -ENXIO is that case but the number of retries is host specific). The critical parts are the probe function and the alarm callback so make sure we handle the failure there. Cc: stable@vger.kernel.org # v4.4 Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-rv8803.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index 8d9f35ceb808..f623038e586e 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -61,11 +61,14 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
61 struct i2c_client *client = dev_id; 61 struct i2c_client *client = dev_id;
62 struct rv8803_data *rv8803 = i2c_get_clientdata(client); 62 struct rv8803_data *rv8803 = i2c_get_clientdata(client);
63 unsigned long events = 0; 63 unsigned long events = 0;
64 int flags; 64 int flags, try = 0;
65 65
66 mutex_lock(&rv8803->flags_lock); 66 mutex_lock(&rv8803->flags_lock);
67 67
68 flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); 68 do {
69 flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
70 try++;
71 } while ((flags == -ENXIO) && (try < 3));
69 if (flags <= 0) { 72 if (flags <= 0) {
70 mutex_unlock(&rv8803->flags_lock); 73 mutex_unlock(&rv8803->flags_lock);
71 return IRQ_NONE; 74 return IRQ_NONE;
@@ -424,7 +427,7 @@ static int rv8803_probe(struct i2c_client *client,
424{ 427{
425 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 428 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
426 struct rv8803_data *rv8803; 429 struct rv8803_data *rv8803;
427 int err, flags; 430 int err, flags, try = 0;
428 431
429 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | 432 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
430 I2C_FUNC_SMBUS_I2C_BLOCK)) { 433 I2C_FUNC_SMBUS_I2C_BLOCK)) {
@@ -441,7 +444,16 @@ static int rv8803_probe(struct i2c_client *client,
441 rv8803->client = client; 444 rv8803->client = client;
442 i2c_set_clientdata(client, rv8803); 445 i2c_set_clientdata(client, rv8803);
443 446
444 flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); 447 /*
448 * There is a 60µs window where the RTC may not reply on the i2c bus in
449 * that case, the transfer is not ACKed. In that case, ensure there are
450 * multiple attempts.
451 */
452 do {
453 flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
454 try++;
455 } while ((flags == -ENXIO) && (try < 3));
456
445 if (flags < 0) 457 if (flags < 0)
446 return flags; 458 return flags;
447 459
@@ -476,8 +488,12 @@ static int rv8803_probe(struct i2c_client *client,
476 return PTR_ERR(rv8803->rtc); 488 return PTR_ERR(rv8803->rtc);
477 } 489 }
478 490
479 err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT, 491 try = 0;
480 RV8803_EXT_WADA); 492 do {
493 err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT,
494 RV8803_EXT_WADA);
495 try++;
496 } while ((err == -ENXIO) && (try < 3));
481 if (err) 497 if (err)
482 return err; 498 return err;
483 499