diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2015-01-22 12:24:28 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-02-02 13:11:27 -0500 |
commit | e72abd5da0730dfc4c8f566f7896c15c2d1bb88f (patch) | |
tree | 8bd40b7a67a98e221997cdde6e8cabbc3a99368b /drivers/tty | |
parent | 0ec3f585cfb503a18b82cd181c9bf32b45a24f5e (diff) |
serial: 8250: Refactor divisor programming
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>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/8250/8250_core.c | 87 |
1 files changed, 48 insertions, 39 deletions
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index b63b9c352cc2..fd9e723926cd 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c | |||
@@ -2478,6 +2478,50 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, | |||
2478 | return cval; | 2478 | return cval; |
2479 | } | 2479 | } |
2480 | 2480 | ||
2481 | void serial8250_set_divisor(struct uart_port *port, unsigned int baud, | ||
2482 | unsigned int quot) | ||
2483 | { | ||
2484 | struct uart_8250_port *up = up_to_u8250p(port); | ||
2485 | |||
2486 | /* Workaround to enable 115200 baud on OMAP1510 internal ports */ | ||
2487 | if (is_omap1510_8250(up)) { | ||
2488 | if (baud == 115200) { | ||
2489 | quot = 1; | ||
2490 | serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1); | ||
2491 | } else | ||
2492 | serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0); | ||
2493 | } | ||
2494 | |||
2495 | /* | ||
2496 | * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2, | ||
2497 | * otherwise just set DLAB | ||
2498 | */ | ||
2499 | if (up->capabilities & UART_NATSEMI) | ||
2500 | serial_port_out(port, UART_LCR, 0xe0); | ||
2501 | else | ||
2502 | serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); | ||
2503 | |||
2504 | serial_dl_write(up, quot); | ||
2505 | |||
2506 | /* | ||
2507 | * XR17V35x UARTs have an extra fractional divisor register (DLD) | ||
2508 | * | ||
2509 | * We need to recalculate all of the registers, because DLM and DLL | ||
2510 | * are already rounded to a whole integer. | ||
2511 | * | ||
2512 | * When recalculating we use a 32x clock instead of a 16x clock to | ||
2513 | * allow 1-bit for rounding in the fractional part. | ||
2514 | */ | ||
2515 | if (up->port.type == PORT_XR17V35X) { | ||
2516 | unsigned int baud_x32 = (port->uartclk * 2) / baud; | ||
2517 | u16 quot = baud_x32 / 32; | ||
2518 | u8 quot_frac = DIV_ROUND_CLOSEST(baud_x32 % 32, 2); | ||
2519 | |||
2520 | serial_dl_write(up, quot); | ||
2521 | serial_port_out(port, 0x2, quot_frac & 0xf); | ||
2522 | } | ||
2523 | } | ||
2524 | |||
2481 | void | 2525 | void |
2482 | serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, | 2526 | serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, |
2483 | struct ktermios *old) | 2527 | struct ktermios *old) |
@@ -2526,6 +2570,8 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2526 | serial8250_rpm_get(up); | 2570 | serial8250_rpm_get(up); |
2527 | spin_lock_irqsave(&port->lock, flags); | 2571 | spin_lock_irqsave(&port->lock, flags); |
2528 | 2572 | ||
2573 | up->lcr = cval; /* Save computed LCR */ | ||
2574 | |||
2529 | /* | 2575 | /* |
2530 | * Update the per-port timeout. | 2576 | * Update the per-port timeout. |
2531 | */ | 2577 | */ |
@@ -2590,43 +2636,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2590 | serial_port_out(port, UART_EFR, efr); | 2636 | serial_port_out(port, UART_EFR, efr); |
2591 | } | 2637 | } |
2592 | 2638 | ||
2593 | /* Workaround to enable 115200 baud on OMAP1510 internal ports */ | 2639 | serial8250_set_divisor(port, baud, quot); |
2594 | if (is_omap1510_8250(up)) { | ||
2595 | if (baud == 115200) { | ||
2596 | quot = 1; | ||
2597 | serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1); | ||
2598 | } else | ||
2599 | serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0); | ||
2600 | } | ||
2601 | |||
2602 | /* | ||
2603 | * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2, | ||
2604 | * otherwise just set DLAB | ||
2605 | */ | ||
2606 | if (up->capabilities & UART_NATSEMI) | ||
2607 | serial_port_out(port, UART_LCR, 0xe0); | ||
2608 | else | ||
2609 | serial_port_out(port, UART_LCR, cval | UART_LCR_DLAB); | ||
2610 | |||
2611 | serial_dl_write(up, quot); | ||
2612 | |||
2613 | /* | ||
2614 | * XR17V35x UARTs have an extra fractional divisor register (DLD) | ||
2615 | * | ||
2616 | * We need to recalculate all of the registers, because DLM and DLL | ||
2617 | * are already rounded to a whole integer. | ||
2618 | * | ||
2619 | * When recalculating we use a 32x clock instead of a 16x clock to | ||
2620 | * allow 1-bit for rounding in the fractional part. | ||
2621 | */ | ||
2622 | if (up->port.type == PORT_XR17V35X) { | ||
2623 | unsigned int baud_x32 = (port->uartclk * 2) / baud; | ||
2624 | u16 quot = baud_x32 / 32; | ||
2625 | u8 quot_frac = DIV_ROUND_CLOSEST(baud_x32 % 32, 2); | ||
2626 | |||
2627 | serial_dl_write(up, quot); | ||
2628 | serial_port_out(port, 0x2, quot_frac & 0xf); | ||
2629 | } | ||
2630 | 2640 | ||
2631 | /* | 2641 | /* |
2632 | * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR | 2642 | * 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, | |||
2635 | if (port->type == PORT_16750) | 2645 | if (port->type == PORT_16750) |
2636 | serial_port_out(port, UART_FCR, up->fcr); | 2646 | serial_port_out(port, UART_FCR, up->fcr); |
2637 | 2647 | ||
2638 | serial_port_out(port, UART_LCR, cval); /* reset DLAB */ | 2648 | serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */ |
2639 | up->lcr = cval; /* Save LCR */ | ||
2640 | if (port->type != PORT_16750) { | 2649 | if (port->type != PORT_16750) { |
2641 | /* emulated UARTs (Lucent Venus 167x) need two steps */ | 2650 | /* emulated UARTs (Lucent Venus 167x) need two steps */ |
2642 | if (up->fcr & UART_FCR_ENABLE_FIFO) | 2651 | if (up->fcr & UART_FCR_ENABLE_FIFO) |