[PATCH v5 16/18] hw/hexagon: connect qtimer device

Brian Cain <[email protected]>
Newsgroups org.nongnu.qemu-devel
Message-ID <[email protected]>
Add the QTimer to the shared hex-subsys so both machine models pick it
up.  Map its view region, wire its interrupt lines into l2vic, and link
it to the globalreg device backing HEX_SREG_TIMERLO/TIMERHI.

Reviewed-by: Pierrick Bouvier <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 include/hw/hexagon/hexagon.h           |  1 +
 include/hw/hexagon/hexagon_globalreg.h |  4 ++++
 hw/hexagon/hex-subsys.c                | 28 ++++++++++++++++++++++++++
 hw/hexagon/hexagon_globalreg.c         | 17 ++++++++++++++++
 hw/hexagon/Kconfig                     |  1 +
 5 files changed, 51 insertions(+)

diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h
index ec1578807d8..3d7b3cb12dc 100644
--- a/include/hw/hexagon/hexagon.h
+++ b/include/hw/hexagon/hexagon.h
@@ -159,6 +159,7 @@ struct HexagonCommonMachineState {
     MemoryRegion vtcm;
     DeviceState *cluster;
     DeviceState *l2vic;
+    DeviceState *qtimer;
     DeviceState *glob_regs;
     DeviceState *tlb;
 };
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/hex-subsys.c b/hw/hexagon/hex-subsys.c
index 25c028f6579..4e3a418340e 100644
--- a/hw/hexagon/hex-subsys.c
+++ b/hw/hexagon/hex-subsys.c
@@ -11,6 +11,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/cpu/cluster.h"
 #include "hw/core/loader.h"
 #include "hw/core/qdev-properties.h"
@@ -20,6 +21,11 @@
 
 #define HEX_L2VIC_CPU_IRQS 8
 
+/* Number of QTimer frames instantiated for every Hexagon machine. */
+#define HEX_QTIMER_NR_FRAMES 3
+
+#define HEX_QTIMER_L2VIC_IRQ_BASE 2
+
 static DeviceState *l2vic_create(HexagonCommonMachineState *hms,
                                  const struct hexagon_machine_config *m_cfg)
 {
@@ -43,6 +49,25 @@ static void l2vic_connect_cpu(DeviceState *l2vic, DeviceState *cpu)
     }
 }
 
+static DeviceState *qtimer_create(HexagonCommonMachineState *hms,
+                                  const struct hexagon_machine_config *m_cfg)
+{
+    DeviceState *qtimer = qdev_new(TYPE_QCT_QTIMER);
+
+    object_property_add_child(OBJECT(hms), "qtimer", OBJECT(qtimer));
+    qdev_prop_set_uint32(qtimer, "nr_frames", HEX_QTIMER_NR_FRAMES);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(qtimer), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(qtimer), 0, m_cfg->csr_base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(qtimer), 1, m_cfg->qtmr_region);
+    for (unsigned int i = 0; i < HEX_QTIMER_NR_FRAMES; i++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(qtimer), i,
+                           qdev_get_gpio_in(hms->l2vic,
+                                            HEX_QTIMER_L2VIC_IRQ_BASE + i));
+    }
+
+    return qtimer;
+}
+
 static DeviceState *globalreg_create(HexagonCommonMachineState *hms,
                                      const struct hexagon_machine_config *m_cfg,
                                      Rev_t rev)
@@ -54,6 +79,8 @@ static DeviceState *globalreg_create(HexagonCommonMachineState *hms,
     qdev_prop_set_uint32(glob_regs, "dsp-rev", rev);
     object_property_set_link(OBJECT(glob_regs), "l2vic", OBJECT(hms->l2vic),
                              &error_fatal);
+    object_property_set_link(OBJECT(glob_regs), "qtimer", OBJECT(hms->qtimer),
+                             &error_fatal);
     sysbus_realize_and_unref(SYS_BUS_DEVICE(glob_regs), &error_fatal);
 
     return glob_regs;
@@ -110,6 +137,7 @@ void hex_subsys_create(HexagonCommonMachineState *hms,
 
     hms->cluster = cluster_create(hms);
     hms->l2vic = l2vic_create(hms, m_cfg);
+    hms->qtimer = qtimer_create(hms, m_cfg);
     hms->glob_regs = globalreg_create(hms, m_cfg, rev);
     hms->tlb = tlb_create(hms, m_cfg);
 }
diff --git a/hw/hexagon/hexagon_globalreg.c b/hw/hexagon/hexagon_globalreg.c
index 285cb48c44b..61621cf2b8f 100644
--- a/hw/hexagon/hexagon_globalreg.c
+++ b/hw/hexagon/hexagon_globalreg.c
@@ -12,6 +12,7 @@
 #include "hw/core/sysbus.h"
 #include "hw/core/resettable.h"
 #include "hw/intc/hex-l2vic.h"
+#include "hw/timer/qct-qtimer.h"
 #include "migration/vmstate.h"
 #include "qom/object.h"
 #include "target/hexagon/cpu.h"
@@ -141,11 +142,21 @@ 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;
+}
+
 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);
     }
+    if (is_timer_reg(reg)) {
+        return reg == HEX_SREG_TIMERLO ?
+                qct_qtimer_get_timer_lo(s->qtimer) :
+                qct_qtimer_get_timer_hi(s->qtimer);
+    }
     return s->regs[reg];
 }
 
@@ -289,6 +300,10 @@ static void hexagon_globalreg_realize(DeviceState *dev, Error **errp)
         error_setg(errp, "hexagon_globalreg: 'l2vic' link property not set");
         return;
     }
+    if (!s->qtimer) {
+        error_setg(errp, "hexagon_globalreg: 'qtimer' link property not set");
+        return;
+    }
 }
 
 static const VMStateDescription vmstate_hexagon_globalreg = {
@@ -312,6 +327,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/Kconfig b/hw/hexagon/Kconfig
index c75090c44a1..83b2763d1e3 100644
--- a/hw/hexagon/Kconfig
+++ b/hw/hexagon/Kconfig
@@ -4,6 +4,7 @@ config HEX_DSP
     depends on HEXAGON
     select CPU_CLUSTER
     select HEX_L2VIC
+    select HEX_QTIMER
 
 config HEX_VIRT
     bool
-- 
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.