diff mbox

Message ID 1300223318-31450-1-git-send-email-bengardiner@nanometrics.ca (mailing list archive)
State Not Applicable
Headers show

Commit Message

Ben Gardiner March 15, 2011, 9:08 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 5795c83..52e5e60 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -89,6 +89,7 @@ 
 #define DAVINCI_I2C_MDR_XA	BIT(8)
 #define DAVINCI_I2C_MDR_RM	BIT(7)
 #define DAVINCI_I2C_MDR_IRS	BIT(5)
+#define DAVINCI_I2C_MDR_FDF	BIT(3)
 
 #define DAVINCI_I2C_IMR_AAS	BIT(6)
 #define DAVINCI_I2C_IMR_SCD	BIT(5)
@@ -149,6 +150,36 @@  static void generic_i2c_clock_pulse(unsigned int scl_pin)
 	}
 }
 
+static void alternate_i2c_clock_pulse(struct davinci_i2c_dev *dev)
+{
+	u32 flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
+	/* free data format mode */
+	flag |= DAVINCI_I2C_MDR_FDF;
+	/* receive byte */
+	flag &= ~DAVINCI_I2C_MDR_TRX;
+	/* repeat */
+	flag |= DAVINCI_I2C_MDR_RM;
+
+	/*
+	 * Write mode register first as needed for correct behaviour
+	 * on OMAP-L138, but don't set STT yet to avoid a race with XRDY
+	 * occuring before we have loaded DXR
+	 */
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
+	/* Disable receive and transmit interrupts */
+	flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
+	flag &= ~DAVINCI_I2C_IMR_RRDY;
+	flag &= ~DAVINCI_I2C_IMR_XRDY;
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, flag);
+
+	/* Set STT to begin transmit now DXR is loaded */
+	flag |= DAVINCI_I2C_MDR_STT;
+	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
+	udelay(40*9);
+}
+
 /* This routine does i2c bus recovery as specified in the
  * i2c protocol Rev. 03 section 3.16 titled "Bus clear"
  */
@@ -163,8 +194,10 @@  static void i2c_recover_bus(struct davinci_i2c_dev *dev)
 	flag |=  DAVINCI_I2C_MDR_NACK;
 	/* write the data into mode register */
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-	if (pdata)
+	if (pdata->scl_pin)
 		generic_i2c_clock_pulse(pdata->scl_pin);
+	else
+		alternate_i2c_clock_pulse(dev);
 	/* Send STOP */
 	flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
 	flag |= DAVINCI_I2C_MDR_STP;