* [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg @ 2009-05-14 8:10 Esben Haabendal 2009-05-14 8:34 ` Wolfram Sang 0 siblings, 1 reply; 10+ messages in thread From: Esben Haabendal @ 2009-05-14 8:10 UTC (permalink / raw) To: linux-i2c; +Cc: linuxppc-dev This fixes MAL (arbitration lost) bug caused by illegal use of RSTA (repeated START) after STOP condition generated after last byte of reads. Signed-off-by: Esben Haabendal <eha@doredevelopment.dk> --- drivers/i2c/busses/i2c-mpc.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 4af5c09..9fe05d9 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -456,17 +456,22 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) } for (i = 0; ret >= 0 && i < num; i++) { + int restart = i; pmsg = &msgs[i]; dev_dbg(i2c->dev, "Doing %s %d bytes to 0x%02x - %d of %d messages\n", pmsg->flags & I2C_M_RD ? "read" : "write", pmsg->len, pmsg->addr, i + 1, num); + if (i > 0 && ((pmsg-1)->flags & I2C_M_RD)) + restart = 0; 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, + restart); else ret = - mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); + mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, + restart); } mpc_i2c_stop(i2c); return (ret < 0) ? ret : num; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-14 8:10 [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg Esben Haabendal @ 2009-05-14 8:34 ` Wolfram Sang 2009-05-14 8:48 ` Esben Haabendal 0 siblings, 1 reply; 10+ messages in thread From: Wolfram Sang @ 2009-05-14 8:34 UTC (permalink / raw) To: Esben Haabendal; +Cc: linuxppc-dev, linux-i2c [-- Attachment #1: Type: text/plain, Size: 2050 bytes --] On Thu, May 14, 2009 at 10:10:03AM +0200, Esben Haabendal wrote: > This fixes MAL (arbitration lost) bug caused by illegal use of > RSTA (repeated START) after STOP condition generated after last byte > of reads. > Could you elaborate a bit, please? Like an example when the original bug occured (so I could reproduce easily) and how this patch actually solves the problem. > Signed-off-by: Esben Haabendal <eha@doredevelopment.dk> > --- > drivers/i2c/busses/i2c-mpc.c | 9 +++++++-- > 1 files changed, 7 insertions(+), 2 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c > index 4af5c09..9fe05d9 100644 > --- a/drivers/i2c/busses/i2c-mpc.c > +++ b/drivers/i2c/busses/i2c-mpc.c > @@ -456,17 +456,22 @@ static int mpc_xfer(struct i2c_adapter *adap, > struct i2c_msg *msgs, int num) > } > > for (i = 0; ret >= 0 && i < num; i++) { > + int restart = i; > pmsg = &msgs[i]; > dev_dbg(i2c->dev, > "Doing %s %d bytes to 0x%02x - %d of %d messages\n", > pmsg->flags & I2C_M_RD ? "read" : "write", > pmsg->len, pmsg->addr, i + 1, num); > + if (i > 0 && ((pmsg-1)->flags & I2C_M_RD)) CodingStyle: Spaces around '-' > + restart = 0; > 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, > + restart); > else > ret = > - mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); > + mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, > + restart); > } > mpc_i2c_stop(i2c); > return (ret < 0) ? ret : num; > -- > 1.6.0.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-i2c" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-14 8:34 ` Wolfram Sang @ 2009-05-14 8:48 ` Esben Haabendal 2009-05-14 9:58 ` Joakim Tjernlund 0 siblings, 1 reply; 10+ messages in thread From: Esben Haabendal @ 2009-05-14 8:48 UTC (permalink / raw) To: Wolfram Sang; +Cc: linuxppc-dev, linux-i2c Wolfram Sang wrote: > On Thu, May 14, 2009 at 10:10:03AM +0200, Esben Haabendal wrote: > >> This fixes MAL (arbitration lost) bug caused by illegal use of >> RSTA (repeated START) after STOP condition generated after last byte >> of reads. >> >> > > Could you elaborate a bit, please? Like an example when the original bug > occured (so I could reproduce easily) and how this patch actually solves > the problem. > Sure. I used the following code to initialize a CS4265 chip: (simplified here for the example) static int i2c_init_chip(void) { int err=0; char write_dac_control_1[] = { 0x03, chip->regs.dac_control_1 }; char seek_chip_id[] = { 0x01 }; char write_power_control[] = { 0x02, chip->regs.power_control }; struct i2c_msg cs4265_init_cmds[] = { { chip->i2c_addr, 0, 2, write_dac_control_1 }, { chip->i2c_addr, 0, 1, seek_chip_id }, { chip->i2c_addr, I2C_M_RD, 1, ®s.chip_id }, { chip->i2c_addr, 0, 2, write_power_control }, }; err = i2c_transfer(i2c, cs4265_init_cmds, sizeof(cs4265_init_cmds)/sizeof(*cs4265_init_cmds)); if (err < 0) { printk(KERN_ERR "i2c_transfer failed: %d\n", err); return err; } return 0; } I have added some additional debug output and traces something like this: [ 36.114297] writeccr 80 [MEN] [ 36.114324] mpc_xfer: 2 bytes to 4f:W - 1 of 5 messages [ 36.120176] next 1 bytes to 4f:W [ 36.124159] mpc_write addr=4f len=2 [ 36.128044] writeccr 80 [MEN] [ 36.128062] writeccr f0 [MEN MIEN MSTA MTX] -> START [ 36.128219] I2C: SR=a2 [ 36.131528] I2C: SR=a6 [ 36.134406] I2C: SR=a2 [ 36.137165] mpc_xfer: 1 bytes to 4f:W - 2 of 5 messages [ 36.142802] next 1 bytes to 4f:R [ 36.146699] mpc_write addr=4f len=1 [ 36.150583] writeccr f4 [MEN MIEN MSTA MTX RSTA] -> repeated START [ 36.150758] I2C: SR=a2 [ 36.153851] I2C: SR=a6 [ 36.156236] mpc_xfer: 1 bytes to 4f:R - 3 of 5 messages [ 36.162081] next 2 bytes to 4f:W [ 36.166062] mpc_read addr=4f len=1 [ 36.169858] writeccr f4 [MEN MIEN MSTA MTX RSTA] -> repeated START [ 36.170031] I2C: SR=a6 [ 36.172993] writeccr e8 [MEN MIEN MSTA TXAK] -> receive & no ACK [ 36.173143] I2C: SR=a7 [ 36.175511] writeccr c8 [MEN MIEN TXAK] -> STOP [ 36.175529] mpc_xfer: 2 bytes to 4f:W - 4 of 5 messages [ 36.181804] next 2 bytes to 4f:W [ 36.185788] mpc_write addr=4f len=2 [ 36.189672] writeccr f4 [MEN MIEN MSTA MTX RSTA] -> repeated START [ 36.189704] I2C: SR=b7 [ 36.192072] I2C: MAL [ 36.195075] i2c_wait(address) error: -5 [ 36.199311] writeccr 80 The problem is that after the STOP condition, the following i2c_msg will be attempted with a repeated START, which according to specification will cause a MAL, which also happens. My MPC8360ERM reads: "Attempting a repeated START at the wrong time (or if the bus is owned by another master), results in loss of arbitration." Which I know read as it that we must own the I2C bus when using RSTA. > > >> Signed-off-by: Esben Haabendal <eha@doredevelopment.dk> >> --- >> drivers/i2c/busses/i2c-mpc.c | 9 +++++++-- >> 1 files changed, 7 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c >> index 4af5c09..9fe05d9 100644 >> --- a/drivers/i2c/busses/i2c-mpc.c >> +++ b/drivers/i2c/busses/i2c-mpc.c >> @@ -456,17 +456,22 @@ static int mpc_xfer(struct i2c_adapter *adap, >> struct i2c_msg *msgs, int num) >> } >> >> for (i = 0; ret >= 0 && i < num; i++) { >> + int restart = i; >> pmsg = &msgs[i]; >> dev_dbg(i2c->dev, >> "Doing %s %d bytes to 0x%02x - %d of %d messages\n", >> pmsg->flags & I2C_M_RD ? "read" : "write", >> pmsg->len, pmsg->addr, i + 1, num); >> + if (i > 0 && ((pmsg-1)->flags & I2C_M_RD)) >> > > CodingStyle: Spaces around '-' > Ok. > >> + restart = 0; >> 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, >> + restart); >> else >> ret = >> - mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); >> + mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, >> + restart); >> } >> mpc_i2c_stop(i2c); >> return (ret < 0) ? ret : num; >> -- >> 1.6.0.4 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-14 8:48 ` Esben Haabendal @ 2009-05-14 9:58 ` Joakim Tjernlund [not found] ` <d2b9ea600905140317u7a4b9a70s574568d79a1ce7cc@mail.gmail.com> 0 siblings, 1 reply; 10+ messages in thread From: Joakim Tjernlund @ 2009-05-14 9:58 UTC (permalink / raw) To: Esben Haabendal; +Cc: linuxppc-dev, linux-i2c > > Wolfram Sang wrote: > > On Thu, May 14, 2009 at 10:10:03AM +0200, Esben Haabendal wrote: > > > >> This fixes MAL (arbitration lost) bug caused by illegal use of > >> RSTA (repeated START) after STOP condition generated after last byte > >> of reads. > >> > >> > > > > Could you elaborate a bit, please? Like an example when the original bug > > occured (so I could reproduce easily) and how this patch actually solves > > the problem. > > > Sure. I used the following code to initialize a CS4265 chip: > (simplified here for the example) > > static int > i2c_init_chip(void) > { > int err=0; > char write_dac_control_1[] = { 0x03, chip->regs.dac_control_1 }; > char seek_chip_id[] = { 0x01 }; > char write_power_control[] = { 0x02, chip->regs.power_control }; > struct i2c_msg cs4265_init_cmds[] = { > { chip->i2c_addr, 0, 2, write_dac_control_1 }, > { chip->i2c_addr, 0, 1, seek_chip_id }, > { chip->i2c_addr, I2C_M_RD, 1, ®s.chip_id }, > { chip->i2c_addr, 0, 2, write_power_control }, > }; > > err = i2c_transfer(i2c, cs4265_init_cmds, > sizeof(cs4265_init_cmds)/sizeof(*cs4265_init_cmds)); > if (err < 0) { > printk(KERN_ERR "i2c_transfer failed: %d\n", err); > return err; > } > > return 0; > } > > I have added some additional debug output and traces something like this: > > [ 36.114297] writeccr 80 [MEN] > [ 36.114324] mpc_xfer: 2 bytes to 4f:W - 1 of 5 messages > [ 36.120176] next 1 bytes to 4f:W > [ 36.124159] mpc_write addr=4f len=2 > [ 36.128044] writeccr 80 [MEN] > [ 36.128062] writeccr f0 [MEN MIEN MSTA MTX] -> START > [ 36.128219] I2C: SR=a2 > [ 36.131528] I2C: SR=a6 > [ 36.134406] I2C: SR=a2 > > [ 36.137165] mpc_xfer: 1 bytes to 4f:W - 2 of 5 messages > [ 36.142802] next 1 bytes to 4f:R > [ 36.146699] mpc_write addr=4f len=1 > [ 36.150583] writeccr f4 [MEN MIEN MSTA MTX RSTA] -> repeated START > [ 36.150758] I2C: SR=a2 > [ 36.153851] I2C: SR=a6 > > [ 36.156236] mpc_xfer: 1 bytes to 4f:R - 3 of 5 messages > [ 36.162081] next 2 bytes to 4f:W > [ 36.166062] mpc_read addr=4f len=1 > [ 36.169858] writeccr f4 [MEN MIEN MSTA MTX RSTA] -> repeated START > [ 36.170031] I2C: SR=a6 > [ 36.172993] writeccr e8 [MEN MIEN MSTA TXAK] -> receive & no ACK > [ 36.173143] I2C: SR=a7 > [ 36.175511] writeccr c8 [MEN MIEN TXAK] -> STOP > > [ 36.175529] mpc_xfer: 2 bytes to 4f:W - 4 of 5 messages > [ 36.181804] next 2 bytes to 4f:W > [ 36.185788] mpc_write addr=4f len=2 > [ 36.189672] writeccr f4 [MEN MIEN MSTA MTX RSTA] -> repeated START > [ 36.189704] I2C: SR=b7 > [ 36.192072] I2C: MAL > [ 36.195075] i2c_wait(address) error: -5 > [ 36.199311] writeccr 80 > > The problem is that after the STOP condition, the following i2c_msg will be > attempted with a repeated START, which according to specification will > cause a MAL, which also happens. My MPC8360ERM reads: > > "Attempting a repeated START at the wrong time (or if the bus is owned > by another master), results in loss of arbitration." > > Which I know read as it that we must own the I2C bus when using RSTA. I agree with the theory, but isn't the problem here that STOP is performed in the middle of this transaction? Remove the STOP and RSTA will work I think. Jocke ^ permalink raw reply [flat|nested] 10+ messages in thread
[parent not found: <d2b9ea600905140317u7a4b9a70s574568d79a1ce7cc@mail.gmail.com>]
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg [not found] ` <d2b9ea600905140317u7a4b9a70s574568d79a1ce7cc@mail.gmail.com> @ 2009-05-14 16:52 ` Joakim Tjernlund 2009-05-15 10:18 ` Esben Haabendal 0 siblings, 1 reply; 10+ messages in thread From: Joakim Tjernlund @ 2009-05-14 16:52 UTC (permalink / raw) To: Esben Haabendal; +Cc: linuxppc-dev Esben Haabendal <esbenhaabendal@gmail.com> wrote on 14/05/2009 12:17:48= : > On Thu, May 14, 2009 at 11:58 AM, Joakim Tjernlund > <joakim.tjernlund@transmode.se> wrote: > >> > >> The problem is that after the STOP condition, the following i2c_ms= g will be > >> attempted with a repeated START, which according to specification = will > >> cause a MAL, which also happens. =A0My MPC8360ERM reads: > >> > >> "Attempting a repeated START at the wrong time (or if the bus is o= wned > >> by another master), results in loss of arbitration." > >> > >> Which I know read as it that we must own the I2C bus when using RS= TA. > > > > I agree with the theory, but isn't the problem here that STOP is pe= rformed in > > the middle of this transaction? > > Remove the STOP and RSTA will work I think. > > That was also my first idea. > > But at least for my CS4265, reads does not work without a STOP follow= ing the > last byte. I guess I am not the first to experience this, as indicate= d > by the current > i2c-mpc.c implementation. > As far as I can understand the I2C specification, a STOP should not b= e required > after reads, but I am not sure. > > The cost of the additional STOP is really small. The only issue I ca= n see, > is that with the STOP in the midle of an i2c_transfer, the I2C bus is= released. > This naturally also happens with the current implementation, so I bel= ieve > that this patch is a clean improvement. > > Anyways, if someone can figure out how to achive this without STOP, > I will be happy (re)test with my hardware setup here. >From just playing a little, I think the below patch will get you far. However, I had to change this too to make it stable: static void mpc_i2c_start(struct mpc_i2c *i2c) { /* Clear arbitration */ writeb(0, i2c->base + MPC_I2C_SR); #if 1 // fix, not sure why writeccr(i2c, 0); udelay(5); #endif /* Start with MEN */ writeccr(i2c, CCR_MEN); } PS. I added back the linuxppc list, let it stay. diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.= c index 6c1cddd..d7edcd2 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 targe= t, unsigned timeout =3D i2c->adap.timeout; u32 flags =3D 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 */ @@ -220,9 +217,6 @@ static int mpc_read(struct mpc_i2c *i2c, int target= , int i, result; u32 flags =3D 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,15 @@ static int mpc_read(struct mpc_i2c *i2c, int targ= et, readb(i2c->base + MPC_I2C_DR); } - for (i =3D 0; i < length; i++) { + for (i =3D length; i ; --i) { result =3D i2c_wait(i2c, timeout, 0); if (result < 0) return result; - /* Generate txack on next to last byte */ - if (i =3D=3D length - 2) + /* Generate txack on next to last byte(s) */ + if (i <=3D 2) writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); - /* Generate stop on last byte */ - if (i =3D=3D length - 1) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK); - data[i] =3D readb(i2c->base + MPC_I2C_DR); + data[length-i] =3D readb(i2c->base + MPC_I2C_DR); } return length; = ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-14 16:52 ` Joakim Tjernlund @ 2009-05-15 10:18 ` Esben Haabendal 2009-05-15 11:05 ` Joakim Tjernlund 0 siblings, 1 reply; 10+ messages in thread From: Esben Haabendal @ 2009-05-15 10:18 UTC (permalink / raw) To: Joakim Tjernlund; +Cc: linuxppc-dev, linux-i2c Hi Your patch (and the small addition to mpc_i2c_start) does not work for me. [ 35.765803] mpc_xfer() [ 35.785480] writeccr 0 [ 35.785505] writeccr 80 [ 35.785523] mpc_xfer: 1 bytes to 2c:W - 1 of 2 messages [ 35.798817] mpc_write addr=3D2c len=3D1 restart=3D0 [ 35.815327] writeccr f0 [ 35.815503] I2C: SR=3Da2 [ 35.818675] I2C: SR=3Da6 [ 35.821450] mpc_xfer: 1 bytes to 2c:R - 2 of 2 messages [ 35.827119] mpc_read addr=3D2c len=3D1 restart=3D1 [ 35.837463] writeccr f4 [ 35.837641] I2C: SR=3Da6 [ 35.840011] writeccr e8 [ 35.840133] I2C: SR=3Da3 [ 35.843596] writeccr 80 [ 35.843632] mpc_xfer() [ 35.855068] writeccr 0 [ 35.855093] writeccr 80 [ 35.855111] mpc_xfer: 1 bytes to 2c:W - 1 of 2 messages [ 35.865346] mpc_write addr=3D2c len=3D1 restart=3D0 [ 35.870109] writeccr f0 [ 35.870272] I2C: SR=3Da2 [ 35.873372] I2C: SR=3Da6 [ 35.875757] mpc_xfer: 1 bytes to 2c:R - 2 of 2 messages [ 35.881606] mpc_read addr=3D2c len=3D1 restart=3D1 [ 35.886290] writeccr f4 [ 35.886463] I2C: SR=3Da6 [ 35.889425] writeccr e8 [ 35.889575] I2C: SR=3Da7 [ 35.891944] writeccr 80 [ 35.961177] mpc_xfer() [ 35.972517] writeccr 0 [ 35.972541] writeccr 80 [ 35.972559] mpc_xfer: 1 bytes to 4e:W - 1 of 20 messages [ 35.982628] mpc_write addr=3D4e len=3D1 restart=3D0 [ 35.987389] writeccr f0 [ 35.987424] I2C: SR=3Db3 [ 35.990386] I2C: MAL [ 35.992971] i2c_wait(address) error: -5 [ 35.997215] writeccr 80 [ 35.997241] Error: i2c_transfer failed: -5 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. 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. Best regards, Esben Haabendal --=20 Esben Haabendal, Senior Software Consultant Dor=E9Development ApS, Ved Stranden 1, 9560 Hadsund, DK-Denmark Phone: +45 51 92 53 93, E-mail: eha@doredevelopment.dk WWW: http://www.doredevelopment.dk ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-15 10:18 ` Esben Haabendal @ 2009-05-15 11:05 ` Joakim Tjernlund 2009-05-15 12:52 ` Esben Haabendal 0 siblings, 1 reply; 10+ messages in thread From: Joakim Tjernlund @ 2009-05-15 11:05 UTC (permalink / raw) To: Esben Haabendal; +Cc: linuxppc-dev, linux-i2c Esben Haabendal <esbenhaabendal@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); ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-15 11:05 ` Joakim Tjernlund @ 2009-05-15 12:52 ` Esben Haabendal 2009-05-15 14:16 ` Joakim Tjernlund 2009-05-18 11:04 ` Wolfram Sang 0 siblings, 2 replies; 10+ messages in thread From: Esben Haabendal @ 2009-05-15 12:52 UTC (permalink / raw) To: Joakim Tjernlund; +Cc: linuxppc-dev, linux-i2c Your new patch also does not work. Have you tested it? I already tried something very much what you sent here, I believe the only difference was that I named the "last" variable "stop". I also tried several other aproaches, and none of them worked. I would appreciate not to have to test all of them seperately again through this mailing list ;-) Anyway, your patch also is in conflict with the MPC8360ERM. The spec specifies that a repeated start must follow an ACK, and not a "NO ACK". When doing a repeated start after a NO ACK, the slave does not ACK the address (I get an RXAK). When doing as specified, ACK'ing the last byte read and then doing a repeated START, i2c_wait() fails due to CSR_MCF bit missing. I thought it would be possible to find somewhere to do a dummy read to get around this, but failed to do so without breaking something else. Could we go forward with my initial patch, and then continue the work on this repeated START approach for future releases? /Esben ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-15 12:52 ` Esben Haabendal @ 2009-05-15 14:16 ` Joakim Tjernlund 2009-05-18 11:04 ` Wolfram Sang 1 sibling, 0 replies; 10+ messages in thread From: Joakim Tjernlund @ 2009-05-15 14:16 UTC (permalink / raw) To: Esben Haabendal; +Cc: linuxppc-dev, linux-i2c Esben Haabendal <esbenhaabendal@gmail.com> wrote on 15/05/2009 14:52:28: > > Your new patch also does not work. > > Have you tested it? sure, works fine. I haven't stressed it too much though. > > I already tried something very much what you sent here, I believe the > only difference was that I named the "last" variable "stop". I also > tried several other aproaches, and none of them worked. I would > appreciate not to have to test all of them seperately again through > this mailing list ;-) :), point taken. > > Anyway, your patch also is in conflict with the MPC8360ERM. The spec > specifies that a repeated start must follow an ACK, and not a "NO > ACK". Ouch, will have to check too, but later. > > When doing a repeated start after a NO ACK, the slave does not ACK the > address (I get an RXAK). When doing as specified, ACK'ing the last > byte read and then doing a repeated START, i2c_wait() fails due to > CSR_MCF bit missing. I thought it would be possible to find somewhere > to do a dummy read to get around this, but failed to do so without > breaking something else. > > Could we go forward with my initial patch, and then continue the work > on this repeated START approach for future releases? Yes, go ahead. Jocke ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg 2009-05-15 12:52 ` Esben Haabendal 2009-05-15 14:16 ` Joakim Tjernlund @ 2009-05-18 11:04 ` Wolfram Sang 1 sibling, 0 replies; 10+ messages in thread From: Wolfram Sang @ 2009-05-18 11:04 UTC (permalink / raw) To: Esben Haabendal; +Cc: linuxppc-dev, linux-i2c [-- Attachment #1: Type: text/plain, Size: 497 bytes --] > Could we go forward with my initial patch, and then continue the work > on this repeated START approach for future releases? Then could you please send another version of your patch with the CodingStyle issue removed and an updated description what this patch fixes and what still needs to be resolved? Regards, Wolfram -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-05-18 11:05 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-14 8:10 [PATCH] i2c-mpc: generate START condition after STOP caused by read i2c_msg Esben Haabendal
2009-05-14 8:34 ` Wolfram Sang
2009-05-14 8:48 ` Esben Haabendal
2009-05-14 9:58 ` Joakim Tjernlund
[not found] ` <d2b9ea600905140317u7a4b9a70s574568d79a1ce7cc@mail.gmail.com>
2009-05-14 16:52 ` Joakim Tjernlund
2009-05-15 10:18 ` Esben Haabendal
2009-05-15 11:05 ` Joakim Tjernlund
2009-05-15 12:52 ` Esben Haabendal
2009-05-15 14:16 ` Joakim Tjernlund
2009-05-18 11:04 ` Wolfram Sang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).