From 50f63ba95b36f7cfe0cf82fc1b464945d0e11b4a Mon Sep 17 00:00:00 2001 From: John Rigby Date: Thu, 22 Sep 2011 19:50:22 -0600 Subject: SAUCE: Revert "ARMV7: OMAP: Write more than 1 byte at a time in i2c_write" This causes current kernel to fault due to a bug in the omap i2c code. This can be un-reverted after once the kernel is fixed. This reverts commit 0607e2b97a907ed3bdf926227e5ad0603a6216ad. --- drivers/i2c/omap24xx_i2c.c | 136 ++++++++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 58 deletions(-) diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 4ae237aa8..7e35f6c11 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -217,6 +217,77 @@ read_exit: return i2c_error; } +static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) +{ + int i2c_error = 0; + u16 status; + + /* wait until bus not busy */ + wait_for_bb (); + + /* two bytes */ + writew (2, &i2c_base->cnt); + /* set slave address */ + writew (devaddr, &i2c_base->sa); + /* stop bit needed here */ + writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | + I2C_CON_STP, &i2c_base->con); + + while (1) { + status = wait_for_pin(); + if (status == 0 || status & I2C_STAT_NACK) { + i2c_error = 1; + goto write_exit; + } + if (status & I2C_STAT_XRDY) { +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ + defined(CONFIG_OMAP44XX) + /* send register offset */ + writeb(regoffset, &i2c_base->data); + writew(I2C_STAT_XRDY, &i2c_base->stat); + + while (1) { + status = wait_for_pin(); + if (status == 0 || status & I2C_STAT_NACK) { + i2c_error = 1; + goto write_exit; + } + if (status & I2C_STAT_XRDY) { + /* send data */ + writeb(value, &i2c_base->data); + writew(I2C_STAT_XRDY, &i2c_base->stat); + } + if (status & I2C_STAT_ARDY) { + writew(I2C_STAT_ARDY, &i2c_base->stat); + break; + } + } + break; +#else + /* send out two bytes */ + writew((value << 8) + regoffset, &i2c_base->data); + writew(I2C_STAT_XRDY, &i2c_base->stat); +#endif + } + if (status & I2C_STAT_ARDY) { + writew(I2C_STAT_ARDY, &i2c_base->stat); + break; + } + } + + wait_for_bb(); + + status = readw(&i2c_base->stat); + if (status & I2C_STAT_NACK) + i2c_error = 1; + +write_exit: + flush_fifo(); + writew (0xFFFF, &i2c_base->stat); + writew (0, &i2c_base->cnt); + return i2c_error; +} + static void flush_fifo(void) { u16 stat; @@ -302,77 +373,26 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) { int i; - u16 status; - int i2c_error = 0; if (alen > 1) { - printf("I2C write: addr len %d not supported\n", alen); + printf ("I2C read: addr len %d not supported\n", alen); return 1; } if (addr + len > 256) { - printf("I2C write: address 0x%x + 0x%x out of range\n", - addr, len); + printf ("I2C read: address out of range\n"); return 1; } - /* wait until bus not busy */ - wait_for_bb(); - - /* start address phase - will write regoffset + len bytes data */ - /* TODO consider case when !CONFIG_OMAP243X/34XX/44XX */ - writew(alen + len, &i2c_base->cnt); - /* set slave address */ - writew(chip, &i2c_base->sa); - /* stop bit needed here */ - writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | - I2C_CON_STP, &i2c_base->con); - - /* Send address byte */ - status = wait_for_pin(); - - if (status == 0 || status & I2C_STAT_NACK) { - i2c_error = 1; - printf("error waiting for i2c address ACK (status=0x%x)\n", - status); - goto write_exit; - } - - if (status & I2C_STAT_XRDY) { - writeb(addr & 0xFF, &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); - } else { - i2c_error = 1; - printf("i2c bus not ready for transmit (status=0x%x)\n", - status); - goto write_exit; - } - - /* address phase is over, now write data */ for (i = 0; i < len; i++) { - status = wait_for_pin(); - - if (status == 0 || status & I2C_STAT_NACK) { - i2c_error = 1; - printf("i2c error waiting for data ACK (status=0x%x)\n", - status); - goto write_exit; - } - - if (status & I2C_STAT_XRDY) { - writeb(buffer[i], &i2c_base->data); - writew(I2C_STAT_XRDY, &i2c_base->stat); - } else { - i2c_error = 1; - printf("i2c bus not ready for Tx (i=%d)\n", i); - goto write_exit; + if (i2c_write_byte (chip, addr + i, buffer[i])) { + printf ("I2C read: I/O error\n"); + i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + return 1; } } -write_exit: - flush_fifo(); - writew(0xFFFF, &i2c_base->stat); - return i2c_error; + return 0; } static void wait_for_bb(void) -- cgit v1.2.3