mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
serial: a37xx: Fix parent clock rate value and divider calculation
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>
This commit is contained in:
parent
fd075f77ca
commit
139d081384
1 changed files with 10 additions and 4 deletions
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue