commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=7df51d4c8c2e93b5cd0a002935697eec2b509fa3 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk
TWI transfer interrupts may be lost when system is heavily handling other interrupts, while current transfer handler depends on each accurate interrupt and miss some data in this case. Because there are 2 2-byte fifos in blackfin twi controller, the occurrence of the data loss can be reduced by reading and writing till the FIFO is full. Signed-off-by: Sonic Zhang <[email protected]> --- drivers/i2c/busses/i2c-bfin-twi.c | 47 +++++++++++++++++++++--------------- 1 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index cc93f80..18c0ea6 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -39,33 +39,40 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, unsigned short mast_stat = read_MASTER_STAT(iface); if (twi_int_status & XMTSERV) { + if (iface->writeNum <= 0) { + /* start receive immediately after complete sending in + * combine mode. + */ + if (iface->cur_mode == TWI_I2C_MODE_COMBINED) + write_MASTER_CTL(iface, + read_MASTER_CTL(iface) | MDIR); + else if (iface->manual_stop) + write_MASTER_CTL(iface, + read_MASTER_CTL(iface) | STOP); + else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && + iface->cur_msg + 1 < iface->msg_num) { + if (iface->pmsg[iface->cur_msg + 1].flags & + I2C_M_RD) + write_MASTER_CTL(iface, + read_MASTER_CTL(iface) | + MDIR); + else + write_MASTER_CTL(iface, + read_MASTER_CTL(iface) & + ~MDIR); + } + } /* Transmit next data */ - if (iface->writeNum > 0) { + while (iface->writeNum > 0 && + (read_FIFO_STAT(iface) & XMTSTAT) != XMT_FULL) { SSYNC(); write_XMT_DATA8(iface, *(iface->transPtr++)); iface->writeNum--; } - /* start receive immediately after complete sending in - * combine mode. - */ - else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | MDIR); - else if (iface->manual_stop) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | STOP); - else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg + 1 < iface->msg_num) { - if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | MDIR); - else - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) & ~MDIR); - } } if (twi_int_status & RCVSERV) { - if (iface->readNum > 0) { + while (iface->readNum > 0 && + (read_FIFO_STAT(iface) & RCVSTAT) != RCV_FULL) { /* Receive next data */ *(iface->transPtr) = read_RCV_DATA8(iface); if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
_______________________________________________ Linux-kernel-commits mailing list [email protected] https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits
