diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2015-03-13 12:51:13 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-03-26 18:00:36 -0400 |
commit | c1a67b48f6a5878b7ec9f49144faa02f94e965cc (patch) | |
tree | 1efe602835a2267abf95d90c588d6c8924277876 /drivers/tty/serial | |
parent | 21947ba654a685ab48f2d4089c5c2d27443c2d0d (diff) |
serial: 8250_pci: replace switch-case by formula for Intel MID
This patch replaces a switch-case by a formula using rational best
approximation that does necessary calculations for intel_mid_set_termios().
Below is a list of the calculations done for all defined baud rates. Each line
in a format: 1) nominator, 2) denominator, 3) prescaler, 4) Fuart, 5) port UART
clock, 6) list of baud rates with DLAB values.
24 25 12 48000000 64000000 4000000(1)
49 50 14 49000000 56000000 3500000(1)
4 5 16 40000000 40000000 2500000(1)
16 25 16 32000000 32000000 500000(4),1000000(2),2000000(1)
24 25 16 48000000 48000000 1500000(2),3000000(1)
2304 3125 16 36864000 36864000 576000(4),1152000(2)
8192 15625 16 26214400 26214400 50(32768),200(8192)
9216 15625 16 29491200 29491200 1800(1024),57600(32),115200(16),
230400(8),460800(4),921600(2),1843200(1)
12288 15625 16 39321600 39321600 75(32768),150(16384),300(8192),
600(4096),1200(2048),2400(1024),4800(512),
9600(256),19200(128),38400(64)
45056 78125 16 28835840 28835840 110(16384)
274432 390625 16 35127296 35127296 134(16384)
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/serial')
-rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 78 |
1 files changed, 34 insertions, 44 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 7e0519923eb5..0be8dd84f9dc 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -1506,60 +1506,50 @@ byt_serial_setup(struct serial_private *priv, | |||
1506 | 1506 | ||
1507 | #define INTEL_MID_UART_PS 0x30 | 1507 | #define INTEL_MID_UART_PS 0x30 |
1508 | #define INTEL_MID_UART_MUL 0x34 | 1508 | #define INTEL_MID_UART_MUL 0x34 |
1509 | #define INTEL_MID_UART_DIV 0x38 | ||
1509 | 1510 | ||
1510 | static void intel_mid_set_termios_50M(struct uart_port *p, | 1511 | static void intel_mid_set_termios(struct uart_port *p, |
1511 | struct ktermios *termios, | 1512 | struct ktermios *termios, |
1512 | struct ktermios *old) | 1513 | struct ktermios *old, |
1514 | unsigned long fref) | ||
1513 | { | 1515 | { |
1514 | unsigned int baud = tty_termios_baud_rate(termios); | 1516 | unsigned int baud = tty_termios_baud_rate(termios); |
1515 | u32 ps, mul; | 1517 | unsigned short ps = 16; |
1516 | 1518 | unsigned long fuart = baud * ps; | |
1517 | /* | 1519 | unsigned long w = BIT(24) - 1; |
1518 | * The uart clk is 50Mhz, and the baud rate come from: | 1520 | unsigned long mul, div; |
1519 | * baud = 50M * MUL / (DIV * PS * DLAB) | 1521 | |
1520 | * | 1522 | if (fref < fuart) { |
1521 | * For those basic low baud rate we can get the direct | 1523 | /* Find prescaler value that satisfies Fuart < Fref */ |
1522 | * scalar from 2746800, like 115200 = 2746800/24. For those | 1524 | if (fref > baud) |
1523 | * higher baud rate, we handle them case by case, mainly by | 1525 | ps = fref / baud; /* baud rate too high */ |
1524 | * adjusting the MUL/PS registers, and DIV register is kept | 1526 | else |
1525 | * as default value 0x3d09 to make things simple. | 1527 | ps = 1; /* PLL case */ |
1526 | */ | 1528 | fuart = baud * ps; |
1527 | 1529 | } else { | |
1528 | ps = 0x10; | 1530 | /* Get Fuart closer to Fref */ |
1529 | 1531 | fuart *= rounddown_pow_of_two(fref / fuart); | |
1530 | switch (baud) { | ||
1531 | case 500000: | ||
1532 | case 1000000: | ||
1533 | case 1500000: | ||
1534 | case 3000000: | ||
1535 | mul = 0x3a98; | ||
1536 | p->uartclk = 48000000; | ||
1537 | break; | ||
1538 | case 2000000: | ||
1539 | case 4000000: | ||
1540 | mul = 0x2710; | ||
1541 | ps = 0x08; | ||
1542 | p->uartclk = 64000000; | ||
1543 | break; | ||
1544 | case 2500000: | ||
1545 | mul = 0x30d4; | ||
1546 | p->uartclk = 40000000; | ||
1547 | break; | ||
1548 | case 3500000: | ||
1549 | mul = 0x3345; | ||
1550 | ps = 0x0c; | ||
1551 | p->uartclk = 56000000; | ||
1552 | break; | ||
1553 | default: | ||
1554 | mul = 0x2400; | ||
1555 | p->uartclk = 29491200; | ||
1556 | } | 1532 | } |
1557 | 1533 | ||
1534 | rational_best_approximation(fuart, fref, w, w, &mul, &div); | ||
1535 | p->uartclk = fuart * 16 / ps; /* core uses ps = 16 always */ | ||
1536 | |||
1558 | writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */ | 1537 | writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */ |
1559 | writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */ | 1538 | writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */ |
1539 | writel(div, p->membase + INTEL_MID_UART_DIV); | ||
1560 | 1540 | ||
1561 | serial8250_do_set_termios(p, termios, old); | 1541 | serial8250_do_set_termios(p, termios, old); |
1562 | } | 1542 | } |
1543 | static void intel_mid_set_termios_50M(struct uart_port *p, | ||
1544 | struct ktermios *termios, | ||
1545 | struct ktermios *old) | ||
1546 | { | ||
1547 | /* | ||
1548 | * The uart clk is 50Mhz, and the baud rate come from: | ||
1549 | * baud = 50M * MUL / (DIV * PS * DLAB) | ||
1550 | */ | ||
1551 | intel_mid_set_termios(p, termios, old, 50000000); | ||
1552 | } | ||
1563 | 1553 | ||
1564 | static bool intel_mid_dma_filter(struct dma_chan *chan, void *param) | 1554 | static bool intel_mid_dma_filter(struct dma_chan *chan, void *param) |
1565 | { | 1555 | { |