Dear Maintainer,
For octeon TWSI controller, I found below two cases, maybe can be improved.
>From 09d9f0ce658d7f6a50d1af352dde619c29bc8bcf Mon Sep 17 00:00:00 2001
From: hgt463 <[email protected]>
Date: Thu, 23 Nov 2017 18:46:09 +0800
Subject: [PATCH] Driver updates:
- In the case of I2C bus dead lock occurred during driver probing,
it is better try to recovery it. so added bus recovery step in
octeon_i2c_probe();
- The purpose of function octeon_i2c_start() is to send START, so after
bus recovery, also need try to send START again.
Signed-off-by: hgt463 <[email protected]>
---
drivers/i2c/busses/i2c-octeon-core.c | 31 ++++++++++++++++++++++++++++++-
drivers/i2c/busses/i2c-octeon-platdrv.c | 15 +++++++++------
2 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c
index 1d87757..3ae1e03 100644
--- a/drivers/i2c/busses/i2c-octeon-core.c
+++ b/drivers/i2c/busses/i2c-octeon-core.c
@@ -255,6 +255,35 @@ static int octeon_i2c_recovery(struct octeon_i2c *i2c)
return ret;
}
+/*
+ * octeon_i2c_start_retry - send START to the bus after bus recovery.
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_start_retry(struct octeon_i2c *i2c)
+{
+ int ret;
+ u8 stat;
+
+ ret = octeon_i2c_recovery(i2c);
+ if (ret)
+ goto error;
+
+ octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA);
+ ret = octeon_i2c_wait(i2c);
+ if (ret)
+ goto error;
+
+ stat = octeon_i2c_stat_read(i2c);
+ if (stat == STAT_START || stat == STAT_REP_START)
+ /* START successful, bail out */
+ return 0;
+
+error:
+ return (ret) ? ret : -EAGAIN;
+}
+
/**
* octeon_i2c_start - send START to the bus
* @i2c: The struct octeon_i2c
@@ -280,7 +309,7 @@ static int octeon_i2c_start(struct octeon_i2c *i2c)
error:
/* START failed, try to recover */
- ret = octeon_i2c_recovery(i2c);
+ ret = octeon_i2c_start_retry(i2c);
return (ret) ? ret : -EAGAIN;
}
diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c
index 64bda83..98063af 100644
--- a/drivers/i2c/busses/i2c-octeon-platdrv.c
+++ b/drivers/i2c/busses/i2c-octeon-platdrv.c
@@ -228,12 +228,6 @@ static int octeon_i2c_probe(struct platform_device *pdev)
if (OCTEON_IS_MODEL(OCTEON_CN38XX))
i2c->broken_irq_check = true;
- result = octeon_i2c_init_lowlevel(i2c);
- if (result) {
- dev_err(i2c->dev, "init low level failed\n");
- goto out;
- }
-
octeon_i2c_set_clock(i2c);
i2c->adap = octeon_i2c_ops;
@@ -245,6 +239,15 @@ static int octeon_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&i2c->adap, i2c);
platform_set_drvdata(pdev, i2c);
+ stat = octeon_i2c_stat_read(i2c);
+ if (stat != STAT_IDLE) {
+ result = octeon_i2c_recovery(i2c);
+ if (result) {
+ dev_err(i2c->dev, "octeon i2c recovery failed\n");
+ goto out;
+ }
+ }
+
result = i2c_add_adapter(&i2c->adap);
if (result < 0)
goto out;
Attached patch for you review. Thanks in advance.
BR,
Sean Zhang