
On 25.05.21 19:42, Marek Behún wrote:
From: Pali Rohár pali@kernel.org
UART parent clock is by default the platform's xtal clock, which is 25 MHz.
The value defined in the driver, though, is 25.8048 MHz. This is a hack for the suboptimal divisor calculation Divisor = UART clock / (16 * baudrate) which does not use rounding division, resulting in a suboptimal value for divisor if the correct parent clock rate was used.
Change the code for divisor calculation to round to closest value, i.e. Divisor = Round(UART clock / (16 * baudrate)) and change the parent clock rate value to that returned by get_ref_clk().
This makes A3720 UART stable at standard UART baudrates between 1800 and 230400.
Signed-off-by: Pali Rohár pali@kernel.org Reviewed-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
drivers/serial/serial_mvebu_a3700.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c index 8f404879a5..9e7e479f80 100644 --- a/drivers/serial/serial_mvebu_a3700.c +++ b/drivers/serial/serial_mvebu_a3700.c @@ -7,6 +7,7 @@ #include <dm.h> #include <serial.h> #include <asm/io.h> +#include <asm/arch/cpu.h>
struct mvebu_plat { void __iomem *base; @@ -29,8 +30,6 @@ struct mvebu_plat { #define UART_CTRL_RXFIFO_RESET 0x4000 #define UART_CTRL_TXFIFO_RESET 0x8000
-#define CONFIG_UART_BASE_CLOCK 25804800
- static int mvebu_serial_putc(struct udevice *dev, const char ch) { struct mvebu_plat *plat = dev_get_plat(dev);
@@ -75,12 +74,15 @@ static int mvebu_serial_setbrg(struct udevice *dev, int baudrate) { struct mvebu_plat *plat = dev_get_plat(dev); void __iomem *base = plat->base;
u32 parent_rate, divider;
/*
- Calculate divider
- baudrate = clock / 16 / divider
*/
- writel(CONFIG_UART_BASE_CLOCK / baudrate / 16, base + UART_BAUD_REG);
parent_rate = get_ref_clk() * 1000000;
divider = DIV_ROUND_CLOSEST(parent_rate, baudrate * 16);
writel(divider, base + UART_BAUD_REG);
/*
- Set Programmable Oversampling Stack to 0,
@@ -144,6 +146,7 @@ U_BOOT_DRIVER(serial_mvebu) = { static inline void _debug_uart_init(void) { void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
u32 baudrate, parent_rate, divider;
/* reset FIFOs */ writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
@@ -156,7 +159,10 @@ static inline void _debug_uart_init(void) * Calculate divider * baudrate = clock / 16 / divider */
- writel(CONFIG_UART_BASE_CLOCK / 115200 / 16, base + UART_BAUD_REG);
baudrate = 115200;
parent_rate = get_ref_clk() * 1000000;
divider = DIV_ROUND_CLOSEST(parent_rate, baudrate * 16);
writel(divider, base + UART_BAUD_REG);
/*
- Set Programmable Oversampling Stack to 0,
Viele Grüße, Stefan