[PATCH - OMAPZOOM] I2C: fix OMAP3430 errata 1.11

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux