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 <jay.dolan@xxxxxxxxxxx> --- 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