linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Bug fix] octeon-i2c driver updates
@ 2017-11-23 11:42 Zhang, Sean C. (NSB - CN/Hangzhou)
  2017-11-24 13:10 ` Jan Glauber
  0 siblings, 1 reply; 8+ messages in thread
From: Zhang, Sean C. (NSB - CN/Hangzhou) @ 2017-11-23 11:42 UTC (permalink / raw)
  To: jglauber@cavium.com, david.daney@cavium.com, wsa@the-dreams.de,
	linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 3543 bytes --]

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 <sean.c.zhang@nokia.com>
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 <sean.c.zhang@nokia.com>
---
 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

[-- Attachment #2: 0001-Driver-updates.patch --]
[-- Type: application/octet-stream, Size: 2929 bytes --]

From 09d9f0ce658d7f6a50d1af352dde619c29bc8bcf Mon Sep 17 00:00:00 2001
From: hgt463 <sean.c.zhang@nokia.com>
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 <sean.c.zhang@nokia.com>
---
 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;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-12-06  7:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-11-23 11:42 [Bug fix] octeon-i2c driver updates Zhang, Sean C. (NSB - CN/Hangzhou)
2017-11-24 13:10 ` Jan Glauber
2017-11-27  8:37   ` Zhang, Sean C. (NSB - CN/Hangzhou)
2017-11-30  1:56     ` Zhang, Sean C. (NSB - CN/Hangzhou)
2017-12-01 10:06       ` Jan Glauber
2017-12-05  6:44         ` Zhang, Sean C. (NSB - CN/Hangzhou)
2017-12-05 16:42           ` David Daney
2017-12-06  7:11             ` Zhang, Sean C. (NSB - CN/Hangzhou)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).