14f4c6206SPeter Maydell /* 24f4c6206SPeter Maydell * ARM CMSDK APB dual-timer emulation 34f4c6206SPeter Maydell * 44f4c6206SPeter Maydell * Copyright (c) 2018 Linaro Limited 54f4c6206SPeter Maydell * Written by Peter Maydell 64f4c6206SPeter Maydell * 74f4c6206SPeter Maydell * This program is free software; you can redistribute it and/or modify 84f4c6206SPeter Maydell * it under the terms of the GNU General Public License version 2 or 94f4c6206SPeter Maydell * (at your option) any later version. 104f4c6206SPeter Maydell */ 114f4c6206SPeter Maydell 124f4c6206SPeter Maydell /* 134f4c6206SPeter Maydell * This is a model of the "APB dual-input timer" which is part of the Cortex-M 144f4c6206SPeter Maydell * System Design Kit (CMSDK) and documented in the Cortex-M System 154f4c6206SPeter Maydell * Design Kit Technical Reference Manual (ARM DDI0479C): 164f4c6206SPeter Maydell * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit 174f4c6206SPeter Maydell * 184f4c6206SPeter Maydell * QEMU interface: 194f4c6206SPeter Maydell * + QOM property "pclk-frq": frequency at which the timer is clocked 20*55fd0f84SPeter Maydell * + Clock input "TIMCLK": clock (for both timers) 214f4c6206SPeter Maydell * + sysbus MMIO region 0: the register bank 224f4c6206SPeter Maydell * + sysbus IRQ 0: combined timer interrupt TIMINTC 234f4c6206SPeter Maydell * + sysbus IRO 1: timer block 1 interrupt TIMINT1 244f4c6206SPeter Maydell * + sysbus IRQ 2: timer block 2 interrupt TIMINT2 254f4c6206SPeter Maydell */ 264f4c6206SPeter Maydell 274f4c6206SPeter Maydell #ifndef CMSDK_APB_DUALTIMER_H 284f4c6206SPeter Maydell #define CMSDK_APB_DUALTIMER_H 294f4c6206SPeter Maydell 304f4c6206SPeter Maydell #include "hw/sysbus.h" 314f4c6206SPeter Maydell #include "hw/ptimer.h" 32*55fd0f84SPeter Maydell #include "hw/clock.h" 33db1015e9SEduardo Habkost #include "qom/object.h" 344f4c6206SPeter Maydell 354f4c6206SPeter Maydell #define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer" 368063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBDualTimer, CMSDK_APB_DUALTIMER) 374f4c6206SPeter Maydell 384f4c6206SPeter Maydell 394f4c6206SPeter Maydell /* One of the two identical timer modules in the dual-timer module */ 404f4c6206SPeter Maydell typedef struct CMSDKAPBDualTimerModule { 414f4c6206SPeter Maydell CMSDKAPBDualTimer *parent; 424f4c6206SPeter Maydell struct ptimer_state *timer; 434f4c6206SPeter Maydell qemu_irq timerint; 444f4c6206SPeter Maydell /* 454f4c6206SPeter Maydell * We must track the guest LOAD and VALUE register state by hand 464f4c6206SPeter Maydell * rather than leaving this state only in the ptimer limit/count, 474f4c6206SPeter Maydell * because if CONTROL.SIZE is 0 then only the low 16 bits of the 484f4c6206SPeter Maydell * counter actually counts, but the high half is still guest 494f4c6206SPeter Maydell * accessible. 504f4c6206SPeter Maydell */ 514f4c6206SPeter Maydell uint32_t load; 524f4c6206SPeter Maydell uint32_t value; 534f4c6206SPeter Maydell uint32_t control; 544f4c6206SPeter Maydell uint32_t intstatus; 554f4c6206SPeter Maydell } CMSDKAPBDualTimerModule; 564f4c6206SPeter Maydell 574f4c6206SPeter Maydell #define CMSDK_APB_DUALTIMER_NUM_MODULES 2 584f4c6206SPeter Maydell 594f4c6206SPeter Maydell struct CMSDKAPBDualTimer { 604f4c6206SPeter Maydell /*< private >*/ 614f4c6206SPeter Maydell SysBusDevice parent_obj; 624f4c6206SPeter Maydell 634f4c6206SPeter Maydell /*< public >*/ 644f4c6206SPeter Maydell MemoryRegion iomem; 654f4c6206SPeter Maydell qemu_irq timerintc; 664f4c6206SPeter Maydell uint32_t pclk_frq; 67*55fd0f84SPeter Maydell Clock *timclk; 684f4c6206SPeter Maydell 694f4c6206SPeter Maydell CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES]; 704f4c6206SPeter Maydell uint32_t timeritcr; 714f4c6206SPeter Maydell uint32_t timeritop; 724f4c6206SPeter Maydell }; 734f4c6206SPeter Maydell 744f4c6206SPeter Maydell #endif 75