From: Greg Kroah-Hartman Date: Wed, 9 Dec 2020 11:03:58 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v5.9.14~33 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9ab904441a74f5dfd5c3b1ad80cf707a0d98f20d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: i2c-imx-check-for-i2sr_ial-after-every-byte.patch i2c-imx-fix-reset-of-i2sr_ial-flag.patch --- diff --git a/queue-4.14/i2c-imx-check-for-i2sr_ial-after-every-byte.patch b/queue-4.14/i2c-imx-check-for-i2sr_ial-after-every-byte.patch new file mode 100644 index 00000000000..1e11beac80a --- /dev/null +++ b/queue-4.14/i2c-imx-check-for-i2sr_ial-after-every-byte.patch @@ -0,0 +1,46 @@ +From 1de67a3dee7a279ebe4d892b359fe3696938ec15 Mon Sep 17 00:00:00 2001 +From: Christian Eggers +Date: Fri, 9 Oct 2020 13:03:19 +0200 +Subject: i2c: imx: Check for I2SR_IAL after every byte + +From: Christian Eggers + +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 +Tested (not extensively) on Vybrid VF500 (Toradex VF50): +Tested-by: Krzysztof Kozlowski +Acked-by: Oleksij Rempel +Cc: stable@vger.kernel.org +Signed-off-by: Wolfram Sang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/i2c/busses/i2c-imx.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -465,6 +465,16 @@ static int i2c_imx_trx_complete(struct i + 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; diff --git a/queue-4.14/i2c-imx-fix-reset-of-i2sr_ial-flag.patch b/queue-4.14/i2c-imx-fix-reset-of-i2sr_ial-flag.patch new file mode 100644 index 00000000000..213901bbdfa --- /dev/null +++ b/queue-4.14/i2c-imx-fix-reset-of-i2sr_ial-flag.patch @@ -0,0 +1,72 @@ +From 384a9565f70a876c2e78e58c5ca0bbf0547e4f6d Mon Sep 17 00:00:00 2001 +From: Christian Eggers +Date: Fri, 9 Oct 2020 13:03:18 +0200 +Subject: i2c: imx: Fix reset of I2SR_IAL flag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Christian Eggers + +commit 384a9565f70a876c2e78e58c5ca0bbf0547e4f6d upstream. + +According to the "VFxxx Controller Reference Manual" (and the comment +block starting at line 97), Vybrid requires writing a one for clearing +an interrupt flag. Syncing the method for clearing I2SR_IIF in +i2c_imx_isr(). + +Signed-off-by: Christian Eggers +Fixes: 4b775022f6fd ("i2c: imx: add struct to hold more configurable quirks") +Reviewed-by: Uwe Kleine-König +Acked-by: Oleksij Rempel +Cc: stable@vger.kernel.org +Signed-off-by: Wolfram Sang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/i2c/busses/i2c-imx.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/drivers/i2c/busses/i2c-imx.c ++++ b/drivers/i2c/busses/i2c-imx.c +@@ -413,6 +413,19 @@ static void i2c_imx_dma_free(struct imx_ + dma->chan_using = NULL; + } + ++static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits) ++{ ++ unsigned int temp; ++ ++ /* ++ * i2sr_clr_opcode is the value to clear all interrupts. Here we want to ++ * clear only , so we write ~i2sr_clr_opcode with just ++ * toggled. This is required because i.MX needs W0C and Vybrid uses W1C. ++ */ ++ temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits; ++ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); ++} ++ + static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) + { + unsigned long orig_jiffies = jiffies; +@@ -425,8 +438,7 @@ static int i2c_imx_bus_busy(struct imx_i + + /* check for arbitration lost */ + if (temp & I2SR_IAL) { +- temp &= ~I2SR_IAL; +- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); ++ i2c_imx_clear_irq(i2c_imx, I2SR_IAL); + return -EAGAIN; + } + +@@ -595,9 +607,7 @@ static irqreturn_t i2c_imx_isr(int irq, + if (temp & I2SR_IIF) { + /* save status register */ + i2c_imx->i2csr = temp; +- temp &= ~I2SR_IIF; +- temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF); +- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); ++ i2c_imx_clear_irq(i2c_imx, I2SR_IIF); + wake_up(&i2c_imx->queue); + return IRQ_HANDLED; + } diff --git a/queue-4.14/series b/queue-4.14/series index 2cd95f53d26..43b54dfa1e6 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -16,3 +16,5 @@ alsa-hda-generic-add-option-to-enforce-preferred_dacs-pairs.patch ftrace-fix-updating-ftrace_fl_tramp.patch cifs-fix-potential-use-after-free-in-cifs_echo_request.patch mm-swapfile-do-not-sleep-with-a-spin-lock-held.patch +i2c-imx-fix-reset-of-i2sr_ial-flag.patch +i2c-imx-check-for-i2sr_ial-after-every-byte.patch