Skip to content
Snippets Groups Projects
Commit b97cd681 authored by Dirk Eibach's avatar Dirk Eibach Committed by Heiko Schocher
Browse files

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: default avatarDirk Eibach <dirk.eibach@gdsys.cc>
Reviewed-by: default avatarStefan Roese <sr@denx.de>
parent 7e78f7ad
No related branches found
No related tags found
No related merge requests found
...@@ -72,6 +72,8 @@ struct ppc4xx_i2c { ...@@ -72,6 +72,8 @@ struct ppc4xx_i2c {
#define IIC_EXTSTS_XFRA 0x01 #define IIC_EXTSTS_XFRA 0x01
#define IIC_EXTSTS_ICT 0x02 #define IIC_EXTSTS_ICT 0x02
#define IIC_EXTSTS_LA 0x04 #define IIC_EXTSTS_LA 0x04
#define IIC_EXTSTS_BCS_MASK 0x70
#define IIC_EXTSTS_BCS_FREE 0x40
/* XTCNTLSS Register Bit definition */ /* XTCNTLSS Register Bit definition */
#define IIC_XTCNTLSS_SRST 0x01 #define IIC_XTCNTLSS_SRST 0x01
......
...@@ -289,6 +289,27 @@ static int _i2c_transfer(struct i2c_adapter *adap, ...@@ -289,6 +289,27 @@ static int _i2c_transfer(struct i2c_adapter *adap,
/* Transfer aborted? */ /* Transfer aborted? */
if (status & IIC_EXTSTS_XFRA) if (status & IIC_EXTSTS_XFRA)
result = IIC_NOK_XFRA; result = IIC_NOK_XFRA;
/* Is bus free?
* If error happened during combined xfer
* IIC interface is usually stuck in some strange
* state without a valid stop condition.
* Brute, but working: generate stop, then soft reset.
*/
if ((status & IIC_EXTSTS_BCS_MASK)
!= IIC_EXTSTS_BCS_FREE){
u8 mdcntl = in_8(&i2c->mdcntl);
/* Generate valid stop condition */
out_8(&i2c->xtcntlss, IIC_XTCNTLSS_SRST);
out_8(&i2c->directcntl, IIC_DIRCNTL_SCC);
udelay(10);
out_8(&i2c->directcntl,
IIC_DIRCNTL_SCC | IIC_DIRCNTL_SDAC);
out_8(&i2c->xtcntlss, 0);
ppc4xx_i2c_init(adap, (mdcntl & IIC_MDCNTL_FSM)
? 400000 : 100000, 0);
}
} else if ( status & IIC_STS_PT) { } else if ( status & IIC_STS_PT) {
result = IIC_NOK_TOUT; result = IIC_NOK_TOUT;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment