1*4f4c6206SPeter Maydell /* 2*4f4c6206SPeter Maydell * ARM CMSDK APB dual-timer emulation 3*4f4c6206SPeter Maydell * 4*4f4c6206SPeter Maydell * Copyright (c) 2018 Linaro Limited 5*4f4c6206SPeter Maydell * Written by Peter Maydell 6*4f4c6206SPeter Maydell * 7*4f4c6206SPeter Maydell * This program is free software; you can redistribute it and/or modify 8*4f4c6206SPeter Maydell * it under the terms of the GNU General Public License version 2 or 9*4f4c6206SPeter Maydell * (at your option) any later version. 10*4f4c6206SPeter Maydell */ 11*4f4c6206SPeter Maydell 12*4f4c6206SPeter Maydell /* 13*4f4c6206SPeter Maydell * This is a model of the "APB dual-input timer" which is part of the Cortex-M 14*4f4c6206SPeter Maydell * System Design Kit (CMSDK) and documented in the Cortex-M System 15*4f4c6206SPeter Maydell * Design Kit Technical Reference Manual (ARM DDI0479C): 16*4f4c6206SPeter Maydell * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit 17*4f4c6206SPeter Maydell * 18*4f4c6206SPeter Maydell * QEMU interface: 19*4f4c6206SPeter Maydell * + QOM property "pclk-frq": frequency at which the timer is clocked 20*4f4c6206SPeter Maydell * + sysbus MMIO region 0: the register bank 21*4f4c6206SPeter Maydell * + sysbus IRQ 0: combined timer interrupt TIMINTC 22*4f4c6206SPeter Maydell * + sysbus IRO 1: timer block 1 interrupt TIMINT1 23*4f4c6206SPeter Maydell * + sysbus IRQ 2: timer block 2 interrupt TIMINT2 24*4f4c6206SPeter Maydell */ 25*4f4c6206SPeter Maydell 26*4f4c6206SPeter Maydell #ifndef CMSDK_APB_DUALTIMER_H 27*4f4c6206SPeter Maydell #define CMSDK_APB_DUALTIMER_H 28*4f4c6206SPeter Maydell 29*4f4c6206SPeter Maydell #include "hw/sysbus.h" 30*4f4c6206SPeter Maydell #include "hw/ptimer.h" 31*4f4c6206SPeter Maydell 32*4f4c6206SPeter Maydell #define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer" 33*4f4c6206SPeter Maydell #define CMSDK_APB_DUALTIMER(obj) OBJECT_CHECK(CMSDKAPBDualTimer, (obj), \ 34*4f4c6206SPeter Maydell TYPE_CMSDK_APB_DUALTIMER) 35*4f4c6206SPeter Maydell 36*4f4c6206SPeter Maydell typedef struct CMSDKAPBDualTimer CMSDKAPBDualTimer; 37*4f4c6206SPeter Maydell 38*4f4c6206SPeter Maydell /* One of the two identical timer modules in the dual-timer module */ 39*4f4c6206SPeter Maydell typedef struct CMSDKAPBDualTimerModule { 40*4f4c6206SPeter Maydell CMSDKAPBDualTimer *parent; 41*4f4c6206SPeter Maydell struct ptimer_state *timer; 42*4f4c6206SPeter Maydell qemu_irq timerint; 43*4f4c6206SPeter Maydell /* 44*4f4c6206SPeter Maydell * We must track the guest LOAD and VALUE register state by hand 45*4f4c6206SPeter Maydell * rather than leaving this state only in the ptimer limit/count, 46*4f4c6206SPeter Maydell * because if CONTROL.SIZE is 0 then only the low 16 bits of the 47*4f4c6206SPeter Maydell * counter actually counts, but the high half is still guest 48*4f4c6206SPeter Maydell * accessible. 49*4f4c6206SPeter Maydell */ 50*4f4c6206SPeter Maydell uint32_t load; 51*4f4c6206SPeter Maydell uint32_t value; 52*4f4c6206SPeter Maydell uint32_t control; 53*4f4c6206SPeter Maydell uint32_t intstatus; 54*4f4c6206SPeter Maydell } CMSDKAPBDualTimerModule; 55*4f4c6206SPeter Maydell 56*4f4c6206SPeter Maydell #define CMSDK_APB_DUALTIMER_NUM_MODULES 2 57*4f4c6206SPeter Maydell 58*4f4c6206SPeter Maydell struct CMSDKAPBDualTimer { 59*4f4c6206SPeter Maydell /*< private >*/ 60*4f4c6206SPeter Maydell SysBusDevice parent_obj; 61*4f4c6206SPeter Maydell 62*4f4c6206SPeter Maydell /*< public >*/ 63*4f4c6206SPeter Maydell MemoryRegion iomem; 64*4f4c6206SPeter Maydell qemu_irq timerintc; 65*4f4c6206SPeter Maydell uint32_t pclk_frq; 66*4f4c6206SPeter Maydell 67*4f4c6206SPeter Maydell CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES]; 68*4f4c6206SPeter Maydell uint32_t timeritcr; 69*4f4c6206SPeter Maydell uint32_t timeritop; 70*4f4c6206SPeter Maydell }; 71*4f4c6206SPeter Maydell 72*4f4c6206SPeter Maydell #endif 73