]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
amba_pl011: Round input clock up
authorPhil Elwell <phil@raspberrypi.org>
Wed, 1 Mar 2017 16:07:39 +0000 (16:07 +0000)
committerStefan Bader <stefan.bader@canonical.com>
Tue, 8 Aug 2017 12:51:58 +0000 (14:51 +0200)
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

index dda708752c85fadfd86e138db82513cb9bc89f0a..f0685b7aab7efd6d641684249b6506d78d7fe50e 100644 (file)
@@ -1674,6 +1674,23 @@ static void pl011_put_poll_char(struct uart_port *port,
 
 #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 =
@@ -1690,7 +1707,7 @@ static int pl011_hwinit(struct uart_port *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 |
@@ -2330,7 +2347,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
                        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;
@@ -2513,6 +2530,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;
@@ -2544,6 +2562,7 @@ static int pl011_probe_dt_alias(int index, struct device *dev)
 
        return ret;
 }
+#endif
 
 /* unregisters the driver also if no more ports are left */
 static void pl011_unregister_port(struct uart_amba_port *uap)