1 From 610cb34f3d7c5fdffb0db82538731714a2df1d13 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Wed, 1 Mar 2017 16:07:39 +0000
4 Subject: [PATCH] amba_pl011: Round input clock up
6 The UART clock is initialised to be as close to the requested
7 frequency as possible without exceeding it. Now that there is a
8 clock manager that returns the actual frequencies, an expected
9 48MHz clock is reported as 47999625. If the requested baudrate
10 == requested clock/16, there is no headroom and the slight
11 reduction in actual clock rate results in failure.
13 Detect cases where it looks like a "round" clock was chosen and
14 adjust the reported clock to match that "round" value. As the
18 * If increasing a clock by less than 0.1% changes it
19 * from ..999.. to ..000.., round up.
22 Signed-off-by: Phil Elwell <phil@raspberrypi.org>
24 drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++--
25 1 file changed, 21 insertions(+), 2 deletions(-)
27 --- a/drivers/tty/serial/amba-pl011.c
28 +++ b/drivers/tty/serial/amba-pl011.c
29 @@ -1650,6 +1650,23 @@ static void pl011_put_poll_char(struct u
31 #endif /* CONFIG_CONSOLE_POLL */
33 +unsigned long pl011_clk_round(unsigned long clk)
35 + unsigned long scaler;
38 + * If increasing a clock by less than 0.1% changes it
39 + * from ..999.. to ..000.., round up.
42 + while (scaler * 100000 < clk)
44 + if ((clk + scaler - 1)/scaler % 1000 == 0)
45 + clk = (clk/scaler + 1) * scaler;
50 static int pl011_hwinit(struct uart_port *port)
52 struct uart_amba_port *uap =
53 @@ -1666,7 +1683,7 @@ static int pl011_hwinit(struct uart_port
57 - uap->port.uartclk = clk_get_rate(uap->clk);
58 + uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
60 /* Clear pending error and receive interrupts */
61 pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
62 @@ -2322,7 +2339,7 @@ static int __init pl011_console_setup(st
66 - uap->port.uartclk = clk_get_rate(uap->clk);
67 + uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
69 if (uap->vendor->fixed_options) {
70 baud = uap->fixed_baud;
71 @@ -2507,6 +2524,7 @@ static struct uart_driver amba_reg = {
76 static int pl011_probe_dt_alias(int index, struct device *dev)
78 struct device_node *np;
79 @@ -2538,6 +2556,7 @@ static int pl011_probe_dt_alias(int inde
85 /* unregisters the driver also if no more ports are left */
86 static void pl011_unregister_port(struct uart_amba_port *uap)