diff options
author | Tom Rini <trini@ti.com> | 2012-05-21 06:46:29 +0000 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2012-07-07 14:07:22 +0200 |
commit | 168a5acb81a8d92a7effcb2727aaa89367b97e05 (patch) | |
tree | 0888b4c9f17157dff5e0e30334d7dc6c666e9d06 | |
parent | d5b069ecb4199f1672fd98041bd0037bd33d2f0f (diff) | |
download | u-boot-imx-168a5acb81a8d92a7effcb2727aaa89367b97e05.zip u-boot-imx-168a5acb81a8d92a7effcb2727aaa89367b97e05.tar.gz u-boot-imx-168a5acb81a8d92a7effcb2727aaa89367b97e05.tar.bz2 |
Revert "I2C: OMAP: detect more devices when probing an i2c bus"
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>
Acked-by: Heiko Schocher <hs@denx.de>
-rw-r--r-- | drivers/i2c/omap24xx_i2c.c | 42 |
1 files changed, 31 insertions, 11 deletions
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); |