Mian Yousaf Kaukab 456791
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
Mian Yousaf Kaukab 456791
Date: Tue, 28 Jun 2022 12:09:22 +0200
Mian Yousaf Kaukab 456791
Subject: serial: mvebu-uart: correctly report configured baudrate value
Mian Yousaf Kaukab 456791
MIME-Version: 1.0
Mian Yousaf Kaukab 456791
Content-Type: text/plain; charset=UTF-8
Mian Yousaf Kaukab 456791
Content-Transfer-Encoding: 8bit
Mian Yousaf Kaukab 456791
Mian Yousaf Kaukab 456791
Git-commit: 4f532c1e25319e42996ec18a1f473fd50c8e575d
Mian Yousaf Kaukab 456791
Patch-mainline: v5.19-rc7
Mian Yousaf Kaukab 456791
References: git-fixes
Mian Yousaf Kaukab 456791
Mian Yousaf Kaukab 456791
Functions tty_termios_encode_baud_rate() and uart_update_timeout() should
Mian Yousaf Kaukab 456791
be called with the baudrate value which was set to hardware. Linux then
Mian Yousaf Kaukab 456791
report exact values via ioctl(TCGETS2) to userspace.
Mian Yousaf Kaukab 456791
Mian Yousaf Kaukab 456791
Change mvebu_uart_baud_rate_set() function to return baudrate value which
Mian Yousaf Kaukab 456791
was set to hardware and propagate this value to above mentioned functions.
Mian Yousaf Kaukab 456791
Mian Yousaf Kaukab 456791
With this change userspace would see precise value in termios c_ospeed
Mian Yousaf Kaukab 456791
field.
Mian Yousaf Kaukab 456791
Mian Yousaf Kaukab 456791
Fixes: 68a0db1d7da2 ("serial: mvebu-uart: add function to change baudrate")
Mian Yousaf Kaukab 456791
Cc: stable <stable@kernel.org>
Mian Yousaf Kaukab 456791
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mian Yousaf Kaukab 456791
Signed-off-by: Pali Rohár <pali@kernel.org>
Mian Yousaf Kaukab 456791
Link: https://lore.kernel.org/r/20220628100922.10717-1-pali@kernel.org
Mian Yousaf Kaukab 456791
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Mian Yousaf Kaukab 456791
Signed-off-by: Mian Yousaf Kaukab <ykaukab@suse.de>
Mian Yousaf Kaukab 456791
---
Mian Yousaf Kaukab 456791
 drivers/tty/serial/mvebu-uart.c |   25 +++++++++++++------------
Mian Yousaf Kaukab 456791
 1 file changed, 13 insertions(+), 12 deletions(-)
Mian Yousaf Kaukab 456791
Mian Yousaf Kaukab 456791
--- a/drivers/tty/serial/mvebu-uart.c
Mian Yousaf Kaukab 456791
+++ b/drivers/tty/serial/mvebu-uart.c
Mian Yousaf Kaukab 456791
@@ -453,13 +453,13 @@ static void mvebu_uart_shutdown(struct u
Mian Yousaf Kaukab 456791
 	}
Mian Yousaf Kaukab 456791
 }
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
-static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
Mian Yousaf Kaukab 456791
+static unsigned int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
Mian Yousaf Kaukab 456791
 {
Mian Yousaf Kaukab 456791
 	unsigned int d_divisor, m_divisor;
Mian Yousaf Kaukab 456791
 	u32 brdv;
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
 	if (!port->uartclk)
Mian Yousaf Kaukab 456791
-		return -EOPNOTSUPP;
Mian Yousaf Kaukab 456791
+		return 0;
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
 	/*
Mian Yousaf Kaukab 456791
 	 * The baudrate is derived from the UART clock thanks to two divisors:
Mian Yousaf Kaukab 456791
@@ -479,7 +479,7 @@ static int mvebu_uart_baud_rate_set(stru
Mian Yousaf Kaukab 456791
 	brdv |= d_divisor;
Mian Yousaf Kaukab 456791
 	writel(brdv, port->membase + UART_BRDV);
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
-	return 0;
Mian Yousaf Kaukab 456791
+	return DIV_ROUND_CLOSEST(port->uartclk, d_divisor * m_divisor);
Mian Yousaf Kaukab 456791
 }
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
 static void mvebu_uart_set_termios(struct uart_port *port,
Mian Yousaf Kaukab 456791
@@ -516,15 +516,11 @@ static void mvebu_uart_set_termios(struc
Mian Yousaf Kaukab 456791
 	max_baud = 230400;
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
 	baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud);
Mian Yousaf Kaukab 456791
-	if (mvebu_uart_baud_rate_set(port, baud)) {
Mian Yousaf Kaukab 456791
-		/* No clock available, baudrate cannot be changed */
Mian Yousaf Kaukab 456791
-		if (old)
Mian Yousaf Kaukab 456791
-			baud = uart_get_baud_rate(port, old, NULL,
Mian Yousaf Kaukab 456791
-						  min_baud, max_baud);
Mian Yousaf Kaukab 456791
-	} else {
Mian Yousaf Kaukab 456791
-		tty_termios_encode_baud_rate(termios, baud, baud);
Mian Yousaf Kaukab 456791
-		uart_update_timeout(port, termios->c_cflag, baud);
Mian Yousaf Kaukab 456791
-	}
Mian Yousaf Kaukab 456791
+	baud = mvebu_uart_baud_rate_set(port, baud);
Mian Yousaf Kaukab 456791
+
Mian Yousaf Kaukab 456791
+	/* In case baudrate cannot be changed, report previous old value */
Mian Yousaf Kaukab 456791
+	if (baud == 0 && old)
Mian Yousaf Kaukab 456791
+		baud = tty_termios_baud_rate(old);
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
 	/* Only the following flag changes are supported */
Mian Yousaf Kaukab 456791
 	if (old) {
Mian Yousaf Kaukab 456791
@@ -535,6 +531,11 @@ static void mvebu_uart_set_termios(struc
Mian Yousaf Kaukab 456791
 		termios->c_cflag |= CS8;
Mian Yousaf Kaukab 456791
 	}
Mian Yousaf Kaukab 456791
 
Mian Yousaf Kaukab 456791
+	if (baud != 0) {
Mian Yousaf Kaukab 456791
+		tty_termios_encode_baud_rate(termios, baud, baud);
Mian Yousaf Kaukab 456791
+		uart_update_timeout(port, termios->c_cflag, baud);
Mian Yousaf Kaukab 456791
+	}
Mian Yousaf Kaukab 456791
+
Mian Yousaf Kaukab 456791
 	spin_unlock_irqrestore(&port->lock, flags);
Mian Yousaf Kaukab 456791
 }
Mian Yousaf Kaukab 456791