summary refs log tree commit diff
path: root/drivers/tty
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2015-03-13 18:51:12 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-26 23:00:36 +0100
commit21947ba654a685ab48f2d4089c5c2d27443c2d0d (patch)
tree2d1ab7e24472a8bf2754feb2283f4d976280aef4 /drivers/tty
parent49708c9e6cbb3c534677f429053bd18c2e948069 (diff)
downloadlinux-21947ba654a685ab48f2d4089c5c2d27443c2d0d.tar.gz
serial: 8250_pci: replace switch-case by formula
This patch replaces a switch-case by a formula using rational best
approximation that does necessary calculations for byt_set_termios().

Below is a list of the calculations done for all defined baud rates. Each line
in a format: 1) numerator, 2) denominator, 3) prescaler, 4) Fuart, 5) port UART
clock, 6) list of baud rates with DLAB values.

4        5        16 80000000   80000000   2500000(2)
14       25       16 56000000   56000000   3500000(1)
16       25       16 64000000   64000000   500000(8),1000000(4),2000000(2),
					4000000(1)
24       25       16 96000000   96000000   1500000(4),3000000(2)
2180     3103     16 70254592   70254592   134(32768)
2304     3125     16 73728000   73728000   576000(8),1152000(4)
8192     15625    16 52428800   52428800   50(65536),200(16384)
9216     15625    16 58982400   58982400   1800(2048),57600(64),115200(32),
					230400(16),460800(8),921600(4),1843200(2)
12288    15625    16 78643200   78643200   75(65536),150(32768),300(16384),
					600(8192),1200(4096),2400(2048),
					4800(1024),9600(512),19200(256),38400(128)
9893     17154    16 57671680   57671680   110(32768)

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/8250/8250_pci.c40
-rw-r--r--drivers/tty/serial/8250/Kconfig1
2 files changed, 10 insertions, 31 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 495da0643278..7e0519923eb5 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -21,6 +21,7 @@
 #include <linux/serial_core.h>
 #include <linux/8250_pci.h>
 #include <linux/bitops.h>
+#include <linux/rational.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -1393,45 +1394,22 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
 		struct ktermios *old)
 {
 	unsigned int baud = tty_termios_baud_rate(termios);
-	unsigned int m, n;
+	unsigned long fref = 100000000, fuart = baud * 16;
+	unsigned long w = BIT(15) - 1;
+	unsigned long m, n;
 	u32 reg;
 
+	/* Get Fuart closer to Fref */
+	fuart *= rounddown_pow_of_two(fref / fuart);
+
 	/*
 	 * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
 	 * dividers must be adjusted.
 	 *
 	 * uartclk = (m / n) * 100 MHz, where m <= n
 	 */
-	switch (baud) {
-	case 500000:
-	case 1000000:
-	case 2000000:
-	case 4000000:
-		m = 64;
-		n = 100;
-		p->uartclk = 64000000;
-		break;
-	case 3500000:
-		m = 56;
-		n = 100;
-		p->uartclk = 56000000;
-		break;
-	case 1500000:
-	case 3000000:
-		m = 48;
-		n = 100;
-		p->uartclk = 48000000;
-		break;
-	case 2500000:
-		m = 40;
-		n = 100;
-		p->uartclk = 40000000;
-		break;
-	default:
-		m = 2304;
-		n = 3125;
-		p->uartclk = 73728000;
-	}
+	rational_best_approximation(fuart, fref, w, w, &m, &n);
+	p->uartclk = fuart;
 
 	/* Reset the clock */
 	reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 6f7f2d753def..c35070356528 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -108,6 +108,7 @@ config SERIAL_8250_PCI
 	tristate "8250/16550 PCI device support" if EXPERT
 	depends on SERIAL_8250 && PCI
 	default SERIAL_8250
+	select RATIONAL
 	help
 	  This builds standard PCI serial support. You may be able to
 	  disable this feature if you only need legacy serial support.