i2c-bfin-twi: handle faulty slave devices better
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 <michael.hennerich@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
This commit is contained in:
parent
f878133bf0
commit
540ac5553e
@ -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.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user