brcm2708: update to latest patches from RPi Foundation
[openwrt/staging/chunkeey.git] / target / linux / brcm2708 / patches-4.19 / 950-0034-amba_pl011-Round-input-clock-up.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0034-amba_pl011-Round-input-clock-up.patch b/target/linux/brcm2708/patches-4.19/950-0034-amba_pl011-Round-input-clock-up.patch
new file mode 100644 (file)
index 0000000..8768351
--- /dev/null
@@ -0,0 +1,86 @@
+From 610cb34f3d7c5fdffb0db82538731714a2df1d13 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 1 Mar 2017 16:07:39 +0000
+Subject: [PATCH] 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
+@@ -1650,6 +1650,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 =
+@@ -1666,7 +1683,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 |
+@@ -2322,7 +2339,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;
+@@ -2507,6 +2524,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;
+@@ -2538,6 +2556,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)