@samitouri / QOSamiQemu / commits / f9e0efe1ea

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