[PATCH RFC 4/9] serial: serial_meson: add minimal non-DM driver
Neil Armstrong
neil.armstrong at linaro.org
Mon Sep 8 10:11:59 CEST 2025
On 07/09/2025 16:36, Ferass El Hafidi wrote:
> It is very limited and minimal, only implements putc/puts.
> This minimal driver is intended to be used in SPL, and other
> size-constrained situations.
>
> Signed-off-by: Ferass El Hafidi <funderscore at postmarketos.org>
> ---
> drivers/serial/serial.c | 2 +
> drivers/serial/serial_meson.c | 112 +++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 113 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
> index e10ca6eef768502ea32bf39a41ae2e3ccd168c66..c0b1eb3056181b95e1861f1ce08fcd82ff81eb71 100644
> --- a/drivers/serial/serial.c
> +++ b/drivers/serial/serial.c
> @@ -129,6 +129,7 @@ serial_initfunc(pxa_serial_initialize);
> serial_initfunc(smh_serial_initialize);
> serial_initfunc(sh_serial_initialize);
> serial_initfunc(mtk_serial_initialize);
> +serial_initfunc(meson_serial_initialize);
>
> /**
> * serial_register() - Register serial driver with serial driver core
> @@ -167,6 +168,7 @@ int serial_initialize(void)
> smh_serial_initialize();
> sh_serial_initialize();
> mtk_serial_initialize();
> + meson_serial_initialize();
>
> serial_assign(default_serial_console()->name);
>
> diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c
> index bb79b9729579a661084425d6b3c5357da31dc3c0..981ea5e159062b7d13885325e17b833145281158 100644
> --- a/drivers/serial/serial_meson.c
> +++ b/drivers/serial/serial_meson.c
> @@ -3,9 +3,11 @@
> * (C) Copyright 2016 Beniamino Galvani <b.galvani at gmail.com>
> */
>
> +#if CONFIG_IS_ENABLED(DM_SERIAL)
> #include <dm.h>
> -#include <errno.h>
> #include <fdtdec.h>
> +#endif
> +#include <errno.h>
> #include <linux/kernel.h>
> #include <linux/bitops.h>
> #include <linux/compiler.h>
> @@ -51,6 +53,7 @@ struct meson_serial_plat {
> #define AML_UART_REG5_USE_NEW_BAUD BIT(23) /* default 1 (use new baud rate register) */
> #define AML_UART_REG5_BAUD_MASK 0x7fffff
>
> +#if CONFIG_IS_ENABLED(DM_SERIAL)
> static u32 meson_calc_baud_divisor(ulong src_rate, u32 baud)
> {
> /*
> @@ -245,6 +248,113 @@ U_BOOT_DRIVER(serial_meson) = {
> .plat_auto = sizeof(struct meson_serial_plat),
> };
>
> +DM_DRIVER_ALIAS(serial_meson, amlogic_meson_gx_uart);
Why is this needed ?
> +
> +#else
> +
> +static int meson_serial_init(void)
> +{
> + struct meson_uart *const uart = (struct meson_uart *)CONFIG_VAL(DEBUG_UART_BASE);
> + u32 val;
> +
> + val = readl(&uart->control);
> + val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
> + writel(val, &uart->control);
> + val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
> + writel(val, &uart->control);
> + val |= (AML_UART_RX_EN | AML_UART_TX_EN);
> + writel(val, &uart->control);
> +
> + return 0;
> +}
> +
> +static int meson_serial_stop(void)
> +{
> + return 0;
> +}
> +
> +static void meson_serial_setbrg(void)
> +{
> +}
> +
> +static void meson_serial_putc(const char ch)
> +{
> + struct meson_uart *uart = (struct meson_uart *)CONFIG_VAL(DEBUG_UART_BASE);
> +
> + /* On '\n' also do '\r' */
> + if (ch == '\n')
> + meson_serial_putc('\r');
> +
> + while (readl(&uart->status) & AML_UART_TX_FULL)
> + ;
> +
> + writel(ch, &uart->wfifo);
> +}
> +
> +static void meson_serial_puts(const char *s)
> +{
> + while (*s)
> + meson_serial_putc(*s++);
> +}
> +
> +static int meson_serial_getc(void)
> +{
> + struct meson_uart *const uart = (struct meson_uart *)CONFIG_VAL(DEBUG_UART_BASE);
> + uint32_t status = readl(&uart->status);
> +
> + if (status & AML_UART_RX_EMPTY)
> + return -EAGAIN;
> +
> + if (status & AML_UART_ERR) {
> + u32 val = readl(&uart->control);
> +
> + /* Clear error */
> + val |= AML_UART_CLR_ERR;
> + writel(val, &uart->control);
> + val &= ~AML_UART_CLR_ERR;
> + writel(val, &uart->control);
> +
> + /* Remove spurious byte from fifo */
> + readl(&uart->rfifo);
> + return -EIO;
> + }
> +
> + return readl(&uart->rfifo) & 0xff;
> +}
> +
> +static int meson_serial_tstc(void)
> +{
> + struct meson_uart *const uart = (struct meson_uart *)CONFIG_VAL(DEBUG_UART_BASE);
> + uint32_t status = readl(&uart->status);
> +
> + if (status & AML_UART_RX_EMPTY)
> + return 0;
> + return 1;
> +}
> +
> +struct serial_device meson_serial_device = {
> + .name = "meson_serial",
> + .start = meson_serial_init,
> + .stop = meson_serial_stop,
> + .setbrg = meson_serial_setbrg,
> + .getc = meson_serial_getc,
> + .tstc = meson_serial_tstc,
> + .putc = meson_serial_putc,
> + .puts = meson_serial_puts,
> +};
> +
> +void meson_serial_initialize(void)
> +{
> + serial_register(&meson_serial_device);
> +}
> +
> +__weak struct serial_device *default_serial_console(void)
> +{
> + return &meson_serial_device;
> +}
> +
> +#endif
> +
> #ifdef CONFIG_DEBUG_UART_MESON
>
> #include <debug_uart.h>
>
More information about the U-Boot
mailing list