Expose l2vic as a device-tree interrupt-controller node and reference
it via interrupt-parent, so guest kernels can discover the virtio-mmio
transports.

Signed-off-by: Brian Cain <[email protected]>
---
 hw/hexagon/virt.c | 43 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c
index 46ff0687528..78e71d3bd65 100644
--- a/hw/hexagon/virt.c
+++ b/hw/hexagon/virt.c
@@ -76,6 +76,30 @@ static void create_fdt(HexagonVirtMachineState *vms)
     qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
 }
 
+static int32_t fdt_add_l2vic(HexagonVirtMachineState *vms,
+                             const struct hexagon_machine_config *m_cfg)
+{
+    MachineState *ms = MACHINE(vms);
+    int32_t l2vic_phandle = qemu_fdt_alloc_phandle(ms->fdt);
+    char *nodename = g_strdup_printf("/soc/interrupt-controller@%x",
+                                     m_cfg->l2vic_base);
+    const char compat[] = "qcom,h2-pic\0hvm-pic";
+
+    qemu_fdt_setprop_cell(ms->fdt, "/soc", "interrupt-parent", l2vic_phandle);
+
+    qemu_fdt_add_subnode(ms->fdt, nodename);
+    qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x0);
+    qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 0x1);
+    qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0,
+                           m_cfg->l2vic_base, m_cfg->l2vic_size);
+    qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
+    qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", l2vic_phandle);
+
+    g_free(nodename);
+    return l2vic_phandle;
+}
+
 static void fdt_add_hvx(HexagonVirtMachineState *vms,
                         const struct hexagon_machine_config *m_cfg)
 {
@@ -176,13 +200,16 @@ static void fdt_add_cpu_nodes(const 
HexagonVirtMachineState *vms)
     }
 }
 
-static void create_virtio_devices(const HexagonVirtMachineState *vms)
+static void create_virtio_devices(const HexagonVirtMachineState *vms,
+                                  int32_t l2vic_phandle)
 {
+    MachineState *ms = MACHINE(vms);
     hwaddr size = base_memmap[VIRT_MMIO].size;
 
     for (int i = 0; i < VIRTIO_DEV_COUNT; i++) {
         int irq = VIRTIO_IRQ_BASE + i;
         hwaddr base = base_memmap[VIRT_MMIO].base + i * size;
+        char *nodename = g_strdup_printf("/soc/virtio_mmio@%" PRIx64, base);
         DeviceState *dev = qdev_new("virtio-mmio");
         SysBusDevice *s = SYS_BUS_DEVICE(dev);
 
@@ -192,6 +219,16 @@ static void create_virtio_devices(const 
HexagonVirtMachineState *vms)
         sysbus_mmio_map(s, 0, base);
         sysbus_connect_irq(s, 0,
                            qdev_get_gpio_in(vms->parent_obj.l2vic, irq));
+
+        qemu_fdt_add_subnode(ms->fdt, nodename);
+        qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
+                                "virtio,mmio");
+        qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, size);
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupts", irq);
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
+                              l2vic_phandle);
+
+        g_free(nodename);
     }
 }
 
@@ -258,6 +295,7 @@ static void virt_init(MachineState *ms)
     HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(ms);
     const struct hexagon_machine_config *m_cfg = &v68n_1024;
     int32_t clk_phandle;
+    int32_t l2vic_phandle;
 
     qemu_fdt_setprop_string(ms->fdt, "/chosen", "bootargs", 
ms->kernel_cmdline);
 
@@ -278,7 +316,8 @@ static void virt_init(MachineState *ms)
 
     fdt_add_hvx(vms, m_cfg);
 
-    create_virtio_devices(vms);
+    l2vic_phandle = fdt_add_l2vic(vms, m_cfg);
+    create_virtio_devices(vms, l2vic_phandle);
 
     for (int i = 0; i < ms->smp.cpus; i++) {
         HexagonCPU *cpu = HEXAGON_CPU(object_new(ms->cpu_type));
-- 
2.34.1

Reply via email to