@@ -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;