aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/amba-pl011.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2012-03-13 08:27:23 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-14 15:27:39 -0400
commit9b96fbacda34079dea0638ee1e92c56286f6114a (patch)
tree20e4ef458942e413347a75143255f1b0ef62fd90 /drivers/tty/serial/amba-pl011.c
parent60f4b002ab209525c2b818703291ac9a14890e17 (diff)
serial: PL011: clear pending interrupts
Chanho Min reported that when the boot loader transfers control to the kernel, there may be pending interrupts causing the UART to lock up in an eternal loop trying to pick tokens from the FIFO (since the RX interrupt flag indicates there are tokens) while in practice there are no tokens - in fact there is only a pending IRQ flag. This patch address the issue with a combination of two patches suggested by Russell King that clears and mask all interrupts at probe() and clears any pending error and RX interrupts at port startup time. We suspect the spurious interrupts are a side-effect of switching the UART from FIFO to non-FIFO mode. Cc: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com> Reported-by: Chanho Min <chanho0207@gmail.com> Suggested-by: Russell King <linux@arm.linux.org.uk> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Jong-Sung Kim <neidhard.kim@lge.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/amba-pl011.c')
-rw-r--r--drivers/tty/serial/amba-pl011.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index cc3ea066c43a..20d795d9b591 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1396,6 +1396,10 @@ static int pl011_startup(struct uart_port *port)
1396 1396
1397 uap->port.uartclk = clk_get_rate(uap->clk); 1397 uap->port.uartclk = clk_get_rate(uap->clk);
1398 1398
1399 /* Clear pending error and receive interrupts */
1400 writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
1401 UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
1402
1399 /* 1403 /*
1400 * Allocate the IRQ 1404 * Allocate the IRQ
1401 */ 1405 */
@@ -1432,10 +1436,6 @@ static int pl011_startup(struct uart_port *port)
1432 cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; 1436 cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
1433 writew(cr, uap->port.membase + UART011_CR); 1437 writew(cr, uap->port.membase + UART011_CR);
1434 1438
1435 /* Clear pending error interrupts */
1436 writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
1437 uap->port.membase + UART011_ICR);
1438
1439 /* 1439 /*
1440 * initialise the old status of the modem signals 1440 * initialise the old status of the modem signals
1441 */ 1441 */
@@ -1450,6 +1450,9 @@ static int pl011_startup(struct uart_port *port)
1450 * as well. 1450 * as well.
1451 */ 1451 */
1452 spin_lock_irq(&uap->port.lock); 1452 spin_lock_irq(&uap->port.lock);
1453 /* Clear out any spuriously appearing RX interrupts */
1454 writew(UART011_RTIS | UART011_RXIS,
1455 uap->port.membase + UART011_ICR);
1453 uap->im = UART011_RTIM; 1456 uap->im = UART011_RTIM;
1454 if (!pl011_dma_rx_running(uap)) 1457 if (!pl011_dma_rx_running(uap))
1455 uap->im |= UART011_RXIM; 1458 uap->im |= UART011_RXIM;
@@ -1942,6 +1945,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
1942 goto unmap; 1945 goto unmap;
1943 } 1946 }
1944 1947
1948 /* Ensure interrupts from this UART are masked and cleared */
1949 writew(0, uap->port.membase + UART011_IMSC);
1950 writew(0xffff, uap->port.membase + UART011_ICR);
1951
1945 uap->vendor = vendor; 1952 uap->vendor = vendor;
1946 uap->lcrh_rx = vendor->lcrh_rx; 1953 uap->lcrh_rx = vendor->lcrh_rx;
1947 uap->lcrh_tx = vendor->lcrh_tx; 1954 uap->lcrh_tx = vendor->lcrh_tx;