I tried the following patch based on the description of the steps you took to recover the bus. Is there anything you can add? I still get lots of 'controller timed out' errors. Best Regards, Ben Gardiner Nanometrics Inc. http://www.nanometrics.ca --- 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; -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html