| From 503ecaae6755bbb4a5ea1ff00e15ccb8e5e8cd30 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 25 Jun 2021 00:49:02 +0200 |
| Subject: serial: mvebu-uart: correctly calculate minimal possible baudrate |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Pali Rohár <pali@kernel.org> |
| |
| [ Upstream commit deeaf963569a0d9d1b08babb771f61bb501a5704 ] |
| |
| For default (x16) scheme which is currently used by mvebu-uart.c driver, |
| maximal divisor of UART base clock is 1023*16. Therefore there is limit for |
| minimal supported baudrate. This change calculate it correctly and prevents |
| setting invalid divisor 0 into hardware registers. |
| |
| Signed-off-by: Pali Rohár <pali@kernel.org> |
| Fixes: 68a0db1d7da2 ("serial: mvebu-uart: add function to change baudrate") |
| Link: https://lore.kernel.org/r/20210624224909.6350-4-pali@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/tty/serial/mvebu-uart.c | 11 ++++++++--- |
| 1 file changed, 8 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c |
| index 9638ae6aae79..1e26220c7852 100644 |
| --- a/drivers/tty/serial/mvebu-uart.c |
| +++ b/drivers/tty/serial/mvebu-uart.c |
| @@ -481,7 +481,7 @@ static void mvebu_uart_set_termios(struct uart_port *port, |
| struct ktermios *old) |
| { |
| unsigned long flags; |
| - unsigned int baud; |
| + unsigned int baud, min_baud, max_baud; |
| |
| spin_lock_irqsave(&port->lock, flags); |
| |
| @@ -500,16 +500,21 @@ static void mvebu_uart_set_termios(struct uart_port *port, |
| port->ignore_status_mask |= STAT_RX_RDY(port) | STAT_BRK_ERR; |
| |
| /* |
| + * Maximal divisor is 1023 * 16 when using default (x16) scheme. |
| * Maximum achievable frequency with simple baudrate divisor is 230400. |
| * Since the error per bit frame would be of more than 15%, achieving |
| * higher frequencies would require to implement the fractional divisor |
| * feature. |
| */ |
| - baud = uart_get_baud_rate(port, termios, old, 0, 230400); |
| + min_baud = DIV_ROUND_UP(port->uartclk, 1023 * 16); |
| + max_baud = 230400; |
| + |
| + baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud); |
| if (mvebu_uart_baud_rate_set(port, baud)) { |
| /* No clock available, baudrate cannot be changed */ |
| if (old) |
| - baud = uart_get_baud_rate(port, old, NULL, 0, 230400); |
| + baud = uart_get_baud_rate(port, old, NULL, |
| + min_baud, max_baud); |
| } else { |
| tty_termios_encode_baud_rate(termios, baud, baud); |
| uart_update_timeout(port, termios->c_cflag, baud); |
| -- |
| 2.30.2 |
| |