mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
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>
This commit is contained in:
@@ -1725,6 +1725,23 @@ static void pl011_put_poll_char(struct uart_port *port,
|
|||||||
|
|
||||||
#endif /* CONFIG_CONSOLE_POLL */
|
#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)
|
static int pl011_hwinit(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_amba_port *uap =
|
struct uart_amba_port *uap =
|
||||||
@@ -1741,7 +1758,7 @@ static int pl011_hwinit(struct uart_port *port)
|
|||||||
if (retval)
|
if (retval)
|
||||||
return 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 */
|
/* Clear pending error and receive interrupts */
|
||||||
pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
|
pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS |
|
||||||
@@ -2432,7 +2449,7 @@ static int pl011_console_setup(struct console *co, char *options)
|
|||||||
plat->init();
|
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) {
|
if (uap->vendor->fixed_options) {
|
||||||
baud = uap->fixed_baud;
|
baud = uap->fixed_baud;
|
||||||
@@ -2649,6 +2666,7 @@ static struct uart_driver amba_reg = {
|
|||||||
.cons = AMBA_CONSOLE,
|
.cons = AMBA_CONSOLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int pl011_probe_dt_alias(int index, struct device *dev)
|
static int pl011_probe_dt_alias(int index, struct device *dev)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
@@ -2680,6 +2698,7 @@ static int pl011_probe_dt_alias(int index, struct device *dev)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* unregisters the driver also if no more ports are left */
|
/* unregisters the driver also if no more ports are left */
|
||||||
static void pl011_unregister_port(struct uart_amba_port *uap)
|
static void pl011_unregister_port(struct uart_amba_port *uap)
|
||||||
|
|||||||
Reference in New Issue
Block a user