Title: [7659] branches/2009R1/drivers/i2c/busses/i2c-bfin-twi.c: Fix bug[#5275] Clear i2c int state earlier and loop till no ints left
Revision
7659
Author
sonicz
Date
2009-10-16 00:11:06 -0400 (Fri, 16 Oct 2009)

Log Message

Fix bug[#5275] Clear i2c int state earlier and loop till no ints left

i2c event of next read/write byte may trigger before current int state
is cleared in the interrupt handler. So, this should be done at the
beginning of interrupt handler to avoid losing new i2c events.

Modified Paths

Diff

Modified: branches/2009R1/drivers/i2c/busses/i2c-bfin-twi.c (7658 => 7659)


--- branches/2009R1/drivers/i2c/busses/i2c-bfin-twi.c	2009-10-16 03:19:15 UTC (rev 7658)
+++ branches/2009R1/drivers/i2c/busses/i2c-bfin-twi.c	2009-10-16 04:11:06 UTC (rev 7659)
@@ -79,9 +79,9 @@
 	{P_TWI1_SCL, P_TWI1_SDA, 0},
 };
 
-static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
+					unsigned short twi_int_status)
 {
-	unsigned short twi_int_status = read_INT_STAT(iface);
 	unsigned short mast_stat = read_MASTER_STAT(iface);
 
 	if (twi_int_status & XMTSERV) {
@@ -109,9 +109,6 @@
 					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
 		}
 		SSYNC();
-		/* Clear status */
-		write_INT_STAT(iface, XMTSERV);
-		SSYNC();
 	}
 	if (twi_int_status & RCVSERV) {
 		if (iface->readNum > 0) {
@@ -144,12 +141,8 @@
 					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
 			SSYNC();
 		}
-		/* Clear interrupt source */
-		write_INT_STAT(iface, RCVSERV);
-		SSYNC();
 	}
 	if (twi_int_status & MERR) {
-		write_INT_STAT(iface, MERR);
 		write_INT_MASK(iface, 0);
 		write_MASTER_STAT(iface, 0x3e);
 		write_MASTER_CTL(iface, 0);
@@ -159,10 +152,6 @@
 		 * results.
 		 */
 		if (twi_int_status & MCOMP) {
-			write_INT_STAT(iface, MCOMP);
-			write_INT_MASK(iface, 0);
-			write_MASTER_CTL(iface, 0);
-			SSYNC();
 			/* If it is a quick transfer, only address without data,
 			 * not an err, return 1.
 			 * If address is acknowledged return 1.
@@ -175,8 +164,6 @@
 		return;
 	}
 	if (twi_int_status & MCOMP) {
-		write_INT_STAT(iface, MCOMP);
-		SSYNC();
 		if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
 			if (iface->readNum == 0) {
 				/* set the read number to 1 and ask for manual
@@ -251,9 +238,18 @@
 {
 	struct bfin_twi_iface *iface = dev_id;
 	unsigned long flags;
+	unsigned short twi_int_status;
 
 	spin_lock_irqsave(&iface->lock, flags);
-	bfin_twi_handle_interrupt(iface);
+	while (1) {
+		twi_int_status = read_INT_STAT(iface);
+		if (!twi_int_status)
+			break;
+		/* Clear interrupt status */
+		write_INT_STAT(iface, twi_int_status);
+		SSYNC();
+		bfin_twi_handle_interrupt(iface, twi_int_status);
+	}
 	spin_unlock_irqrestore(&iface->lock, flags);
 	return IRQ_HANDLED;
 }
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to