|
@@ -158,8 +158,7 @@ static void ppc4xx_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
|
|
*
|
|
*
|
|
* Typical case is a Write of an addr followd by a Read. The
|
|
* Typical case is a Write of an addr followd by a Read. The
|
|
* IBM FAQ does not cover this. On the last byte of the write
|
|
* IBM FAQ does not cover this. On the last byte of the write
|
|
- * we don't set the creg CHT bit, and on the first bytes of the
|
|
|
|
- * read we set the RPST bit.
|
|
|
|
|
|
+ * we don't set the creg CHT bit but the RPST bit.
|
|
*
|
|
*
|
|
* It does not support address only transfers, there must be
|
|
* It does not support address only transfers, there must be
|
|
* a data part. If you want to write the address yourself, put
|
|
* a data part. If you want to write the address yourself, put
|
|
@@ -247,6 +246,10 @@ static int _i2c_transfer(struct i2c_adapter *adap,
|
|
if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt))
|
|
if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt))
|
|
creg |= IIC_CNTL_CHT;
|
|
creg |= IIC_CNTL_CHT;
|
|
|
|
|
|
|
|
+ /* last part of address, prepare for repeated start on read */
|
|
|
|
+ if (cmd_type && (ptr == addr) && ((tran + bc) == cnt))
|
|
|
|
+ creg |= IIC_CNTL_RPST;
|
|
|
|
+
|
|
if (reading) {
|
|
if (reading) {
|
|
creg |= IIC_CNTL_READ;
|
|
creg |= IIC_CNTL_READ;
|
|
} else {
|
|
} else {
|
|
@@ -286,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;
|
|
}
|
|
}
|
|
@@ -314,8 +338,6 @@ static int _i2c_transfer(struct i2c_adapter *adap,
|
|
cnt = data_len;
|
|
cnt = data_len;
|
|
tran = 0;
|
|
tran = 0;
|
|
reading = cmd_type;
|
|
reading = cmd_type;
|
|
- if (reading)
|
|
|
|
- creg = IIC_CNTL_RPST;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|