[PATCH] lib: utils/serial: Add support for Altera JTAG UART
Anup Patel
anup at brainfault.org
Fri Feb 20 03:29:29 PST 2026
On Sun, Jan 4, 2026 at 12:25 PM Icenowy Zheng <zhengxingda at iscas.ac.cn> wrote:
>
> Altera provides a JTAG UART core that provides virtual UART over JTAG
> and can coexist with their virtual JTAG. [1] This core has already been
> supported by Linux and the programming interface has always been stable.
>
> Add support for it to OpenSBI to ease JTAG prototype bringing up.
>
> The driver follows the device tree binding in mainline Linux. [2]
>
> [1] https://docs.altera.com/r/docs/683130/25.3/embedded-peripherals-ip-user-guide/jtag-uart-core
> [2] https://github.com/torvalds/linux/blob/v6.19-rc1/Documentation/devicetree/bindings/serial/altr%2Cjuart-1.0.yaml
>
> Signed-off-by: Icenowy Zheng <zhengxingda at iscas.ac.cn>
LGTM.
Reviewed-by: Anup Patel <anup at brainfault.org>
Applied this patch to the riscv/opensbi repo.
Thanks,
Anup
> ---
> include/sbi_utils/serial/altr-juart.h | 17 ++++++
> lib/utils/serial/Kconfig | 9 +++
> lib/utils/serial/altr-juart.c | 74 ++++++++++++++++++++++++
> lib/utils/serial/fdt_serial_altr_juart.c | 40 +++++++++++++
> lib/utils/serial/objects.mk | 4 ++
> platform/generic/configs/defconfig | 1 +
> 6 files changed, 145 insertions(+)
> create mode 100644 include/sbi_utils/serial/altr-juart.h
> create mode 100644 lib/utils/serial/altr-juart.c
> create mode 100644 lib/utils/serial/fdt_serial_altr_juart.c
>
> diff --git a/include/sbi_utils/serial/altr-juart.h b/include/sbi_utils/serial/altr-juart.h
> new file mode 100644
> index 00000000..1304ee08
> --- /dev/null
> +++ b/include/sbi_utils/serial/altr-juart.h
> @@ -0,0 +1,17 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 ISCAS
> + *
> + * Authors:
> + * Icenowy Zheng <zhengxingda at iscas.ac.cn>
> + */
> +
> +#ifndef __SERIAL_ALTR_JUART_H__
> +#define __SERIAL_ALTR_JUART_H__
> +
> +#include <sbi/sbi_types.h>
> +
> +int altr_juart_init(unsigned long base);
> +
> +#endif
> diff --git a/lib/utils/serial/Kconfig b/lib/utils/serial/Kconfig
> index e3589cac..21619d0d 100644
> --- a/lib/utils/serial/Kconfig
> +++ b/lib/utils/serial/Kconfig
> @@ -9,6 +9,11 @@ config FDT_SERIAL
>
> if FDT_SERIAL
>
> +config FDT_SERIAL_ALTR_JUART
> + bool "Altera JTAG UART FDT driver"
> + select SERIAL_ALTR_JUART
> + default n
> +
> config FDT_SERIAL_CADENCE
> bool "Cadence UART FDT driver"
> select SERIAL_CADENCE
> @@ -56,6 +61,10 @@ config FDT_SERIAL_XILINX_UARTLITE
>
> endif
>
> +config SERIAL_ALTR_JUART
> + bool "Altera JTAG UART support"
> + default n
> +
> config SERIAL_CADENCE
> bool "Cadence UART support"
> default n
> diff --git a/lib/utils/serial/altr-juart.c b/lib/utils/serial/altr-juart.c
> new file mode 100644
> index 00000000..a230a561
> --- /dev/null
> +++ b/lib/utils/serial/altr-juart.c
> @@ -0,0 +1,74 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 ISCAS
> + *
> + * Authors:
> + * Icenowy Zheng <zhengxingda at iscas.ac.cn>
> + */
> +
> +#include <sbi/riscv_io.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi_utils/serial/altr-juart.h>
> +
> +/* clang-format off */
> +
> +#define JUART_DATA_OFFSET 0x00
> +# define JUART_DATA_DATA_MASK 0x000000ff
> +# define JUART_DATA_RVALID (1 << 15)
> +# define JUART_DATA_RAVAIL_MASK 0xffff0000
> +# define JUART_DATA_RAVAIL_SHIFT 16
> +#define JUART_CTRL_OFFSET 0x04
> +# define JUART_CTRL_RE (1 << 0)
> +# define JUART_CTRL_WE (1 << 1)
> +# define JUART_CTRL_RI (1 << 8)
> +# define JUART_CTRL_WI (1 << 9)
> +# define JUART_CTRL_AC (1 << 10)
> +# define JUART_CTRL_WSPACE_MASK 0xffff0000
> +# define JUART_CTRL_WSPACE_SHIFT 16
> +
> +/* clang-format on */
> +
> +static volatile char *altr_juart_base;
> +
> +static u32 get_reg(u32 offset)
> +{
> + return readl(altr_juart_base + offset);
> +}
> +
> +static void set_reg(u32 offset, u32 val)
> +{
> + writel(val, altr_juart_base + offset);
> +}
> +
> +static void altr_juart_putc(char ch)
> +{
> + while(!(get_reg(JUART_CTRL_OFFSET) & JUART_CTRL_WSPACE_MASK))
> + ;
> +
> + set_reg(JUART_DATA_OFFSET, (unsigned char)ch);
> +}
> +
> +static int altr_juart_getc(void)
> +{
> + u32 reg = get_reg(JUART_DATA_OFFSET);
> + if (reg & JUART_DATA_RVALID)
> + return reg & JUART_DATA_DATA_MASK;
> +
> + return -1;
> +}
> +
> +static struct sbi_console_device altr_juart_console = {
> + .name = "altr-juart",
> + .console_putc = altr_juart_putc,
> + .console_getc = altr_juart_getc
> +};
> +
> +int altr_juart_init(unsigned long base)
> +{
> + altr_juart_base = (volatile char *)base;
> +
> + sbi_console_set_device(&altr_juart_console);
> +
> + return 0;
> +}
> diff --git a/lib/utils/serial/fdt_serial_altr_juart.c b/lib/utils/serial/fdt_serial_altr_juart.c
> new file mode 100644
> index 00000000..7901aa57
> --- /dev/null
> +++ b/lib/utils/serial/fdt_serial_altr_juart.c
> @@ -0,0 +1,40 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2025 ISCAS
> + *
> + * Authors:
> + * Icenowy Zheng <zhengxingda at iscas.ac.cn>
> + */
> +
> +#include <sbi/sbi_error.h>
> +#include <sbi_utils/fdt/fdt_helper.h>
> +#include <sbi_utils/serial/fdt_serial.h>
> +#include <sbi_utils/serial/altr-juart.h>
> +
> +static int serial_altr_juart_init(const void *fdt, int nodeoff,
> + const struct fdt_match *match)
> +{
> + uint64_t reg_addr, reg_size;
> + int rc;
> +
> + if (nodeoff < 0 || !fdt)
> + return SBI_ENODEV;
> +
> + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, ®_size);
> + /* Two 32-bit registers */
> + if (rc < 0 || !reg_addr || !reg_size || reg_size < 0x8)
> + return SBI_ENODEV;
> +
> + return altr_juart_init(reg_addr);
> +}
> +
> +static const struct fdt_match serial_altr_juart_match[] = {
> + { .compatible = "altr,juart-1.0" },
> + { },
> +};
> +
> +const struct fdt_driver fdt_serial_altr_juart = {
> + .match_table = serial_altr_juart_match,
> + .init = serial_altr_juart_init,
> +};
> diff --git a/lib/utils/serial/objects.mk b/lib/utils/serial/objects.mk
> index 7c973c83..94cf3a4b 100644
> --- a/lib/utils/serial/objects.mk
> +++ b/lib/utils/serial/objects.mk
> @@ -10,6 +10,9 @@
> libsbiutils-objs-$(CONFIG_FDT_SERIAL) += serial/fdt_serial.o
> libsbiutils-objs-$(CONFIG_FDT_SERIAL) += serial/fdt_serial_drivers.carray.o
>
> +carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_ALTR_JUART) += fdt_serial_altr_juart
> +libsbiutils-objs-$(CONFIG_FDT_SERIAL_ALTR_JUART) += serial/fdt_serial_altr_juart.o
> +
> carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_CADENCE) += fdt_serial_cadence
> libsbiutils-objs-$(CONFIG_FDT_SERIAL_CADENCE) += serial/fdt_serial_cadence.o
>
> @@ -37,6 +40,7 @@ libsbiutils-objs-$(CONFIG_FDT_SERIAL_UART8250) += serial/fdt_serial_uart8250.o
> carray-fdt_serial_drivers-$(CONFIG_FDT_SERIAL_XILINX_UARTLITE) += fdt_serial_xlnx_uartlite
> libsbiutils-objs-$(CONFIG_FDT_SERIAL_XILINX_UARTLITE) += serial/fdt_serial_xlnx_uartlite.o
>
> +libsbiutils-objs-$(CONFIG_SERIAL_ALTR_JUART) += serial/altr-juart.o
> libsbiutils-objs-$(CONFIG_SERIAL_CADENCE) += serial/cadence-uart.o
> libsbiutils-objs-$(CONFIG_SERIAL_GAISLER) += serial/gaisler-uart.o
> libsbiutils-objs-$(CONFIG_SERIAL_RENESAS_SCIF) += serial/renesas_scif.o
> diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
> index aab1560f..9d977960 100644
> --- a/platform/generic/configs/defconfig
> +++ b/platform/generic/configs/defconfig
> @@ -49,6 +49,7 @@ CONFIG_FDT_RESET_SG2042_HWMON_MCU=y
> CONFIG_FDT_RESET_SUNXI_WDT=y
> CONFIG_FDT_RESET_SYSCON=y
> CONFIG_FDT_SERIAL=y
> +CONFIG_FDT_SERIAL_ALTR_JUART=y
> CONFIG_FDT_SERIAL_CADENCE=y
> CONFIG_FDT_SERIAL_GAISLER=y
> CONFIG_FDT_SERIAL_HTIF=y
> --
> 2.52.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
More information about the opensbi
mailing list