Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8419c8de authored by Sonic Zhang's avatar Sonic Zhang Committed by Wolfram Sang
Browse files

i2c: bfin-twi: Read and write the FIFO in loop



TWI transfer interrupts may be lost when system is heavily handling other
interrupts, while current transfer handler depends on each accurate interrupt
and misses 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 till
the RX FIFO is empty and writing till the TX FIFO is full.

Reported-by: default avatarBob Maris <mail@maris-ee.eu>
Signed-off-by: default avatarSonic Zhang <sonic.zhang@analog.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent c80f5284
Loading
Loading
Loading
Loading
+27 −20
Original line number Diff line number Diff line
@@ -39,16 +39,11 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
	unsigned short mast_stat = read_MASTER_STAT(iface);

	if (twi_int_status & XMTSERV) {
		/* Transmit next data */
		if (iface->writeNum > 0) {
			SSYNC();
			write_XMT_DATA8(iface, *(iface->transPtr++));
			iface->writeNum--;
		}
		if (iface->writeNum <= 0) {
			/* start receive immediately after complete sending in
			 * combine mode.
			 */
		else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
			if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
				write_MASTER_CTL(iface,
					read_MASTER_CTL(iface) | MDIR);
			else if (iface->manual_stop)
@@ -56,16 +51,28 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *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)
				if (iface->pmsg[iface->cur_msg + 1].flags &
					I2C_M_RD)
					write_MASTER_CTL(iface,
					read_MASTER_CTL(iface) | MDIR);
						read_MASTER_CTL(iface) |
						MDIR);
				else
					write_MASTER_CTL(iface,
					read_MASTER_CTL(iface) & ~MDIR);
						read_MASTER_CTL(iface) &
						~MDIR);
			}
		}
		/* Transmit next data */
		while (iface->writeNum > 0 &&
			(read_FIFO_STAT(iface) & XMTSTAT) != XMT_FULL) {
			SSYNC();
			write_XMT_DATA8(iface, *(iface->transPtr++));
			iface->writeNum--;
		}
	}
	if (twi_int_status & RCVSERV) {
		if (iface->readNum > 0) {
		while (iface->readNum > 0 &&
			(read_FIFO_STAT(iface) & RCVSTAT)) {
			/* Receive next data */
			*(iface->transPtr) = read_RCV_DATA8(iface);
			if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {