openwrt/target/linux/ipq40xx/patches-4.14/088-0007-i2c-qup-proper-error-handling-for-i2c-error-in-BAM-m.patch
Piotr Dymacz 24de7c29e5 ipq40xx: backport I2C QUP driver changes from 4.17
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>
2019-03-08 19:28:31 +01:00

91 lines
3.2 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
+ /*
+ * Dont 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;
}