[PATCH v4 09/18] hw/hexagon: connect l2vic device

Brian Cain <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
Add the l2vic to the shared hex-subsys so both machine models pick it
up.  Map its register banks, wire the interrupt lines to CPU[0]
and link each vCPU, globalregs.

Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Reviewed-by: Pierrick Bouvier <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 include/hw/hexagon/hex-subsys.h        |  5 ++--
 include/hw/hexagon/hexagon.h           |  1 +
 include/hw/hexagon/hexagon_globalreg.h |  4 +++
 hw/hexagon/hex-subsys.c                | 38 +++++++++++++++++++++++++-
 hw/hexagon/hexagon_dsp.c               |  2 +-
 hw/hexagon/hexagon_globalreg.c         | 25 +++++++++++++++++
 hw/hexagon/virt.c                      |  2 +-
 7 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/include/hw/hexagon/hex-subsys.h b/include/hw/hexagon/hex-subsys.h
index 6d0d5e1da86..5792f7b5af3 100644
--- a/include/hw/hexagon/hex-subsys.h
+++ b/include/hw/hexagon/hex-subsys.h
@@ -18,7 +18,7 @@ void hex_subsys_create(HexagonCommonMachineState *hms,
 /*
  * Parent a CPU into the subsystem's cluster and wire its links.  Call for
  * every CPU before hex_subsys_realize_cluster(), then realize each CPU with
- * hex_subsys_realize_cpu().
+ * hex_subsys_realize_cpu().  CPU[0] receives the L2VIC outputs.
  */
 void hex_subsys_add_cpu(HexagonCommonMachineState *hms, DeviceState *cpu);
 
@@ -26,6 +26,7 @@ void hex_subsys_add_cpu(HexagonCommonMachineState *hms, DeviceState *cpu);
 void hex_subsys_realize_cluster(HexagonCommonMachineState *hms);
 
 /* Realize a CPU previously parented via hex_subsys_add_cpu(). */
-void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu);
+void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu,
+                            bool boot_cpu);
 
 #endif /* HW_HEXAGON_HEX_SUBSYS_H */
diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h
index 31669a829f8..ec1578807d8 100644
--- a/include/hw/hexagon/hexagon.h
+++ b/include/hw/hexagon/hexagon.h
@@ -158,6 +158,7 @@ struct HexagonCommonMachineState {
     MemoryRegion cfgtable_rom;
     MemoryRegion vtcm;
     DeviceState *cluster;
+    DeviceState *l2vic;
     DeviceState *glob_regs;
     DeviceState *tlb;
 };
diff --git a/include/hw/hexagon/hexagon_globalreg.h b/include/hw/hexagon/hexagon_globalreg.h
index 950099808fd..397dc6854c9 100644
--- a/include/hw/hexagon/hexagon_globalreg.h
+++ b/include/hw/hexagon/hexagon_globalreg.h
@@ -10,6 +10,7 @@
 
 #include "hw/core/qdev.h"
 #include "hw/core/sysbus.h"
+#include "hw/intc/hex-l2vic.h"
 #include "qom/object.h"
 #include "target/hexagon/cpu.h"
 
