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 #include <config.h>
10 
11 #define TISR_OVF_FLAG       BIT(1)
12 #define TISR_MATCH_FLAG     BIT(0)
13 
14 struct timer {
15     uint32_t tidr;   /* GPTIMER_TIDR 0x00 */
16     uint32_t padding1[3];
17     uint32_t cfg;    /* GPTIMER_CFG 0x10 */
18     uint32_t tistat; /* GPTIMER_TISTAT 0x14 */
19     uint32_t tisr;   /* GPTIMER_TISR 0x18 */
20     uint32_t tier;   /* GPTIMER_TIER 0x1C */
21     uint32_t twer;   /* GPTIMER_TWER 0x20 */
22     uint32_t tclr;   /* GPTIMER_TCLR 0x24 */
23     uint32_t tcrr;   /* GPTIMER_TCRR 0x28 */
24     uint32_t tldr;   /* GPTIMER_TLDR 0x2C */
25     uint32_t ttgr;   /* GPTIMER_TTGR 0x30 */
26     uint32_t twps;   /* GPTIMER_TWPS 0x34 */
27     uint32_t tmar;   /* GPTIMER_TMAR 0x38 */
28     uint32_t tcar1;  /* GPTIMER_TCAR1 0x3C */
29     uint32_t tsicr;  /* GPTIMER_TSICR 0x40 */
30     uint32_t tcar2;  /* GPTIMER_TCAR2 0x44 */
31     uint32_t tpir;   /* GPTIMER_TPIR 0x48 */
32     uint32_t tnir;   /* GPTIMER_TNIR 0x4C */
33     uint32_t tcvr;   /* GPTIMER_TCVR 0x50 */
34     uint32_t tocr;   /* GPTIMER_TOCR 0x54 */
35     uint32_t towr;   /* GPTIMER_TOWR 0x58 */
36 };
37 typedef volatile struct timer timer_t;
38 extern timer_t *timer;
39 
40 #ifdef CONFIG_KERNEL_MCS
41 /* this is a 32-bit timer, track high_bits here */
42 extern uint32_t high_bits;
43 
44 /** DONT_TRANSLATE */
setDeadline(ticks_t deadline)45 static inline void setDeadline(ticks_t deadline)
46 {
47     timer->tmar = (uint32_t) deadline;
48 }
49 
50 /** DONT_TRANSLATE */
getCurrentTime(void)51 static inline ticks_t getCurrentTime(void)
52 {
53     bool_t overflow = !!(timer->tisr & TISR_OVF_FLAG);
54     return (((uint64_t) high_bits + overflow) << 32llu) + timer->tcrr;
55 }
56 
57 /** DONT_TRANSLATE */
ackDeadlineIRQ(void)58 static inline void ackDeadlineIRQ(void)
59 {
60     /* check if this is an overflow irq */
61     if (timer->tisr & TISR_OVF_FLAG) {
62         high_bits++;
63     }
64 
65     /* ack everything */
66     timer->tisr = TISR_OVF_FLAG | TISR_MATCH_FLAG;
67     assert((timer->tisr & TISR_OVF_FLAG) == 0);
68 }
69 #else /* CONFIG_KERNEL_MCS */
resetTimer(void)70 static inline void resetTimer(void)
71 {
72     timer->tisr = TISR_OVF_FLAG;
73     ackInterrupt(KERNEL_TIMER_IRQ);
74 }
75 #endif /* !CONFIG_KERNEL_MCS */
76