From: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@xxxxxx> Following patch taken over the omapzoom.org tree fixes OMAP 3430 errata 1.11 for I2C: if the I2C module is configured as slave, in autoidle mode (I2C_SYSC.AUTOIDLE=1) and the ARDY (I2C.I2C_STAT[2]) condition and the START condition are detected in the module at the same time, internal clock gating will be wrongly applied. This will cause the I2C to NACK (I2C.I2C_STAT[1])the transfer for which the START (I2C.I2C_STAT[6]) condition was received. Next transfers will be ACKed as expected. Fix disables AUTO_IDLE from the start of a transaction, in slave mode, till the end of it. Signed-off-by: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@xxxxxx> Index: 34+_master/drivers/i2c/busses/i2c-omap.c =================================================================== --- 34+_master.orig/drivers/i2c/busses/i2c-omap.c 2008-09-29 18:18:35.000000000 +0530 +++ 34+_master/drivers/i2c/busses/i2c-omap.c 2008-10-01 13:12:29.299298673 +0530 @@ -544,6 +544,16 @@ omap_i2c_slave_xfer_msg(struct i2c_adapt if (!(msg->flags & I2C_M_RD)) dev->slave_tx = 1; + /* As per OMAP3430 silicon errata 1.11, I2C in slave mode + * with AUTO_IDLE enabled can lead to race conditions. So disabling + * AUTO_IDLE for transactions in slave mode. + */ + if (cpu_is_omap3430()) { + w = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG); + w &= ~1; + omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, w); + } + dev->cmd_err = 0; w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); w &= ~OMAP_I2C_CON_MST; @@ -597,6 +607,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct omap_i2c_dev *dev = i2c_get_adapdata(adap); int i; int r; + u16 val; omap_i2c_enable_clocks(dev); @@ -632,6 +643,22 @@ omap_i2c_xfer(struct i2c_adapter *adap, #endif out: disable_irq(dev->irq); + + /* Switching to master mode */ + val = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); + val |= OMAP_I2C_CON_MST; + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, val); + + /* As per OMAP3430 silicon errata 1.11, I2C in slave mode + * with AUTO_IDLE enabled can lead to race conditions. The AUTO_IDLE + * disabled at the beginning of a slave transaction is enabled back. + */ + if (cpu_is_omap3430()) { + val = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG); + val |= 1; + omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, val); + } + omap_i2c_disable_clocks(dev); /* Default master mode */ dev->mode = OMAP_I2C_MASTER_MODE; -- With Regards, Jagadeesh Bhaskar P ---------------------------- Some men see things as they are and say why - I dream things that never were and say why not. - George Bernard Shaw ------------------- -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html