[PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg
Joakim Tjernlund
joakim.tjernlund at transmode.se
Fri May 15 21:05:56 EST 2009
Esben Haabendal <esbenhaabendal at gmail.com> wrote on 15/05/2009 12:18:39:
>
> I have now spent a few hours trying a lot of different paths to fix
> this approach, but I simply cannot find a way to get i2c read to work
> without a trailing STOP condition with this controller.
I found a bug which lets me remove the "fix" and seems related to your
problem. Updated patch last in mail
>
> Is there a problem in applying my patch, as it should be "clean"
> improvement over the current implementation, which uses STOP
> condition, but does not work.
>
> Until Isomeone finds a way to get it to work without STOP, we will
> have a working driver, which I assume is what we want.
Your patch appears OK too. I just wanted to see if a better fix was
possible. Your patch is less risky and it is the safe bet so soon before
release.
Jocke
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 6c1cddd..04eff40 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -189,9 +189,6 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
unsigned timeout = i2c->adap.timeout;
u32 flags = restart ? CCR_RSTA : 0;
- /* Start with MEN */
- if (!restart)
- writeccr(i2c, CCR_MEN);
/* Start as master */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target byte */
@@ -214,15 +211,12 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
}
static int mpc_read(struct mpc_i2c *i2c, int target,
- u8 * data, int length, int restart)
+ u8 * data, int length, int restart, int last)
{
unsigned timeout = i2c->adap.timeout;
int i, result;
u32 flags = restart ? CCR_RSTA : 0;
- /* Start with MEN */
- if (!restart)
- writeccr(i2c, CCR_MEN);
/* Switch to read - restart */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target address byte - this time with the read flag set */
@@ -241,18 +235,18 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
readb(i2c->base + MPC_I2C_DR);
}
- for (i = 0; i < length; i++) {
+ for (i = length; i ; --i) {
result = i2c_wait(i2c, timeout, 0);
if (result < 0)
return result;
/* Generate txack on next to last byte */
- if (i == length - 2)
+ if (i == 2)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
- /* Generate stop on last byte */
- if (i == length - 1)
- writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
- data[i] = readb(i2c->base + MPC_I2C_DR);
+ /* Generate stop on last byte, iff last transaction */
+ if (i == 1 && last)
+ writeccr(i2c, CCR_MIEN | CCR_MEN);
+ data[length-i] = readb(i2c->base + MPC_I2C_DR);
}
return length;
@@ -294,7 +288,7 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
tm_i2c_select_mux(pmsg->addr);
if (pmsg->flags & I2C_M_RD)
ret =
- mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+ mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i, i == num-1);
else
ret =
mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
More information about the Linuxppc-dev
mailing list