aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/amba-pl011.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/amba-pl011.c')
-rw-r--r--drivers/tty/serial/amba-pl011.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 9ae024025ff3..6800f5f26241 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -159,6 +159,7 @@ struct uart_amba_port {
159 unsigned int fifosize; /* vendor-specific */ 159 unsigned int fifosize; /* vendor-specific */
160 unsigned int lcrh_tx; /* vendor-specific */ 160 unsigned int lcrh_tx; /* vendor-specific */
161 unsigned int lcrh_rx; /* vendor-specific */ 161 unsigned int lcrh_rx; /* vendor-specific */
162 unsigned int old_cr; /* state during shutdown */
162 bool autorts; 163 bool autorts;
163 char type[12]; 164 char type[12];
164 bool interrupt_may_hang; /* vendor-specific */ 165 bool interrupt_may_hang; /* vendor-specific */
@@ -1411,7 +1412,9 @@ static int pl011_startup(struct uart_port *port)
1411 while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY) 1412 while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
1412 barrier(); 1413 barrier();
1413 1414
1414 cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; 1415 /* restore RTS and DTR */
1416 cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
1417 cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
1415 writew(cr, uap->port.membase + UART011_CR); 1418 writew(cr, uap->port.membase + UART011_CR);
1416 1419
1417 /* Clear pending error interrupts */ 1420 /* Clear pending error interrupts */
@@ -1469,6 +1472,7 @@ static void pl011_shutdown_channel(struct uart_amba_port *uap,
1469static void pl011_shutdown(struct uart_port *port) 1472static void pl011_shutdown(struct uart_port *port)
1470{ 1473{
1471 struct uart_amba_port *uap = (struct uart_amba_port *)port; 1474 struct uart_amba_port *uap = (struct uart_amba_port *)port;
1475 unsigned int cr;
1472 1476
1473 /* 1477 /*
1474 * disable all interrupts 1478 * disable all interrupts
@@ -1488,9 +1492,16 @@ static void pl011_shutdown(struct uart_port *port)
1488 1492
1489 /* 1493 /*
1490 * disable the port 1494 * disable the port
1495 * disable the port. It should not disable RTS and DTR.
1496 * Also RTS and DTR state should be preserved to restore
1497 * it during startup().
1491 */ 1498 */
1492 uap->autorts = false; 1499 uap->autorts = false;
1493 writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR); 1500 cr = readw(uap->port.membase + UART011_CR);
1501 uap->old_cr = cr;
1502 cr &= UART011_CR_RTS | UART011_CR_DTR;
1503 cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
1504 writew(cr, uap->port.membase + UART011_CR);
1494 1505
1495 /* 1506 /*
1496 * disable break condition and fifos 1507 * disable break condition and fifos
@@ -1740,9 +1751,19 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
1740{ 1751{
1741 struct uart_amba_port *uap = amba_ports[co->index]; 1752 struct uart_amba_port *uap = amba_ports[co->index];
1742 unsigned int status, old_cr, new_cr; 1753 unsigned int status, old_cr, new_cr;
1754 unsigned long flags;
1755 int locked = 1;
1743 1756
1744 clk_enable(uap->clk); 1757 clk_enable(uap->clk);
1745 1758
1759 local_irq_save(flags);
1760 if (uap->port.sysrq)
1761 locked = 0;
1762 else if (oops_in_progress)
1763 locked = spin_trylock(&uap->port.lock);
1764 else
1765 spin_lock(&uap->port.lock);
1766
1746 /* 1767 /*
1747 * First save the CR then disable the interrupts 1768 * First save the CR then disable the interrupts
1748 */ 1769 */
@@ -1762,6 +1783,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
1762 } while (status & UART01x_FR_BUSY); 1783 } while (status & UART01x_FR_BUSY);
1763 writew(old_cr, uap->port.membase + UART011_CR); 1784 writew(old_cr, uap->port.membase + UART011_CR);
1764 1785
1786 if (locked)
1787 spin_unlock(&uap->port.lock);
1788 local_irq_restore(flags);
1789
1765 clk_disable(uap->clk); 1790 clk_disable(uap->clk);
1766} 1791}
1767 1792
@@ -1905,6 +1930,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
1905 uap->vendor = vendor; 1930 uap->vendor = vendor;
1906 uap->lcrh_rx = vendor->lcrh_rx; 1931 uap->lcrh_rx = vendor->lcrh_rx;
1907 uap->lcrh_tx = vendor->lcrh_tx; 1932 uap->lcrh_tx = vendor->lcrh_tx;
1933 uap->old_cr = 0;
1908 uap->fifosize = vendor->fifosize; 1934 uap->fifosize = vendor->fifosize;
1909 uap->interrupt_may_hang = vendor->interrupt_may_hang; 1935 uap->interrupt_may_hang = vendor->interrupt_may_hang;
1910 uap->port.dev = &dev->dev; 1936 uap->port.dev = &dev->dev;