diff options
author | Ryo Kataoka <ryo.kataoka.wt@renesas.com> | 2014-10-21 16:26:09 +0900 |
---|---|---|
committer | Simon Horman <horms+renesas@verge.net.au> | 2014-12-07 13:18:56 +0900 |
commit | 9714052c61f712fc71276a0f2c343cce47b2ad72 (patch) | |
tree | 5aa5166c41a0cb1eab5b012e2fb850b141478d16 | |
parent | 38618cf8ce0bb2120a747c7e46d67d1aeae61b42 (diff) | |
download | renesas-backport-backport/v3.10.28-ltsi-rc1/bsp/i2c-rcar.wip.tar.gz |
i2c: rcar: Support ACK by HW auto restart after NACKbackport/v3.10.28-ltsi-rc1/bsp/i2c-rcar.wip
Even if R-Car I2C received NACK, after that it might receive ACK
by HW auto restart. In case of that, driver would continue process.
If R-Car I2C didn't receive ACK, the driver would detect timeout
and would report NACK as -ENXIO.
Signed-off-by: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
(cherry picked from commit 4df6b2af6c0f795d810eb1e2e9411ad1cbbe4245)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 2a825544addb76..e67aef1f1bb2e3 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -522,7 +522,6 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) /* go to stop phase */ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP); - rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_STOP); rcar_i2c_flags_set(priv, ID_NACK); rcar_i2c_status_bit_clear(priv, MNR); goto out; @@ -533,8 +532,14 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) */ if (msr & MST) { dev_dbg(dev, "Stop\n"); - rcar_i2c_flags_set(priv, ID_DONE); - rcar_i2c_status_clear(priv); + if (rcar_i2c_flags_has(priv, ID_NACK)) { + /* don't set ID_DONE for expecting ACK + after auto-restart by HW */ + rcar_i2c_status_bit_clear(priv, MST); + } else { + rcar_i2c_flags_set(priv, ID_DONE); + rcar_i2c_status_clear(priv); + } goto out; } @@ -611,6 +616,10 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, rcar_i2c_flags_has(priv, ID_DONE), 5 * HZ); if (!timeout) { + if (rcar_i2c_flags_has(priv, ID_NACK)) { + ret = -ENXIO; + break; + } ret = -ETIMEDOUT; break; } @@ -618,11 +627,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, /* * error handling */ - if (rcar_i2c_flags_has(priv, ID_NACK)) { - ret = -ENXIO; - break; - } - if (rcar_i2c_flags_has(priv, ID_ARBLOST)) { ret = -EAGAIN; break; |