serial: 8250_fintek: UART dynamic clocksource on Fintek F81866

The F81866 had 4 clocksource 1.8432/18.432/14.769/24MHz and baud rates can
be up to 1.5Mbits with 24MHz. We'll implements the dynamic clocksource in
fintek_8250_set_termios().

Signed-off-by: Ji-Ze Hong (Peter Hong) <hpeter+linux_kernel@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ji-Ze Hong (Peter Hong) 2017-10-03 11:08:33 +08:00 committed by Greg Kroah-Hartman
parent 3b837fa233
commit 195638b6d4
1 changed files with 54 additions and 0 deletions

View File

@ -287,6 +287,59 @@ static void fintek_8250_goto_highspeed(struct uart_8250_port *uart,
}
}
void fintek_8250_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct fintek_8250 *pdata = port->private_data;
unsigned int baud = tty_termios_baud_rate(termios);
int i;
static u32 baudrate_table[] = {115200, 921600, 1152000, 1500000};
static u8 clock_table[] = { F81866_UART_CLK_1_8432MHZ,
F81866_UART_CLK_14_769MHZ, F81866_UART_CLK_18_432MHZ,
F81866_UART_CLK_24MHZ };
for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
if (baud > baudrate_table[i] || baudrate_table[i] % baud != 0)
continue;
if (port->uartclk == baudrate_table[i] * 16)
break;
if (fintek_8250_enter_key(pdata->base_port, pdata->key))
continue;
port->uartclk = baudrate_table[i] * 16;
sio_write_reg(pdata, LDN, pdata->index);
sio_write_mask_reg(pdata, F81866_UART_CLK,
F81866_UART_CLK_MASK, clock_table[i]);
fintek_8250_exit_key(pdata->base_port);
break;
}
if (i == ARRAY_SIZE(baudrate_table)) {
baud = tty_termios_baud_rate(old);
tty_termios_encode_baud_rate(termios, baud, baud);
}
serial8250_do_set_termios(port, termios, old);
}
static void fintek_8250_set_termios_handler(struct uart_8250_port *uart)
{
struct fintek_8250 *pdata = uart->port.private_data;
switch (pdata->pid) {
case CHIP_ID_F81866:
uart->port.set_termios = fintek_8250_set_termios;
break;
default:
break;
}
}
static int probe_setup_port(struct fintek_8250 *pdata,
struct uart_8250_port *uart)
{
@ -373,6 +426,7 @@ int fintek_8250_probe(struct uart_8250_port *uart)
memcpy(pdata, &probe_data, sizeof(probe_data));
uart->port.private_data = pdata;
fintek_8250_set_rs485_handler(uart);
fintek_8250_set_termios_handler(uart);
return 0;
}