[PATCH u-boot-marvell 1/5] serial: a37xx: Fix parent clock rate value and divider calculation
Stefan Roese
sr at denx.de
Thu May 27 08:13:44 CEST 2021
On 25.05.21 19:42, Marek Behún wrote:
> From: Pali Rohár <pali at 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 at kernel.org>
> Reviewed-by: Marek Behún <marek.behun at nic.cz>
Reviewed-by: Stefan Roese <sr at 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
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de
More information about the U-Boot
mailing list