diff options
author | Ben Dooks <ben-linux@fluff.org> | 2011-01-12 22:26:12 +0000 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2011-01-12 22:26:12 +0000 |
commit | dad92924ea4c9167e64a2835ec9310c73570b10b (patch) | |
tree | b0a0c3dfb1abb7cbab7916eeacec7dbe4dc1e021 /drivers | |
parent | adeaf46d311715deee9ae38ef1edb0d6b6fb0d55 (diff) | |
parent | 74f56c4ad4e4627862bddb0b8c3ab394e3c004f7 (diff) |
Merge branch 'for-2638/i2c/bfin2' into for-linus/i2c-2638
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-bfin-twi.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index fb26e5c67515..52b545a795f2 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. */ @@ -760,7 +782,7 @@ static void __exit i2c_bfin_twi_exit(void) platform_driver_unregister(&i2c_bfin_twi_driver); } -module_init(i2c_bfin_twi_init); +subsys_initcall(i2c_bfin_twi_init); module_exit(i2c_bfin_twi_exit); MODULE_AUTHOR("Bryan Wu, Sonic Zhang"); |