diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-06-23 10:05:41 -0400 |
---|---|---|
committer | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-06-23 10:05:41 -0400 |
commit | 55d3b282b90620e02e825304a9433732a84c58a5 (patch) | |
tree | ba48375ac5262a8587eb6237134ed0aa57e7174a | |
parent | 4ba5e35daa90871fcb9b01f5ad1e5723343cc0a9 (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.c | 31 | ||||
-rw-r--r-- | drivers/serial/8250.h | 1 |
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 | ||
1030 | static void transmit_chars(struct uart_8250_port *up); | ||
1031 | |||
1030 | static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) | 1032 | static 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 |