diff options
author | Troy Kisky <troy.kisky@boundarydevices.com> | 2012-07-19 08:18:16 +0000 |
---|---|---|
committer | Heiko Schocher <hs@denx.de> | 2012-07-31 07:53:36 +0200 |
commit | a7f1a0051078052cb81ba1ff5985b908f39cefd5 (patch) | |
tree | 56236eb45ce4de4f0b4710a7f35e80e044dea07f /drivers/i2c | |
parent | d5383a63cd1286392a9792f3bd9e9b0d87e02171 (diff) | |
download | u-boot-imx-a7f1a0051078052cb81ba1ff5985b908f39cefd5.zip u-boot-imx-a7f1a0051078052cb81ba1ff5985b908f39cefd5.tar.gz u-boot-imx-a7f1a0051078052cb81ba1ff5985b908f39cefd5.tar.bz2 |
mxc_i2c: add retries
Retry unexpected hardware errors. This
will not retry a received NAK.
Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/mxc_i2c.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 093a73f..cbb0fff 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -218,7 +218,7 @@ void i2c_imx_stop(void) * Send start signal, chip address and * write register address */ -static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, +static int i2c_init_transfer_(struct mxc_i2c_regs *i2c_regs, uchar chip, uint addr, int alen) { unsigned int temp; @@ -235,7 +235,7 @@ static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, writeb(0, &i2c_regs->i2sr); ret = wait_for_sr_state(i2c_regs, ST_BUS_IDLE); if (ret < 0) - goto exit; + return ret; /* Start I2C transaction */ temp = readb(&i2c_regs->i2cr); @@ -244,7 +244,7 @@ static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, ret = wait_for_sr_state(i2c_regs, ST_BUS_BUSY); if (ret < 0) - goto exit; + return ret; temp |= I2CR_MTX | I2CR_TX_NO_AK; writeb(temp, &i2c_regs->i2cr); @@ -252,18 +252,36 @@ static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, /* write slave address */ ret = tx_byte(i2c_regs, chip << 1); if (ret < 0) - goto exit; + return ret; while (alen--) { ret = tx_byte(i2c_regs, (addr >> (alen * 8)) & 0xff); if (ret < 0) - goto exit; + return ret; } return 0; -exit: - i2c_imx_stop(); - /* Disable I2C controller */ - writeb(0, &i2c_regs->i2cr); +} + +static int i2c_init_transfer(struct mxc_i2c_regs *i2c_regs, + uchar chip, uint addr, int alen) +{ + int retry; + int ret; + for (retry = 0; retry < 3; retry++) { + ret = i2c_init_transfer_(i2c_regs, chip, addr, alen); + if (ret >= 0) + return 0; + i2c_imx_stop(); + if (ret == -ENODEV) + return ret; + + printf("%s: failed for chip 0x%x retry=%d\n", __func__, chip, + retry); + if (ret != -ERESTART) + writeb(0, &i2c_regs->i2cr); /* Disable controller */ + udelay(100); + } + printf("%s: give up i2c_regs=%p\n", __func__, i2c_regs); return ret; } |