RE: [PATCH] i2c: imx: double check IIF in case interrupt lost

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sorry, pls ignore the mail, I send it again.

>-----Original Message-----
>From: Fugang Duan [mailto:b38611@xxxxxxxxxxxxx]
>Sent: Thursday, August 14, 2014 4:23 PM
>To: wsa@xxxxxxxxxxxxx
>Cc: linux-i2c@xxxxxxxxxxxxxxx; u.kleine-koenig@xxxxxxxxxxxxxx; Duan
>Fugang-B38611
>Subject: [PATCH] i2c: imx: double check IIF in case interrupt lost
>
>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@xxxxxxxxxxxxx>
>---
> 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
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux