Thread (10 messages) 10 messages, 3 authors, 2021-11-25
STALE1702d

[PATCH 1/3] serial: 8250_pci: rewrite pericom_do_set_divisor

From: Jay Dolan <hidden>
Date: 2021-11-14 18:39:18
Subsystem: 8250/16?50 (and clone uarts) serial driver, the rest, tty layer and serial drivers · Maintainers: Greg Kroah-Hartman, Linus Torvalds, Jiri Slaby

Fixes: 6bf4e42f1d19de10800f4483b4bb7945aab283cb

Have pericom_do_set_divisor() use the uartclk instead of a hardcoded
value to work with different speed crystals. Tested with 14.7456 and 24
MHz crystals
Have pericom_do_set_divisor always calculate the divisor rather than
call serial8250_do_set_divisor() for rates below baud_base.
Do not write registers or call serial8250_do_set_divisor() if valid
divisors could not be found.

Signed-off-by: Jay Dolan <redacted>
---
 drivers/tty/serial/8250/8250_pci.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 5d43de143f33..aea43683b76d 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1325,28 +1325,32 @@ pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
 	int scr;
 	int lcr;
 	int actual_baud;
-	int tolerance;
+	int divisor;
 
-	for (scr = 5 ; scr <= 15 ; scr++) {
-		actual_baud = 921600 * 16 / scr;
-		tolerance = actual_baud / 50;
+	for (scr = 16 ; scr > 4 ; scr--) {
+		if (baud > (port->uartclk / scr) + (baud/50))
+			continue;
 
-		if ((baud < actual_baud + tolerance) &&
-			(baud > actual_baud - tolerance)) {
+		divisor = port->uartclk / scr / baud;
+		if (divisor == 0 ||
+			port->uartclk / scr / divisor - baud > baud/50) {
+			divisor++;
+		}
+
+		if (divisor > 0xffff)
+			continue;
 
+		actual_baud = port->uartclk / scr / divisor;
+		if (abs(actual_baud - baud) < baud/50) {
 			lcr = serial_port_in(port, UART_LCR);
 			serial_port_out(port, UART_LCR, lcr | 0x80);
-
-			serial_port_out(port, UART_DLL, 1);
-			serial_port_out(port, UART_DLM, 0);
+			serial_port_out(port, UART_DLL, divisor & 0xff);
+			serial_port_out(port, UART_DLM, divisor >> 8 & 0xff);
 			serial_port_out(port, 2, 16 - scr);
 			serial_port_out(port, UART_LCR, lcr);
 			return;
-		} else if (baud > actual_baud) {
-			break;
 		}
 	}
-	serial8250_do_set_divisor(port, baud, quot, quot_frac);
 }
 static int pci_pericom_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
-- 
2.25.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help