[PATCH 2/6] serial: max310x: Setup baud rate generator more precisely

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxx>
---
 drivers/tty/serial/max310x.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 8d71e40..313bdf0 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1,7 +1,7 @@
 /*
  *  Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver
  *
- *  Copyright (C) 2012-2013 Alexander Shiyan <shc_work@xxxxxxx>
+ *  Copyright (C) 2012-2014 Alexander Shiyan <shc_work@xxxxxxx>
  *
  *  Based on max3100.c, by Christian Pellegrin <chripell@xxxxxxxxxxxx>
  *  Based on max3110.c, by Feng Tang <feng.tang@xxxxxxxxx>
@@ -504,25 +504,33 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
 	return false;
 }
 
-static void max310x_set_baud(struct uart_port *port, int baud)
+static int max310x_set_baud(struct uart_port *port, int baud)
 {
-	unsigned int mode = 0, div = port->uartclk / baud;
+	unsigned int mode = 0, clk = port->uartclk, div = clk / baud;
 
-	if (!(div / 16)) {
+	/* Check for minimal value for divider */
+	if (div < 16)
+		div = 16;
+
+	if (clk % baud && (div / 16) < 0x8000) {
 		/* Mode x2 */
 		mode = MAX310X_BRGCFG_2XMODE_BIT;
-		div = (port->uartclk * 2) / baud;
-	}
-
-	if (!(div / 16)) {
-		/* Mode x4 */
-		mode = MAX310X_BRGCFG_4XMODE_BIT;
-		div = (port->uartclk * 4) / baud;
+		clk = port->uartclk * 2;
+		div = clk / baud;
+
+		if (clk % baud && (div / 16) < 0x8000) {
+			/* Mode x4 */
+			mode = MAX310X_BRGCFG_4XMODE_BIT;
+			clk = port->uartclk * 4;
+			div = clk / baud;
+		}
 	}
 
 	max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8);
 	max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16);
 	max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode);
+
+	return DIV_ROUND_CLOSEST(clk, div);
 }
 
 static int max310x_update_best_err(unsigned long f, long *besterr)
@@ -875,7 +883,7 @@ static void max310x_set_termios(struct uart_port *port,
 				  port->uartclk / 4);
 
 	/* Setup baudrate generator */
-	max310x_set_baud(port, baud);
+	baud = max310x_set_baud(port, baud);
 
 	/* Update timeout according to new baud rate */
 	uart_update_timeout(port, termios->c_cflag, baud);
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux