[PATCH] lib: utils/serial: Add support for Altera JTAG UART
Icenowy Zheng
zhengxingda at iscas.ac.cn
Sat Jan 3 22:55:06 PST 2026
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>
---
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
More information about the opensbi
mailing list