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: 19*55fd0f84SPeter Maydell * + Clock input "TIMCLK": clock (for both timers) 204f4c6206SPeter Maydell * + sysbus MMIO region 0: the register bank 214f4c6206SPeter Maydell * + sysbus IRQ 0: combined timer interrupt TIMINTC 224f4c6206SPeter Maydell * + sysbus IRO 1: timer block 1 interrupt TIMINT1 234f4c6206SPeter Maydell * + sysbus IRQ 2: timer block 2 interrupt TIMINT2 244f4c6206SPeter Maydell */ 254f4c6206SPeter Maydell 264f4c6206SPeter Maydell #ifndef CMSDK_APB_DUALTIMER_H 274f4c6206SPeter Maydell #define CMSDK_APB_DUALTIMER_H 284f4c6206SPeter Maydell 294f4c6206SPeter Maydell #include "hw/sysbus.h" 304f4c6206SPeter Maydell #include "hw/ptimer.h" 31*55fd0f84SPeter Maydell #include "hw/clock.h" 32db1015e9SEduardo Habkost #include "qom/object.h" 334f4c6206SPeter Maydell 344f4c6206SPeter Maydell #define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer" 358063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBDualTimer, CMSDK_APB_DUALTIMER) 364f4c6206SPeter Maydell 374f4c6206SPeter Maydell 384f4c6206SPeter Maydell /* One of the two identical timer modules in the dual-timer module */ 394f4c6206SPeter Maydell typedef struct CMSDKAPBDualTimerModule { 404f4c6206SPeter Maydell CMSDKAPBDualTimer *parent; 414f4c6206SPeter Maydell struct ptimer_state *timer; 424f4c6206SPeter Maydell qemu_irq timerint; 434f4c6206SPeter Maydell /* 444f4c6206SPeter Maydell * We must track the guest LOAD and VALUE register state by hand 454f4c6206SPeter Maydell * rather than leaving this state only in the ptimer limit/count, 464f4c6206SPeter Maydell * because if CONTROL.SIZE is 0 then only the low 16 bits of the 474f4c6206SPeter Maydell * counter actually counts, but the high half is still guest 484f4c6206SPeter Maydell * accessible. 494f4c6206SPeter Maydell */ 504f4c6206SPeter Maydell uint32_t load; 514f4c6206SPeter Maydell uint32_t value; 524f4c6206SPeter Maydell uint32_t control; 534f4c6206SPeter Maydell uint32_t intstatus; 544f4c6206SPeter Maydell } CMSDKAPBDualTimerModule; 554f4c6206SPeter Maydell 564f4c6206SPeter Maydell #define CMSDK_APB_DUALTIMER_NUM_MODULES 2 574f4c6206SPeter Maydell 584f4c6206SPeter Maydell struct CMSDKAPBDualTimer { 594f4c6206SPeter Maydell /*< private >*/ 604f4c6206SPeter Maydell SysBusDevice parent_obj; 614f4c6206SPeter Maydell 624f4c6206SPeter Maydell /*< public >*/ 634f4c6206SPeter Maydell MemoryRegion iomem; 644f4c6206SPeter Maydell qemu_irq timerintc; 65*55fd0f84SPeter Maydell Clock *timclk; 664f4c6206SPeter Maydell 674f4c6206SPeter Maydell CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES]; 684f4c6206SPeter Maydell uint32_t timeritcr; 694f4c6206SPeter Maydell uint32_t timeritop; 704f4c6206SPeter Maydell }; 714f4c6206SPeter Maydell 724f4c6206SPeter Maydell #endif 73