serial: 8250: Refactor divisor programming
authorPeter Hurley <peter@hurleysoftware.com>
Thu, 22 Jan 2015 17:24:28 +0000 (12:24 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Feb 2015 18:11:27 +0000 (10:11 -0800)
Refactor divisor register programming into a new function,
serial8250_set_divisor; this allows serial console to reinitialize
early after resume from suspend.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/8250/8250_core.c

index b63b9c3..fd9e723 100644 (file)
@@ -2478,6 +2478,50 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
        return cval;
 }
 
+void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
+                           unsigned int quot)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+       if (is_omap1510_8250(up)) {
+               if (baud == 115200) {
+                       quot = 1;
+                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
+               } else
+                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
+       }
+
+       /*
+        * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
+        * otherwise just set DLAB
+        */
+       if (up->capabilities & UART_NATSEMI)
+               serial_port_out(port, UART_LCR, 0xe0);
+       else
+               serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
+
+       serial_dl_write(up, quot);
+
+       /*
+        * XR17V35x UARTs have an extra fractional divisor register (DLD)
+        *
+        * We need to recalculate all of the registers, because DLM and DLL
+        * are already rounded to a whole integer.
+        *
+        * When recalculating we use a 32x clock instead of a 16x clock to
+        * allow 1-bit for rounding in the fractional part.
+        */
+       if (up->port.type == PORT_XR17V35X) {
+               unsigned int baud_x32 = (port->uartclk * 2) / baud;
+               u16 quot = baud_x32 / 32;
+               u8 quot_frac = DIV_ROUND_CLOSEST(baud_x32 % 32, 2);
+
+               serial_dl_write(up, quot);
+               serial_port_out(port, 0x2, quot_frac & 0xf);
+       }
+}
+
 void
 serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
                          struct ktermios *old)
@@ -2526,6 +2570,8 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
        serial8250_rpm_get(up);
        spin_lock_irqsave(&port->lock, flags);
 
+       up->lcr = cval;                                 /* Save computed LCR */
+
        /*
         * Update the per-port timeout.
         */
@@ -2590,43 +2636,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
                        serial_port_out(port, UART_EFR, efr);
        }
 
-       /* Workaround to enable 115200 baud on OMAP1510 internal ports */
-       if (is_omap1510_8250(up)) {
-               if (baud == 115200) {
-                       quot = 1;
-                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
-               } else
-                       serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
-       }
-
-       /*
-        * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
-        * otherwise just set DLAB
-        */
-       if (up->capabilities & UART_NATSEMI)
-               serial_port_out(port, UART_LCR, 0xe0);
-       else
-               serial_port_out(port, UART_LCR, cval | UART_LCR_DLAB);
-
-       serial_dl_write(up, quot);
-
-       /*
-        * XR17V35x UARTs have an extra fractional divisor register (DLD)
-        *
-        * We need to recalculate all of the registers, because DLM and DLL
-        * are already rounded to a whole integer.
-        *
-        * When recalculating we use a 32x clock instead of a 16x clock to
-        * allow 1-bit for rounding in the fractional part.
-        */
-       if (up->port.type == PORT_XR17V35X) {
-               unsigned int baud_x32 = (port->uartclk * 2) / baud;
-               u16 quot = baud_x32 / 32;
-               u8 quot_frac = DIV_ROUND_CLOSEST(baud_x32 % 32, 2);
-
-               serial_dl_write(up, quot);
-               serial_port_out(port, 0x2, quot_frac & 0xf);
-       }
+       serial8250_set_divisor(port, baud, quot);
 
        /*
         * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
@@ -2635,8 +2645,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
        if (port->type == PORT_16750)
                serial_port_out(port, UART_FCR, up->fcr);
 
-       serial_port_out(port, UART_LCR, cval);          /* reset DLAB */
-       up->lcr = cval;                                 /* Save LCR */
+       serial_port_out(port, UART_LCR, up->lcr);       /* reset DLAB */
        if (port->type != PORT_16750) {
                /* emulated UARTs (Lucent Venus 167x) need two steps */
                if (up->fcr & UART_FCR_ENABLE_FIFO)