1/*
2 * Copyright 2019, 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#include <errno.h>
14#include <stdlib.h>
15#include <utils/util.h>
16#include <platsupport/timer.h>
17#include <platsupport/plat/meson_timer.h>
18
19int meson_init(meson_timer_t *timer, meson_timer_config_t config)
20{
21    if (timer == NULL || config.vaddr == NULL) {
22        return EINVAL;
23    }
24
25    timer->regs = (void *)((uintptr_t) config.vaddr + (TIMER_BASE + TIMER_REG_START * 4 - TIMER_MAP_BASE));
26
27    timer->regs->mux = TIMER_A_EN | (TIMESTAMP_TIMEBASE_1_US << TIMER_E_INPUT_CLK) |
28                       (TIMEOUT_TIMEBASE_1_MS << TIMER_A_INPUT_CLK);
29
30    timer->regs->timer_e = 0;
31
32    return 0;
33}
34
35uint64_t meson_get_time(meson_timer_t *timer)
36{
37    uint64_t initial_high = timer->regs->timer_e_hi;
38    uint64_t low = timer->regs->timer_e;
39    uint64_t high = timer->regs->timer_e_hi;
40    if (high != initial_high) {
41        low = timer->regs->timer_e;
42    }
43
44    uint64_t ticks = (high << 32) | low;
45    uint64_t time = ticks * NS_IN_US;
46    return time;
47}
48
49void meson_set_timeout(meson_timer_t *timer, uint16_t timeout, bool periodic)
50{
51    if (periodic) {
52        timer->regs->mux |= TIMER_A_MODE;
53    } else {
54        timer->regs->mux &= ~TIMER_A_MODE;
55    }
56
57    timer->regs->timer_a = timeout;
58
59    if (timer->disable) {
60        timer->regs->mux |= TIMER_A_EN;
61        timer->disable = false;
62    }
63}
64
65void meson_stop_timer(meson_timer_t *timer)
66{
67    timer->regs->mux &= ~TIMER_A_EN;
68    timer->disable = true;
69}
70