Re: [PATCH RFC v3 3/8] serial: serial_meson: add minimal non-DM driver
Neil Armstrong <[email protected]> Wed, 8 Oct 2025 15:31:08 +0200
| Newsgroups | io.groups.u-boot-amlogic,org.u-boot-project.lists.u-boot |
|---|---|
| Organization | Linaro |
| Message-ID | <[email protected]> |
On 10/8/25 12:00, 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 <[email protected]> > --- > drivers/serial/serial.c | 2 + > drivers/serial/serial_meson.c | 119 +++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 120 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..cc71381f87e1e2d192e5f4450f881c2a69511ca3 100644 > --- a/drivers/serial/serial_meson.c > +++ b/drivers/serial/serial_meson.c > @@ -3,9 +3,11 @@ > * (C) Copyright 2016 Beniamino Galvani <[email protected]> > */ > > +#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> > @@ -25,6 +27,15 @@ struct meson_serial_plat { > struct meson_uart *reg; > }; > > +#if !CONFIG_IS_ENABLED(DM_SERIAL) > +/* UART base address */ > +#if defined(CONFIG_MESON_GX) > +#define AML_UART_BASE 0xc81004c0 > +#else /* G12A, AXG, ... */ > +#define AML_UART_BASE 0xff803000 > +#endif > +#endif > + > /* AML_UART_STATUS bits */ > #define AML_UART_PARITY_ERR BIT(16) > #define AML_UART_FRAME_ERR BIT(17) > @@ -51,6 +62,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 +257,111 @@ U_BOOT_DRIVER(serial_meson) = { > .plat_auto = sizeof(struct meson_serial_plat), > }; > > +#else > + > +static int meson_serial_init(void) > +{ > + struct meson_uart *const uart = (struct meson_uart *)AML_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 *)AML_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 *)AML_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 *)AML_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> > Reviewed-by: Neil Armstrong <[email protected]>