diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2014-02-07 09:16:04 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-13 12:33:04 -0500 |
commit | e97e15561cd885926f78200a1e75e713172da60e (patch) | |
tree | 03146120f801947ec35364278b657fb52026c280 /drivers/tty/serial/max310x.c | |
parent | d0fd413cffb7cd8efac6d4d192ba62fc2fa60d2d (diff) |
serial: max310x: Setup baud rate generator more precisely
This patch provide more precisely setup of baud rate generator.
If the result of division has a remainder, we use the multiplier
for the base frequency. Additionally, we report result baud rate
back to serial core.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/max310x.c')
-rw-r--r-- | drivers/tty/serial/max310x.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 8d71e4047bb3..313bdf0bb21b 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver | 2 | * Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver |
3 | * | 3 | * |
4 | * Copyright (C) 2012-2013 Alexander Shiyan <shc_work@mail.ru> | 4 | * Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru> |
5 | * | 5 | * |
6 | * Based on max3100.c, by Christian Pellegrin <chripell@evolware.org> | 6 | * Based on max3100.c, by Christian Pellegrin <chripell@evolware.org> |
7 | * Based on max3110.c, by Feng Tang <feng.tang@intel.com> | 7 | * Based on max3110.c, by Feng Tang <feng.tang@intel.com> |
@@ -504,25 +504,33 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg) | |||
504 | return false; | 504 | return false; |
505 | } | 505 | } |
506 | 506 | ||
507 | static void max310x_set_baud(struct uart_port *port, int baud) | 507 | static int max310x_set_baud(struct uart_port *port, int baud) |
508 | { | 508 | { |
509 | unsigned int mode = 0, div = port->uartclk / baud; | 509 | unsigned int mode = 0, clk = port->uartclk, div = clk / baud; |
510 | 510 | ||
511 | if (!(div / 16)) { | 511 | /* Check for minimal value for divider */ |
512 | if (div < 16) | ||
513 | div = 16; | ||
514 | |||
515 | if (clk % baud && (div / 16) < 0x8000) { | ||
512 | /* Mode x2 */ | 516 | /* Mode x2 */ |
513 | mode = MAX310X_BRGCFG_2XMODE_BIT; | 517 | mode = MAX310X_BRGCFG_2XMODE_BIT; |
514 | div = (port->uartclk * 2) / baud; | 518 | clk = port->uartclk * 2; |
515 | } | 519 | div = clk / baud; |
516 | 520 | ||
517 | if (!(div / 16)) { | 521 | if (clk % baud && (div / 16) < 0x8000) { |
518 | /* Mode x4 */ | 522 | /* Mode x4 */ |
519 | mode = MAX310X_BRGCFG_4XMODE_BIT; | 523 | mode = MAX310X_BRGCFG_4XMODE_BIT; |
520 | div = (port->uartclk * 4) / baud; | 524 | clk = port->uartclk * 4; |
525 | div = clk / baud; | ||
526 | } | ||
521 | } | 527 | } |
522 | 528 | ||
523 | max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8); | 529 | max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8); |
524 | max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16); | 530 | max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16); |
525 | max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode); | 531 | max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode); |
532 | |||
533 | return DIV_ROUND_CLOSEST(clk, div); | ||
526 | } | 534 | } |
527 | 535 | ||
528 | static int max310x_update_best_err(unsigned long f, long *besterr) | 536 | static int max310x_update_best_err(unsigned long f, long *besterr) |
@@ -875,7 +883,7 @@ static void max310x_set_termios(struct uart_port *port, | |||
875 | port->uartclk / 4); | 883 | port->uartclk / 4); |
876 | 884 | ||
877 | /* Setup baudrate generator */ | 885 | /* Setup baudrate generator */ |
878 | max310x_set_baud(port, baud); | 886 | baud = max310x_set_baud(port, baud); |
879 | 887 | ||
880 | /* Update timeout according to new baud rate */ | 888 | /* Update timeout according to new baud rate */ |
881 | uart_update_timeout(port, termios->c_cflag, baud); | 889 | uart_update_timeout(port, termios->c_cflag, baud); |