lib: utils/serial: Add support for Altera JTAG UART

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@iscas.ac.cn>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260104065506.70182-1-zhengxingda@iscas.ac.cn
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Icenowy Zheng
2026-01-04 14:55:06 +08:00
committed by Anup Patel
parent ecdb6c90c8
commit b07e449d15
6 changed files with 145 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2025 ISCAS
*
* Authors:
* Icenowy Zheng <zhengxingda@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;
}