aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-05-17 18:12:37 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-19 19:51:02 -0400
commit5f873bae704cf8b7cbd64b5720912266286c9146 (patch)
tree0e861218bdb25d0ad3f41aa569f89d0f56d59d18
parent4539c24fe4f92c09ee668ef959d3e8180df619b9 (diff)
tty/serial: Fix break handling for PORT_TEGRA
When a break is received, Tegra's UART apparently fills the FIFO with 0 bytes. These must be drained so that they aren't interpreted as actual data received. This allows e.g. MAGIC_SYSRQ to work on Tegra's UARTs. v2: Added FIXME comment to clear_rx_fifo Originally-by: Laxman Dewangan <ldewangan@nvidia.com> Cc: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com> Acked-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/tty/serial/8250.c28
-rw-r--r--include/linux/serial_reg.h1
2 files changed, 29 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index a5e290de8c93..b40f7b90c81d 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1433,6 +1433,27 @@ static void serial8250_enable_ms(struct uart_port *port)
1433 serial_out(up, UART_IER, up->ier); 1433 serial_out(up, UART_IER, up->ier);
1434} 1434}
1435 1435
1436/*
1437 * Clear the Tegra rx fifo after a break
1438 *
1439 * FIXME: This needs to become a port specific callback once we have a
1440 * framework for this
1441 */
1442static void clear_rx_fifo(struct uart_8250_port *up)
1443{
1444 unsigned int status, tmout = 10000;
1445 do {
1446 status = serial_in(up, UART_LSR);
1447 if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS))
1448 status = serial_in(up, UART_RX);
1449 else
1450 break;
1451 if (--tmout == 0)
1452 break;
1453 udelay(1);
1454 } while (1);
1455}
1456
1436static void 1457static void
1437receive_chars(struct uart_8250_port *up, unsigned int *status) 1458receive_chars(struct uart_8250_port *up, unsigned int *status)
1438{ 1459{
@@ -1468,6 +1489,13 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
1468 lsr &= ~(UART_LSR_FE | UART_LSR_PE); 1489 lsr &= ~(UART_LSR_FE | UART_LSR_PE);
1469 up->port.icount.brk++; 1490 up->port.icount.brk++;
1470 /* 1491 /*
1492 * If tegra port then clear the rx fifo to
1493 * accept another break/character.
1494 */
1495 if (up->port.type == PORT_TEGRA)
1496 clear_rx_fifo(up);
1497
1498 /*
1471 * We do the SysRQ and SAK checking 1499 * We do the SysRQ and SAK checking
1472 * here because otherwise the break 1500 * here because otherwise the break
1473 * may get masked by ignore_status_mask 1501 * may get masked by ignore_status_mask
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 5f66e8499fb9..c75bda37c18e 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -119,6 +119,7 @@
119#define UART_MCR_DTR 0x01 /* DTR complement */ 119#define UART_MCR_DTR 0x01 /* DTR complement */
120 120
121#define UART_LSR 5 /* In: Line Status Register */ 121#define UART_LSR 5 /* In: Line Status Register */
122#define UART_LSR_FIFOE 0x80 /* Fifo error */
122#define UART_LSR_TEMT 0x40 /* Transmitter empty */ 123#define UART_LSR_TEMT 0x40 /* Transmitter empty */
123#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ 124#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
124#define UART_LSR_BI 0x10 /* Break interrupt indicator */ 125#define UART_LSR_BI 0x10 /* Break interrupt indicator */