From a8ff098df88b61dd7966d7830f15c852a692b010 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 9 Dec 2020 12:04:15 +0100 Subject: [PATCH] 4.19-stable patches added patches: i2c-imx-check-for-i2sr_ial-after-every-byte.patch i2c-imx-fix-reset-of-i2sr_ial-flag.patch --- ...-check-for-i2sr_ial-after-every-byte.patch | 46 ++++++++++++ .../i2c-imx-fix-reset-of-i2sr_ial-flag.patch | 72 +++++++++++++++++++ queue-4.19/series | 2 + 3 files changed, 120 insertions(+) create mode 100644 queue-4.19/i2c-imx-check-for-i2sr_ial-after-every-byte.patch create mode 100644 queue-4.19/i2c-imx-fix-reset-of-i2sr_ial-flag.patch diff --git a/queue-4.19/i2c-imx-check-for-i2sr_ial-after-every-byte.patch b/queue-4.19/i2c-imx-check-for-i2sr_ial-after-every-byte.patch new file mode 100644 index 00000000000..08641a58681 --- /dev/null +++ b/queue-4.19/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 +@@ -460,6 +460,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.19/i2c-imx-fix-reset-of-i2sr_ial-flag.patch b/queue-4.19/i2c-imx-fix-reset-of-i2sr_ial-flag.patch new file mode 100644 index 00000000000..9d67d7720f7 --- /dev/null +++ b/queue-4.19/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 +@@ -404,6 +404,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; +@@ -416,8 +429,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; + } + +@@ -589,9 +601,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.19/series b/queue-4.19/series index 1bc7a1ec9b6..cdac0cbaf2c 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -22,3 +22,5 @@ dm-remove-invalid-sparse-__acquires-and-__releases-annotations.patch mm-list_lru-set-shrinker-map-bit-when-child-nr_items-is-not-zero.patch mm-swapfile-do-not-sleep-with-a-spin-lock-held.patch x86-uprobes-do-not-use-prefixes.nbytes-when-looping-over-prefixes.bytes.patch +i2c-imx-fix-reset-of-i2sr_ial-flag.patch +i2c-imx-check-for-i2sr_ial-after-every-byte.patch -- 2.47.3