aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Rigby <john.rigby@linaro.org>2011-09-22 19:50:22 -0600
committerJohn Rigby <john.rigby@linaro.org>2011-09-23 07:10:47 -0600
commit50f63ba95b36f7cfe0cf82fc1b464945d0e11b4a (patch)
tree1d5f4cb8a5436eada33f3053b96e89171ab13238
parent276276f63832218254049907b9f27002d0bf6109 (diff)
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.
-rw-r--r--drivers/i2c/omap24xx_i2c.c136
1 files 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)