mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-20 14:13:16 +00:00
24de7c29e5
Backport below changes for I2C QUP driver from v4.17: 0668bc44a426 i2c: qup: fix copyrights and update to SPDX identifier 7239872fb340 i2c: qup: fixed releasing dma without flush operation completion eb422b539c1f i2c: qup: minor code reorganization for use_dma 6d5f37f166bb i2c: qup: remove redundant variables for BAM SG count c5adc0fa63a9 i2c: qup: schedule EOT and FLUSH tags at the end of transfer 7e6c35fe602d i2c: qup: fix the transfer length for BAM RX EOT FLUSH tags 3f450d3eea14 i2c: qup: proper error handling for i2c error in BAM mode 08f15963bc75 i2c: qup: use the complete transfer length to choose DMA mode ecb6e1e5f435 i2c: qup: change completion timeout according to transfer length 6f2f0f6465ac i2c: qup: fix buffer overflow for multiple msg of maximum xfer len f7714b4e451b i2c: qup: send NACK for last read sub transfers fbfab1ab0658 i2c: qup: reorganization of driver code to remove polling for qup v1 7545c7dba169 i2c: qup: reorganization of driver code to remove polling for qup v2 This fixes various I2C issues observed on AP120C-AC board equipped with Atmel/Microchip AT97SC3205T TPM module. Tested-by: Christian Lamparter <chunkeey@gmail.com> Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
91 lines
3.2 KiB
Diff
91 lines
3.2 KiB
Diff
From 3f450d3eea14799b14192231840c1753a660f150 Mon Sep 17 00:00:00 2001
|
||
From: Abhishek Sahu <absahu@codeaurora.org>
|
||
Date: Mon, 12 Mar 2018 18:44:56 +0530
|
||
Subject: [PATCH 07/13] i2c: qup: proper error handling for i2c error in BAM
|
||
mode
|
||
|
||
Currently the i2c error handling in BAM mode is not working
|
||
properly in stress condition.
|
||
|
||
1. After an error, the FIFO are being written with FLUSH and
|
||
EOT tags which should not be required since already these tags
|
||
have been written in BAM descriptor itself.
|
||
|
||
2. QUP state is being moved to RESET in IRQ handler in case
|
||
of error. When QUP HW encounters an error in BAM mode then it
|
||
moves the QUP STATE to PAUSE state. In this case, I2C_FLUSH
|
||
command needs to be executed while moving to RUN_STATE by writing
|
||
to the QUP_STATE register with the I2C_FLUSH bit set to 1.
|
||
|
||
3. In Error case, sometimes, QUP generates more than one
|
||
interrupt which will trigger the complete again. After an error,
|
||
the flush operation will be scheduled after doing
|
||
reinit_completion which should be triggered by BAM IRQ callback.
|
||
If the second QUP IRQ comes during this time then it will call
|
||
the complete and the transfer function will assume the all the
|
||
BAM HW descriptors have been completed.
|
||
|
||
4. The release DMA is being called after each error which
|
||
will free the DMA tx and rx channels. The error like NACK is very
|
||
common in I2C transfer and every time this will be overhead. Now,
|
||
since the error handling is proper so this release channel can be
|
||
completely avoided.
|
||
|
||
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
|
||
Reviewed-by: Sricharan R <sricharan@codeaurora.org>
|
||
Reviewed-by: Austin Christ <austinwc@codeaurora.org>
|
||
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
|
||
---
|
||
drivers/i2c/busses/i2c-qup.c | 25 ++++++++++++++++---------
|
||
1 file changed, 16 insertions(+), 9 deletions(-)
|
||
|
||
--- a/drivers/i2c/busses/i2c-qup.c
|
||
+++ b/drivers/i2c/busses/i2c-qup.c
|
||
@@ -219,9 +219,24 @@ static irqreturn_t qup_i2c_interrupt(int
|
||
if (bus_err)
|
||
writel(bus_err, qup->base + QUP_I2C_STATUS);
|
||
|
||
+ /*
|
||
+ * Check for BAM mode and returns if already error has come for current
|
||
+ * transfer. In Error case, sometimes, QUP generates more than one
|
||
+ * interrupt.
|
||
+ */
|
||
+ if (qup->use_dma && (qup->qup_err || qup->bus_err))
|
||
+ return IRQ_HANDLED;
|
||
+
|
||
/* Reset the QUP State in case of error */
|
||
if (qup_err || bus_err) {
|
||
- writel(QUP_RESET_STATE, qup->base + QUP_STATE);
|
||
+ /*
|
||
+ * Don’t reset the QUP state in case of BAM mode. The BAM
|
||
+ * flush operation needs to be scheduled in transfer function
|
||
+ * which will clear the remaining schedule descriptors in BAM
|
||
+ * HW FIFO and generates the BAM interrupt.
|
||
+ */
|
||
+ if (!qup->use_dma)
|
||
+ writel(QUP_RESET_STATE, qup->base + QUP_STATE);
|
||
goto done;
|
||
}
|
||
|
||
@@ -847,20 +862,12 @@ static int qup_i2c_bam_do_xfer(struct qu
|
||
goto desc_err;
|
||
}
|
||
|
||
- if (rx_cnt)
|
||
- writel(QUP_BAM_INPUT_EOT,
|
||
- qup->base + QUP_OUT_FIFO_BASE);
|
||
-
|
||
- writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
|
||
-
|
||
qup_i2c_flush(qup);
|
||
|
||
/* wait for remaining interrupts to occur */
|
||
if (!wait_for_completion_timeout(&qup->xfer, HZ))
|
||
dev_err(qup->dev, "flush timed out\n");
|
||
|
||
- qup_i2c_rel_dma(qup);
|
||
-
|
||
ret = (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO;
|
||
}
|
||
|