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>
Daniel Henrique Barboza committed
Jun 15, 2026 at 17:37 UTC
f9e0efe1ea0513a72a215d7139c5ce29a33412cc
6 files changed
+61
-49
hw/riscv/fdt-common.c
new
+37
@@ -0,0 +1,37 @@
1
+/*
2
+ * RISC-V board helpers for FDT generation.
3
+ *
4
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#include "qemu/osdep.h"
10
+
11
+#include "qemu/error-report.h"
12
+#include "system/device_tree.h"
13
+#include "hw/riscv/fdt-common.h"
14
+
15
+void *create_board_device_tree(const char *model, const char *compatible,
16
+ int *fdt_size)
17
+{
18
+ void *fdt = create_device_tree(fdt_size);
19
+
20
+ if (!fdt) {
21
+ error_report("create_device_tree() failed");
22
+ exit(1);
23
+ }
24
+
25
+ qemu_fdt_setprop_string(fdt, "/", "model", model);
26
+ qemu_fdt_setprop_string(fdt, "/", "compatible", compatible);
27
+ qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
28
+ qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
29
+
30
+ qemu_fdt_add_subnode(fdt, "/soc");
31
+ qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
32
+ qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
33
+ qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
34
+ qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
35
+
36
+ return fdt;
37
+}
hw/riscv/meson.build
+1
@@ -1,5 +1,6 @@
1
riscv_ss = ss.source_set()
2
riscv_ss.add(files('boot.c'))
3
+riscv_ss.add(files('fdt-common.c'))
4
riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c'))
5
riscv_ss.add(files('riscv_hart.c'))
6
riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c'))
hw/riscv/sifive_u.c
+3
-17
@@ -52,6 +52,7 @@
52
#include "hw/riscv/sifive_u.h"
53
#include "hw/riscv/boot.h"
54
#include "hw/riscv/machines-qom.h"
55
+#include "hw/riscv/fdt-common.h"
56
#include "hw/char/sifive_uart.h"
57
#include "hw/intc/riscv_aclint.h"
58
#include "hw/intc/sifive_plic.h"
@@ -112,23 +113,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
113
"sifive,plic-1.0.0", "riscv,plic0"
114
};
115
115
- fdt = ms->fdt = create_device_tree(&s->fdt_size);
116
- if (!fdt) {
117
- error_report("create_device_tree() failed");
118
- exit(1);
119
- }
120
-
121
- qemu_fdt_setprop_string(fdt, "/", "model", "SiFive HiFive Unleashed A00");
122
- qemu_fdt_setprop_string(fdt, "/", "compatible",
123
- "sifive,hifive-unleashed-a00");
124
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
125
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
126
-
127
- qemu_fdt_add_subnode(fdt, "/soc");
128
- qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
129
- qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
130
- qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
131
- qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
116
+ fdt = ms->fdt = create_board_device_tree("SiFive HiFive Unleashed A00",
117
+ "sifive,hifive-unleashed-a00", &s->fdt_size);
118
119
hfclk_phandle = phandle++;
120
nodename = g_strdup_printf("/hfclk");
hw/riscv/spike.c
+3
-16
@@ -32,6 +32,7 @@
32
#include "hw/riscv/riscv_hart.h"
33
#include "hw/riscv/spike.h"
34
#include "hw/riscv/boot.h"
35
+#include "hw/riscv/fdt-common.h"
36
#include "hw/riscv/numa.h"
37
#include "hw/riscv/machines-qom.h"
38
#include "hw/char/riscv_htif.h"
@@ -66,16 +67,8 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
67
"sifive,clint0", "riscv,clint0"
68
};
69
69
- fdt = ms->fdt = create_device_tree(&fdt_size);
70
- if (!fdt) {
71
- error_report("create_device_tree() failed");
72
- exit(1);
73
- }
74
-
75
- qemu_fdt_setprop_string(fdt, "/", "model", "ucbbar,spike-bare,qemu");
76
- qemu_fdt_setprop_string(fdt, "/", "compatible", "ucbbar,spike-bare-dev");
77
- qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
78
- qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
70
+ fdt = ms->fdt = create_board_device_tree("ucbbar,spike-bare,qemu",
71
+ "ucbbar,spike-bare-dev", &fdt_size);
72
73
qemu_fdt_add_subnode(fdt, "/htif");
74
qemu_fdt_setprop_string(fdt, "/htif", "compatible", "ucb,htif0");
@@ -84,12 +77,6 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
77
0x0, memmap[SPIKE_HTIF].base, 0x0, memmap[SPIKE_HTIF].size);
78
}
79
87
- qemu_fdt_add_subnode(fdt, "/soc");
88
- qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
89
- qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
90
- qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
91
- qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
92
-
80
qemu_fdt_add_subnode(fdt, "/cpus");
81
qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency",
82
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ);
hw/riscv/virt.c
+3
-16
@@ -36,6 +36,7 @@
36
#include "hw/riscv/riscv-iommu-bits.h"
37
#include "hw/riscv/virt.h"
38
#include "hw/riscv/boot.h"
39
+#include "hw/riscv/fdt-common.h"
40
#include "hw/riscv/machines-qom.h"
41
#include "hw/riscv/numa.h"
42
#include "kvm/kvm_riscv.h"
@@ -1150,22 +1151,8 @@ static void create_fdt(RISCVVirtState *s)
1151
uint8_t rng_seed[32];
1152
g_autofree char *name = NULL;
1153
1153
- ms->fdt = create_device_tree(&s->fdt_size);
1154
- if (!ms->fdt) {
1155
- error_report("create_device_tree() failed");
1156
- exit(1);
1157
- }
1158
-
1159
- qemu_fdt_setprop_string(ms->fdt, "/", "model", "riscv-virtio,qemu");
1160
- qemu_fdt_setprop_string(ms->fdt, "/", "compatible", "riscv-virtio");
1161
- qemu_fdt_setprop_cell(ms->fdt, "/", "#size-cells", 0x2);
1162
- qemu_fdt_setprop_cell(ms->fdt, "/", "#address-cells", 0x2);
1163
-
1164
- qemu_fdt_add_subnode(ms->fdt, "/soc");
1165
- qemu_fdt_setprop(ms->fdt, "/soc", "ranges", NULL, 0);
1166
- qemu_fdt_setprop_string(ms->fdt, "/soc", "compatible", "simple-bus");
1167
- qemu_fdt_setprop_cell(ms->fdt, "/soc", "#size-cells", 0x2);
1168
- qemu_fdt_setprop_cell(ms->fdt, "/soc", "#address-cells", 0x2);
1154
+ ms->fdt = create_board_device_tree("riscv-virtio,qemu", "riscv-virtio",
1155
+ &s->fdt_size);
1156
1157
/*
1158
* The "/soc/pci@..." node is needed for PCIE hotplugs
include/hw/riscv/fdt-common.h
new
+14
@@ -0,0 +1,14 @@
1
+/*
2
+ * RISC-V board helpers for FDT generation.
3
+ *
4
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+
9
+#ifndef RISCV_VIRT_FDT_H
10
+#define RISCV_VIRT_FDT_H
11
+
12
+void *create_board_device_tree(const char *model, const char *compatible,
13
+ int *fdt_size);
14
+#endif