@@ -22,6 +23,9 @@ struct HexagonGlobalRegState {
     /* Array of system registers */
     uint32_t regs[NUM_SREGS];
 
+    /* L2VIC interface used to back the VID/VID1 registers */
+    HexL2VicInterface *l2vic;
+
     /* Global performance cycle counter base */
     uint64_t g_pcycle_base;
 
diff --git a/hw/hexagon/hex-subsys.c b/hw/hexagon/hex-subsys.c
index 6fad6fe0a4d..25c028f6579 100644
--- a/hw/hexagon/hex-subsys.c
+++ b/hw/hexagon/hex-subsys.c
@@ -10,6 +10,7 @@
 #include "hw/hexagon/hex-subsys.h"
 #include "hw/hexagon/hexagon_globalreg.h"
 #include "hw/hexagon/hexagon_tlb.h"
+#include "hw/intc/hex-l2vic.h"
 #include "hw/cpu/cluster.h"
 #include "hw/core/loader.h"
 #include "hw/core/qdev-properties.h"
@@ -17,6 +18,31 @@
 #include "hw/core/sysbus.h"
 #include "system/address-spaces.h"
 
+#define HEX_L2VIC_CPU_IRQS 8
+
+static DeviceState *l2vic_create(HexagonCommonMachineState *hms,
+                                 const struct hexagon_machine_config *m_cfg)
+{
+    DeviceState *l2vic = qdev_new(TYPE_HEX_L2VIC);
+
+    object_property_add_child(OBJECT(hms), "l2vic", OBJECT(l2vic));
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(l2vic), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(l2vic), 0, m_cfg->l2vic_base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(l2vic), 1,
+                    m_cfg->cfgtable.fastl2vic_base << 16);
+
+    return l2vic;
+}
+
+static void l2vic_connect_cpu(DeviceState *l2vic, DeviceState *cpu)
+{
+    int i;
+
+    for (i = 0; i < HEX_L2VIC_CPU_IRQS; i++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(l2vic), i, qdev_get_gpio_in(cpu, i));
+    }
+}
+
 static DeviceState *globalreg_create(HexagonCommonMachineState *hms,
                                      const struct hexagon_machine_config *m_cfg,
                                      Rev_t rev)
@@ -26,6 +52,8 @@ static DeviceState *globalreg_create(HexagonCommonMachineState *hms,
     object_property_add_child(OBJECT(hms), "global-regs", OBJECT(glob_regs));
     qdev_prop_set_uint64(glob_regs, "config-table-addr", m_cfg->cfgbase);
     qdev_prop_set_uint32(glob_regs, "dsp-rev", rev);
+    object_property_set_link(OBJECT(glob_regs), "l2vic", OBJECT(hms->l2vic),
+                             &error_fatal);
     sysbus_realize_and_unref(SYS_BUS_DEVICE(glob_regs), &error_fatal);
 
     return glob_regs;
@@ -81,6 +109,7 @@ void hex_subsys_create(HexagonCommonMachineState *hms,
     }
 
     hms->cluster = cluster_create(hms);
+    hms->l2vic = l2vic_create(hms, m_cfg);
     hms->glob_regs = globalreg_create(hms, m_cfg, rev);
     hms->tlb = tlb_create(hms, m_cfg);
 }
@@ -92,6 +121,8 @@ void hex_subsys_add_cpu(HexagonCommonMachineState *hms, DeviceState *cpu)
                              OBJECT(hms->glob_regs), &error_fatal);
     object_property_set_link(OBJECT(cpu), "tlb", OBJECT(hms->tlb),
                              &error_fatal);
+    object_property_set_link(OBJECT(cpu), "l2vic", OBJECT(hms->l2vic),
+                             &error_fatal);
 }
 
 void hex_subsys_realize_cluster(HexagonCommonMachineState *hms)
@@ -105,7 +136,12 @@ void hex_subsys_realize_cluster(HexagonCommonMachineState *hms)
     qdev_realize_and_unref(hms->cluster, NULL, &error_fatal);
 }
 
-void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu)
+void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu,
+                            bool boot_cpu)
 {
     qdev_realize_and_unref(cpu, NULL, &error_fatal);
+
+    if (boot_cpu) {
+        l2vic_connect_cpu(hms->l2vic, cpu);
+    }
 }
diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
index 1db5d681665..20306c28e72 100644
--- a/hw/hexagon/hexagon_dsp.c
+++ b/hw/hexagon/hexagon_dsp.c
@@ -139,7 +139,7 @@ static void hexagon_common_init(MachineState *machine, Rev_t rev,
     hex_subsys_realize_cluster(hms);
 
     for (int i = 0; i < machine->smp.cpus; i++) {
-        hex_subsys_realize_cpu(hms, DEVICE(cpus[i]));
+        hex_subsys_realize_cpu(hms, DEVICE(cpus[i]), (i == 0));
     }
 }
 
