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#ifndef CONFIG_KERNEL_MCS
12#error "This driver should only be selected for MCS kernel"
13#endif /* CONFIG_KERNEL_MCS */
14
15/* gptir and gptsr bits */
16#define OF1IE 0 /* output compare 1 */
17#define ROV   5 /* roll over */
18
19/* Memory map for GPT (General Purpose Timer). */
20struct timer {
21    uint32_t gptcr; /* control */
22    uint32_t gptpr; /* prescaler */
23    uint32_t gptsr; /* status register */
24    uint32_t gptir; /* interrupt register */
25    uint32_t gptcr1;
26    uint32_t gptcr2;
27    uint32_t gptcr3;
28    uint32_t gpticr1;
29    uint32_t gpticr2;
30    uint32_t gptcnt;
31};
32typedef volatile struct timer timer_t;
33extern timer_t *gpt;
34extern ticks_t high_bits;
35
36static inline ticks_t getCurrentTime(void)
37{
38    return ((high_bits + !!(gpt->gptsr & BIT(ROV))) << 32llu) + gpt->gptcnt;
39}
40
41static inline void setDeadline(ticks_t deadline)
42{
43    if (((uint32_t) deadline) > gpt->gptcnt) {
44        /* turn on compare irq */
45        gpt->gptir |= BIT(OF1IE);
46        /* set the deadline */
47        do {
48            gpt->gptcr1 = (uint32_t) deadline;
49        } while (gpt->gptcr1 != (uint32_t) deadline);
50    }
51}
52
53static inline void ackDeadlineIRQ(void)
54{
55    if (gpt->gptsr & BIT(ROV)) {
56        high_bits++;
57    }
58
59    /* turn off compare irq */
60    gpt->gptir &= ~(BIT(OF1IE));
61    /* ack either irq */
62    gpt->gptsr |= (BIT(OF1IE) | BIT(ROV));
63}
64
65