summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Eggers <ceggers@arri.de>2020-10-09 13:03:19 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-12-11 13:25:02 +0100
commitd614a21c7460e97873ac974d66b866a8e416c8f2 (patch)
tree825132ba0e1772f0f5d392423075de2ab57cb385
parent7d4904a1a2523cd2e5ee98c52f09a2fb048ae7b7 (diff)
downloadlinux-stable-d614a21c7460e97873ac974d66b866a8e416c8f2.tar.gz
linux-stable-d614a21c7460e97873ac974d66b866a8e416c8f2.tar.bz2
linux-stable-d614a21c7460e97873ac974d66b866a8e416c8f2.zip
i2c: imx: Check for I2SR_IAL after every byte
commit 1de67a3dee7a279ebe4d892b359fe3696938ec15 upstream. 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 Signed-off-by: Wolfram Sang <wsa@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/i2c/busses/i2c-imx.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 61eceb1809ed..83c246e30399 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -460,6 +460,16 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
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;