Hi Brian,

On 18/7/26 03:32, Brian Cain wrote:
Implement the QCT QTimer generic timer device used by Hexagon DSP
systems.

Co-authored-by: Damien Hedde <[email protected]>
Co-authored-by: Tobias Röhmel <[email protected]>
Co-authored-by: Sid Manning <[email protected]>
Co-authored-by: Thomas Marceron <[email protected]>
Co-authored-by: Mahmoud Kamel <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
  MAINTAINERS                   |   2 +
  include/hw/timer/qct-qtimer.h |  78 +++++
  hw/timer/qct-qtimer.c         | 613 ++++++++++++++++++++++++++++++++++
  hw/timer/Kconfig              |   3 +
  hw/timer/meson.build          |   2 +
  hw/timer/trace-events         |   5 +
  6 files changed, 703 insertions(+)
  create mode 100644 include/hw/timer/qct-qtimer.h
  create mode 100644 hw/timer/qct-qtimer.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a5df21aa12d..2c73705c727 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -253,6 +253,8 @@ F: target/hexagon/
  F: hw/intc/hex-l2vic.c
  F: include/hw/intc/hex-l2vic.h
  F: tests/qtest/l2vic-test.c
+F: hw/timer/qct-qtimer.c
+F: include/hw/timer/qct-qtimer.h
  X: target/hexagon/idef-parser/
  X: target/hexagon/gen_idef_parser_funcs.py
  F: linux-user/hexagon/
diff --git a/include/hw/timer/qct-qtimer.h b/include/hw/timer/qct-qtimer.h
new file mode 100644
index 00000000000..d2ef9447b26
--- /dev/null
+++ b/include/hw/timer/qct-qtimer.h
@@ -0,0 +1,78 @@
+/*
+ * Qualcomm QCT QTimer
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_TIMER_QCT_QTIMER_H
+#define HW_TIMER_QCT_QTIMER_H
+
+#include "qom/object.h"
+
+#define TYPE_QCT_QTIMER "qct-qtimer"
+
+#define QCT_QTIMER_TIMER_FRAME_ELTS (16)
+#define QCT_QTIMER_TIMER_VIEW_ELTS (2)
+
+#define QCT_QTIMER_AC_CNTFRQ (0x000)
+#define QCT_QTIMER_AC_CNTSR (0x004)
+#define QCT_QTIMER_AC_CNTTID_0 (0x08)
+#define QCT_QTIMER_AC_CNTACR_START (0x40)
+#define QCT_QTIMER_AC_CNTACR_END (0x5c)
+#define QCT_QTIMER_AC_CNTTID_1 (0x108)
+#define QCT_QTIMER_AC_CNTACR_RWPT (1 << 5) /* R/W of CNTP_* regs */
+#define QCT_QTIMER_AC_CNTACR_RWVT (1 << 4) /* R/W of CNTV_* regs */
+#define QCT_QTIMER_AC_CNTACR_RVOFF (1 << 3) /* R/W of CNTVOFF register */
+#define QCT_QTIMER_AC_CNTACR_RFRQ (1 << 2) /* R/W of CNTFRQ register */
+#define QCT_QTIMER_AC_CNTACR_RPVCT (1 << 1) /* R/W of CNTVCT register */
+#define QCT_QTIMER_AC_CNTACR_RPCT (1 << 0) /* R/W of CNTPCT register */
+#define QCT_QTIMER_VERSION (0x0fd0)
+
+#define QCT_QTIMER_CNTPCT_LO (0x000)
+#define QCT_QTIMER_CNTPCT_HI (0x004)
+#define QCT_QTIMER_CNT_FREQ (0x010)
+#define QCT_QTIMER_CNTPL0ACR (0x014)
+#define QCT_QTIMER_CNTPL0ACR_PL0CTEN (1 << 9)
+#define QCT_QTIMER_CNTPL0ACR_PL0TVEN (1 << 8)
+#define QCT_QTIMER_CNTPL0ACR_PL0VCTEN (1 << 1)
+#define QCT_QTIMER_CNTPL0ACR_PL0PCTEN (1 << 0)
+#define QCT_QTIMER_CNTP_CVAL_LO (0x020)
+#define QCT_QTIMER_CNTP_CVAL_HI (0x024)
+#define QCT_QTIMER_CNT_MASK 0x00ffffffffffffffULL
+#define QCT_QTIMER_CNT_HI_BITS 24
+#define QCT_QTIMER_CNTP_TVAL (0x028)
+#define QCT_QTIMER_CNTP_CTL (0x02c)
+#define QCT_QTIMER_CNTP_CTL_ENABLE (1 << 0)
+#define QCT_QTIMER_CNTP_CTL_INTEN (1 << 1)
+#define QCT_QTIMER_CNTP_CTL_ISTAT (1 << 2)

The register related definitions aren't consumed outside of the
implementation, so no need to expose them, they could be moved
to the single place using them, the source file.

+
+/* QTimer interface for external access from hexagon_globalreg */
+#define TYPE_QCT_QTIMER_INTERFACE "qct-qtimer-if"
+
+typedef struct QctQtimerInterface QctQtimerInterface;
+
+typedef struct QctQtimerInterfaceClass {
+    InterfaceClass parent_class;
+
+    /* Read the live physical counter, backing HEX_SREG_TIMERLO/TIMERHI */
+    uint32_t (*get_timer_lo)(QctQtimerInterface *qtimer);

const qtimer

+    uint32_t (*get_timer_hi)(QctQtimerInterface *qtimer);

const qtimer

+} QctQtimerInterfaceClass;


diff --git a/hw/timer/qct-qtimer.c b/hw/timer/qct-qtimer.c
new file mode 100644
index 00000000000..fd56a7118b1
--- /dev/null
+++ b/hw/timer/qct-qtimer.c
@@ -0,0 +1,613 @@


+static const MemoryRegionOps qct_qtimer_ac_ops = {
+    .read = qct_qtimer_ac_read,
+    .write = qct_qtimer_ac_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },

Missing .impl = {4, 4}

+};


+static const Property qct_qtimer_properties[] = {
+    DEFINE_PROP_UINT32("freq", QCTQtimerState, freq, QTIMER_DEFAULT_FREQ_HZ),

"freq-hz", freq_hz if possible.

+    DEFINE_PROP_UINT32("freq-scale", QCTQtimerState, freq_scale, 1),
+    DEFINE_PROP_UINT32("nr_frames", QCTQtimerState, nr_frames, 2),
+    DEFINE_PROP_UINT32("nr_views", QCTQtimerState, nr_views, 1),
+    DEFINE_PROP_UINT32("frame_stride", QCTQtimerState, frame_stride, 0x1000),
+    DEFINE_PROP_UINT32("cnttid_0", QCTQtimerState, cnttid_0, 0x11),
+    DEFINE_PROP_UINT32("cnttid_1", QCTQtimerState, cnttid_1, 0x0),
+};
+
+static void qct_qtimer_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    device_class_set_props(dc, qct_qtimer_properties);
+    dc->realize = qct_qtimer_realize;

Missing unrealize.

+    dc->vmsd = &vmstate_qct_qtimer;
+    rc->phases.hold = qct_qtimer_reset_hold;
+}


+static void qct_qtimer_register_types(void)
+{
+    type_register_static(&qct_qtimer_interface_info);
+    type_register_static(&qct_qtimer_info);
+}
+
+type_init(qct_qtimer_register_types)

Prefer DEFINE_TYPES.

Regards,

Phil.

Reply via email to