summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.9/950-0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-4.9/950-0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch')
-rw-r--r--target/linux/brcm2708/patches-4.9/950-0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch124
1 files changed, 0 insertions, 124 deletions
diff --git a/target/linux/brcm2708/patches-4.9/950-0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch b/target/linux/brcm2708/patches-4.9/950-0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch
deleted file mode 100644
index 0d9b165aba..0000000000
--- a/target/linux/brcm2708/patches-4.9/950-0107-i2c-bcm2835-Protect-against-unexpected-TXW-RXR-inter.patch
+++ /dev/null
@@ -1,124 +0,0 @@
-From 8feb8081c74d15ce368baa42981ca98e77800c03 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
-Date: Fri, 23 Sep 2016 18:24:38 +0200
-Subject: [PATCH] i2c: bcm2835: Protect against unexpected TXW/RXR interrupts
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0),
-the driver has no way to fill/drain the FIFO to stop the interrupts.
-In this case the controller has to be disabled and the transfer
-completed to avoid hang.
-
-(CLKT | ERR) and DONE interrupts are completed in their own paths, and
-the controller is disabled in the transfer function after completion.
-Unite the code paths and do disabling inside the interrupt routine.
-
-Clear interrupt status bits in the united completion path instead of
-trying to do it on every interrupt which isn't necessary.
-Only CLKT, ERR and DONE can be cleared that way.
-
-Add the status value to the error value in case of TXW/RXR errors to
-distinguish them from the other S_LEN error.
-
-Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
-Reviewed-by: Eric Anholt <eric@anholt.net>
----
- drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++---------
- 1 file changed, 31 insertions(+), 9 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -50,8 +50,6 @@
- #define BCM2835_I2C_S_CLKT BIT(9)
- #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */
-
--#define BCM2835_I2C_BITMSK_S 0x03FF
--
- #define BCM2835_I2C_CDIV_MIN 0x0002
- #define BCM2835_I2C_CDIV_MAX 0xFFFE
-
-@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct
- }
- }
-
-+/*
-+ * Note about I2C_C_CLEAR on error:
-+ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
-+ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through
-+ * the state machine to send a NACK and a STOP. Since we're setting CLEAR
-+ * without I2CEN, that NACK will be hanging around queued up for next time
-+ * we start the engine.
-+ */
-+
- static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
- {
- struct bcm2835_i2c_dev *i2c_dev = data;
- u32 val, err;
-
- val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
-- val &= BCM2835_I2C_BITMSK_S;
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
-
- err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
- if (err) {
- i2c_dev->msg_err = err;
-- complete(&i2c_dev->completion);
-- return IRQ_HANDLED;
-+ goto complete;
- }
-
- if (val & BCM2835_I2C_S_DONE) {
-@@ -139,21 +143,38 @@ static irqreturn_t bcm2835_i2c_isr(int t
- i2c_dev->msg_err = BCM2835_I2C_S_LEN;
- else
- i2c_dev->msg_err = 0;
-- complete(&i2c_dev->completion);
-- return IRQ_HANDLED;
-+ goto complete;
- }
-
- if (val & BCM2835_I2C_S_TXW) {
-+ if (!i2c_dev->msg_buf_remaining) {
-+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN;
-+ goto complete;
-+ }
-+
- bcm2835_fill_txfifo(i2c_dev);
- return IRQ_HANDLED;
- }
-
- if (val & BCM2835_I2C_S_RXR) {
-+ if (!i2c_dev->msg_buf_remaining) {
-+ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN;
-+ goto complete;
-+ }
-+
- bcm2835_drain_rxfifo(i2c_dev);
- return IRQ_HANDLED;
- }
-
- return IRQ_NONE;
-+
-+complete:
-+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
-+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT |
-+ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE);
-+ complete(&i2c_dev->completion);
-+
-+ return IRQ_HANDLED;
- }
-
- static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
-@@ -183,8 +204,9 @@ static int bcm2835_i2c_xfer_msg(struct b
-
- time_left = wait_for_completion_timeout(&i2c_dev->completion,
- BCM2835_I2C_TIMEOUT);
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
- if (!time_left) {
-+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
-+ BCM2835_I2C_C_CLEAR);
- dev_err(i2c_dev->dev, "i2c transfer timed out\n");
- return -ETIMEDOUT;
- }