summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Sakoman <steve@sakoman.com>2010-10-20 06:07:45 -0700
committerHeiko Schocher <hs@denx.de>2010-10-20 15:28:37 +0200
commitda0cc665bc0b74c6650f340275c5462ec4c08645 (patch)
treea7300a037c81655bae1ab5b05ba22bafcb691bc2
parent73e8747fe48c54dda16670421dbc370b5b2a4a52 (diff)
downloadu-boot-imx-da0cc665bc0b74c6650f340275c5462ec4c08645.zip
u-boot-imx-da0cc665bc0b74c6650f340275c5462ec4c08645.tar.gz
u-boot-imx-da0cc665bc0b74c6650f340275c5462ec4c08645.tar.bz2
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>
-rw-r--r--drivers/i2c/omap24xx_i2c.c76
1 files changed, 37 insertions, 39 deletions
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index b69d051..d176b5d 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -159,58 +159,56 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
/* no stop bit needed here */
writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, &i2c_base->con);
- status = wait_for_pin ();
-
- if (status & I2C_STAT_XRDY) {
- /* Important: have to use byte access */
- writeb (regoffset, &i2c_base->data);
- udelay (20000);
- if (readw (&i2c_base->stat) & I2C_STAT_NACK) {
+ /* 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) {
+ /* 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) {
- writew (I2C_CON_EN, &i2c_base->con);
- while (readw(&i2c_base->stat) &
- (I2C_STAT_XRDY | I2C_STAT_ARDY)) {
- udelay (10000);
- /* Have to clear pending interrupt to clear I2C_STAT */
- writew (0xFFFF, &i2c_base->stat);
+ /* 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;
}
-
- /* 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 defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
defined(CONFIG_OMAP44XX)
- *value = readb (&i2c_base->data);
+ *value = readb(&i2c_base->data);
#else
- *value = readw (&i2c_base->data);
+ *value = readw(&i2c_base->data);
#endif
- udelay (20000);
- } else {
- i2c_error = 1;
+ writew(I2C_STAT_RRDY, &i2c_base->stat);
}
-
- if (!i2c_error) {
- writew (I2C_CON_EN, &i2c_base->con);
- while (readw (&i2c_base->stat) &
- (I2C_STAT_RRDY | I2C_STAT_ARDY)) {
- udelay (10000);
- writew (0xFFFF, &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);