diff options
author | Max Krummenacher <max.krummenacher@toradex.com> | 2012-12-13 19:47:32 -0700 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2012-12-17 13:27:29 +0100 |
commit | f6417beb8f7bbfcbb9e047b582a22f4feaee3124 (patch) | |
tree | 5a5ff1bd8c6d35cd7a9c19de055273c4d7aa243c | |
parent | 8ec3b97a69a7aaa9fe0d9e2d977b118a62e03579 (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.c | 21 |
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; |