1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#pragma once
14
15#include <platsupport/sel4_arch/util.h>
16#include <platsupport/timer.h>
17#include <autoconf.h>
18#include <platsupport/gen_config.h>
19
20#define GENERIC_TIMER_ENABLE BIT(0)
21#define GENERIC_TIMER_IMASK  BIT(1)
22#define GENERIC_TIMER_STATUS BIT(2)
23/* Tested to work on ARM A53's */
24#define GENERIC_TIMER_PCNT_IRQ 30
25
26/*
27 * This timer will only work if the kernel has configured
28 * CNTPCT to be read from user-level. This is done by setting CONFIG_EXPORT_PCNT_USER in
29 * a kernel configuration.
30 */
31typedef struct {
32    uint32_t freq;
33} generic_timer_t;
34
35static inline timer_properties_t get_generic_timer_properties(void)
36{
37    return (timer_properties_t) {
38        .upcounter = true,
39        .bit_width = 64
40    };
41}
42
43static inline uint64_t generic_timer_get_ticks(void)
44{
45    uint64_t time;
46    COPROC_READ_64(CNTPCT, time);
47    return time;
48}
49
50static inline void generic_timer_set_compare(uint64_t ticks)
51{
52    COPROC_WRITE_64(CNTP_CVAL, ticks);
53}
54
55static inline uint32_t generic_timer_get_freq(void)
56{
57    uintptr_t freq;
58    COPROC_READ_WORD(CNTFRQ, freq);
59    return (uint32_t) freq;
60}
61
62static inline uint32_t generic_timer_read_ctrl(void)
63{
64    uintptr_t ctrl;
65    COPROC_READ_WORD(CNTP_CTL, ctrl);
66    return ctrl;
67}
68
69static inline void generic_timer_write_ctrl(uintptr_t ctrl)
70{
71    COPROC_WRITE_WORD(CNTP_CTL, ctrl);
72}
73
74static inline void generic_timer_or_ctrl(uintptr_t bits)
75{
76    uintptr_t ctrl = generic_timer_read_ctrl();
77    generic_timer_write_ctrl(ctrl | bits);
78}
79
80static inline void generic_timer_and_ctrl(uintptr_t bits)
81{
82    uintptr_t ctrl = generic_timer_read_ctrl();
83    generic_timer_write_ctrl(ctrl & bits);
84}
85
86static inline void generic_timer_enable(void)
87{
88    generic_timer_or_ctrl(GENERIC_TIMER_ENABLE);
89}
90
91static inline void generic_timer_disable(void)
92{
93    generic_timer_and_ctrl(~GENERIC_TIMER_ENABLE);
94}
95
96static inline void generic_timer_unmask_irq(void)
97{
98    generic_timer_and_ctrl(~GENERIC_TIMER_IMASK);
99}
100
101static inline void generic_timer_mask_irq(void)
102{
103    generic_timer_or_ctrl(GENERIC_TIMER_IMASK);
104}
105
106static inline uintptr_t generic_timer_status(void)
107{
108    return generic_timer_read_ctrl() & GENERIC_TIMER_STATUS;
109}
110
111int generic_timer_init(generic_timer_t *timer);
112uint64_t generic_timer_get_time(generic_timer_t *timer);
113