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>
This commit is contained in:
Andy Shevchenko 2015-03-13 18:51:13 +02:00 committed by Greg Kroah-Hartman
parent 21947ba654
commit c1a67b48f6

View File

@ -1506,59 +1506,49 @@ byt_serial_setup(struct serial_private *priv,
#define INTEL_MID_UART_PS 0x30
#define INTEL_MID_UART_MUL 0x34
#define INTEL_MID_UART_DIV 0x38
static void intel_mid_set_termios(struct uart_port *p,
struct ktermios *termios,
struct ktermios *old,
unsigned long fref)
{
unsigned int baud = tty_termios_baud_rate(termios);
unsigned short ps = 16;
unsigned long fuart = baud * ps;
unsigned long w = BIT(24) - 1;
unsigned long mul, div;
if (fref < fuart) {
/* Find prescaler value that satisfies Fuart < Fref */
if (fref > baud)
ps = fref / baud; /* baud rate too high */
else
ps = 1; /* PLL case */
fuart = baud * ps;
} else {
/* Get Fuart closer to Fref */
fuart *= rounddown_pow_of_two(fref / fuart);
}
rational_best_approximation(fuart, fref, w, w, &mul, &div);
p->uartclk = fuart * 16 / ps; /* core uses ps = 16 always */
writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */
writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */
writel(div, p->membase + INTEL_MID_UART_DIV);
serial8250_do_set_termios(p, termios, old);
}
static void intel_mid_set_termios_50M(struct uart_port *p,
struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
u32 ps, mul;
/*
* The uart clk is 50Mhz, and the baud rate come from:
* baud = 50M * MUL / (DIV * PS * DLAB)
*
* For those basic low baud rate we can get the direct
* scalar from 2746800, like 115200 = 2746800/24. For those
* higher baud rate, we handle them case by case, mainly by
* adjusting the MUL/PS registers, and DIV register is kept
* as default value 0x3d09 to make things simple.
*/
ps = 0x10;
switch (baud) {
case 500000:
case 1000000:
case 1500000:
case 3000000:
mul = 0x3a98;
p->uartclk = 48000000;
break;
case 2000000:
case 4000000:
mul = 0x2710;
ps = 0x08;
p->uartclk = 64000000;
break;
case 2500000:
mul = 0x30d4;
p->uartclk = 40000000;
break;
case 3500000:
mul = 0x3345;
ps = 0x0c;
p->uartclk = 56000000;
break;
default:
mul = 0x2400;
p->uartclk = 29491200;
}
writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */
writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */
serial8250_do_set_termios(p, termios, old);
intel_mid_set_termios(p, termios, old, 50000000);
}
static bool intel_mid_dma_filter(struct dma_chan *chan, void *param)