xref: /haiku/src/system/kernel/arch/arm64/arch_timer.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
1 /*
2  * Copyright 2019-2022 Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #include <boot/stage2.h>
6 #include <kernel.h>
7 #include <debug.h>
8 #include <int.h>
9 
10 #include <timer.h>
11 #include <arch/timer.h>
12 #include <arch/cpu.h>
13 
14 
15 static uint64 sTimerTicksUS;
16 static bigtime_t sTimerMaxInterval;
17 static uint64 sBootTime;
18 
19 #define TIMER_DISABLED (0)
20 #define TIMER_ENABLE (1)
21 #define TIMER_IMASK (2)
22 #define TIMER_ISTATUS (4)
23 
24 #define TIMER_IRQ 27
25 
26 
27 void
28 arch_timer_set_hardware_timer(bigtime_t timeout)
29 {
30 	if (timeout > sTimerMaxInterval)
31 		timeout = sTimerMaxInterval;
32 
33 	WRITE_SPECIALREG(CNTV_TVAL_EL0, timeout * sTimerTicksUS);
34 	WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_ENABLE);
35 }
36 
37 
38 void
39 arch_timer_clear_hardware_timer()
40 {
41 	WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_DISABLED);
42 }
43 
44 
45 int32
46 arch_timer_interrupt(void *data)
47 {
48 	WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_DISABLED);
49 	return timer_interrupt();
50 }
51 
52 
53 int
54 arch_init_timer(kernel_args *args)
55 {
56 	sTimerTicksUS = READ_SPECIALREG(CNTFRQ_EL0) / 1000000;
57 	sTimerMaxInterval = INT32_MAX / sTimerTicksUS;
58 
59 	WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_DISABLED);
60 	install_io_interrupt_handler(TIMER_IRQ, &arch_timer_interrupt, NULL, 0);
61 
62 	sBootTime = READ_SPECIALREG(CNTPCT_EL0);
63 
64 	return B_OK;
65 }
66 
67 
68 bigtime_t
69 system_time(void)
70 {
71 	return (READ_SPECIALREG(CNTPCT_EL0) - sBootTime) / sTimerTicksUS;
72 }
73