serial: 8250_pci: replace switch-case by formula
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Fri, 13 Mar 2015 16:51:12 +0000 (18:51 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 26 Mar 2015 22:00:36 +0000 (23:00 +0100)
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>
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/Kconfig

index 495da064327806f648058e5b19d7276c01e5fccd..7e0519923eb54d89ac4818f56a234d04e0dc8122 100644 (file)
@@ -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);
index 6f7f2d753defe9695925ea9aaa0f503066858e55..c3507035652891e4e25070c6f7fa79c94cd549f8 100644 (file)
@@ -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.