Commit b97cd6814ec08be56225975a050ee486bfa7c13a

Authored by Dirk Eibach
Committed by Heiko Schocher
1 parent 7e78f7ad7f

ppc4xx: Handle i2c stuck on combined xfer

ppc4xx i2c master gets stuck on errors while repeated start is
active. Can be easily reproduced by "i2c md" on an unpopulated
i2c address. There is not stop condition given, scl remains
pulled low.
The only way out seems to be doing a stop manually and then a
soft reset.

Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc>
Reviewed-by: Stefan Roese <sr@denx.de>

Showing 2 changed files with 23 additions and 0 deletions Side-by-side Diff

arch/powerpc/include/asm/ppc4xx-i2c.h
... ... @@ -72,6 +72,8 @@
72 72 #define IIC_EXTSTS_XFRA 0x01
73 73 #define IIC_EXTSTS_ICT 0x02
74 74 #define IIC_EXTSTS_LA 0x04
  75 +#define IIC_EXTSTS_BCS_MASK 0x70
  76 +#define IIC_EXTSTS_BCS_FREE 0x40
75 77  
76 78 /* XTCNTLSS Register Bit definition */
77 79 #define IIC_XTCNTLSS_SRST 0x01
drivers/i2c/ppc4xx_i2c.c
... ... @@ -289,6 +289,27 @@
289 289 /* Transfer aborted? */
290 290 if (status & IIC_EXTSTS_XFRA)
291 291 result = IIC_NOK_XFRA;
  292 + /* Is bus free?
  293 + * If error happened during combined xfer
  294 + * IIC interface is usually stuck in some strange
  295 + * state without a valid stop condition.
  296 + * Brute, but working: generate stop, then soft reset.
  297 + */
  298 + if ((status & IIC_EXTSTS_BCS_MASK)
  299 + != IIC_EXTSTS_BCS_FREE){
  300 + u8 mdcntl = in_8(&i2c->mdcntl);
  301 +
  302 + /* Generate valid stop condition */
  303 + out_8(&i2c->xtcntlss, IIC_XTCNTLSS_SRST);
  304 + out_8(&i2c->directcntl, IIC_DIRCNTL_SCC);
  305 + udelay(10);
  306 + out_8(&i2c->directcntl,
  307 + IIC_DIRCNTL_SCC | IIC_DIRCNTL_SDAC);
  308 + out_8(&i2c->xtcntlss, 0);
  309 +
  310 + ppc4xx_i2c_init(adap, (mdcntl & IIC_MDCNTL_FSM)
  311 + ? 400000 : 100000, 0);
  312 + }
292 313 } else if ( status & IIC_STS_PT) {
293 314 result = IIC_NOK_TOUT;
294 315 }