aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2015-09-25 15:36:10 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-10-04 14:12:25 -0400
commit4f56f3fdca43c9a18339b6e0c3b1aa2f57f6d0b0 (patch)
tree4cc3ba6f84127d0b79630f48eb24d47f06d4c648
parentd215d80957ce98c318064c249ad0b7800c63a19d (diff)
serial: 8250: Tolerate clock variance for max baud rate
When the UART clock is set slightly under 1.8432MHz, the 8250 driver core doesn't permit the 115200 baud rate since it calculates the maximum frequency to pass to uart_get_baud_rate by simply dividing the uart clock by 16 which yields a value slightly under 115200, even though the frequency is close enough for the UART to operate reliably. Therefore add some tolerance in the calculation of the maximum baud rate. 1% tolerance allows for marginally slower uart clk than nominal without introducing transmission errors. Signed-off-by: James Hogan <james.hogan@imgtec.com> [pjh: Forward-port & refactor original patch; change tolerance to 1%] Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/8250/8250_port.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 554a63e4c4a0..e54de0037df4 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2225,6 +2225,23 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
2225 serial_port_out(port, 0x2, quot_frac); 2225 serial_port_out(port, 0x2, quot_frac);
2226} 2226}
2227 2227
2228static unsigned int
2229serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios,
2230 struct ktermios *old)
2231{
2232 unsigned int tolerance = port->uartclk / 100;
2233
2234 /*
2235 * Ask the core to calculate the divisor for us.
2236 * Allow 1% tolerance at the upper limit so uart clks marginally
2237 * slower than nominal still match standard baud rates without
2238 * causing transmission errors.
2239 */
2240 return uart_get_baud_rate(port, termios, old,
2241 port->uartclk / 16 / 0xffff,
2242 (port->uartclk + tolerance) / 16);
2243}
2244
2228void 2245void
2229serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, 2246serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
2230 struct ktermios *old) 2247 struct ktermios *old)
@@ -2236,12 +2253,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
2236 2253
2237 cval = serial8250_compute_lcr(up, termios->c_cflag); 2254 cval = serial8250_compute_lcr(up, termios->c_cflag);
2238 2255
2239 /* 2256 baud = serial8250_get_baud_rate(port, termios, old);
2240 * Ask the core to calculate the divisor for us.
2241 */
2242 baud = uart_get_baud_rate(port, termios, old,
2243 port->uartclk / 16 / 0xffff,
2244 port->uartclk / 16);
2245 quot = serial8250_get_divisor(up, baud, &frac); 2257 quot = serial8250_get_divisor(up, baud, &frac);
2246 2258
2247 /* 2259 /*
@@ -2834,9 +2846,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
2834 if (port->state->port.tty && termios.c_cflag == 0) 2846 if (port->state->port.tty && termios.c_cflag == 0)
2835 termios.c_cflag = port->state->port.tty->termios.c_cflag; 2847 termios.c_cflag = port->state->port.tty->termios.c_cflag;
2836 2848
2837 baud = uart_get_baud_rate(port, &termios, NULL, 2849 baud = serial8250_get_baud_rate(port, &termios, NULL);
2838 port->uartclk / 16 / 0xffff,
2839 port->uartclk / 16);
2840 quot = serial8250_get_divisor(up, baud, &frac); 2850 quot = serial8250_get_divisor(up, baud, &frac);
2841 2851
2842 serial8250_set_divisor(port, baud, quot, frac); 2852 serial8250_set_divisor(port, baud, quot, frac);