diff --git a/hw/hexagon/hexagon_globalreg.c b/hw/hexagon/hexagon_globalreg.c
index 105475219ab..285cb48c44b 100644
--- a/hw/hexagon/hexagon_globalreg.c
+++ b/hw/hexagon/hexagon_globalreg.c
@@ -11,6 +11,7 @@
 #include "hw/core/qdev-properties.h"
 #include "hw/core/sysbus.h"
 #include "hw/core/resettable.h"
+#include "hw/intc/hex-l2vic.h"
 #include "migration/vmstate.h"
 #include "qom/object.h"
 #include "target/hexagon/cpu.h"
@@ -135,8 +136,16 @@ static inline uint32_t apply_write_mask(uint32_t new_val, uint32_t cur_val,
     return new_val;
 }
 
+static inline bool is_vid_reg(uint32_t reg)
+{
+    return reg == HEX_SREG_VID || reg == HEX_SREG_VID1;
+}
+
 static uint32_t get_reg_value(HexagonGlobalRegState *s, uint32_t reg)
 {
+    if (is_vid_reg(reg)) {
+        return l2vic_read_vid(s->l2vic, reg == HEX_SREG_VID ? 0 : 1);
+    }
     return s->regs[reg];
 }
 
@@ -144,6 +153,9 @@ static void set_reg_value(HexagonGlobalRegState *s, uint32_t reg,
                           uint32_t value)
 {
     s->regs[reg] = value;
+    if (is_vid_reg(reg)) {
+        l2vic_update_vid(s->l2vic, reg == HEX_SREG_VID ? 0 : 1, value);
+    }
 }
 
 uint32_t hexagon_globalreg_read(HexagonGlobalRegState *s, uint32_t reg,
@@ -269,6 +281,16 @@ static void hexagon_globalreg_reset_hold(Object *obj, ResetType type)
     do_hexagon_globalreg_reset(s);
 }
 
+static void hexagon_globalreg_realize(DeviceState *dev, Error **errp)
+{
+    HexagonGlobalRegState *s = HEXAGON_GLOBALREG(dev);
+
+    if (!s->l2vic) {
+        error_setg(errp, "hexagon_globalreg: 'l2vic' link property not set");
+        return;
+    }
+}
+
 static const VMStateDescription vmstate_hexagon_globalreg = {
     .name = "hexagon_globalreg",
     .version_id = 1,
@@ -288,6 +310,8 @@ static const VMStateDescription vmstate_hexagon_globalreg = {
 };
 
 static const Property hexagon_globalreg_properties[] = {
+    DEFINE_PROP_LINK("l2vic", HexagonGlobalRegState, l2vic,
+                     TYPE_HEX_L2VIC_INTERFACE, HexL2VicInterface *),
     DEFINE_PROP_UINT32("boot-evb", HexagonGlobalRegState, boot_evb, 0x0),
     DEFINE_PROP_UINT64("config-table-addr", HexagonGlobalRegState,
                        config_table_addr, 0xffffffffULL),
@@ -308,6 +332,7 @@ static void hexagon_globalreg_class_init(ObjectClass *klass, const void *data)
     ResettableClass *rc = RESETTABLE_CLASS(klass);
 
     rc->phases.hold = hexagon_globalreg_reset_hold;
+    dc->realize = hexagon_globalreg_realize;
     dc->vmsd = &vmstate_hexagon_globalreg;
     dc->user_creatable = false;
     device_class_set_props(dc, hexagon_globalreg_properties);
diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c
index dc1d5b6aa24..9a680852c3c 100644
--- a/hw/hexagon/virt.c
+++ b/hw/hexagon/virt.c
@@ -270,7 +270,7 @@ static void virt_init(MachineState *ms)
     hex_subsys_realize_cluster(&vms->parent_obj);
 
     for (int i = 0; i < ms->smp.cpus; i++) {
-        hex_subsys_realize_cpu(&vms->parent_obj, DEVICE(cpus[i]));
+        hex_subsys_realize_cpu(&vms->parent_obj, DEVICE(cpus[i]), (i == 0));
     }
 
     fdt_add_cpu_nodes(vms);
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.