Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

David Woodhouse and committed by
Linus Torvalds
b5b82df6 c97a9e10

+18 -3
+18 -3
drivers/serial/8250.c
··· 894 894 quot = serial_dl_read(up); 895 895 quot <<= 3; 896 896 897 - status1 = serial_in(up, 0x04); /* EXCR1 */ 897 + status1 = serial_in(up, 0x04); /* EXCR2 */ 898 898 status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ 899 899 status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ 900 900 serial_outp(up, 0x04, status1); ··· 2617 2617 */ 2618 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 /* ··· 2709 2694 struct uart_8250_port *up = &serial8250_ports[i]; 2710 2695 2711 2696 if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) 2712 - uart_resume_port(&serial8250_reg, &up->port); 2697 + serial8250_resume_port(i); 2713 2698 } 2714 2699 2715 2700 return 0;