aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorAlexander Shiyan <shc_work@mail.ru>2014-02-07 09:16:04 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-13 12:33:04 -0500
commite97e15561cd885926f78200a1e75e713172da60e (patch)
tree03146120f801947ec35364278b657fb52026c280 /drivers/tty/serial
parentd0fd413cffb7cd8efac6d4d192ba62fc2fa60d2d (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')
-rw-r--r--drivers/tty/serial/max310x.c32
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
507static void max310x_set_baud(struct uart_port *port, int baud) 507static 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
528static int max310x_update_best_err(unsigned long f, long *besterr) 536static 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);