diff options
author | Ji-Ze Hong (Peter Hong) <hpeter@gmail.com> | 2017-10-03 06:08:33 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-10-03 21:31:17 +0300 |
commit | 195638b6d44f22c5fcbd428ebfe4b7c012c576f2 (patch) | |
tree | 9cbf6844d6b4df1cc335f2e745d1c92eee43b1a2 /drivers/tty | |
parent | 3b837fa233254c7f8e46fbb72e4c126774fdb635 (diff) | |
download | linux-195638b6d44f22c5fcbd428ebfe4b7c012c576f2.tar.xz |
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>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/8250/8250_fintek.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index e500f7dd2470..53ea353409ce 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -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; } |