Message ID | 20201009110320.20832-3-ceggers@arri.de |
---|---|
State | Superseded |
Headers | show |
Series | i2c: imx: Fix handling of arbitration loss | expand |
On Fri, Oct 09, 2020 at 01:03:19PM +0200, Christian Eggers wrote: > Arbitration Lost (IAL) can happen after every single byte transfer. If > arbitration is lost, the I2C hardware will autonomously switch from > master mode to slave. If a transfer is not aborted in this state, > consecutive transfers will not be executed by the hardware and will > timeout. > > Signed-off-by: Christian Eggers <ceggers@arri.de> > Tested (not extensively) on Vybrid VF500 (Toradex VF50): > Tested-by: Krzysztof Kozlowski <krzk@kernel.org> > Acked-by: Oleksij Rempel <o.rempel@pengutronix.de> > Cc: stable@vger.kernel.org Applied to for-next, thanks!
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 028f8a626410..69ce5eea9b5a 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -490,6 +490,16 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic) dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); return -ETIMEDOUT; } + + /* check for arbitration lost */ + if (i2c_imx->i2csr & I2SR_IAL) { + dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__); + i2c_imx_clear_irq(i2c_imx, I2SR_IAL); + + i2c_imx->i2csr = 0; + return -EAGAIN; + } + dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__); i2c_imx->i2csr = 0; return 0;