diff options
-rw-r--r-- | drivers/tty/serial/8250/8250_port.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index fc5ab2032282..b96562102b43 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2516,9 +2516,36 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port, unsigned int quot; /* - * Handle magic divisors for baud rates above baud_base on - * SMSC SuperIO chips. + * Handle magic divisors for baud rates above baud_base on SMSC + * Super I/O chips. We clamp custom rates from clk/6 and clk/12 + * up to clk/4 (0x8001) and clk/8 (0x8002) respectively. These + * magic divisors actually reprogram the baud rate generator's + * reference clock derived from chips's 14.318MHz clock input. * + * Documentation claims that with these magic divisors the base + * frequencies of 7.3728MHz and 3.6864MHz are used respectively + * for the extra baud rates of 460800bps and 230400bps rather + * than the usual base frequency of 1.8462MHz. However empirical + * evidence contradicts that. + * + * Instead bit 7 of the DLM register (bit 15 of the divisor) is + * effectively used as a clock prescaler selection bit for the + * base frequency of 7.3728MHz, always used. If set to 0, then + * the base frequency is divided by 4 for use by the Baud Rate + * Generator, for the usual arrangement where the value of 1 of + * the divisor produces the baud rate of 115200bps. Conversely, + * if set to 1 and high-speed operation has been enabled with the + * Serial Port Mode Register in the Device Configuration Space, + * then the base frequency is supplied directly to the Baud Rate + * Generator, so for the divisor values of 0x8001, 0x8002, 0x8003, + * 0x8004, etc. the respective baud rates produced are 460800bps, + * 230400bps, 153600bps, 115200bps, etc. + * + * In all cases only low 15 bits of the divisor are used to divide + * the baud base and therefore 32767 is the maximum divisor value + * possible, even though documentation says that the programmable + * Baud Rate Generator is capable of dividing the internal PLL + * clock by any divisor from 1 to 65535. */ if ((port->flags & UPF_MAGIC_MULTIPLIER) && baud == (port->uartclk/4)) |