ARMV7: OMAP: I2C driver: Restructure i2c_read_byte function

This patch removes the "magic number" delays and instead
monitors state changes in the status register bits.

Signed-off-by: Steve Sakoman <steve.sakomanlinaro.org>
Tested-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
Steve Sakoman 2010-10-20 06:07:45 -07:00 committed by Heiko Schocher
parent 73e8747fe4
commit da0cc665bc

View file

@ -159,58 +159,56 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
/* no stop bit needed here */ /* no stop bit needed here */
writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, &i2c_base->con); writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, &i2c_base->con);
status = wait_for_pin (); /* send register offset */
while (1) {
if (status & I2C_STAT_XRDY) { status = wait_for_pin();
/* Important: have to use byte access */ if (status == 0 || status & I2C_STAT_NACK) {
writeb (regoffset, &i2c_base->data);
udelay (20000);
if (readw (&i2c_base->stat) & I2C_STAT_NACK) {
i2c_error = 1; i2c_error = 1;
goto read_exit;
}
if (status & I2C_STAT_XRDY) {
/* Important: have to use byte access */
writeb(regoffset, &i2c_base->data);
writew(I2C_STAT_XRDY, &i2c_base->stat);
}
if (status & I2C_STAT_ARDY) {
writew(I2C_STAT_ARDY, &i2c_base->stat);
break;
} }
} else {
i2c_error = 1;
} }
if (!i2c_error) { /* set slave address */
writew (I2C_CON_EN, &i2c_base->con); writew(devaddr, &i2c_base->sa);
while (readw(&i2c_base->stat) & /* read one byte from slave */
(I2C_STAT_XRDY | I2C_STAT_ARDY)) { writew(1, &i2c_base->cnt);
udelay (10000); /* need stop bit here */
/* Have to clear pending interrupt to clear I2C_STAT */ writew(I2C_CON_EN | I2C_CON_MST |
writew (0xFFFF, &i2c_base->stat); 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;
} }
/* 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);
status = wait_for_pin ();
if (status & I2C_STAT_RRDY) { if (status & I2C_STAT_RRDY) {
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
defined(CONFIG_OMAP44XX) defined(CONFIG_OMAP44XX)
*value = readb (&i2c_base->data); *value = readb(&i2c_base->data);
#else #else
*value = readw (&i2c_base->data); *value = readw(&i2c_base->data);
#endif #endif
udelay (20000); writew(I2C_STAT_RRDY, &i2c_base->stat);
} else {
i2c_error = 1;
} }
if (status & I2C_STAT_ARDY) {
if (!i2c_error) { writew(I2C_STAT_ARDY, &i2c_base->stat);
writew (I2C_CON_EN, &i2c_base->con); break;
while (readw (&i2c_base->stat) &
(I2C_STAT_RRDY | I2C_STAT_ARDY)) {
udelay (10000);
writew (0xFFFF, &i2c_base->stat);
}
} }
} }
read_exit:
flush_fifo(); flush_fifo();
writew (0xFFFF, &i2c_base->stat); writew (0xFFFF, &i2c_base->stat);
writew (0, &i2c_base->cnt); writew (0, &i2c_base->cnt);