Skip to content

Commit bb1201d

Browse files
Jay Dolangregkh
authored andcommitted
serial: 8250_pci: rewrite pericom_do_set_divisor()
Have pericom_do_set_divisor() use the uartclk instead of a hard coded 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. Fixes: 6bf4e42 ("serial: 8250: Add support for higher baud rates to Pericom chips") Cc: stable <[email protected]> Signed-off-by: Jay Dolan <[email protected]> Signed-off-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent c525c5d commit bb1201d

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

drivers/tty/serial/8250/8250_pci.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,29 +1324,33 @@ pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
13241324
{
13251325
int scr;
13261326
int lcr;
1327-
int actual_baud;
1328-
int tolerance;
13291327

1330-
for (scr = 5 ; scr <= 15 ; scr++) {
1331-
actual_baud = 921600 * 16 / scr;
1332-
tolerance = actual_baud / 50;
1328+
for (scr = 16; scr > 4; scr--) {
1329+
unsigned int maxrate = port->uartclk / scr;
1330+
unsigned int divisor = max(maxrate / baud, 1U);
1331+
int delta = maxrate / divisor - baud;
13331332

1334-
if ((baud < actual_baud + tolerance) &&
1335-
(baud > actual_baud - tolerance)) {
1333+
if (baud > maxrate + baud / 50)
1334+
continue;
13361335

1336+
if (delta > baud / 50)
1337+
divisor++;
1338+
1339+
if (divisor > 0xffff)
1340+
continue;
1341+
1342+
/* Update delta due to possible divisor change */
1343+
delta = maxrate / divisor - baud;
1344+
if (abs(delta) < baud / 50) {
13371345
lcr = serial_port_in(port, UART_LCR);
13381346
serial_port_out(port, UART_LCR, lcr | 0x80);
1339-
1340-
serial_port_out(port, UART_DLL, 1);
1341-
serial_port_out(port, UART_DLM, 0);
1347+
serial_port_out(port, UART_DLL, divisor & 0xff);
1348+
serial_port_out(port, UART_DLM, divisor >> 8 & 0xff);
13421349
serial_port_out(port, 2, 16 - scr);
13431350
serial_port_out(port, UART_LCR, lcr);
13441351
return;
1345-
} else if (baud > actual_baud) {
1346-
break;
13471352
}
13481353
}
1349-
serial8250_do_set_divisor(port, baud, quot, quot_frac);
13501354
}
13511355
static int pci_pericom_setup(struct serial_private *priv,
13521356
const struct pciserial_board *board,

0 commit comments

Comments
 (0)