From: Michael Hennerich <[email protected]>

Faulty slave devices might drive SDA low after a transfer finishes.  So,
when this scenario is detected, have the master generate up to 9 extra
clocks until the SDA is properly released.

Signed-off-by: Michael Hennerich <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
---
 drivers/i2c/busses/i2c-bfin-twi.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/i2c/busses/i2c-bfin-twi.c 
b/drivers/i2c/busses/i2c-bfin-twi.c
index fb26e5c..1ee9d5a 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -20,6 +20,7 @@
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 #include <asm/blackfin.h>
 #include <asm/portmux.h>
@@ -159,6 +160,27 @@ static void bfin_twi_handle_interrupt(struct 
bfin_twi_iface *iface,
                if (mast_stat & BUFWRERR)
                        dev_dbg(&iface->adap.dev, "Buffer Write Error\n");
 
+               /* Faulty slave devices, may drive SDA low after a transfer
+                * finishes. To release the bus this code generates up to 9
+                * extra clocks until SDA is released.
+                */
+
+               if (read_MASTER_STAT(iface) & SDASEN) {
+                       int cnt = 9;
+                       do {
+                               write_MASTER_CTL(iface, SCLOVR);
+                               udelay(6);
+                               write_MASTER_CTL(iface, 0);
+                               udelay(6);
+                       } while ((read_MASTER_STAT(iface) & SDASEN) && cnt--);
+
+                       write_MASTER_CTL(iface, SDAOVR | SCLOVR);
+                       udelay(6);
+                       write_MASTER_CTL(iface, SDAOVR);
+                       udelay(6);
+                       write_MASTER_CTL(iface, 0);
+               }
+
                /* If it is a quick transfer, only address without data,
                 * not an err, return 1.
                 */
-- 
1.7.4.rc1

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to