Instantiate the QTimer device in both machine models, map its view region, connect its interrupt lines into l2vic, and link it to the globalreg device.
Store the QTimer DeviceState pointer in the shared HexagonCommonMachineState. Signed-off-by: Brian Cain <[email protected]> --- include/hw/hexagon/hexagon.h | 1 + include/hw/hexagon/hexagon_globalreg.h | 4 ++++ hw/hexagon/hexagon_dsp.c | 14 ++++++++++++++ hw/hexagon/hexagon_globalreg.c | 17 +++++++++++++++-- hw/hexagon/virt.c | 16 ++++++++++++++++ hw/hexagon/Kconfig | 1 + 6 files changed, 51 insertions(+), 2 deletions(-) diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h index 6753ae32cde..3eea1e54ff2 100644 --- a/include/hw/hexagon/hexagon.h +++ b/include/hw/hexagon/hexagon.h @@ -157,6 +157,7 @@ struct HexagonCommonMachineState { MemoryRegion ram; MemoryRegion cfgtable_rom; DeviceState *l2vic_dev; + DeviceState *qtimer_dev; }; #endif diff --git a/include/hw/hexagon/hexagon_globalreg.h b/include/hw/hexagon/hexagon_globalreg.h index 397dc6854c9..07437dfabb1 100644 --- a/include/hw/hexagon/hexagon_globalreg.h +++ b/include/hw/hexagon/hexagon_globalreg.h @@ -11,6 +11,7 @@ #include "hw/core/qdev.h" #include "hw/core/sysbus.h" #include "hw/intc/hex-l2vic.h" +#include "hw/timer/qct-qtimer.h" #include "qom/object.h" #include "target/hexagon/cpu.h" @@ -26,6 +27,9 @@ struct HexagonGlobalRegState { /* L2VIC interface used to back the VID/VID1 registers */ HexL2VicInterface *l2vic; + /* QTimer interface used to back the TIMERLO/TIMERHI registers */ + QctQtimerInterface *qtimer; + /* Global performance cycle counter base */ uint64_t g_pcycle_base; diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c index 4cf88627c8f..21bb80ac27a 100644 --- a/hw/hexagon/hexagon_dsp.c +++ b/hw/hexagon/hexagon_dsp.c @@ -17,6 +17,7 @@ #include "hw/hexagon/hexagon_globalreg.h" #include "hw/hexagon/hexagon_tlb.h" #include "hw/intc/hex-l2vic.h" +#include "hw/timer/qct-qtimer.h" #include "hw/core/loader.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -141,6 +142,17 @@ static void hexagon_common_init(MachineState *machine, Rev_t rev, sysbus_mmio_map(SYS_BUS_DEVICE(hms->l2vic_dev), 1, m_cfg->cfgtable.fastl2vic_base << 16); + hms->qtimer_dev = qdev_new(TYPE_QCT_QTIMER); + object_property_add_child(OBJECT(machine), "qtimer", + OBJECT(hms->qtimer_dev)); + qdev_prop_set_uint32(hms->qtimer_dev, "nr_frames", 3); + sysbus_realize_and_unref(SYS_BUS_DEVICE(hms->qtimer_dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(hms->qtimer_dev), 1, m_cfg->qtmr_region); + sysbus_connect_irq(SYS_BUS_DEVICE(hms->qtimer_dev), 0, + qdev_get_gpio_in(hms->l2vic_dev, 3)); + sysbus_connect_irq(SYS_BUS_DEVICE(hms->qtimer_dev), 1, + qdev_get_gpio_in(hms->l2vic_dev, 4)); + glob_regs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG); object_property_add_child(OBJECT(machine), "global-regs", OBJECT(glob_regs_dev)); @@ -148,6 +160,8 @@ static void hexagon_common_init(MachineState *machine, Rev_t rev, qdev_prop_set_uint32(glob_regs_dev, "dsp-rev", rev); object_property_set_link(OBJECT(glob_regs_dev), "l2vic", OBJECT(hms->l2vic_dev), &error_fatal); + object_property_set_link(OBJECT(glob_regs_dev), "qtimer", + OBJECT(hms->qtimer_dev), &error_fatal); sysbus_realize_and_unref(SYS_BUS_DEVICE(glob_regs_dev), &error_fatal); tlb_dev = qdev_new(TYPE_HEXAGON_TLB); diff --git a/hw/hexagon/hexagon_globalreg.c b/hw/hexagon/hexagon_globalreg.c index 3d0d6f9516c..0353d89f87b 100644 --- a/hw/hexagon/hexagon_globalreg.c +++ b/hw/hexagon/hexagon_globalreg.c @@ -141,15 +141,26 @@ static inline bool is_vid_reg(uint32_t reg) return reg == HEX_SREG_VID || reg == HEX_SREG_VID1; } +static inline bool is_timer_reg(uint32_t reg) +{ + return reg == HEX_SREG_TIMERLO || reg == HEX_SREG_TIMERHI; +} + /* - * HEX_SREG_VID/VID1 are backed by the L2VIC's VID group registers - * rather than the plain regs[] array, when an L2VIC is wired up. + * HEX_SREG_VID/VID1 are backed by the L2VIC's VID group registers, and + * HEX_SREG_TIMERLO/TIMERHI are backed by the QTimer's live counter, + * rather than the plain regs[] array, when those devices are wired up. */ static uint32_t get_reg_value(HexagonGlobalRegState *s, uint32_t reg) { if (is_vid_reg(reg) && s->l2vic) { return l2vic_read_vid(s->l2vic, reg == HEX_SREG_VID ? 0 : 1); } + if (is_timer_reg(reg) && s->qtimer) { + return reg == HEX_SREG_TIMERLO ? + qct_qtimer_get_timer_lo(s->qtimer) : + qct_qtimer_get_timer_hi(s->qtimer); + } return s->regs[reg]; } @@ -306,6 +317,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_LINK("qtimer", HexagonGlobalRegState, qtimer, + TYPE_QCT_QTIMER_INTERFACE, QctQtimerInterface *), DEFINE_PROP_UINT32("boot-evb", HexagonGlobalRegState, boot_evb, 0x0), DEFINE_PROP_UINT64("config-table-addr", HexagonGlobalRegState, config_table_addr, 0xffffffffULL), diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c index 2256d3d53a5..7e32765d1cc 100644 --- a/hw/hexagon/virt.c +++ b/hw/hexagon/virt.c @@ -16,6 +16,7 @@ #include "hw/hexagon/hexagon_globalreg.h" #include "hw/hexagon/hexagon_tlb.h" #include "hw/intc/hex-l2vic.h" +#include "hw/timer/qct-qtimer.h" #include "hw/core/loader.h" #include "hw/core/qdev-properties.h" #include "hw/core/qdev-clock.h" @@ -279,12 +280,27 @@ static void virt_init(MachineState *ms) sysbus_mmio_map(SYS_BUS_DEVICE(vms->parent_obj.l2vic_dev), 1, m_cfg->cfgtable.fastl2vic_base << 16); + vms->parent_obj.qtimer_dev = qdev_new(TYPE_QCT_QTIMER); + object_property_add_child(OBJECT(ms), "qtimer", + OBJECT(vms->parent_obj.qtimer_dev)); + qdev_prop_set_uint32(vms->parent_obj.qtimer_dev, "nr_frames", 2); + sysbus_realize_and_unref(SYS_BUS_DEVICE(vms->parent_obj.qtimer_dev), + &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(vms->parent_obj.qtimer_dev), 1, + m_cfg->qtmr_region); + sysbus_connect_irq(SYS_BUS_DEVICE(vms->parent_obj.qtimer_dev), 0, + qdev_get_gpio_in(vms->parent_obj.l2vic_dev, 3)); + sysbus_connect_irq(SYS_BUS_DEVICE(vms->parent_obj.qtimer_dev), 1, + qdev_get_gpio_in(vms->parent_obj.l2vic_dev, 4)); + gsregs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG); object_property_add_child(OBJECT(ms), "global-regs", OBJECT(gsregs_dev)); qdev_prop_set_uint64(gsregs_dev, "config-table-addr", m_cfg->cfgbase); qdev_prop_set_uint32(gsregs_dev, "dsp-rev", v68_rev); object_property_set_link(OBJECT(gsregs_dev), "l2vic", OBJECT(vms->parent_obj.l2vic_dev), &error_fatal); + object_property_set_link(OBJECT(gsregs_dev), "qtimer", + OBJECT(vms->parent_obj.qtimer_dev), &error_fatal); sysbus_realize_and_unref(SYS_BUS_DEVICE(gsregs_dev), &error_fatal); tlb_dev = qdev_new(TYPE_HEXAGON_TLB); diff --git a/hw/hexagon/Kconfig b/hw/hexagon/Kconfig index 191c6c5d65c..56cd5b15c55 100644 --- a/hw/hexagon/Kconfig +++ b/hw/hexagon/Kconfig @@ -3,6 +3,7 @@ config HEX_DSP default y depends on HEXAGON select HEX_L2VIC + select HEX_QTIMER config HEX_VIRT bool -- 2.34.1
