aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-05-17 02:27:39 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-17 08:25:49 -0400
commitb5b82df6f461e66af821bff5b51f336af92d96b6 (patch)
treeb0a782f0f97419082d9c40de7fcc9fd5fd560be2 /drivers/serial
parentc97a9e10eaee328e6eea9f76acf7bacd7d48ef56 (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>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/8250.c21
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 */
2618void serial8250_resume_port(int line) 2618void 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;