1 /* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7 #pragma once 8 9 #define TISR_MATCH_FLAG BIT(0) 10 #define TISR_OVF_FLAG BIT(1) 11 #define TISR_TCAR_FLAG BIT(2) 12 13 /* Kernel uses DMTIMER4 */ 14 struct timer { 15 uint32_t tidr; // 00h TIDR Identification Register 16 uint32_t padding1[3]; 17 uint32_t cfg; // 10h TIOCP_CFG Timer OCP Configuration Register 18 uint32_t padding2[3]; 19 uint32_t tieoi; // 20h IRQ_EOI Timer IRQ End-Of-Interrupt Register 20 uint32_t tisrr; // 24h IRQSTATUS_RAW Timer IRQSTATUS Raw Register 21 uint32_t tisr; // 28h IRQSTATUS Timer IRQSTATUS Register 22 uint32_t tier; // 2Ch IRQSTATUS_SET Timer IRQENABLE Set Register 23 uint32_t ticr; // 30h IRQSTATUS_CLR Timer IRQENABLE Clear Register 24 uint32_t twer; // 34h IRQWAKEEN Timer IRQ Wakeup Enable Register 25 uint32_t tclr; // 38h TCLR Timer Control Register 26 uint32_t tcrr; // 3Ch TCRR Timer Counter Register 27 uint32_t tldr; // 40h TLDR Timer Load Register 28 uint32_t ttgr; // 44h TTGR Timer Trigger Register 29 uint32_t twps; // 48h TWPS Timer Write Posted Status Register 30 uint32_t tmar; // 4Ch TMAR Timer Match Register 31 uint32_t tcar1; // 50h TCAR1 Timer Capture Register 32 uint32_t tsicr; // 54h TSICR Timer Synchronous Interface Control Register 33 uint32_t tcar2; // 58h TCAR2 Timer Capture Register 34 }; 35 36 typedef volatile struct timer timer_t; 37 extern timer_t *timer; 38 39 #ifdef CONFIG_KERNEL_MCS 40 41 extern uint32_t high_bits; 42 43 /* Read the current time from the timer. */ getCurrentTime(void)44static inline ticks_t getCurrentTime(void) 45 { 46 bool_t overflow = !!(timer->tisr & TISR_OVF_FLAG); 47 return ((((uint64_t) high_bits + overflow) << 32llu) + timer->tcrr); 48 } 49 50 #define HIGH_BYTES 0xffffffff00000000 51 52 bool_t high_deadline = false; 53 /* set the next deadline irq - deadline is absolute */ setDeadline(ticks_t deadline)54static inline void setDeadline(ticks_t deadline) 55 { 56 /* Set the deadline in two parts */ 57 if ((deadline & HIGH_BYTES) != 0) { 58 deadline = (deadline & HIGH_BYTES) >> 32; 59 high_deadline = true; 60 } 61 assert((deadline & HIGH_BYTES) == 0); 62 timer->tmar = (uint32_t)deadline; 63 } 64 65 /* ack previous deadline irq */ ackDeadlineIRQ(void)66static inline void ackDeadlineIRQ(void) 67 { 68 /* check if this is an overflow or match irq and ack */ 69 if (timer->tisr & TISR_OVF_FLAG) { 70 high_bits++; 71 timer->tisr = TISR_OVF_FLAG; 72 assert((timer->tisr & TISR_OVF_FLAG) == 0); 73 74 } 75 if (timer->tisr & TISR_MATCH_FLAG) { 76 if (high_deadline) { 77 timer->tmar = 0xffffffff; 78 high_deadline = false; 79 } 80 timer->tisr = TISR_MATCH_FLAG; 81 assert((timer->tisr & TISR_MATCH_FLAG) == 0); 82 } 83 } 84 #else /* CONFIG_KERNEL_MCS */ 85 resetTimer(void)86static inline void resetTimer(void) 87 { 88 timer->tisr = TISR_OVF_FLAG | TISR_MATCH_FLAG | TISR_TCAR_FLAG; 89 ackInterrupt(KERNEL_TIMER_IRQ); 90 } 91 #endif /* !CONFIG_KERNEL_MCS */ 92 93