All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] i2c: imx: double check IIF in case interrupt lost
@ 2014-08-14  8:29 Fugang Duan
       [not found] ` <1408004954-29418-1-git-send-email-b38611-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Fugang Duan @ 2014-08-14  8:29 UTC (permalink / raw)
  To: wsa-z923LK4zBo2bacvFa/9K2g
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ,
	b38611-KZfg59tc24xl57MIdRCFDg

In i2c_imx_read():
...
result = i2c_imx_trx_complete(i2c_imx);
if (result)
		return result;
..

If the current byte read complete, "IIF" status is set, and pend
up one GIC interrupt. In irq handler, wake up the wait queue in
.i2c_imx_trx_complete().

But, for imx6q platform with high bus and cpu loading test cases,
after long time test, sometime i2c interrupt is lost, but "IIF" is
set, according to current logic code, i2c_imx_trx_complete() still
return "-ETIMEDOUT", and then i2c host don't read the rest of data,
i2c driver stop transmit, disable controller and clock. Thus, i2c
device cannot wait clock and always drive the SDA line.

So, SDA is pulled down by i2c device, which needs 9 clocks to recovery
the SDA line.

To avoid the issue, we can double check IIF bit after timeout for waiting
event in .i2c_imx_trx_complete(), if IIF bit is set, process it in
normal flow. The patch just to double check IIF in case interrupt lost.

Signed-off-by: Fugang Duan <B38611-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 drivers/i2c/busses/i2c-imx.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index aa8bc14..4b63771 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -285,11 +285,17 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 
 static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
 {
+	unsigned int temp;
+
 	wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
 
 	if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
-		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
-		return -ETIMEDOUT;
+		/* Double check IIF to avoid interrupt lost */
+		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
+		if (!(temp & I2SR_IIF)) {
+			dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
 	}
 	dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
 	i2c_imx->i2csr = 0;
-- 
1.7.8

^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH] i2c: imx: double check IIF in case interrupt lost
@ 2014-08-14  8:23 Fugang Duan
       [not found] ` <1408004588-22408-1-git-send-email-b38611-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Fugang Duan @ 2014-08-14  8:23 UTC (permalink / raw)
  To: wsa-z923LK4zBo2bacvFa/9K2g
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ,
	b38611-KZfg59tc24xl57MIdRCFDg

In i2c_imx_read():
...
result = i2c_imx_trx_complete(i2c_imx);
if (result)
		return result;
..

If the current byte read complete, "IIF" status is set, and pend
up one GIC interrupt. In irq handler, wake up the wait queue in
.i2c_imx_trx_complete().

But, for imx6q platform with high bus and cpu loading test cases,
after long time test, sometime i2c interrupt is lost, but "IIF" is
set, according to current logic code, i2c_imx_trx_complete() still
return "-ETIMEDOUT", and then i2c host don't read the rest of data,
i2c driver stop transmit, disable controller and clock. Thus, i2c
device cannot wait clock and always drive the SDA line.

So, SDA is pulled down by i2c device, which needs 9 clocks to recovery
the SDA line.

To avoid the issue, we can double check IIF bit after timeout for waiting
event in .i2c_imx_trx_complete(), if IIF bit is set, process it in
normal flow. The patch just to double check IIF in case interrupt lost.

Signed-off-by: Fugang Duan <B38611-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
---
 drivers/i2c/busses/i2c-imx.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index aa8bc14..f3845cb 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -285,11 +285,17 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 
 static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
 {
+	unsigned int temp;
+
 	wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
 
 	if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
-		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
-		return -ETIMEDOUT;
+		/* Double check IIF to avoid interrupt lost */
+		temp = readb(i2c_imx->base + IMX_I2C_I2SR);
+		if (!(temp & I2SR_IIF)) {
+			dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
 	}
 	dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
 	i2c_imx->i2csr = 0;
-- 
1.7.8

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

end of thread, other threads:[~2014-08-20  1:52 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-14  8:29 [PATCH] i2c: imx: double check IIF in case interrupt lost Fugang Duan
     [not found] ` <1408004954-29418-1-git-send-email-b38611-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2014-08-14  9:42   ` Uwe Kleine-König
     [not found]     ` <20140814094204.GW5134-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2014-08-14 10:09       ` fugang.duan-KZfg59tc24xl57MIdRCFDg
     [not found]         ` <96d6e524bc524305904730df24bf878f-GeMU99GfrrsHjcGqcGfFzOO6mTEJWrR4XA4E9RH9d+qIuWR1G4zioA@public.gmane.org>
2014-08-14 19:27           ` Uwe Kleine-König
     [not found]             ` <20140814192702.GC5134-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2014-08-15  2:14               ` fugang.duan-KZfg59tc24xl57MIdRCFDg
     [not found]                 ` <01dba3477e664c88a65e276a1c77c3e2-GeMU99GfrrsHjcGqcGfFzOO6mTEJWrR4XA4E9RH9d+qIuWR1G4zioA@public.gmane.org>
2014-08-15  7:18                   ` Uwe Kleine-König
     [not found]                     ` <20140815071814.GD5134-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2014-08-19 14:53                       ` Wolfram Sang
2014-08-20  1:52                         ` fugang.duan-KZfg59tc24xl57MIdRCFDg
  -- strict thread matches above, loose matches on Subject: below --
2014-08-14  8:23 Fugang Duan
     [not found] ` <1408004588-22408-1-git-send-email-b38611-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2014-08-14  8:43   ` fugang.duan-KZfg59tc24xl57MIdRCFDg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.