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#include <stdint.h>
11
12/* convert to khz first to avoid overflow */
13#define TICKS_PER_MS (TIMER_CLOCK_HZ / HZ_IN_KHZ)
14
15#ifdef CONFIG_KERNEL_MCS
16#include <types.h>
17#include <util.h>
18#include <mode/util.h>
19
20#define USE_KHZ (TIMER_CLOCK_HZ % HZ_IN_MHZ > 0)
21#define TIMER_CLOCK_KHZ (TIMER_CLOCK_HZ / HZ_IN_KHZ)
22#define TIMER_CLOCK_MHZ (TIMER_CLOCK_HZ / HZ_IN_MHZ)
23
24#include <plat/platform_gen.h>
25#include <mode/machine/timer.h>
26
27void initTimer(void);
28
29/* get the max value usToTicks can be passed without overflowing */
30static inline CONST time_t getMaxUsToTicks(void)
31{
32#if USE_KHZ
33    return UINT64_MAX / TIMER_CLOCK_KHZ;
34#else
35    return UINT64_MAX / TIMER_CLOCK_MHZ;
36#endif
37}
38
39static inline CONST ticks_t usToTicks(time_t us)
40{
41#if USE_KHZ
42    /* reciprocal division overflows too quickly for dividing by KHZ_IN_MHZ.
43     * This operation isn't  used frequently or on many platforms, so use manual
44     * division here */
45    return div64(us * TIMER_CLOCK_KHZ, KHZ_IN_MHZ);
46#else
47    return us * TIMER_CLOCK_MHZ;
48#endif
49}
50
51static inline CONST ticks_t getTimerPrecision(void)
52{
53    return usToTicks(TIMER_PRECISION);
54}
55#else /* CONFIG_KERNEL_MCS */
56#include <mode/machine/timer.h>
57#include <plat/machine/hardware.h>
58
59#define HZ_IN_KHZ 1000llu
60
61/* but multiply by timer tick ms */
62#define TIMER_RELOAD    (TICKS_PER_MS * CONFIG_TIMER_TICK_MS)
63
64#if (TIMER_RELOAD >= UINTPTR_MAX)
65#error "Timer reload too high"
66#endif
67
68void initTimer(void);
69#endif
70
71