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 = serial_dl_read(up); | ||||||
| 			quot <<= 3; | 			quot <<= 3; | ||||||
| 
 | 
 | ||||||
| 			status1 = serial_in(up, 0x04); /* EXCR1 */ | 			status1 = serial_in(up, 0x04); /* EXCR2 */ | ||||||
| 			status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | 			status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ | ||||||
| 			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */ | 			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */ | ||||||
| 			serial_outp(up, 0x04, status1); | 			serial_outp(up, 0x04, status1); | ||||||
|  | @ -2617,7 +2617,22 @@ void serial8250_suspend_port(int line) | ||||||
|  */ |  */ | ||||||
| void serial8250_resume_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]; | 		struct uart_8250_port *up = &serial8250_ports[i]; | ||||||
| 
 | 
 | ||||||
| 		if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) | 		if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) | ||||||
| 			uart_resume_port(&serial8250_reg, &up->port); | 			serial8250_resume_port(i); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 David Woodhouse
				David Woodhouse