Commit f9e0efe1ea for qemu.org
commit f9e0efe1ea0513a72a215d7139c5ce29a33412cc
Author: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Date: Mon Jun 15 17:37:22 2026 -0300
hw/riscv: add fdt-common helper
There's too much duplication between RISC-V boards and one of the most
common culprits is the FDT functions.
Add a new file for board FDT helpers. Start by creating a helper that
initializes the FDT and init it with the common board boilerplate.
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260615203734.954428-3-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
new file mode 100644
index 0000000000..b155246998
--- /dev/null
+++ b/hw/riscv/fdt-common.c
@@ -0,0 +1,37 @@
+/*
+ * RISC-V board helpers for FDT generation.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu/error-report.h"
+#include "system/device_tree.h"
+#include "hw/riscv/fdt-common.h"
+
+void *create_board_device_tree(const char *model, const char *compatible,
+ int *fdt_size)
+{
+ void *fdt = create_device_tree(fdt_size);
+
+ if (!fdt) {
+ error_report("create_device_tree() failed");
+ exit(1);
+ }
+
+ qemu_fdt_setprop_string(fdt, "/", "model", model);
+ qemu_fdt_setprop_string(fdt, "/", "compatible", compatible);
+ qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+ qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+
+ qemu_fdt_add_subnode(fdt, "/soc");
+ qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
+ qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
+ qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
+ qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+
+ return fdt;
+}
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index 09cf855984..b70a054579 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -1,5 +1,6 @@
riscv_ss = ss.source_set()
riscv_ss.add(files('boot.c'))
+riscv_ss.add(files('fdt-common.c'))
riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c'))
riscv_ss.add(files('riscv_hart.c'))
riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c'))
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 3abbd6c823..5d3b2751ad 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -52,6 +52,7 @@
#include "hw/riscv/sifive_u.h"
#include "hw/riscv/boot.h"
#include "hw/riscv/machines-qom.h"
+#include "hw/riscv/fdt-common.h"
#include "hw/char/sifive_uart.h"
#include "hw/intc/riscv_aclint.h"
#include "hw/intc/sifive_plic.h"
@@ -112,23 +113,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
"sifive,plic-1.0.0", "riscv,plic0"
};
- fdt = ms->fdt = create_device_tree(&s->fdt_size);
- if (!fdt) {
- error_report("create_device_tree() failed");
- exit(1);
- }
-
- qemu_fdt_setprop_string(fdt, "/", "model", "SiFive HiFive Unleashed A00");
- qemu_fdt_setprop_string(fdt, "/", "compatible",
- "sifive,hifive-unleashed-a00");
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
-
- qemu_fdt_add_subnode(fdt, "/soc");
- qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
- qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
- qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
- qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+ fdt = ms->fdt = create_board_device_tree("SiFive HiFive Unleashed A00",
+ "sifive,hifive-unleashed-a00", &s->fdt_size);
hfclk_phandle = phandle++;
nodename = g_strdup_printf("/hfclk");
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index f9d00e0d5c..79c9bb041f 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -32,6 +32,7 @@
#include "hw/riscv/riscv_hart.h"
#include "hw/riscv/spike.h"
#include "hw/riscv/boot.h"
+#include "hw/riscv/fdt-common.h"
#include "hw/riscv/numa.h"
#include "hw/riscv/machines-qom.h"
#include "hw/char/riscv_htif.h"
@@ -66,16 +67,8 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
"sifive,clint0", "riscv,clint0"
};
- fdt = ms->fdt = create_device_tree(&fdt_size);
- if (!fdt) {
- error_report("create_device_tree() failed");
- exit(1);
- }
-
- qemu_fdt_setprop_string(fdt, "/", "model", "ucbbar,spike-bare,qemu");
- qemu_fdt_setprop_string(fdt, "/", "compatible", "ucbbar,spike-bare-dev");
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+ fdt = ms->fdt = create_board_device_tree("ucbbar,spike-bare,qemu",
+ "ucbbar,spike-bare-dev", &fdt_size);
qemu_fdt_add_subnode(fdt, "/htif");
qemu_fdt_setprop_string(fdt, "/htif", "compatible", "ucb,htif0");
@@ -84,12 +77,6 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
0x0, memmap[SPIKE_HTIF].base, 0x0, memmap[SPIKE_HTIF].size);
}
- qemu_fdt_add_subnode(fdt, "/soc");
- qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
- qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
- qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
- qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
-
qemu_fdt_add_subnode(fdt, "/cpus");
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 0c489bb412..cb1d83fd48 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -36,6 +36,7 @@
#include "hw/riscv/riscv-iommu-bits.h"
#include "hw/riscv/virt.h"
#include "hw/riscv/boot.h"
+#include "hw/riscv/fdt-common.h"
#include "hw/riscv/machines-qom.h"
#include "hw/riscv/numa.h"
#include "kvm/kvm_riscv.h"
@@ -1150,22 +1151,8 @@ static void create_fdt(RISCVVirtState *s)
uint8_t rng_seed[32];
g_autofree char *name = NULL;
- ms->fdt = create_device_tree(&s->fdt_size);
- if (!ms->fdt) {
- error_report("create_device_tree() failed");
- exit(1);
- }
-
- qemu_fdt_setprop_string(ms->fdt, "/", "model", "riscv-virtio,qemu");
- qemu_fdt_setprop_string(ms->fdt, "/", "compatible", "riscv-virtio");
- qemu_fdt_setprop_cell(ms->fdt, "/", "#size-cells", 0x2);
- qemu_fdt_setprop_cell(ms->fdt, "/", "#address-cells", 0x2);
-
- qemu_fdt_add_subnode(ms->fdt, "/soc");
- qemu_fdt_setprop(ms->fdt, "/soc", "ranges", NULL, 0);
- qemu_fdt_setprop_string(ms->fdt, "/soc", "compatible", "simple-bus");
- qemu_fdt_setprop_cell(ms->fdt, "/soc", "#size-cells", 0x2);
- qemu_fdt_setprop_cell(ms->fdt, "/soc", "#address-cells", 0x2);
+ ms->fdt = create_board_device_tree("riscv-virtio,qemu", "riscv-virtio",
+ &s->fdt_size);
/*
* The "/soc/pci@..." node is needed for PCIE hotplugs
diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h
new file mode 100644
index 0000000000..adf9b33dfd
--- /dev/null
+++ b/include/hw/riscv/fdt-common.h
@@ -0,0 +1,14 @@
+/*
+ * RISC-V board helpers for FDT generation.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef RISCV_VIRT_FDT_H
+#define RISCV_VIRT_FDT_H
+
+void *create_board_device_tree(const char *model, const char *compatible,
+ int *fdt_size);
+#endif