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>
This commit is contained in:
		
					parent
					
						
							
								c97a9e10ea
							
						
					
				
			
			
				commit
				
					
						b5b82df6f4
					
				
			
		
					 1 changed files with 18 additions and 3 deletions
				
			
		|  | @ -894,7 +894,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
| 			quot = serial_dl_read(up); | ||||
| 			quot <<= 3; | ||||
| 
 | ||||
| 			status1 = serial_in(up, 0x04); /* EXCR1 */ | ||||
| 			status1 = serial_in(up, 0x04); /* EXCR2 */ | ||||
| 			status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | ||||
| 			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */ | ||||
| 			serial_outp(up, 0x04, status1); | ||||
|  | @ -2617,7 +2617,22 @@ void serial8250_suspend_port(int line) | |||
|  */ | ||||
| void serial8250_resume_port(int line) | ||||
| { | ||||
| 	uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); | ||||
| 	struct uart_8250_port *up = &serial8250_ports[line]; | ||||
| 
 | ||||
| 	if (up->capabilities & UART_NATSEMI) { | ||||
| 		unsigned char tmp; | ||||
| 
 | ||||
| 		/* Ensure it's still in high speed mode */ | ||||
| 		serial_outp(up, UART_LCR, 0xE0); | ||||
| 
 | ||||
| 		tmp = serial_in(up, 0x04); /* EXCR2 */ | ||||
| 		tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | ||||
| 		tmp |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */ | ||||
| 		serial_outp(up, 0x04, tmp); | ||||
| 
 | ||||
| 		serial_outp(up, UART_LCR, 0); | ||||
| 	} | ||||
| 	uart_resume_port(&serial8250_reg, &up->port); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -2694,7 +2709,7 @@ static int serial8250_resume(struct platform_device *dev) | |||
| 		struct uart_8250_port *up = &serial8250_ports[i]; | ||||
| 
 | ||||
| 		if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) | ||||
| 			uart_resume_port(&serial8250_reg, &up->port); | ||||
| 			serial8250_resume_port(i); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 David Woodhouse
				David Woodhouse