950-0057-amba_pl011-Round-input-clock-up.patch 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. From 307744a359bddf354711e54836e4757788c9dfc4 Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <[email protected]>
  3. Date: Wed, 1 Mar 2017 16:07:39 +0000
  4. Subject: [PATCH] amba_pl011: Round input clock up
  5. The UART clock is initialised to be as close to the requested
  6. frequency as possible without exceeding it. Now that there is a
  7. clock manager that returns the actual frequencies, an expected
  8. 48MHz clock is reported as 47999625. If the requested baudrate
  9. == requested clock/16, there is no headroom and the slight
  10. reduction in actual clock rate results in failure.
  11. Detect cases where it looks like a "round" clock was chosen and
  12. adjust the reported clock to match that "round" value. As the
  13. code comment says:
  14. /*
  15. * If increasing a clock by less than 0.1% changes it
  16. * from ..999.. to ..000.., round up.
  17. */
  18. Signed-off-by: Phil Elwell <[email protected]>
  19. ---
  20. drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++--
  21. 1 file changed, 21 insertions(+), 2 deletions(-)
  22. --- a/drivers/tty/serial/amba-pl011.c
  23. +++ b/drivers/tty/serial/amba-pl011.c
  24. @@ -1718,6 +1718,23 @@ static void pl011_put_poll_char(struct u
  25. #endif /* CONFIG_CONSOLE_POLL */
  26. +unsigned long pl011_clk_round(unsigned long clk)
  27. +{
  28. + unsigned long scaler;
  29. +
  30. + /*
  31. + * If increasing a clock by less than 0.1% changes it
  32. + * from ..999.. to ..000.., round up.
  33. + */
  34. + scaler = 1;
  35. + while (scaler * 100000 < clk)
  36. + scaler *= 10;
  37. + if ((clk + scaler - 1)/scaler % 1000 == 0)
  38. + clk = (clk/scaler + 1) * scaler;
  39. +
  40. + return clk;
  41. +}
  42. +
  43. static int pl011_hwinit(struct uart_port *port)
  44. {
  45. struct uart_amba_port *uap =
  46. @@ -1734,7 +1751,7 @@ static int pl011_hwinit(struct uart_port
  47. if (retval)
  48. return retval;
  49. - uap->port.uartclk = clk_get_rate(uap->clk);
  50. + uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
  51. /* Clear pending error and receive interrupts */
  52. pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
  53. @@ -2421,7 +2438,7 @@ static int pl011_console_setup(struct co
  54. plat->init();
  55. }
  56. - uap->port.uartclk = clk_get_rate(uap->clk);
  57. + uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk));
  58. if (uap->vendor->fixed_options) {
  59. baud = uap->fixed_baud;
  60. @@ -2638,6 +2655,7 @@ static struct uart_driver amba_reg = {
  61. .cons = AMBA_CONSOLE,
  62. };
  63. +#if 0
  64. static int pl011_probe_dt_alias(int index, struct device *dev)
  65. {
  66. struct device_node *np;
  67. @@ -2669,6 +2687,7 @@ static int pl011_probe_dt_alias(int inde
  68. return ret;
  69. }
  70. +#endif
  71. /* unregisters the driver also if no more ports are left */
  72. static void pl011_unregister_port(struct uart_amba_port *uap)