aboutsummaryrefslogtreecommitdiff
path: root/include/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-08-24 13:29:07 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-08-24 13:29:07 +0100
commitf4e8428b9a6ea440bba057ac03ba0355cd87a72f (patch)
treeca65b40483416b57411a1415563e245538e3e926 /include/hw
parent6b699ae1be9f257478d5eca7ef65dcea270a2796 (diff)
parent239cb6feb298a31faa40b7e97ced107bf9c2f2bf (diff)
downloadqemu-f4e8428b9a6ea440bba057ac03ba0355cd87a72f.zip
qemu-f4e8428b9a6ea440bba057ac03ba0355cd87a72f.tar.gz
qemu-f4e8428b9a6ea440bba057ac03ba0355cd87a72f.tar.bz2
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180824-1' into staging
target-arm queue: * Fix rounding errors in scaling float-to-int and int-to-float operations * Connect virtualization-related IRQs and memory regions of GICv2 in boards that use Cortex-A7 or Cortex-A15 * Support taking exceptions to AArch32 Hyp mode * Clear CPSR.IL and CPSR.J on 32-bit exception entry (a minor bug fix that won't affect non-buggy guest code) * mps2-an505: Implement various missing devices: dual timer, watchdogs, counters in the FPGAIO registers, some missing ID/control registers, TrustZone Master Security Controllers, PL081 DMA controllers, PL022 SPI controllers * correct ID register values for mps2-an385, -an511, -an505 * fix some hardcoded tabs in untouched backwaters of the target/arm codebase * raspi: Refactor framebuffer property handling code and implement support for the virtual framebuffer/viewport # gpg: Signature made Fri 24 Aug 2018 13:19:04 BST # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180824-1: (52 commits) hw/arm/mps2: Fix ID register errors on AN511 and AN385 hw/display/bcm2835_fb: Validate bcm2835_fb_mbox_push() config hw/display/bcm2835_fb: Validate config settings hw/display/bcm2835_fb: Fix handling of virtual framebuffer hw/display/bcm2835_fb: Abstract out calculation of pitch, size hw/display/bcm2835_fb: Reset resolution, etc correctly hw/display/bcm2835_fb: Drop unused size and pitch fields hw/misc/bcm2835_property: Track fb settings using BCM2835FBConfig hw/misc/bcm2835_fb: Move config fields to their own struct target/arm: Remove a handful of stray tabs target/arm: Untabify iwmmxt_helper.c target/arm: Untabify translate.c hw/arm/mps2-tz: Fix MPS2 SCC config register values hw/arm/mps2-tz: Instantiate SPI controllers hw/ssi/pl022: Correct wrong DMACR and ICR handling hw/ssi/pl022: Correct wrong value for PL022_INT_RT hw/ssi/pl022: Use DeviceState::realize rather than SysBusDevice::init hw/ssi/pl022: Don't directly call vmstate_register() hw/ssi/pl022: Set up reset function in class init hw/ssi/pl022: Allow use as embedded-struct device ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include/hw')
-rw-r--r--include/hw/arm/iotkit.h25
-rw-r--r--include/hw/display/bcm2835_fb.h59
-rw-r--r--include/hw/misc/iotkit-secctl.h14
-rw-r--r--include/hw/misc/iotkit-sysctl.h49
-rw-r--r--include/hw/misc/iotkit-sysinfo.h37
-rw-r--r--include/hw/misc/mps2-fpgaio.h10
-rw-r--r--include/hw/misc/tz-msc.h79
-rw-r--r--include/hw/ssi/pl022.h51
-rw-r--r--include/hw/timer/cmsdk-apb-dualtimer.h72
9 files changed, 384 insertions, 12 deletions
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
index 2cddde5..3a8ee63 100644
--- a/include/hw/arm/iotkit.h
+++ b/include/hw/arm/iotkit.h
@@ -28,6 +28,9 @@
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
* are wired to the NVIC lines 32 .. n+32
+ * + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
+ * bus master devices in the board model to make transactions into
+ * all the devices and memory areas in the IoTKit
* Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
* might provide:
* + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
@@ -45,6 +48,11 @@
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
* might provide:
* + named GPIO inputs mpcexp_status[0..15]
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO inputs mscexp_status[0..15]
+ * + named GPIO outputs mscexp_clear[0..15]
+ * + named GPIO outputs mscexp_ns[0..15]
*/
#ifndef IOTKIT_H
@@ -56,7 +64,10 @@
#include "hw/misc/tz-ppc.h"
#include "hw/misc/tz-mpc.h"
#include "hw/timer/cmsdk-apb-timer.h"
-#include "hw/misc/unimp.h"
+#include "hw/timer/cmsdk-apb-dualtimer.h"
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
+#include "hw/misc/iotkit-sysctl.h"
+#include "hw/misc/iotkit-sysinfo.h"
#include "hw/or-irq.h"
#include "hw/core/split-irq.h"
@@ -81,14 +92,22 @@ typedef struct IoTKit {
TZMPC mpc;
CMSDKAPBTIMER timer0;
CMSDKAPBTIMER timer1;
+ CMSDKAPBTIMER s32ktimer;
qemu_or_irq ppc_irq_orgate;
SplitIRQ sec_resp_splitter;
SplitIRQ ppc_irq_splitter[NUM_PPCS];
SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
qemu_or_irq mpc_irq_orgate;
+ qemu_or_irq nmi_orgate;
+
+ CMSDKAPBDualTimer dualtimer;
+
+ CMSDKAPBWatchdog s32kwatchdog;
+ CMSDKAPBWatchdog nswatchdog;
+ CMSDKAPBWatchdog swatchdog;
- UnimplementedDeviceState dualtimer;
- UnimplementedDeviceState s32ktimer;
+ IoTKitSysCtl sysctl;
+ IoTKitSysCtl sysinfo;
MemoryRegion container;
MemoryRegion alias1;
diff --git a/include/hw/display/bcm2835_fb.h b/include/hw/display/bcm2835_fb.h
index ae0a380..228988b 100644
--- a/include/hw/display/bcm2835_fb.h
+++ b/include/hw/display/bcm2835_fb.h
@@ -17,6 +17,20 @@
#define TYPE_BCM2835_FB "bcm2835-fb"
#define BCM2835_FB(obj) OBJECT_CHECK(BCM2835FBState, (obj), TYPE_BCM2835_FB)
+/*
+ * Configuration information about the fb which the guest can program
+ * via the mailbox property interface.
+ */
+typedef struct {
+ uint32_t xres, yres;
+ uint32_t xres_virtual, yres_virtual;
+ uint32_t xoffset, yoffset;
+ uint32_t bpp;
+ uint32_t base;
+ uint32_t pixo;
+ uint32_t alpha;
+} BCM2835FBConfig;
+
typedef struct {
/*< private >*/
SysBusDevice busdev;
@@ -31,16 +45,43 @@ typedef struct {
qemu_irq mbox_irq;
bool lock, invalidate, pending;
- uint32_t xres, yres;
- uint32_t xres_virtual, yres_virtual;
- uint32_t xoffset, yoffset;
- uint32_t bpp;
- uint32_t base, pitch, size;
- uint32_t pixo, alpha;
+
+ BCM2835FBConfig config;
+ BCM2835FBConfig initial_config;
} BCM2835FBState;
-void bcm2835_fb_reconfigure(BCM2835FBState *s, uint32_t *xres, uint32_t *yres,
- uint32_t *xoffset, uint32_t *yoffset, uint32_t *bpp,
- uint32_t *pixo, uint32_t *alpha);
+void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig);
+
+/**
+ * bcm2835_fb_get_pitch: return number of bytes per line of the framebuffer
+ * @config: configuration info for the framebuffer
+ *
+ * Return the number of bytes per line of the framebuffer, ie the number
+ * that must be added to a pixel address to get the address of the pixel
+ * directly below it on screen.
+ */
+static inline uint32_t bcm2835_fb_get_pitch(BCM2835FBConfig *config)
+{
+ uint32_t xres = MAX(config->xres, config->xres_virtual);
+ return xres * (config->bpp >> 3);
+}
+
+/**
+ * bcm2835_fb_get_size: return total size of framebuffer in bytes
+ * @config: configuration info for the framebuffer
+ */
+static inline uint32_t bcm2835_fb_get_size(BCM2835FBConfig *config)
+{
+ uint32_t yres = MAX(config->yres, config->yres_virtual);
+ return yres * bcm2835_fb_get_pitch(config);
+}
+
+/**
+ * bcm2835_fb_validate_config: check provided config
+ *
+ * Validates the configuration information provided by the guest and
+ * adjusts it if necessary.
+ */
+void bcm2835_fb_validate_config(BCM2835FBConfig *config);
#endif
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
index 082c14c..1a193b3 100644
--- a/include/hw/misc/iotkit-secctl.h
+++ b/include/hw/misc/iotkit-secctl.h
@@ -19,6 +19,7 @@
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
* should RAZ/WI or bus error
* + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
+ * + named GPIO output "msc_irq" for the combined IRQ line from the MSCs
* Controlling the 2 APB PPCs in the IoTKit:
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
@@ -44,6 +45,11 @@
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
* might provide:
* + named GPIO inputs mpcexp_status[0..15]
+ * Controlling each of the 16 expansion MSCs which a system using the IoTKit
+ * might provide:
+ * + named GPIO inputs mscexp_status[0..15]
+ * + named GPIO outputs mscexp_clear[0..15]
+ * + named GPIO outputs mscexp_ns[0..15]
*/
#ifndef IOTKIT_SECCTL_H
@@ -62,6 +68,7 @@
#define IOTS_NUM_AHB_EXP_PPC 4
#define IOTS_NUM_EXP_MPC 16
#define IOTS_NUM_MPC 1
+#define IOTS_NUM_EXP_MSC 16
typedef struct IoTKitSecCtl IoTKitSecCtl;
@@ -103,6 +110,13 @@ struct IoTKitSecCtl {
uint32_t brginten;
uint32_t mpcintstatus;
+ uint32_t secmscintstat;
+ uint32_t secmscinten;
+ uint32_t nsmscexp;
+ qemu_irq mscexp_clear[IOTS_NUM_EXP_MSC];
+ qemu_irq mscexp_ns[IOTS_NUM_EXP_MSC];
+ qemu_irq msc_irq;
+
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
new file mode 100644
index 0000000..e36613c
--- /dev/null
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -0,0 +1,49 @@
+/*
+ * ARM IoTKit system control element
+ *
+ * Copyright (c) 2018 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "system control element" which is part of the
+ * Arm IoTKit and documented in
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * Specifically, it implements the "system information block" and
+ * "system control register" blocks.
+ *
+ * QEMU interface:
+ * + sysbus MMIO region 0: the system information register bank
+ * + sysbus MMIO region 1: the system control register bank
+ */
+
+#ifndef HW_MISC_IOTKIT_SYSCTL_H
+#define HW_MISC_IOTKIT_SYSCTL_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_IOTKIT_SYSCTL "iotkit-sysctl"
+#define IOTKIT_SYSCTL(obj) OBJECT_CHECK(IoTKitSysCtl, (obj), \
+ TYPE_IOTKIT_SYSCTL)
+
+typedef struct IoTKitSysCtl {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t secure_debug;
+ uint32_t reset_syndrome;
+ uint32_t reset_mask;
+ uint32_t gretreg;
+ uint32_t initsvrtor0;
+ uint32_t cpuwait;
+ uint32_t wicctrl;
+} IoTKitSysCtl;
+
+#endif
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
new file mode 100644
index 0000000..7b2e1a5
--- /dev/null
+++ b/include/hw/misc/iotkit-sysinfo.h
@@ -0,0 +1,37 @@
+/*
+ * ARM IoTKit system information block
+ *
+ * Copyright (c) 2018 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "system information block" which is part of the
+ * Arm IoTKit and documented in
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * QEMU interface:
+ * + sysbus MMIO region 0: the system information register bank
+ */
+
+#ifndef HW_MISC_IOTKIT_SYSINFO_H
+#define HW_MISC_IOTKIT_SYSINFO_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_IOTKIT_SYSINFO "iotkit-sysinfo"
+#define IOTKIT_SYSINFO(obj) OBJECT_CHECK(IoTKitSysInfo, (obj), \
+ TYPE_IOTKIT_SYSINFO)
+
+typedef struct IoTKitSysInfo {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+} IoTKitSysInfo;
+
+#endif
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
index eedf17e..69e265c 100644
--- a/include/hw/misc/mps2-fpgaio.h
+++ b/include/hw/misc/mps2-fpgaio.h
@@ -37,7 +37,17 @@ typedef struct {
uint32_t prescale;
uint32_t misc;
+ /* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
+ int64_t pscntr_sync_ticks;
+ /* Values of COUNTER and PSCNTR at time pscntr_sync_ticks */
+ uint32_t counter;
+ uint32_t pscntr;
+
uint32_t prescale_clk;
+
+ /* These hold the CLOCK_VIRTUAL ns tick when the CLK1HZ/CLK100HZ was zero */
+ int64_t clk1hz_tick_offset;
+ int64_t clk100hz_tick_offset;
} MPS2FPGAIO;
#endif
diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h
new file mode 100644
index 0000000..116b96a
--- /dev/null
+++ b/include/hw/misc/tz-msc.h
@@ -0,0 +1,79 @@
+/*
+ * ARM TrustZone master security controller emulation
+ *
+ * Copyright (c) 2018 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the TrustZone master security controller (MSC).
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
+ * (DDI 0571G):
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
+ *
+ * The MSC sits in front of a device which can be a bus master (such as
+ * a DMA controller) and allows secure software to configure it to either
+ * pass through or reject transactions made by that bus master.
+ * Rejected transactions may be configured to either be aborted, or to
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
+ *
+ * The MSC has no register interface -- it is configured purely by a
+ * collection of input signals from other hardware in the system. Typically
+ * they are either hardwired or exposed in an ad-hoc register interface by
+ * the SoC that uses the MSC.
+ *
+ * We don't currently implement the irq_enable GPIO input, because on
+ * the MPS2 FPGA images it is always tied high, which is awkward to
+ * implement in QEMU.
+ *
+ * QEMU interface:
+ * + Named GPIO input "cfg_nonsec": set to 1 if the bus master should be
+ * treated as nonsecure, or 0 for secure
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
+ * + Property "downstream": MemoryRegion defining where bus master transactions
+ * are made if they are not blocked
+ * + Property "idau": an object implementing IDAUInterface, which defines which
+ * addresses should be treated as secure and which as non-secure.
+ * This need not be the same IDAU as the one used by the CPU.
+ * + sysbus MMIO region 0: MemoryRegion defining the upstream end of the MSC;
+ * this should be passed to the bus master device as the region it should
+ * make memory transactions to
+ */
+
+#ifndef TZ_MSC_H
+#define TZ_MSC_H
+
+#include "hw/sysbus.h"
+#include "target/arm/idau.h"
+
+#define TYPE_TZ_MSC "tz-msc"
+#define TZ_MSC(obj) OBJECT_CHECK(TZMSC, (obj), TYPE_TZ_MSC)
+
+typedef struct TZMSC {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+
+ /* State: these just track the values of our input signals */
+ bool cfg_nonsec;
+ bool cfg_sec_resp;
+ bool irq_clear;
+ /* State: are we asserting irq ? */
+ bool irq_status;
+
+ qemu_irq irq;
+ MemoryRegion *downstream;
+ AddressSpace downstream_as;
+ MemoryRegion upstream;
+ IDAUInterface *idau;
+} TZMSC;
+
+#endif
diff --git a/include/hw/ssi/pl022.h b/include/hw/ssi/pl022.h
new file mode 100644
index 0000000..a080519
--- /dev/null
+++ b/include/hw/ssi/pl022.h
@@ -0,0 +1,51 @@
+/*
+ * ARM PrimeCell PL022 Synchronous Serial Port
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/* This is a model of the Arm PrimeCell PL022 synchronous serial port.
+ * The PL022 TRM is:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/DDI0194H_ssp_pl022_trm.pdf
+ *
+ * QEMU interface:
+ * + sysbus IRQ: SSPINTR combined interrupt line
+ * + sysbus MMIO region 0: MemoryRegion for the device's registers
+ */
+
+#ifndef HW_SSI_PL022_H
+#define HW_SSI_PL022_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_PL022 "pl022"
+#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
+
+typedef struct PL022State {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t cr0;
+ uint32_t cr1;
+ uint32_t bitmask;
+ uint32_t sr;
+ uint32_t cpsr;
+ uint32_t is;
+ uint32_t im;
+ /* The FIFO head points to the next empty entry. */
+ int tx_fifo_head;
+ int rx_fifo_head;
+ int tx_fifo_len;
+ int rx_fifo_len;
+ uint16_t tx_fifo[8];
+ uint16_t rx_fifo[8];
+ qemu_irq irq;
+ SSIBus *ssi;
+} PL022State;
+
+#endif
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
new file mode 100644
index 0000000..9843a9d
--- /dev/null
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
@@ -0,0 +1,72 @@
+/*
+ * ARM CMSDK APB dual-timer emulation
+ *
+ * Copyright (c) 2018 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or
+ * (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "APB dual-input timer" which is part of the Cortex-M
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
+ *
+ * QEMU interface:
+ * + QOM property "pclk-frq": frequency at which the timer is clocked
+ * + sysbus MMIO region 0: the register bank
+ * + sysbus IRQ 0: combined timer interrupt TIMINTC
+ * + sysbus IRO 1: timer block 1 interrupt TIMINT1
+ * + sysbus IRQ 2: timer block 2 interrupt TIMINT2
+ */
+
+#ifndef CMSDK_APB_DUALTIMER_H
+#define CMSDK_APB_DUALTIMER_H
+
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
+
+#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
+#define CMSDK_APB_DUALTIMER(obj) OBJECT_CHECK(CMSDKAPBDualTimer, (obj), \
+ TYPE_CMSDK_APB_DUALTIMER)
+
+typedef struct CMSDKAPBDualTimer CMSDKAPBDualTimer;
+
+/* One of the two identical timer modules in the dual-timer module */
+typedef struct CMSDKAPBDualTimerModule {
+ CMSDKAPBDualTimer *parent;
+ struct ptimer_state *timer;
+ qemu_irq timerint;
+ /*
+ * We must track the guest LOAD and VALUE register state by hand
+ * rather than leaving this state only in the ptimer limit/count,
+ * because if CONTROL.SIZE is 0 then only the low 16 bits of the
+ * counter actually counts, but the high half is still guest
+ * accessible.
+ */
+ uint32_t load;
+ uint32_t value;
+ uint32_t control;
+ uint32_t intstatus;
+} CMSDKAPBDualTimerModule;
+
+#define CMSDK_APB_DUALTIMER_NUM_MODULES 2
+
+struct CMSDKAPBDualTimer {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ qemu_irq timerintc;
+ uint32_t pclk_frq;
+
+ CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
+ uint32_t timeritcr;
+ uint32_t timeritop;
+};
+
+#endif