OpenWrt – Rev 1

Subversion Repositories:
Rev:
From d25a404a959a57804908c1d615b2ac85d7c4a18e Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Wed, 1 Mar 2017 16:07:39 +0000
Subject: [PATCH 093/454] amba_pl011: Round input clock up

The UART clock is initialised to be as close to the requested
frequency as possible without exceeding it. Now that there is a
clock manager that returns the actual frequencies, an expected
48MHz clock is reported as 47999625. If the requested baudrate
== requested clock/16, there is no headroom and the slight
reduction in actual clock rate results in failure.

Detect cases where it looks like a "round" clock was chosen and
adjust the reported clock to match that "round" value. As the
code comment says:

/*
 * If increasing a clock by less than 0.1% changes it
 * from ..999.. to ..000.., round up.
 */

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
 drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1672,6 +1672,23 @@ static void pl011_put_poll_char(struct u
 
 #endif /* CONFIG_CONSOLE_POLL */
 
+unsigned long pl011_clk_round(unsigned long clk)
+{
+       unsigned long scaler;
+
+       /*
+        * If increasing a clock by less than 0.1% changes it
+        * from ..999.. to ..000.., round up.
+        */
+       scaler = 1;
+       while (scaler * 100000 < clk)
+               scaler *= 10;
+       if ((clk + scaler - 1)/scaler % 1000 == 0)
+               clk = (clk/scaler + 1) * scaler;
+
+       return clk;
+}
+
 static int pl011_hwinit(struct uart_port *port)
 {
        struct uart_amba_port *uap =
@@ -1688,7 +1705,7 @@ static int pl011_hwinit(struct uart_port
        if (retval)
                return retval;
 
-       uap->port.uartclk = clk_get_rate(uap->clk);
+       uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
 
        /* Clear pending error and receive interrupts */
        pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
@@ -2344,7 +2361,7 @@ static int __init pl011_console_setup(st
                        plat->init();
        }
 
-       uap->port.uartclk = clk_get_rate(uap->clk);
+       uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
 
        if (uap->vendor->fixed_options) {
                baud = uap->fixed_baud;
@@ -2529,6 +2546,7 @@ static struct uart_driver amba_reg = {
        .cons                   = AMBA_CONSOLE,
 };
 
+#if 0
 static int pl011_probe_dt_alias(int index, struct device *dev)
 {
        struct device_node *np;
@@ -2560,6 +2578,7 @@ static int pl011_probe_dt_alias(int inde
 
        return ret;
 }
+#endif
 
 /* unregisters the driver also if no more ports are left */
 static void pl011_unregister_port(struct uart_amba_port *uap)