diff options
author | Sonasath, Moiz <m-sonasath@ti.com> | 2009-07-21 10:15:12 -0500 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2009-07-30 01:03:24 +0100 |
commit | cd086d3aa6f7f7bf4d4e1f9fa09af0f0b6bb99ec (patch) | |
tree | ca0452e20152aaab9ef936dd624a0d51ddfee763 | |
parent | 04c688dd7a65935568b44629bfaa122eddf76e94 (diff) |
i2c-omap: OMAP3430 Silicon Errata 1.153
When an XRDY/XDR is hit, wait for XUDF before writing data to DATA_REG.
Otherwise some data bytes can be lost while transferring them from the
memory to the I2C interface.
Do a Busy-wait for XUDF, before writing data to DATA_REG. While waiting
if there is NACK | AL, set the appropriate error flags, ack the pending
interrupts and return from the ISR.
Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
Signed-off-by: Vikram pandita <vikram.pandita@ti.com>
[ben-linux@fluff.org: fixed mail format and added i2c-omap to subject]
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 5c508ccf4384..d258b02aef44 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -672,9 +672,10 @@ omap_i2c_isr(int this_irq, void *dev_id) break; } + err = 0; +complete: omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); - err = 0; if (stat & OMAP_I2C_STAT_NACK) { err |= OMAP_I2C_STAT_NACK; omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, @@ -764,6 +765,27 @@ omap_i2c_isr(int this_irq, void *dev_id) "data to send\n"); break; } + + /* + * OMAP3430 Errata 1.153: When an XRDY/XDR + * is hit, wait for XUDF before writing data + * to DATA_REG. Otherwise some data bytes can + * be lost while transferring them from the + * memory to the I2C interface. + */ + + if (cpu_is_omap34xx()) { + while (!(stat & OMAP_I2C_STAT_XUDF)) { + if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { + omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); + err |= OMAP_I2C_STAT_XUDF; + goto complete; + } + cpu_relax(); + stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); + } + } + omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); } omap_i2c_ack_stat(dev, |