[FE training-materials-updates] Add patch to fix I2C issue with U-Boot 2013.10

Thomas Petazzoni thomas.petazzoni at free-electrons.com
Wed Nov 27 15:55:23 CET 2013


Repository : git://git.free-electrons.com/training-materials.git

On branch  : master
Link       : http://git.free-electrons.com/training-materials/commit/?id=214721504a37b7e3ed978488f9776c3a139f4b65

>---------------------------------------------------------------

commit 214721504a37b7e3ed978488f9776c3a139f4b65
Author: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
Date:   Wed Nov 27 15:51:33 2013 +0100

    Add patch to fix I2C issue with U-Boot 2013.10
    
    Signed-off-by: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>


>---------------------------------------------------------------

214721504a37b7e3ed978488f9776c3a139f4b65
 ...OMAP-I2C-New-read-write-and-probe-functio.patch |  664 ++++++++++++++++++++
 1 file changed, 664 insertions(+)

diff --git a/lab-data/sysdev/bootloader/data/0001-Revert-ARM-OMAP-I2C-New-read-write-and-probe-functio.patch b/lab-data/sysdev/bootloader/data/0001-Revert-ARM-OMAP-I2C-New-read-write-and-probe-functio.patch
new file mode 100644
index 0000000..107ae78
--- /dev/null
+++ b/lab-data/sysdev/bootloader/data/0001-Revert-ARM-OMAP-I2C-New-read-write-and-probe-functio.patch
@@ -0,0 +1,664 @@
+From 9413ec0ce7afbc9eba7fe26ad8527d4231a65fbd Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
+Date: Wed, 27 Nov 2013 10:48:45 +0100
+Subject: [PATCH] Revert "ARM: OMAP: I2C: New read, write and probe functions"
+
+This reverts commit 960187ffa125b3938fec4b827bd9e8c04a204af8.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
+---
+ drivers/i2c/omap24xx_i2c.c | 490 ++++++++++++++++++---------------------------
+ 1 file changed, 191 insertions(+), 299 deletions(-)
+
+diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
+index ef38d71..54e9b15 100644
+--- a/drivers/i2c/omap24xx_i2c.c
++++ b/drivers/i2c/omap24xx_i2c.c
+@@ -18,20 +18,6 @@
+  *
+  * Adapted for OMAP2420 I2C, r-woodruff2 at ti.com
+  *
+- * Copyright (c) 2013 Lubomir Popov <lpopov at mm-sol.com>, MM Solutions
+- * New i2c_read, i2c_write and i2c_probe functions, tested on OMAP4
+- * (4430/60/70), OMAP5 (5430) and AM335X (3359); should work on older
+- * OMAPs and derivatives as well. The only anticipated exception would
+- * be the OMAP2420, which shall require driver modification.
+- * - Rewritten i2c_read to operate correctly with all types of chips
+- *   (old function could not read consistent data from some I2C slaves).
+- * - Optimized i2c_write.
+- * - New i2c_probe, performs write access vs read. The old probe could
+- *   hang the system under certain conditions (e.g. unconfigured pads).
+- * - The read/write/probe functions try to identify unconfigured bus.
+- * - Status functions now read irqstatus_raw as per TRM guidelines
+- *   (except for OMAP243X and OMAP34XX).
+- * - Driver now supports up to I2C5 (OMAP5).
+  */
+ 
+ #include <common.h>
+@@ -45,11 +31,8 @@ DECLARE_GLOBAL_DATA_PTR;
+ 
+ #define I2C_TIMEOUT	1000
+ 
+-/* Absolutely safe for status update at 100 kHz I2C: */
+-#define I2C_WAIT	200
+-
+ static int wait_for_bb(void);
+-static u16 wait_for_event(void);
++static u16 wait_for_pin(void);
+ static void flush_fifo(void);
+ 
+ /*
+@@ -154,14 +137,10 @@ void i2c_init(int speed, int slaveadd)
+ 	/* own address */
+ 	writew(slaveadd, &i2c_base->oa);
+ 	writew(I2C_CON_EN, &i2c_base->con);
+-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+-	/*
+-	 * Have to enable interrupts for OMAP2/3, these IPs don't have
+-	 * an 'irqstatus_raw' register and we shall have to poll 'stat'
+-	 */
++
++	/* have to enable intrrupts or OMAP i2c module doesn't work */
+ 	writew(I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
+-	       I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
+-#endif
++		I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
+ 	udelay(1000);
+ 	flush_fifo();
+ 	writew(0xFFFF, &i2c_base->stat);
+@@ -171,6 +150,88 @@ void i2c_init(int speed, int slaveadd)
+ 		bus_initialized[current_bus] = 1;
+ }
+ 
++static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value)
++{
++	int i2c_error = 0;
++	u16 status;
++	int i = 2 - alen;
++	u8 tmpbuf[2] = {(regoffset) >> 8, regoffset & 0xff};
++	u16 w;
++
++	/* wait until bus not busy */
++	if (wait_for_bb())
++		return 1;
++
++	/* one byte only */
++	writew(alen, &i2c_base->cnt);
++	/* set slave address */
++	writew(devaddr, &i2c_base->sa);
++	/* no stop bit needed here */
++	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT |
++	      I2C_CON_TRX, &i2c_base->con);
++
++	/* send register offset */
++	while (1) {
++		status = wait_for_pin();
++		if (status == 0 || status & I2C_STAT_NACK) {
++			i2c_error = 1;
++			goto read_exit;
++		}
++		if (status & I2C_STAT_XRDY) {
++			w = tmpbuf[i++];
++#if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
++	defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
++	defined(CONFIG_OMAP54XX))
++			w |= tmpbuf[i++] << 8;
++#endif
++			writew(w, &i2c_base->data);
++			writew(I2C_STAT_XRDY, &i2c_base->stat);
++		}
++		if (status & I2C_STAT_ARDY) {
++			writew(I2C_STAT_ARDY, &i2c_base->stat);
++			break;
++		}
++	}
++
++	/* set slave address */
++	writew(devaddr, &i2c_base->sa);
++	/* read one byte from slave */
++	writew(1, &i2c_base->cnt);
++	/* need stop bit here */
++	writew(I2C_CON_EN | I2C_CON_MST |
++		I2C_CON_STT | I2C_CON_STP,
++		&i2c_base->con);
++
++	/* receive data */
++	while (1) {
++		status = wait_for_pin();
++		if (status == 0 || status & I2C_STAT_NACK) {
++			i2c_error = 1;
++			goto read_exit;
++		}
++		if (status & I2C_STAT_RRDY) {
++#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
++	defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
++	defined(CONFIG_OMAP54XX)
++			*value = readb(&i2c_base->data);
++#else
++			*value = readw(&i2c_base->data);
++#endif
++			writew(I2C_STAT_RRDY, &i2c_base->stat);
++		}
++		if (status & I2C_STAT_ARDY) {
++			writew(I2C_STAT_ARDY, &i2c_base->stat);
++			break;
++		}
++	}
++
++read_exit:
++	flush_fifo();
++	writew(0xFFFF, &i2c_base->stat);
++	writew(0, &i2c_base->cnt);
++	return i2c_error;
++}
++
+ static void flush_fifo(void)
+ {	u16 stat;
+ 
+@@ -180,7 +241,13 @@ static void flush_fifo(void)
+ 	while (1) {
+ 		stat = readw(&i2c_base->stat);
+ 		if (stat == I2C_STAT_RRDY) {
++#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
++	defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
++	defined(CONFIG_OMAP54XX)
+ 			readb(&i2c_base->data);
++#else
++			readw(&i2c_base->data);
++#endif
+ 			writew(I2C_STAT_RRDY, &i2c_base->stat);
+ 			udelay(1000);
+ 		} else
+@@ -188,10 +255,6 @@ static void flush_fifo(void)
+ 	}
+ }
+ 
+-/*
+- * i2c_probe: Use write access. Allows to identify addresses that are
+- *            write-only (like the config register of dual-port EEPROMs)
+- */
+ int i2c_probe(uchar chip)
+ {
+ 	u16 status;
+@@ -200,81 +263,61 @@ int i2c_probe(uchar chip)
+ 	if (chip == readw(&i2c_base->oa))
+ 		return res;
+ 
+-	/* Wait until bus is free */
++	/* wait until bus not busy */
+ 	if (wait_for_bb())
+ 		return res;
+ 
+-	/* No data transfer, slave addr only */
+-	writew(0, &i2c_base->cnt);
+-	/* Set slave address */
++	/* try to read one byte */
++	writew(1, &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);
+-
+-	status = wait_for_event();
+-
+-	if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) {
+-		/*
+-		 * With current high-level command implementation, notifying
+-		 * the user shall flood the console with 127 messages. If
+-		 * silent exit is desired upon unconfigured bus, remove the
+-		 * following 'if' section:
+-		 */
+-		if (status == I2C_STAT_XRDY)
+-			printf("i2c_probe: pads on bus %d probably not configured (status=0x%x)\n",
+-			       current_bus, status);
+-
+-		goto pr_exit;
+-	}
++	/* stop bit needed here */
++	writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, &i2c_base->con);
+ 
+-	/* Check for ACK (!NAK) */
+-	if (!(status & I2C_STAT_NACK)) {
+-		res = 0;			/* Device found */
+-		udelay(I2C_WAIT);		/* Required by AM335X in SPL */
+-		/* Abort transfer (force idle state) */
+-		writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
+-		udelay(1000);
+-		writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX |
+-		       I2C_CON_STP, &i2c_base->con);		/* STP */
++	while (1) {
++		status = wait_for_pin();
++		if (status == 0 || status & I2C_STAT_AL) {
++			res = 1;
++			goto probe_exit;
++		}
++		if (status & I2C_STAT_NACK) {
++			res = 1;
++			writew(0xff, &i2c_base->stat);
++			writew (readw (&i2c_base->con) | I2C_CON_STP, &i2c_base->con);
++
++			if (wait_for_bb())
++				res = 1;
++
++			break;
++		}
++		if (status & I2C_STAT_ARDY) {
++			writew(I2C_STAT_ARDY, &i2c_base->stat);
++			break;
++		}
++		if (status & I2C_STAT_RRDY) {
++			res = 0;
++#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
++	defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
++	defined(CONFIG_OMAP54XX)
++			readb(&i2c_base->data);
++#else
++			readw(&i2c_base->data);
++#endif
++			writew(I2C_STAT_RRDY, &i2c_base->stat);
++		}
+ 	}
+-pr_exit:
++
++probe_exit:
+ 	flush_fifo();
+-	writew(0xFFFF, &i2c_base->stat);
++	/* don't allow any more data in... we don't want it. */
+ 	writew(0, &i2c_base->cnt);
++	writew(0xFFFF, &i2c_base->stat);
+ 	return res;
+ }
+ 
+-/*
+- * i2c_read: Function now uses a single I2C read transaction with bulk transfer
+- *           of the requested number of bytes (note that the 'i2c md' command
+- *           limits this to 16 bytes anyway). If CONFIG_I2C_REPEATED_START is
+- *           defined in the board config header, this transaction shall be with
+- *           Repeated Start (Sr) between the address and data phases; otherwise
+- *           Stop-Start (P-S) shall be used (some I2C chips do require a P-S).
+- *           The address (reg offset) may be 0, 1 or 2 bytes long.
+- *           Function now reads correctly from chips that return more than one
+- *           byte of data per addressed register (like TI temperature sensors),
+- *           or that do not need a register address at all (such as some clock
+- *           distributors).
+- */
+ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+ {
+-	int i2c_error = 0;
+-	u16 status;
+-
+-	if (alen < 0) {
+-		puts("I2C read: addr len < 0\n");
+-		return 1;
+-	}
+-	if (len < 0) {
+-		puts("I2C read: data len < 0\n");
+-		return 1;
+-	}
+-	if (buffer == NULL) {
+-		puts("I2C read: NULL pointer passed\n");
+-		return 1;
+-	}
++	int i;
+ 
+ 	if (alen > 2) {
+ 		printf("I2C read: addr len %d not supported\n", alen);
+@@ -286,122 +329,24 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+ 		return 1;
+ 	}
+ 
+-	/* Wait until bus not busy */
+-	if (wait_for_bb())
+-		return 1;
+-
+-	/* Zero, one or two bytes reg address (offset) */
+-	writew(alen, &i2c_base->cnt);
+-	/* Set slave address */
+-	writew(chip, &i2c_base->sa);
+-
+-	if (alen) {
+-		/* Must write reg offset first */
+-#ifdef CONFIG_I2C_REPEATED_START
+-		/* No stop bit, use Repeated Start (Sr) */
+-		writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT |
+-		       I2C_CON_TRX, &i2c_base->con);
+-#else
+-		/* Stop - Start (P-S) */
+-		writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP |
+-		       I2C_CON_TRX, &i2c_base->con);
+-#endif
+-		/* Send register offset */
+-		while (1) {
+-			status = wait_for_event();
+-			/* Try to identify bus that is not padconf'd for I2C */
+-			if (status == I2C_STAT_XRDY) {
+-				i2c_error = 2;
+-				printf("i2c_read (addr phase): pads on bus %d probably not configured (status=0x%x)\n",
+-				       current_bus, status);
+-				goto rd_exit;
+-			}
+-			if (status == 0 || status & I2C_STAT_NACK) {
+-				i2c_error = 1;
+-				printf("i2c_read: error waiting for addr ACK (status=0x%x)\n",
+-				       status);
+-				goto rd_exit;
+-			}
+-			if (alen) {
+-				if (status & I2C_STAT_XRDY) {
+-					alen--;
+-					/* Do we have to use byte access? */
+-					writeb((addr >> (8 * alen)) & 0xff,
+-					       &i2c_base->data);
+-					writew(I2C_STAT_XRDY, &i2c_base->stat);
+-				}
+-			}
+-			if (status & I2C_STAT_ARDY) {
+-				writew(I2C_STAT_ARDY, &i2c_base->stat);
+-				break;
+-			}
+-		}
+-	}
+-	/* Set slave address */
+-	writew(chip, &i2c_base->sa);
+-	/* Read len bytes from slave */
+-	writew(len, &i2c_base->cnt);
+-	/* Need stop bit here */
+-	writew(I2C_CON_EN | I2C_CON_MST |
+-	       I2C_CON_STT | I2C_CON_STP,
+-	       &i2c_base->con);
+-
+-	/* Receive data */
+-	while (1) {
+-		status = wait_for_event();
+-		/*
+-		 * Try to identify bus that is not padconf'd for I2C. This
+-		 * state could be left over from previous transactions if
+-		 * the address phase is skipped due to alen=0.
+-		 */
+-		if (status == I2C_STAT_XRDY) {
+-			i2c_error = 2;
+-			printf("i2c_read (data phase): pads on bus %d probably not configured (status=0x%x)\n",
+-			       current_bus, status);
+-			goto rd_exit;
+-		}
+-		if (status == 0 || status & I2C_STAT_NACK) {
+-			i2c_error = 1;
+-			goto rd_exit;
+-		}
+-		if (status & I2C_STAT_RRDY) {
+-			*buffer++ = readb(&i2c_base->data);
+-			writew(I2C_STAT_RRDY, &i2c_base->stat);
+-		}
+-		if (status & I2C_STAT_ARDY) {
+-			writew(I2C_STAT_ARDY, &i2c_base->stat);
+-			break;
++	for (i = 0; i < len; i++) {
++		if (i2c_read_byte(chip, addr + i, alen, &buffer[i])) {
++			puts("I2C read: I/O error\n");
++			i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
++			return 1;
+ 		}
+ 	}
+ 
+-rd_exit:
+-	flush_fifo();
+-	writew(0xFFFF, &i2c_base->stat);
+-	writew(0, &i2c_base->cnt);
+-	return i2c_error;
++	return 0;
+ }
+ 
+-/* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */
+ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+ {
+ 	int i;
+ 	u16 status;
+ 	int i2c_error = 0;
+-
+-	if (alen < 0) {
+-		puts("I2C write: addr len < 0\n");
+-		return 1;
+-	}
+-
+-	if (len < 0) {
+-		puts("I2C write: data len < 0\n");
+-		return 1;
+-	}
+-
+-	if (buffer == NULL) {
+-		puts("I2C write: NULL pointer passed\n");
+-		return 1;
+-	}
++	u16 w;
++	u8 tmpbuf[2] = {addr >> 8, addr & 0xff};
+ 
+ 	if (alen > 2) {
+ 		printf("I2C write: addr len %d not supported\n", alen);
+@@ -410,137 +355,92 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+ 
+ 	if (addr + len > (1 << 16)) {
+ 		printf("I2C write: address 0x%x + 0x%x out of range\n",
+-		       addr, len);
++				addr, len);
+ 		return 1;
+ 	}
+ 
+-	/* Wait until bus not busy */
++	/* wait until bus not busy */
+ 	if (wait_for_bb())
+ 		return 1;
+ 
+-	/* Start address phase - will write regoffset + len bytes data */
++	/* 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 */
++	/* set slave address */
+ 	writew(chip, &i2c_base->sa);
+-	/* Stop bit needed here */
++	/* stop bit needed here */
+ 	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
+-	       I2C_CON_STP, &i2c_base->con);
+-
+-	while (alen) {
+-		/* Must write reg offset (one or two bytes) */
+-		status = wait_for_event();
+-		/* Try to identify bus that is not padconf'd for I2C */
+-		if (status == I2C_STAT_XRDY) {
+-			i2c_error = 2;
+-			printf("i2c_write: pads on bus %d probably not configured (status=0x%x)\n",
+-			       current_bus, status);
+-			goto wr_exit;
+-		}
+-		if (status == 0 || status & I2C_STAT_NACK) {
+-			i2c_error = 1;
+-			printf("i2c_write: error waiting for addr ACK (status=0x%x)\n",
+-			       status);
+-			goto wr_exit;
+-		}
+-		if (status & I2C_STAT_XRDY) {
+-			alen--;
+-			writeb((addr >> (8 * alen)) & 0xff, &i2c_base->data);
+-			writew(I2C_STAT_XRDY, &i2c_base->stat);
+-		} else {
+-			i2c_error = 1;
+-			printf("i2c_write: bus not ready for addr Tx (status=0x%x)\n",
+-			       status);
+-			goto wr_exit;
+-		}
+-	}
+-	/* Address phase is over, now write data */
+-	for (i = 0; i < len; i++) {
+-		status = wait_for_event();
++		I2C_CON_STP, &i2c_base->con);
++
++	/* Send address and data */
++	for (i = -alen; i < len; i++) {
++		status = wait_for_pin();
++
+ 		if (status == 0 || status & I2C_STAT_NACK) {
+ 			i2c_error = 1;
+-			printf("i2c_write: error waiting for data ACK (status=0x%x)\n",
+-			       status);
+-			goto wr_exit;
++			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);
++			w = (i < 0) ? tmpbuf[2+i] : buffer[i];
++#if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
++	defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
++	defined(CONFIG_OMAP54XX))
++			w |= ((++i < 0) ? tmpbuf[2+i] : buffer[i]) << 8;
++#endif
++			writew(w, &i2c_base->data);
+ 			writew(I2C_STAT_XRDY, &i2c_base->stat);
+ 		} else {
+ 			i2c_error = 1;
+-			printf("i2c_write: bus not ready for data Tx (i=%d)\n",
+-			       i);
+-			goto wr_exit;
++			printf("i2c bus not ready for Tx (i=%d)\n", i);
++			goto write_exit;
+ 		}
+ 	}
+ 
+-wr_exit:
++write_exit:
+ 	flush_fifo();
+ 	writew(0xFFFF, &i2c_base->stat);
+-	writew(0, &i2c_base->cnt);
+ 	return i2c_error;
+ }
+ 
+-/*
+- * Wait for the bus to be free by checking the Bus Busy (BB)
+- * bit to become clear
+- */
+ static int wait_for_bb(void)
+ {
+ 	int timeout = I2C_TIMEOUT;
+ 	u16 stat;
+ 
+ 	writew(0xFFFF, &i2c_base->stat);	/* clear current interrupts...*/
+-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+ 	while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
+-#else
+-	/* Read RAW status */
+-	while ((stat = readw(&i2c_base->irqstatus_raw) &
+-		I2C_STAT_BB) && timeout--) {
+-#endif
+ 		writew(stat, &i2c_base->stat);
+-		udelay(I2C_WAIT);
++		udelay(1000);
+ 	}
+ 
+ 	if (timeout <= 0) {
+-		printf("Timed out in wait_for_bb: status=%04x\n",
+-		       stat);
++		printf("timed out in wait_for_bb: I2C_STAT=%x\n",
++			readw(&i2c_base->stat));
+ 		return 1;
+ 	}
+ 	writew(0xFFFF, &i2c_base->stat);	 /* clear delayed stuff*/
+ 	return 0;
+ }
+ 
+-/*
+- * Wait for the I2C controller to complete current action
+- * and update status
+- */
+-static u16 wait_for_event(void)
++static u16 wait_for_pin(void)
+ {
+ 	u16 status;
+ 	int timeout = I2C_TIMEOUT;
+ 
+ 	do {
+-		udelay(I2C_WAIT);
+-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
++		udelay(1000);
+ 		status = readw(&i2c_base->stat);
+-#else
+-		/* Read RAW status */
+-		status = readw(&i2c_base->irqstatus_raw);
+-#endif
+ 	} while (!(status &
+ 		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
+ 		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
+ 		    I2C_STAT_AL)) && timeout--);
+ 
+ 	if (timeout <= 0) {
+-		printf("Timed out in wait_for_event: status=%04x\n",
+-		       status);
+-		/*
+-		 * If status is still 0 here, probably the bus pads have
+-		 * not been configured for I2C, and/or pull-ups are missing.
+-		 */
+-		printf("Check if pads/pull-ups of bus %d are properly configured\n",
+-		       current_bus);
++		printf("timed out in wait_for_pin: I2C_STAT=%x\n",
++			readw(&i2c_base->stat));
+ 		writew(0xFFFF, &i2c_base->stat);
+ 		status = 0;
+ 	}
+@@ -550,36 +450,28 @@ static u16 wait_for_event(void)
+ 
+ int i2c_set_bus_num(unsigned int bus)
+ {
+-	if (bus >= I2C_BUS_MAX) {
+-		printf("Bad bus: %x\n", bus);
++	if ((bus < 0) || (bus >= I2C_BUS_MAX)) {
++		printf("Bad bus: %d\n", bus);
+ 		return -1;
+ 	}
+ 
+-	switch (bus) {
+-	default:
+-		bus = 0;	/* Fall through */
+-	case 0:
+-		i2c_base = (struct i2c *)I2C_BASE1;
+-		break;
+-	case 1:
+-		i2c_base = (struct i2c *)I2C_BASE2;
+-		break;
+-#if (I2C_BUS_MAX > 2)
+-	case 2:
+-		i2c_base = (struct i2c *)I2C_BASE3;
+-		break;
+-#if (I2C_BUS_MAX > 3)
+-	case 3:
++#if I2C_BUS_MAX == 4
++	if (bus == 3)
+ 		i2c_base = (struct i2c *)I2C_BASE4;
+-		break;
+-#if (I2C_BUS_MAX > 4)
+-	case 4:
+-		i2c_base = (struct i2c *)I2C_BASE5;
+-		break;
+-#endif
++	else
++	if (bus == 2)
++		i2c_base = (struct i2c *)I2C_BASE3;
++	else
+ #endif
++#if I2C_BUS_MAX == 3
++	if (bus == 2)
++		i2c_base = (struct i2c *)I2C_BASE3;
++	else
+ #endif
+-	}
++	if (bus == 1)
++		i2c_base = (struct i2c *)I2C_BASE2;
++	else
++		i2c_base = (struct i2c *)I2C_BASE1;
+ 
+ 	current_bus = bus;
+ 
+-- 
+1.8.1.2
+



More information about the training-materials-updates mailing list