mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 17:18:59 +00:00
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;
|
|||
|
}
|
|||
|
|