Yet another FDT that we want to move to a helper to avoid copy/pasting
code to other boards that will use a mtimer. In particular the future
'riscv-server-ref' board.
No FDT changes made.
Signed-off-by: Daniel Henrique Barboza <[email protected]>
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
---
hw/riscv/fdt-common.c | 96 ++++++++++++++++++++++++++++++++
hw/riscv/virt.c | 101 ++++------------------------------
include/hw/riscv/fdt-common.h | 11 ++++
3 files changed, 119 insertions(+), 89 deletions(-)
diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c
index d815c5adff..76a783709d 100644
--- a/hw/riscv/fdt-common.c
+++ b/hw/riscv/fdt-common.c
@@ -16,6 +16,7 @@
#include "target/riscv/cpu_bits.h"
#include "hw/riscv/riscv-iommu-bits.h"
#include "hw/riscv/iommu.h"
+#include "hw/intc/riscv_aclint.h"
#include "hw/intc/riscv_imsic.h"
#include "hw/pci/pci.h"
#include "hw/pci/pcie_host.h"
@@ -702,3 +703,98 @@ void riscv_create_fdt_socket_aplic(void *fdt,
APLICFdtProps *props,
aplic_phandles[props->socket] = aplic_s_phandle;
}
+
+void riscv_create_fdt_socket_aclint(void *fdt, ACLINTFdtProps *props,
+ uint32_t *intc_phandles)
+{
+ uint32_t aclint_cells_size = props->num_harts * sizeof(uint32_t) * 2;
+ g_autofree uint32_t *aclint_mswi_cells = NULL;
+ g_autofree uint32_t *aclint_sswi_cells = NULL;
+ g_autofree uint32_t *aclint_mtimer_cells = NULL;
+ hwaddr addr, size;
+ char *name;
+ int cpu;
+
+ aclint_mswi_cells = g_new0(uint32_t, props->num_harts * 2);
+ aclint_mtimer_cells = g_new0(uint32_t, props->num_harts * 2);
+ aclint_sswi_cells = g_new0(uint32_t, props->num_harts * 2);
+
+ for (cpu = 0; cpu < props->num_harts; cpu++) {
+ aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+ aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
+ aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+ aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
+ aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+ aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
+ }
+
+ if (props->aia_type != AIA_TYPE_APLIC_IMSIC) {
+ addr = props->clint->base + (props->clint->size * props->socket);
+ name = g_strdup_printf("/soc/mswi@%"HWADDR_PRIx, addr);
+
+ qemu_fdt_add_subnode(fdt, name);
+ qemu_fdt_setprop_string(fdt, name, "compatible", "riscv,aclint-mswi");
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
+ 2, addr, 2, RISCV_ACLINT_SWI_SIZE);
+ qemu_fdt_setprop(fdt, name, "interrupts-extended",
+ aclint_mswi_cells, aclint_cells_size);
+ qemu_fdt_setprop(fdt, name, "interrupt-controller", NULL, 0);
+ qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", 0);
+
+ if (props->numa_enabled) {
+ qemu_fdt_setprop_cell(fdt, name, "numa-node-id", props->socket);
+ }
+
+ g_free(name);
+ }
+
+ if (props->aia_type == AIA_TYPE_APLIC_IMSIC) {
+ addr = props->clint->base +
+ (RISCV_ACLINT_DEFAULT_MTIMER_SIZE * props->socket);
+ size = RISCV_ACLINT_DEFAULT_MTIMER_SIZE;
+ } else {
+ addr = props->clint->base + RISCV_ACLINT_SWI_SIZE +
+ (props->clint->size * props->socket);
+ size = props->clint->size - RISCV_ACLINT_SWI_SIZE;
+ }
+
+ name = g_strdup_printf("/soc/mtimer@%"HWADDR_PRIx, addr);
+ qemu_fdt_add_subnode(fdt, name);
+ qemu_fdt_setprop_string(fdt, name, "compatible",
+ "riscv,aclint-mtimer");
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
+ 2, addr,