1231200Smm/*
2231200Smm * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3231200Smm *
4231200Smm * SPDX-License-Identifier: GPL-2.0-only
5231200Smm */
6231200Smm
7231200Smm#pragma once
8231200Smm
9231200Smm#include <config.h>
10231200Smm
11231200Smm#ifndef CONFIG_KERNEL_MCS
12231200Smm#error "This driver should only be selected for MCS kernel"
13231200Smm#endif /* CONFIG_KERNEL_MCS */
14231200Smm
15231200Smm/* gptir and gptsr bits */
16231200Smm#define OF1IE 0 /* output compare 1 */
17231200Smm#define ROV   5 /* roll over */
18231200Smm
19231200Smm/* Memory map for GPT (General Purpose Timer). */
20231200Smmstruct timer {
21231200Smm    uint32_t gptcr; /* control */
22231200Smm    uint32_t gptpr; /* prescaler */
23231200Smm    uint32_t gptsr; /* status register */
24231200Smm    uint32_t gptir; /* interrupt register */
25231200Smm    uint32_t gptcr1;
26231200Smm    uint32_t gptcr2;
27231200Smm    uint32_t gptcr3;
28231200Smm    uint32_t gpticr1;
29231200Smm    uint32_t gpticr2;
30231200Smm    uint32_t gptcnt;
31231200Smm};
32231200Smmtypedef volatile struct timer timer_t;
33231200Smmextern timer_t *gpt;
34231200Smmextern ticks_t high_bits;
35231200Smm
36231200Smmstatic inline ticks_t getCurrentTime(void)
37231200Smm{
38231200Smm    return ((high_bits + !!(gpt->gptsr & BIT(ROV))) << 32llu) + gpt->gptcnt;
39231200Smm}
40231200Smm
41231200Smmstatic inline void setDeadline(ticks_t deadline)
42231200Smm{
43231200Smm    if (((uint32_t) deadline) > gpt->gptcnt) {
44231200Smm        /* turn on compare irq */
45231200Smm        gpt->gptir |= BIT(OF1IE);
46231200Smm        /* set the deadline */
47231200Smm        do {
48231200Smm            gpt->gptcr1 = (uint32_t) deadline;
49231200Smm        } while (gpt->gptcr1 != (uint32_t) deadline);
50231200Smm    }
51231200Smm}
52231200Smm
53231200Smmstatic inline void ackDeadlineIRQ(void)
54231200Smm{
55232153Smm    if (gpt->gptsr & BIT(ROV)) {
56232153Smm        high_bits++;
57232153Smm    }
58231200Smm
59231200Smm    /* turn off compare irq */
60231200Smm    gpt->gptir &= ~(BIT(OF1IE));
61231200Smm    /* ack either irq */
62231200Smm    gpt->gptsr |= (BIT(OF1IE) | BIT(ROV));
63231200Smm}
64231200Smm
65231200Smm