diff mbox

[U-Boot,1/5] Revert "I2C: OMAP: detect more devices when probing an i2c bus"

Message ID 1337618793-13934-2-git-send-email-trini@ti.com
State Accepted
Commit 168a5acb81a8d92a7effcb2727aaa89367b97e05
Delegated to: Tom Rini
Headers show

Commit Message

Tom Rini May 21, 2012, 4:46 p.m. UTC
This reverts commit 0e57968a215d1b9d271f3fa5bebeddeaea0c8075.

The short version of the original commit is that some i2c devices cannot
be probed via read as they NAK the first cycle, so try and probe via a
write that we abort before it writes to the device.  This however is not
allowed by the TRM for any of these parts.  The section on I2C_CON
(table 17-35 I2C_CON for am/dm37x for example) says you must not change
the register while STT has been set.  On these parts, the unpredictable
behavior that the chip exhibits is not problematic.  On OMAP4 however it
results in the chip being in a bad state:
Panda # i2c probe
Valid chip addresses: 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12
13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A
2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42
43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A
5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72
73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
Panda # i2c md 50 0
timed out in wait_for_pin: I2C_STAT=0
I2C read: I/O error
Error reading the chip.

We must revert the original behavior to bring probe back into line with
the TRM.

Cc: Nick Thompson <nick.thompson@ge.com>
Cc: Heiko Schocher <hs@denx.de>
Signed-off-by: Tom Rini <trini@ti.com>
---
 drivers/i2c/omap24xx_i2c.c |   42 +++++++++++++++++++++++++++++++-----------
 1 file changed, 31 insertions(+), 11 deletions(-)

Comments

Heiko Schocher May 22, 2012, 12:11 p.m. UTC | #1
Hello Tom,

Tom Rini wrote:
> This reverts commit 0e57968a215d1b9d271f3fa5bebeddeaea0c8075.
> 
> The short version of the original commit is that some i2c devices cannot
> be probed via read as they NAK the first cycle, so try and probe via a
> write that we abort before it writes to the device.  This however is not
> allowed by the TRM for any of these parts.  The section on I2C_CON
> (table 17-35 I2C_CON for am/dm37x for example) says you must not change
> the register while STT has been set.  On these parts, the unpredictable
> behavior that the chip exhibits is not problematic.  On OMAP4 however it
> results in the chip being in a bad state:
> Panda # i2c probe
> Valid chip addresses: 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12
> 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A
> 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42
> 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A
> 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72
> 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
> Panda # i2c md 50 0
> timed out in wait_for_pin: I2C_STAT=0
> I2C read: I/O error
> Error reading the chip.
> 
> We must revert the original behavior to bring probe back into line with
> the TRM.
> 
> Cc: Nick Thompson <nick.thompson@ge.com>
> Cc: Heiko Schocher <hs@denx.de>
> Signed-off-by: Tom Rini <trini@ti.com>
> ---
>  drivers/i2c/omap24xx_i2c.c |   42 +++++++++++++++++++++++++++++++-----------
>  1 file changed, 31 insertions(+), 11 deletions(-)

Acked-by: Heiko Schocher <hs@denx.de>

Thanks!

bye,
Heiko
diff mbox

Patch

diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index a7ffd95..3a50417 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -255,23 +255,43 @@  int i2c_probe(uchar chip)
 	/* wait until bus not busy */
 	wait_for_bb();
 
-	/* try to write one byte */
+	/* 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_pin();
+	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;
-
-	/* abort transfer (force idle state) */
-	writew(0, &i2c_base->con);
+	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);
+			wait_for_bb ();
+			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)
+			readb(&i2c_base->data);
+#else
+			readw(&i2c_base->data);
+#endif
+			writew(I2C_STAT_RRDY, &i2c_base->stat);
+		}
+	}
 
+probe_exit:
 	flush_fifo();
 	/* don't allow any more data in... we don't want it. */
 	writew(0, &i2c_base->cnt);