| From 2de507b6c59647a1a907c18f62785ddf8d36ed50 Mon Sep 17 00:00:00 2001 |
| From: Lars-Peter Clausen <lars@metafoo.de> |
| Date: Thu, 17 Oct 2013 14:08:09 -0700 |
| Subject: tty: xuartps: Force enable the UART in xuartps_console_write |
| |
| It is possible that under certain circumstances xuartps_console_write is entered |
| while the UART disabled. When this happens the code will busy loop in |
| xuartps_console_putchar, since the character is never written and the TXEMPTY |
| flag is never set. The result is a system lockup. This patch force enables the |
| UART for the duration of xuartps_console_write to avoid this. |
| |
| Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> |
| Signed-off-by: John Linn <john.linn@xilinx.com> |
| Signed-off-by: Michal Simek <michal.simek@xilinx.com> |
| Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit d3755f5e6cd222cd5aff949228d32aa8446023a5) |
| Signed-off-by: Daniel Sangorrin <daniel.sangorrin@toshiba.co.jp> |
| Signed-off-by: Yoshitake Kobayashi <yoshitake.kobayashi@toshiba.co.jp> |
| --- |
| drivers/tty/serial/xilinx_uartps.c | 12 +++++++++++- |
| 1 file changed, 11 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c |
| index 4a1f6080ef59..cf5487841362 100644 |
| --- a/drivers/tty/serial/xilinx_uartps.c |
| +++ b/drivers/tty/serial/xilinx_uartps.c |
| @@ -953,7 +953,7 @@ static void xuartps_console_write(struct console *co, const char *s, |
| { |
| struct uart_port *port = &xuartps_port[co->index]; |
| unsigned long flags; |
| - unsigned int imr; |
| + unsigned int imr, ctrl; |
| int locked = 1; |
| |
| if (oops_in_progress) |
| @@ -965,9 +965,19 @@ static void xuartps_console_write(struct console *co, const char *s, |
| imr = xuartps_readl(XUARTPS_IMR_OFFSET); |
| xuartps_writel(imr, XUARTPS_IDR_OFFSET); |
| |
| + /* |
| + * Make sure that the tx part is enabled. Set the TX enable bit and |
| + * clear the TX disable bit to enable the transmitter. |
| + */ |
| + ctrl = xuartps_readl(XUARTPS_CR_OFFSET); |
| + xuartps_writel((ctrl & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN, |
| + XUARTPS_CR_OFFSET); |
| + |
| uart_console_write(port, s, count, xuartps_console_putchar); |
| xuartps_console_wait_tx(port); |
| |
| + xuartps_writel(ctrl, XUARTPS_CR_OFFSET); |
| + |
| /* restore interrupt state, it seems like there may be a h/w bug |
| * in that the interrupt enable register should not need to be |
| * written based on the data sheet |
| -- |
| 1.8.5.rc3 |
| |