* [PATCH 1/2] serial: mvebu-uart: clarify the baud rate derivation
@ 2018-11-23 15:45 Miquel Raynal
2018-11-23 15:45 ` [PATCH 2/2] serial: mvebu-uart: initialize over sampling stack register Miquel Raynal
0 siblings, 1 reply; 2+ messages in thread
From: Miquel Raynal @ 2018-11-23 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Thomas Petazzoni, Nadav Haklai, Antoine Tenart, Maxime Chevallier,
Gregory Clement, linux-serial, linux-kernel, Russell King,
Marc Zyngier, Miquel Raynal
The current comment in ->set_baud_rate() is rather incomplete as it
fails to describe what are the actual stages for the baudrate
derivation. Replace this comment with something more explicit and
close to the functional specification. Also adapt the variable names
to it.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
drivers/tty/serial/mvebu-uart.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
index 170e446a2f62..df6e4d8cdbd6 100644
--- a/drivers/tty/serial/mvebu-uart.c
+++ b/drivers/tty/serial/mvebu-uart.c
@@ -72,6 +72,7 @@
#define BRDV_BAUD_MASK 0x3FF
#define UART_OSAMP 0x14
+#define OSAMP_DEFAULT_DIVISOR 16
#define MVEBU_NR_UARTS 2
@@ -444,23 +445,28 @@ static void mvebu_uart_shutdown(struct uart_port *port)
static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
{
struct mvebu_uart *mvuart = to_mvuart(port);
- unsigned int baud_rate_div;
+ unsigned int d_divisor, m_divisor;
u32 brdv;
if (IS_ERR(mvuart->clk))
return -PTR_ERR(mvuart->clk);
/*
- * The UART clock is divided by the value of the divisor to generate
- * UCLK_OUT clock, which is 16 times faster than the baudrate.
- * This prescaler can achieve all standard baudrates until 230400.
- * Higher baudrates could be achieved for the extended UART by using the
- * programmable oversampling stack (also called fractional divisor).
+ * The baudrate is derived from the UART clock thanks to two divisors:
+ * > D ("baud generator"): can divide the clock from 2 to 2^10 - 1.
+ * > M ("fractional divisor"): allows a better accuracy for
+ * baudrates higher than 230400.
+ *
+ * As the derivation of M is rather complicated, the code sticks to its
+ * default value (x16) when all the prescalers are zeroed, and only
+ * makes use of D to configure the desired baudrate.
*/
- baud_rate_div = DIV_ROUND_UP(port->uartclk, baud * 16);
+ m_divisor = OSAMP_DEFAULT_DIVISOR;
+ d_divisor = DIV_ROUND_UP(port->uartclk, baud * m_divisor);
+
brdv = readl(port->membase + UART_BRDV);
brdv &= ~BRDV_BAUD_MASK;
- brdv |= baud_rate_div;
+ brdv |= d_divisor;
writel(brdv, port->membase + UART_BRDV);
return 0;
--
2.19.1
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH 2/2] serial: mvebu-uart: initialize over sampling stack register
2018-11-23 15:45 [PATCH 1/2] serial: mvebu-uart: clarify the baud rate derivation Miquel Raynal
@ 2018-11-23 15:45 ` Miquel Raynal
0 siblings, 0 replies; 2+ messages in thread
From: Miquel Raynal @ 2018-11-23 15:45 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Thomas Petazzoni, Nadav Haklai, Antoine Tenart, Maxime Chevallier,
Gregory Clement, linux-serial, linux-kernel, Russell King,
Marc Zyngier, Miquel Raynal
The baudrate derivation relies on the state of the programmable over
sampling stack (OSAMP register) being empty, while never initializing
it.
Set all the fields of this register to 0 (except reserved areas) to
ensure a x16 divisor, as assumed by the driver.
The suspend/resume callbacks are untouched because they already
save/restore correctly this register.
Suggested-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
drivers/tty/serial/mvebu-uart.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
index df6e4d8cdbd6..231f751d1ef4 100644
--- a/drivers/tty/serial/mvebu-uart.c
+++ b/drivers/tty/serial/mvebu-uart.c
@@ -73,6 +73,7 @@
#define UART_OSAMP 0x14
#define OSAMP_DEFAULT_DIVISOR 16
+#define OSAMP_DIVISORS_MASK 0x3F3F3F3F
#define MVEBU_NR_UARTS 2
@@ -446,7 +447,7 @@ static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
{
struct mvebu_uart *mvuart = to_mvuart(port);
unsigned int d_divisor, m_divisor;
- u32 brdv;
+ u32 brdv, osamp;
if (IS_ERR(mvuart->clk))
return -PTR_ERR(mvuart->clk);
@@ -469,6 +470,10 @@ static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
brdv |= d_divisor;
writel(brdv, port->membase + UART_BRDV);
+ osamp = readl(port->membase + UART_OSAMP);
+ osamp &= ~OSAMP_DIVISORS_MASK;
+ writel(osamp, port->membase + UART_OSAMP);
+
return 0;
}
--
2.19.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-11-23 15:45 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-11-23 15:45 [PATCH 1/2] serial: mvebu-uart: clarify the baud rate derivation Miquel Raynal
2018-11-23 15:45 ` [PATCH 2/2] serial: mvebu-uart: initialize over sampling stack register Miquel Raynal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox