@@ -199,6 +199,7 @@ struct omap_i2c_dev {
u16 bufstate;
u16 syscstate;
u16 westate;
+ bool errata_i207;
};
const static u8 reg_map[] = {
@@ -498,6 +499,12 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+ dev->errata_i207 = false;
+
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ dev->errata_i207 = true;
+ }
+
/* Enable interrupts */
dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
@@ -695,6 +702,34 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
}
+static inline void i2c_omap_errata_i207(struct omap_i2c_dev *dev, u16 stat)
+{
+ /*
+ * I2C Errata(Errata Nos. OMAP2: 1.67, OMAP3: 1.8)
+ * Not applicable for OMAP4.
+ * Under certain rare conditions, RDR could be set again
+ * when the bus is busy, then ignore the interrupt and
+ * clear the interrupt.
+ */
+ if (stat & OMAP_I2C_STAT_RDR) {
+ /* Step 1: If RDR is set, clear it */
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
+
+ /* Step 2: */
+ if(!(omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG)
+ & OMAP_I2C_STAT_BB)) {
+
+ /* Step 3: */
+ if(omap_i2c_read_reg(dev,OMAP_I2C_STAT_REG)
+ & OMAP_I2C_STAT_RDR) {
+ omap_i2c_ack_stat(dev,OMAP_I2C_STAT_RDR);
+ dev_dbg(dev->dev,"RDR when the bus is busy.\n");
+ }
+
+ }
+ }
+}
+
/* rev1 devices are apparently only on some 15xx */
#ifdef CONFIG_ARCH_OMAP15XX
@@ -826,6 +861,10 @@ complete:
}
if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
u8 num_bytes = 1;
+
+ if (dev->errata_i207)
+ i2c_omap_errata_i207(dev, stat);
+
if (dev->fifo_size) {
if (stat & OMAP_I2C_STAT_RRDY)
num_bytes = dev->fifo_size;