aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-23 10:05:41 -0400
committerRussell King <rmk@dyn-67.arm.linux.org.uk>2005-06-23 10:05:41 -0400
commit55d3b282b90620e02e825304a9433732a84c58a5 (patch)
treeba48375ac5262a8587eb6237134ed0aa57e7174a
parent4ba5e35daa90871fcb9b01f5ad1e5723343cc0a9 (diff)
[PATCH] Serial: Mobility's 16550A ports need a helping hand
The Mobility 16550A serial ports don't behave the same as standard 16550A ports, and need a helping hand to get them going once the transmitter has drained and been disabled. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/serial/8250.c31
-rw-r--r--drivers/serial/8250.h1
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 27cc288e91d0..341c644591ae 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1027,6 +1027,8 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
1027 } 1027 }
1028} 1028}
1029 1029
1030static void transmit_chars(struct uart_8250_port *up);
1031
1030static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) 1032static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
1031{ 1033{
1032 struct uart_8250_port *up = (struct uart_8250_port *)port; 1034 struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1034,6 +1036,14 @@ static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
1034 if (!(up->ier & UART_IER_THRI)) { 1036 if (!(up->ier & UART_IER_THRI)) {
1035 up->ier |= UART_IER_THRI; 1037 up->ier |= UART_IER_THRI;
1036 serial_out(up, UART_IER, up->ier); 1038 serial_out(up, UART_IER, up->ier);
1039
1040 if (up->capabilities & UART_BUG_TXEN) {
1041 unsigned char lsr, iir;
1042 lsr = serial_in(up, UART_LSR);
1043 iir = serial_in(up, UART_IIR);
1044 if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)
1045 transmit_chars(up);
1046 }
1037 } 1047 }
1038 /* 1048 /*
1039 * We only do this from uart_start 1049 * We only do this from uart_start
@@ -1439,6 +1449,7 @@ static int serial8250_startup(struct uart_port *port)
1439{ 1449{
1440 struct uart_8250_port *up = (struct uart_8250_port *)port; 1450 struct uart_8250_port *up = (struct uart_8250_port *)port;
1441 unsigned long flags; 1451 unsigned long flags;
1452 unsigned char lsr, iir;
1442 int retval; 1453 int retval;
1443 1454
1444 up->capabilities = uart_config[up->port.type].flags; 1455 up->capabilities = uart_config[up->port.type].flags;
@@ -1542,6 +1553,26 @@ static int serial8250_startup(struct uart_port *port)
1542 up->port.mctrl |= TIOCM_OUT2; 1553 up->port.mctrl |= TIOCM_OUT2;
1543 1554
1544 serial8250_set_mctrl(&up->port, up->port.mctrl); 1555 serial8250_set_mctrl(&up->port, up->port.mctrl);
1556
1557 /*
1558 * Do a quick test to see if we receive an
1559 * interrupt when we enable the TX irq.
1560 */
1561 serial_outp(up, UART_IER, UART_IER_THRI);
1562 lsr = serial_in(up, UART_LSR);
1563 iir = serial_in(up, UART_IIR);
1564 serial_outp(up, UART_IER, 0);
1565
1566 if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
1567 if (!(up->capabilities & UART_BUG_TXEN)) {
1568 up->capabilities |= UART_BUG_TXEN;
1569 pr_debug("ttyS%d - enabling bad tx status workarounds\n",
1570 port->line);
1571 }
1572 } else {
1573 up->capabilities &= ~UART_BUG_TXEN;
1574 }
1575
1545 spin_unlock_irqrestore(&up->port.lock, flags); 1576 spin_unlock_irqrestore(&up->port.lock, flags);
1546 1577
1547 /* 1578 /*
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index cd5c3dd2d910..9225c82faeb8 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -52,6 +52,7 @@ struct serial8250_config {
52#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ 52#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
53 53
54#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ 54#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
55#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
55 56
56#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) 57#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
57#define _INLINE_ inline 58#define _INLINE_ inline