diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-05-17 02:27:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-17 08:25:49 -0400 |
commit | b5b82df6f461e66af821bff5b51f336af92d96b6 (patch) | |
tree | b0a782f0f97419082d9c40de7fcc9fd5fd560be2 | |
parent | c97a9e10eaee328e6eea9f76acf7bacd7d48ef56 (diff) |
NS16550A: Restore HS settings in EXCR2 on resume
After a suspend/resume cycle, the UART may have been reset into
low-speed mode -- either because it's actually been reset, or because
the firmware pokes at the old-style divisor registers. If we detected it
as a NS16550A SuperIO chip in the first place and set baud_base to
921600, then we should do so again in the resume path.
This patch adds that code to serial8250_resume_port(), and also makes
serial8250_resume() actually call serial8250_resume_port() for each port
instead of just calling uart_resume_port() directly. And thus fixes
serial port operation after suspend/resume.
It also fixes a bogus comment where we write the EXCR2 register with a
comment saying /* EXCR1 */
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Acked-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/serial/8250.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 48e259a0167d..c84dab083a85 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -894,7 +894,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
894 | quot = serial_dl_read(up); | 894 | quot = serial_dl_read(up); |
895 | quot <<= 3; | 895 | quot <<= 3; |
896 | 896 | ||
897 | status1 = serial_in(up, 0x04); /* EXCR1 */ | 897 | status1 = serial_in(up, 0x04); /* EXCR2 */ |
898 | status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | 898 | status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ |
899 | status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ | 899 | status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ |
900 | serial_outp(up, 0x04, status1); | 900 | serial_outp(up, 0x04, status1); |
@@ -2617,7 +2617,22 @@ void serial8250_suspend_port(int line) | |||
2617 | */ | 2617 | */ |
2618 | void serial8250_resume_port(int line) | 2618 | void serial8250_resume_port(int line) |
2619 | { | 2619 | { |
2620 | uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); | 2620 | struct uart_8250_port *up = &serial8250_ports[line]; |
2621 | |||
2622 | if (up->capabilities & UART_NATSEMI) { | ||
2623 | unsigned char tmp; | ||
2624 | |||
2625 | /* Ensure it's still in high speed mode */ | ||
2626 | serial_outp(up, UART_LCR, 0xE0); | ||
2627 | |||
2628 | tmp = serial_in(up, 0x04); /* EXCR2 */ | ||
2629 | tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | ||
2630 | tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ | ||
2631 | serial_outp(up, 0x04, tmp); | ||
2632 | |||
2633 | serial_outp(up, UART_LCR, 0); | ||
2634 | } | ||
2635 | uart_resume_port(&serial8250_reg, &up->port); | ||
2621 | } | 2636 | } |
2622 | 2637 | ||
2623 | /* | 2638 | /* |
@@ -2694,7 +2709,7 @@ static int serial8250_resume(struct platform_device *dev) | |||
2694 | struct uart_8250_port *up = &serial8250_ports[i]; | 2709 | struct uart_8250_port *up = &serial8250_ports[i]; |
2695 | 2710 | ||
2696 | if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) | 2711 | if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) |
2697 | uart_resume_port(&serial8250_reg, &up->port); | 2712 | serial8250_resume_port(i); |
2698 | } | 2713 | } |
2699 | 2714 | ||
2700 | return 0; | 2715 | return 0; |