[U-Boot] [PATCH v2 0/2] serial: atmel_usart: Fix uart init and add clk support

The patches is rework the uart init to fix the early debug not work in SPL, and add the clock support.
Changes in v2: - Fix the DBGU clock handling. - Add Reviewed-by tag.
Wenyou Yang (2): serial: atmel_usart: Fix early debug not work in SPL serial: atmel_usart: Add clk support
drivers/serial/atmel_usart.c | 84 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 6 deletions(-)

Add the uart init function to be used on both probe and the early debug uart init. For the latter, the input clock should be from CONFIG_DEBUG_UART_CLOCK.
Signed-off-by: Wenyou Yang wenyou.yang@atmel.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/serial/atmel_usart.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c index 7674f97e8d..8b1e0d55a4 100644 --- a/drivers/serial/atmel_usart.c +++ b/drivers/serial/atmel_usart.c @@ -25,6 +25,7 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_DM_SERIAL static void atmel_serial_setbrg_internal(atmel_usart3_t *usart, int id, int baudrate) { @@ -66,7 +67,6 @@ static void atmel_serial_activate(atmel_usart3_t *usart) __udelay(100); }
-#ifndef CONFIG_DM_SERIAL static void atmel_serial_setbrg(void) { atmel_serial_setbrg_internal((atmel_usart3_t *)CONFIG_USART_BASE, @@ -138,12 +138,37 @@ struct atmel_serial_priv { atmel_usart3_t *usart; };
+static void _atmel_serial_set_brg(atmel_usart3_t *usart, + ulong usart_clk_rate, int baudrate) +{ + unsigned long divisor; + + divisor = (usart_clk_rate / 16 + baudrate / 2) / baudrate; + writel(USART3_BF(CD, divisor), &usart->brgr); +} + +void _atmel_serial_init(atmel_usart3_t *usart, + ulong usart_clk_rate, int baudrate) +{ + writel(USART3_BIT(RXDIS) | USART3_BIT(TXDIS), &usart->cr); + + writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) | + USART3_BF(USCLKS, USART3_USCLKS_MCK) | + USART3_BF(CHRL, USART3_CHRL_8) | + USART3_BF(PAR, USART3_PAR_NONE) | + USART3_BF(NBSTOP, USART3_NBSTOP_1)), &usart->mr); + + _atmel_serial_set_brg(usart, usart_clk_rate, baudrate); + + writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr); + writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr); +} + int atmel_serial_setbrg(struct udevice *dev, int baudrate) { struct atmel_serial_priv *priv = dev_get_priv(dev);
- atmel_serial_setbrg_internal(priv->usart, 0 /* ignored */, baudrate); - atmel_serial_activate(priv->usart); + _atmel_serial_set_brg(priv->usart, get_usart_clk_rate(0), baudrate);
return 0; } @@ -202,7 +227,8 @@ static int atmel_serial_probe(struct udevice *dev) plat->base_addr = (uint32_t)addr_base; #endif priv->usart = (atmel_usart3_t *)plat->base_addr; - atmel_serial_init_internal(priv->usart); + + _atmel_serial_init(priv->usart, get_usart_clk_rate(0), gd->baudrate);
return 0; } @@ -233,7 +259,7 @@ static inline void _debug_uart_init(void) { atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_DEBUG_UART_BASE;
- atmel_serial_setbrg_internal(usart, 0, CONFIG_BAUDRATE); + _atmel_serial_init(usart, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); }
static inline void _debug_uart_putc(int ch)

Add the clock support.
The clock handling of DBGU is different fromt the one of USART.
Signed-off-by: Wenyou Yang wenyou.yang@atmel.com Reviewed-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Fix the DBGU clock handling. - Add Reviewed-by tag.
drivers/serial/atmel_usart.c | 52 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-)
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c index 8b1e0d55a4..453f8eb451 100644 --- a/drivers/serial/atmel_usart.c +++ b/drivers/serial/atmel_usart.c @@ -7,6 +7,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <clk.h> #include <dm.h> #include <errno.h> #include <watchdog.h> @@ -133,9 +134,14 @@ __weak struct serial_device *default_serial_console(void) #endif
#ifdef CONFIG_DM_SERIAL +enum serial_clk_type { + CLK_TYPE_NORMAL = 0, + CLK_TYPE_DBGU, +};
struct atmel_serial_priv { atmel_usart3_t *usart; + ulong usart_clk_rate; };
static void _atmel_serial_set_brg(atmel_usart3_t *usart, @@ -168,7 +174,7 @@ int atmel_serial_setbrg(struct udevice *dev, int baudrate) { struct atmel_serial_priv *priv = dev_get_priv(dev);
- _atmel_serial_set_brg(priv->usart, get_usart_clk_rate(0), baudrate); + _atmel_serial_set_brg(priv->usart, priv->usart_clk_rate, baudrate);
return 0; } @@ -213,10 +219,39 @@ static const struct dm_serial_ops atmel_serial_ops = { .setbrg = atmel_serial_setbrg, };
+static int atmel_serial_enable_clk(struct udevice *dev) +{ + struct atmel_serial_priv *priv = dev_get_priv(dev); + struct clk clk; + ulong clk_rate; + int ret; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return -EINVAL; + + if (dev_get_driver_data(dev) == CLK_TYPE_NORMAL) { + ret = clk_enable(&clk); + if (ret) + return ret; + } + + clk_rate = clk_get_rate(&clk); + if (!clk_rate) + return -EINVAL; + + priv->usart_clk_rate = clk_rate; + + clk_free(&clk); + + return 0; +} + static int atmel_serial_probe(struct udevice *dev) { struct atmel_serial_platdata *plat = dev->platdata; struct atmel_serial_priv *priv = dev_get_priv(dev); + int ret; #if CONFIG_IS_ENABLED(OF_CONTROL) fdt_addr_t addr_base;
@@ -228,14 +263,25 @@ static int atmel_serial_probe(struct udevice *dev) #endif priv->usart = (atmel_usart3_t *)plat->base_addr;
- _atmel_serial_init(priv->usart, get_usart_clk_rate(0), gd->baudrate); + ret = atmel_serial_enable_clk(dev); + if (ret) + return ret; + + _atmel_serial_init(priv->usart, priv->usart_clk_rate, gd->baudrate);
return 0; }
#if CONFIG_IS_ENABLED(OF_CONTROL) static const struct udevice_id atmel_serial_ids[] = { - { .compatible = "atmel,at91sam9260-usart" }, + { + .compatible = "atmel,at91sam9260-dbgu", + .data = CLK_TYPE_DBGU, + }, + { + .compatible = "atmel,at91sam9260-usart", + .data = CLK_TYPE_NORMAL, + }, { } }; #endif
participants (1)
-
Wenyou Yang