|
@@ -1284,11 +1284,40 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_CONSOLE_POLL
|
|
|
+
|
|
|
+static void pl011_quiesce_irqs(struct uart_port *port)
|
|
|
+{
|
|
|
+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
|
|
+ unsigned char __iomem *regs = uap->port.membase;
|
|
|
+
|
|
|
+ writew(readw(regs + UART011_MIS), regs + UART011_ICR);
|
|
|
+ /*
|
|
|
+ * There is no way to clear TXIM as this is "ready to transmit IRQ", so
|
|
|
+ * we simply mask it. start_tx() will unmask it.
|
|
|
+ *
|
|
|
+ * Note we can race with start_tx(), and if the race happens, the
|
|
|
+ * polling user might get another interrupt just after we clear it.
|
|
|
+ * But it should be OK and can happen even w/o the race, e.g.
|
|
|
+ * controller immediately got some new data and raised the IRQ.
|
|
|
+ *
|
|
|
+ * And whoever uses polling routines assumes that it manages the device
|
|
|
+ * (including tx queue), so we're also fine with start_tx()'s caller
|
|
|
+ * side.
|
|
|
+ */
|
|
|
+ writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC);
|
|
|
+}
|
|
|
+
|
|
|
static int pl011_get_poll_char(struct uart_port *port)
|
|
|
{
|
|
|
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
|
|
unsigned int status;
|
|
|
|
|
|
+ /*
|
|
|
+ * The caller might need IRQs lowered, e.g. if used with KDB NMI
|
|
|
+ * debugger.
|
|
|
+ */
|
|
|
+ pl011_quiesce_irqs(port);
|
|
|
+
|
|
|
status = readw(uap->port.membase + UART01x_FR);
|
|
|
if (status & UART01x_FR_RXFE)
|
|
|
return NO_POLL_CHAR;
|