| diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c |
| index 2209620..659c1bb 100644 |
| |
| |
| @@ -7,6 +7,9 @@ |
| * |
| * Copyright (C) 2001 Russell King. |
| * |
| + * 2005/09/16: Enabled higher baud rates for 16C95x. |
| + * (Mathias Adam <a2@adamis.de>) |
| + * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| @@ -2227,6 +2230,14 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int |
| else if ((port->flags & UPF_MAGIC_MULTIPLIER) && |
| baud == (port->uartclk/8)) |
| quot = 0x8002; |
| + /* |
| + * For 16C950s UART_TCR is used in combination with divisor==1 |
| + * to achieve baud rates up to baud_base*4. |
| + */ |
| + else if ((port->type == PORT_16C950) && |
| + baud > (port->uartclk/16)) |
| + quot = 1; |
| + |
| else |
| quot = uart_get_divisor(port, baud); |
| |
| @@ -2240,7 +2251,7 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| struct uart_8250_port *up = (struct uart_8250_port *)port; |
| unsigned char cval, fcr = 0; |
| unsigned long flags; |
| - unsigned int baud, quot; |
| + unsigned int baud, quot, max_baud; |
| |
| switch (termios->c_cflag & CSIZE) { |
| case CS5: |
| @@ -2272,9 +2283,10 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| /* |
| * Ask the core to calculate the divisor for us. |
| */ |
| + max_baud = (up->port.type == PORT_16C950 ? port->uartclk/4 : port->uartclk/16); |
| baud = uart_get_baud_rate(port, termios, old, |
| port->uartclk / 16 / 0xffff, |
| - port->uartclk / 16); |
| + max_baud); |
| quot = serial8250_get_divisor(port, baud); |
| |
| /* |
| @@ -2311,6 +2323,19 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| spin_lock_irqsave(&up->port.lock, flags); |
| |
| /* |
| + * 16C950 supports additional prescaler ratios between 1:16 and 1:4 |
| + * thus increasing max baud rate to uartclk/4. |
| + */ |
| + if (up->port.type == PORT_16C950) { |
| + if (baud == port->uartclk/4) |
| + serial_icr_write(up, UART_TCR, 0x4); |
| + else if (baud == port->uartclk/8) |
| + serial_icr_write(up, UART_TCR, 0x8); |
| + else |
| + serial_icr_write(up, UART_TCR, 0); |
| + } |
| + |
| + /* |
| * Update the per-port timeout. |
| */ |
| uart_update_timeout(port, termios->c_cflag, baud); |