Commit d1a938f421 for qemu.org
commit d1a938f421cea22f8b261bfb5519a97482af3b0e
Author: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Date: Fri Aug 28 17:39:12 2026 -0300
hw/riscv/fdt-common, virt.c: add riscv_create_fdt_uart()
Add a common uart FDT helper to be used by 'virt' and the future
'riscv-server-ref' board.
The 'tt-atlantis' board is left out of this patch because it's going
through UART related changes and its FDT might change soon, thus it's
better to wait for the final DT to be determined and then we can
evaluate whether it can share a common helper.
The "/chosen" and "/alias" changes are UART0 only so we're keeping them
out of the common helper. The board can set both manually as
appropriate.
No FDT changes intended.
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Message-ID: <20260828203918.350131-11-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c
index d2ce93ad28..0107aadaad 100644
--- a/hw/riscv/fdt-common.c
+++ b/hw/riscv/fdt-common.c
@@ -22,6 +22,8 @@
#include "hw/pci/pcie_host.h"
#include "hw/riscv/aia.h"
+#define UART_STD_CLOCK_FREQ 3686400 /* 3.6864 MHz */
+
void *riscv_create_board_device_tree(const char *model, const char *compatible,
int *fdt_size)
{
@@ -799,3 +801,30 @@ void riscv_create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props,
g_free(name);
}
}
+
+char *riscv_fdt_get_uart_nodename(hwaddr addr)
+{
+ return g_strdup_printf("/soc/serial@%"HWADDR_PRIx, addr);
+}
+
+void riscv_create_fdt_uart(void *fdt, const MemMapEntry *uart_mem,
+ int uart_irq, int aia_type,
+ uint32_t irq_phandle)
+{
+ g_autofree char *name = riscv_fdt_get_uart_nodename(uart_mem->base);
+
+ qemu_fdt_add_subnode(fdt, name);
+ qemu_fdt_setprop_string(fdt, name, "compatible", "ns16550a");
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
+ 2, uart_mem->base,
+ 2, uart_mem->size);
+
+ qemu_fdt_setprop_cell(fdt, name, "clock-frequency", UART_STD_CLOCK_FREQ);
+ qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", irq_phandle);
+
+ if (aia_type == AIA_TYPE_NONE) {
+ qemu_fdt_setprop_cell(fdt, name, "interrupts", uart_irq);
+ } else {
+ qemu_fdt_setprop_cells(fdt, name, "interrupts", uart_irq, 0x4);
+ }
+}
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index c9b1a669a5..ae809ecb5f 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -417,39 +417,22 @@ static void create_fdt_virtio(RISCVVirtState *s, uint32_t irq_virtio_phandle)
}
}
-static void create_fdt_uart(RISCVVirtState *s,
- uint32_t irq_mmio_phandle, int memId, int irqNo)
+static void create_fdt_uarts(RISCVVirtState *s, uint32_t irq_mmio_phandle)
{
g_autofree char *name = NULL;
MachineState *ms = MACHINE(s);
- name = g_strdup_printf("/soc/serial@%"HWADDR_PRIx,
- s->memmap[memId].base);
- qemu_fdt_add_subnode(ms->fdt, name);
- qemu_fdt_setprop_string(ms->fdt, name, "compatible", "ns16550a");
- qemu_fdt_setprop_sized_cells(ms->fdt, name, "reg",
- 2, s->memmap[memId].base,
- 2, s->memmap[memId].size);
- qemu_fdt_setprop_cell(ms->fdt, name, "clock-frequency", 3686400);
- qemu_fdt_setprop_cell(ms->fdt, name, "interrupt-parent", irq_mmio_phandle);
- if (s->aia_type == VIRT_AIA_TYPE_NONE) {
- qemu_fdt_setprop_cell(ms->fdt, name, "interrupts", irqNo);
- } else {
- qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", irqNo, 0x4);
+ if (s->uart1_present) {
+ riscv_create_fdt_uart(ms->fdt, &s->memmap[VIRT_UART1],
+ UART1_IRQ, s->aia_type, irq_mmio_phandle);
}
- if (VIRT_UART0 == memId) {
- qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name);
- qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", name);
- }
-}
+ riscv_create_fdt_uart(ms->fdt, &s->memmap[VIRT_UART0], UART0_IRQ,
+ s->aia_type, irq_mmio_phandle);
-static void create_fdt_uarts(RISCVVirtState *s, uint32_t irq_mmio_phandle)
-{
- if (s->uart1_present) {
- create_fdt_uart(s, irq_mmio_phandle, VIRT_UART1, UART1_IRQ);
- }
- create_fdt_uart(s, irq_mmio_phandle, VIRT_UART0, UART0_IRQ);
+ name = riscv_fdt_get_uart_nodename(s->memmap[VIRT_UART0].base);
+ qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name);
+ qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", name);
}
static void create_fdt_rtc(RISCVVirtState *s,
diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h
index a45b063f66..c8b25348bd 100644
--- a/include/hw/riscv/fdt-common.h
+++ b/include/hw/riscv/fdt-common.h
@@ -128,4 +128,9 @@ void riscv_create_fdt_socket_aplic(void *fdt, APLICFdtProps *props,
uint32_t *aplic_phandles);
void riscv_create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props,
uint32_t *intc_phandles);
+/* Caller must free the returned string. */
+char *riscv_fdt_get_uart_nodename(hwaddr addr);
+void riscv_create_fdt_uart(void *fdt, const MemMapEntry *uart_mem,
+ int uart_irq, int aia_type,
+ uint32_t irq_phandle);
#endif