提交 239d5fc7 编写于 作者: P Phil Elwell 提交者: Zheng Zengkai

amba_pl011: Round input clock up

raspberrypi inclusion
category: feature
bugzilla: 50432

--------------------------------

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: NPhil Elwell <phil@raspberrypi.org>
Signed-off-by: NFang Yafen <yafen@iscas.ac.cn>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 2664a74e
...@@ -1642,6 +1642,23 @@ static void pl011_put_poll_char(struct uart_port *port, ...@@ -1642,6 +1642,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 =
...@@ -1658,7 +1675,7 @@ static int pl011_hwinit(struct uart_port *port) ...@@ -1658,7 +1675,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 |
...@@ -2313,7 +2330,7 @@ static int pl011_console_setup(struct console *co, char *options) ...@@ -2313,7 +2330,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;
...@@ -2530,6 +2547,7 @@ static struct uart_driver amba_reg = { ...@@ -2530,6 +2547,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;
...@@ -2561,6 +2579,7 @@ static int pl011_probe_dt_alias(int index, struct device *dev) ...@@ -2561,6 +2579,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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册