summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNick Thompson <nick.thompson@ge.com>2011-04-11 22:37:41 +0000
committerHeiko Schocher <hs@denx.de>2011-04-14 08:33:23 +0200
commit0e57968a215d1b9d271f3fa5bebeddeaea0c8075 (patch)
treecac33061d68c9d6af986a3e1b52326259f0a9ee2 /drivers
parent73e5476e1edf1b860dbd9b5fc21ef32ac1b551ba (diff)
downloadu-boot-imx-0e57968a215d1b9d271f3fa5bebeddeaea0c8075.zip
u-boot-imx-0e57968a215d1b9d271f3fa5bebeddeaea0c8075.tar.gz
u-boot-imx-0e57968a215d1b9d271f3fa5bebeddeaea0c8075.tar.bz2
I2C: OMAP: detect more devices when probing an i2c bus
The omap24xx driver only seems to support devices that have a single subaddress byte. With these types of devices, the first access in a bus transaction is usually a write (writes the subaddress) followed by either a read or write to access the devices registers. Many such devices will respond to a read as the first access, but there are at least some that will NACK such a read. (e.g. ADV7180.) The probe function attempts to detect a devices ACK to a read access only and fails to find devices that NACK a read. This commit modifies the probe function to start a write instead. This detects devices that respond to reads (since they must also respond to writes) as well as those that only respond to writes. The bus is immediately set to idle after a (N)ACK avoiding actually writing anything to the device. Signed-off-by: Nick Thompson <nick.thompson@ge.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/omap24xx_i2c.c42
1 files changed, 11 insertions, 31 deletions
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 215be34..71251d8 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -321,43 +321,23 @@ int i2c_probe (uchar chip)
/* wait until bus not busy */
wait_for_bb ();
- /* try to read one byte */
+ /* try to write 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_STP, &i2c_base->con);
+ 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_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);
- }
- }
+ status = wait_for_pin();
+
+ /* check for ACK (!NAK) */
+ if (!(status & I2C_STAT_NACK))
+ res = 0;
+
+ /* abort transfer (force idle state) */
+ writew(0, &i2c_base->con);
-probe_exit:
flush_fifo();
writew (0, &i2c_base->cnt); /* don't allow any more data in...we don't want it.*/
writew(0xFFFF, &i2c_base->stat);