From b63d4f0fb80918ab37b6c0ee1adcd49e05c9994c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 19 Nov 2005 11:10:35 +0000 Subject: [SERIAL] Fix status reporting with PL011 serial driver The receiver status register reports latched error conditions, which must be cleared by writing to it. However, the data register reports unlatched conditions which are associated with the current character. Use the data register to interpret error status rather than the RSR. Signed-off-by: Russell King --- drivers/serial/amba-pl011.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 938d185841c..89d7bd3eaee 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -49,7 +49,6 @@ #include #include -#include #include #include #include @@ -63,7 +62,8 @@ #define AMBA_ISR_PASS_LIMIT 256 -#define UART_DUMMY_RSR_RX 256 +#define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) +#define UART_DUMMY_DR_RX (1 << 16) /* * We wrap our port structure around the generic uart_port. @@ -116,7 +116,7 @@ pl011_rx_chars(struct uart_amba_port *uap) #endif { struct tty_struct *tty = uap->port.info->tty; - unsigned int status, ch, flag, rsr, max_count = 256; + unsigned int status, ch, flag, max_count = 256; status = readw(uap->port.membase + UART01x_FR); while ((status & UART01x_FR_RXFE) == 0 && max_count--) { @@ -129,7 +129,7 @@ pl011_rx_chars(struct uart_amba_port *uap) */ } - ch = readw(uap->port.membase + UART01x_DR); + ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX; flag = TTY_NORMAL; uap->port.icount.rx++; @@ -137,34 +137,33 @@ pl011_rx_chars(struct uart_amba_port *uap) * Note that the error handling code is * out of the main execution path */ - rsr = readw(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; - if (unlikely(rsr & UART01x_RSR_ANY)) { - if (rsr & UART01x_RSR_BE) { - rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); + if (unlikely(ch & UART_DR_ERROR)) { + if (ch & UART011_DR_BE) { + ch &= ~(UART011_DR_FE | UART011_DR_PE); uap->port.icount.brk++; if (uart_handle_break(&uap->port)) goto ignore_char; - } else if (rsr & UART01x_RSR_PE) + } else if (ch & UART011_DR_PE) uap->port.icount.parity++; - else if (rsr & UART01x_RSR_FE) + else if (ch & UART011_DR_FE) uap->port.icount.frame++; - if (rsr & UART01x_RSR_OE) + if (ch & UART011_DR_OE) uap->port.icount.overrun++; - rsr &= uap->port.read_status_mask; + ch &= uap->port.read_status_mask; - if (rsr & UART01x_RSR_BE) + if (ch & UART011_DR_BE) flag = TTY_BREAK; - else if (rsr & UART01x_RSR_PE) + else if (ch & UART011_DR_PE) flag = TTY_PARITY; - else if (rsr & UART01x_RSR_FE) + else if (ch & UART011_DR_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(&uap->port, ch, regs)) goto ignore_char; - uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag); + uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); ignore_char: status = readw(uap->port.membase + UART01x_FR); @@ -476,33 +475,33 @@ pl011_set_termios(struct uart_port *port, struct termios *termios, */ uart_update_timeout(port, termios->c_cflag, baud); - port->read_status_mask = UART01x_RSR_OE; + port->read_status_mask = UART011_DR_OE | 255; if (termios->c_iflag & INPCK) - port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; + port->read_status_mask |= UART011_DR_FE | UART011_DR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) - port->read_status_mask |= UART01x_RSR_BE; + port->read_status_mask |= UART011_DR_BE; /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; + port->ignore_status_mask |= UART011_DR_FE | UART011_DR_PE; if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= UART01x_RSR_BE; + port->ignore_status_mask |= UART011_DR_BE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= UART01x_RSR_OE; + port->ignore_status_mask |= UART011_DR_OE; } /* * Ignore all characters if CREAD is not set. */ if ((termios->c_cflag & CREAD) == 0) - port->ignore_status_mask |= UART_DUMMY_RSR_RX; + port->ignore_status_mask |= UART_DUMMY_DR_RX; if (UART_ENABLE_MS(port, termios->c_cflag)) pl011_enable_ms(port); -- cgit v1.2.3 From 832f4ede791ae0a96dcbb231ccb181ad7a54bfc2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 19 Nov 2005 11:26:17 +0000 Subject: [SERIAL] Remove unused variable in sa1100.c Since the spinlock was removed from sa1100_start_tx(), the "flags" variable becomes redundant. Remove it. Signed-off-by: Russell King --- drivers/serial/sa1100.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 0e3daf6d7b5..25a086458ab 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -161,7 +161,6 @@ static void sa1100_stop_tx(struct uart_port *port) static void sa1100_start_tx(struct uart_port *port) { struct sa1100_port *sport = (struct sa1100_port *)port; - unsigned long flags; u32 utcr3; utcr3 = UART_GET_UTCR3(sport); -- cgit v1.2.3