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.

Signed-off-by: Brian Cain <[email protected]>
---
 include/hw/hexagon/hex-subsys.h        |  8 ++++--
 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, 75 insertions(+), 5 deletions(-)

diff --git a/include/hw/hexagon/hex-subsys.h b/include/hw/hexagon/hex-subsys.h
index 73403e8951c..cdd59f09e4f 100644
--- a/include/hw/hexagon/hex-subsys.h
+++ b/include/hw/hexagon/hex-subsys.h
@@ -15,8 +15,12 @@
 void hex_subsys_create(HexagonCommonMachineState *hms,
                        const struct hexagon_machine_config *m_cfg, Rev_t rev);
 
-/* Realize a CPU into the subsystem, then hex_subsys_realize_cluster(). */
-void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu);
+/*
+ * Realize a CPU into the subsystem, then hex_subsys_realize_cluster().
+ * CPU[0] receives the L2VIC outputs.
+ */
+void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu,
+                            bool boot_cpu);
 
 /* Realize the CPU cluster, once all CPUs have been parented into it. */
 void hex_subsys_realize_cluster(HexagonCommonMachineState *hms);
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 638b6429100..5f238006bae 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,18 +109,26 @@ 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);
 }
 
-void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu)
+void hex_subsys_realize_cpu(HexagonCommonMachineState *hms, DeviceState *cpu,
+                            bool boot_cpu)
 {
     object_property_add_child(OBJECT(hms->cluster), "cpu[*]", OBJECT(cpu));
     object_property_set_link(OBJECT(cpu), "global-regs",
                              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);
     qdev_realize_and_unref(cpu, NULL, &error_fatal);
+
+    if (boot_cpu) {
+        l2vic_connect_cpu(hms->l2vic, cpu);
+    }
 }
 
 void hex_subsys_realize_cluster(HexagonCommonMachineState *hms)
diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
index 5275ab92386..6be5668471c 100644
--- a/hw/hexagon/hexagon_dsp.c
+++ b/hw/hexagon/hexagon_dsp.c
@@ -130,7 +130,7 @@ static void hexagon_common_init(MachineState *machine, 
Rev_t rev,
         if (i == 0) {
             hexagon_init_bootstrap(dms, cpu);
         }
-        hex_subsys_realize_cpu(hms, DEVICE(cpu));
+        hex_subsys_realize_cpu(hms, DEVICE(cpu), (i == 0));
     }
 
     hex_subsys_realize_cluster(hms);
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 ac2b6605dbd..7561aedd2b7 100644
--- a/hw/hexagon/virt.c
+++ b/hw/hexagon/virt.c
@@ -267,7 +267,7 @@ static void virt_init(MachineState *ms)
         }
         qdev_prop_set_uint32(DEVICE(cpu), "htid", i);
         qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0));
-        hex_subsys_realize_cpu(&vms->parent_obj, DEVICE(cpu));
+        hex_subsys_realize_cpu(&vms->parent_obj, DEVICE(cpu), (i == 0));
     }
 
     hex_subsys_realize_cluster(&vms->parent_obj);
-- 
2.34.1

Reply via email to