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
