Patch 2/4: Force PCI MMIO posted writes to complete for time 
           sensitive i2c bus line manipulation

Since i2c-algo-bit performs timing functions between i2c bus line
transitions, it is important to ensure the I2C bus line manipulation
commands are actually transferred to the cx23418 before returning
control to i2c-algo-bit.

This change performs a read back from PCI MMIO registers of the CX23418
to ensure PCI posted writes are actually flushed to the CX23418 and not
buffered in the host bridge or another PCI-PCI bridge.  This is the
Right Thing (tm) to do for ensuring accurate timing of cx23418 I2C bus
transitions.


Refer to

1. linux/Documentation/pci.txt '11. MMIO Space and "Write Posting"'

2. PCI Local Bus Specification, Sections 3.1.1, 3.2.5, and E.2:
http://rm-f.net/~orange/devel/specifications/pci/pci_lb3.0-2-6-04.pdf

3. I2C Bus Specification and User Manual:
http://www.nxp.com/acrobat_download/usermanuals/UM10204_3.pdf


-Andy



--- cx18-f763c5864f9a/linux/drivers/media/video/cx18/cx18-i2c.c.change1	2008-04-17 18:22:52.000000000 -0400
+++ cx18-f763c5864f9a/linux/drivers/media/video/cx18/cx18-i2c.c	2008-04-17 19:03:25.000000000 -0400
@@ -180,9 +180,17 @@ static void cx18_setscl(void *data, int 
 	u32 r = read_reg(addr);
 
 	if (state)
-		write_reg(r | SETSCL_BIT, addr);
+		r |= SETSCL_BIT;
 	else
-		write_reg(r & ~SETSCL_BIT, addr);
+		r &= ~SETSCL_BIT;
+
+	write_reg(r, addr);
+	r = read_reg(addr) & SETSCL_BIT; /* Read back to flush posted write */
+
+	if ((state && !r) || (!state && r))
+		CX18_DEBUG_WARN("setscl failed to write to CX18_REG_I2C_%d_WR "
+		                "register to drive bus %d SCL line to %d\n",
+		                bus_index+1, bus_index+1, state);
 }
 
 static void cx18_setsda(void *data, int state)
@@ -193,9 +201,17 @@ static void cx18_setsda(void *data, int 
 	u32 r = read_reg(addr);
 
 	if (state)
-		write_reg(r | SETSDL_BIT, addr);
+		r |= SETSDL_BIT;
 	else
-		write_reg(r & ~SETSDL_BIT, addr);
+		r &= ~SETSDL_BIT;
+
+	write_reg(r, addr);
+	r = read_reg(addr) & SETSDL_BIT; /* Read back to flush posted write */
+
+	if ((state && !r) || (!state && r))
+		CX18_DEBUG_WARN("setsda failed to write to CX18_REG_I2C_%d_WR "
+		                "register to drive bus %d SDA line to %d\n",
+		                bus_index+1, bus_index+1, state);
 }
 
 static int cx18_getscl(void *data)
@@ -402,9 +418,9 @@ int init_cx18_i2c(struct cx18 *cx)
 		write_reg(0x10001000, 0xc71024); /* Clock Enable */
 	}
 	/* courtesy of Steven Toth <[EMAIL PROTECTED]> */
-	write_reg(0x00C00000, 0xc7001C);
+	write_reg_sync(0x00C00000, 0xc7001C);
 	mdelay(10);
-	write_reg(0x00C000C0, 0xc7001C);
+	write_reg_sync(0x00C000C0, 0xc7001C);
 	mdelay(10);
 	write_reg(0x00C00000, 0xc7001C);
 
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel

Reply via email to