diff options
| -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) |
