summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2012-12-13 19:47:32 -0700
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-12-17 13:27:29 +0100
commitf6417beb8f7bbfcbb9e047b582a22f4feaee3124 (patch)
tree5a5ff1bd8c6d35cd7a9c19de055273c4d7aa243c
parent8ec3b97a69a7aaa9fe0d9e2d977b118a62e03579 (diff)
tty: serial: 8250: tegra: irq 68: nobody cared workaround
The irq request flag sometimes does not get reset or is asserted immediately, but iir does not indicated this, if so ISR is entered with iir set to 0xc1, i.e. no irq pending. Try enabling the transmit register empty interrupt, iir becomes 0xc2, irq gets de-asserted and ier is reverted by the regular code flow in the ISR. We try this every 4096 spurious irq. Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
-rw-r--r--drivers/tty/serial/8250.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index a3f966b39862..295fd2d7c713 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1641,6 +1641,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
struct irq_info *i = dev_id;
struct list_head *l, *end = NULL;
int pass_counter = 0, handled = 0;
+ static unsigned int tegra_spurious = 0;
DEBUG_INTR("serial8250_interrupt(%d)...", irq);
@@ -1674,6 +1675,26 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
handled = 1;
end = NULL;
+ } else if ((up->port.type == PORT_TEGRA) && !handled) {
+ /* irq 68: nobody cared workaround */
+
+ /* The irq request flag sometimes does not get reset or is
+ * asserted immediately, but iir does not indicated this, if
+ * so we get here with iir set to 0xc1, i.e. no irq pending. */
+
+ /* Try enabling the transmit register empty interrupt,
+ * iir becomes 0xc2, irq gets de-asserted and ier is reverted
+ * by the regular code flow in the ISR. */
+ tegra_spurious++;
+ /* Try this every 4096 spurious irq. */
+ if ((tegra_spurious % 0x1000) == 0xfff) {
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ udelay(1);
+ handled = 1;
+ end = NULL;
+ } else if (end == NULL)
+ end = l;
} else if (end == NULL)
end = l;