serial: serial_meson: add minimal non-DM driver

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.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Ferass El Hafidi <funderscore@postmarketos.org>
Link: https://patch.msgid.link/20251126-spl-gx-v5-3-6cbffb2451ca@postmarketos.org
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
This commit is contained in:
Ferass El Hafidi 2025-11-26 12:17:05 +00:00 committed by Neil Armstrong
parent 3eee9c1f61
commit ec958be7cc
2 changed files with 120 additions and 1 deletions

View File

@ -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);

View File

@ -3,9 +3,11 @@
* (C) Copyright 2016 Beniamino Galvani <b.galvani@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>
@ -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>