Skip to content

Commit

Permalink
amba_pl011: Round input clock up
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Phil Elwell authored and popcornmix committed Mar 21, 2022
1 parent 017f25f commit ab3f1b3
Showing 1 changed file with 21 additions and 2 deletions.
23 changes: 21 additions & 2 deletions drivers/tty/serial/amba-pl011.c
Expand Up @@ -1720,6 +1720,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 =
Expand All @@ -1736,7 +1753,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 |
Expand Down Expand Up @@ -2429,7 +2446,7 @@ static int 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;
Expand Down Expand Up @@ -2646,6 +2663,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;
Expand Down Expand Up @@ -2677,6 +2695,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)
Expand Down

0 comments on commit ab3f1b3

Please sign in to comment.