fsl_i2c: Wait for STOP condition to propagate
authorJoakim Tjernlund <Joakim.Tjernlund@transmode.se>
Thu, 17 Sep 2009 09:07:15 +0000 (11:07 +0200)
committerHeiko Schocher <hs@denx.de>
Mon, 28 Sep 2009 05:35:52 +0000 (07:35 +0200)
After issuing a STOP one must wait until the STOP has completed
on the bus before doing something new to the controller.

Also add an extra read of SR as the manual mentions doing that
is a good idea.

Remove surplus write of CR just before a write, isn't required and
could potentially disturb the I2C bus.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
drivers/i2c/fsl_i2c.c

index 47bbf792c40702c68461829014ddfa7e03585f70..56f9680063a2dffe6e25b1e026c5131549176529 100644 (file)
@@ -223,7 +223,7 @@ i2c_init(int speed, int slaveadd)
 #endif
 }
 
-static __inline__ int
+static int
 i2c_wait4bus(void)
 {
        unsigned long long timeval = get_ticks();
@@ -248,6 +248,8 @@ i2c_wait(int write)
                csr = readb(&i2c_dev[i2c_bus_num]->sr);
                if (!(csr & I2C_SR_MIF))
                        continue;
+               /* Read again to allow register to stabilise */
+               csr = readb(&i2c_dev[i2c_bus_num]->sr);
 
                writeb(0x0, &i2c_dev[i2c_bus_num]->sr);
 
@@ -293,9 +295,6 @@ __i2c_write(u8 *data, int length)
 {
        int i;
 
-       writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
-              &i2c_dev[i2c_bus_num]->cr);
-
        for (i = 0; i < length; i++) {
                writeb(data[i], &i2c_dev[i2c_bus_num]->dr);
 
@@ -351,6 +350,9 @@ i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
            && i2c_write_addr(dev, I2C_READ_BIT, 1) != 0)
                i = __i2c_read(data, length);
 
+       if (length && i2c_wait4bus()) /* Wait until STOP */
+               debug("i2c_read: wait4bus timed out\n");
+
        writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr);
 
        if (i == length)
@@ -372,6 +374,8 @@ i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
        }
 
        writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr);
+       if (i2c_wait4bus()) /* Wait until STOP */
+               debug("i2c_write: wait4bus timed out\n");
 
        if (i == length)
            return 0;