xref: /haiku/src/system/kernel/arch/arm/arch_timer_generic.cpp (revision 97f11716bfaa0f385eb0e28a52bf56a5023b9e99)
1 /*
2  * Copyright 2022 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "arch_timer_generic.h"
8 
9 
10 #define TIMER_IRQ 30
11 
12 
13 static uint32_t
get_counter_freq(void)14 get_counter_freq(void)
15 {
16     uint32_t freq;
17     asm volatile ("MRC p15, 0, %0, c14, c0, 0": "=r" (freq));
18     return freq;
19 }
20 
21 
22 static uint64_t
get_counter(void)23 get_counter(void)
24 {
25     uint32_t counter_low;
26     uint32_t counter_high;
27 
28     asm volatile ("ISB\n"
29         "MRRC p15, 0, %0, %1, c14"
30         : "=r" (counter_low), "=r" (counter_high));
31     return ((uint64_t)counter_high << 32) | counter_low;
32 }
33 
34 
35 void
SetTimeout(bigtime_t timeout)36 ARMGenericTimer::SetTimeout(bigtime_t timeout)
37 {
38 	uint32_t timeout_ticks = timeout * fTimerFrequencyMHz;
39 	asm volatile ("ISB\n"
40 		"MCR p15, 0, %0, c14, c2, 0"
41 		: : "r"(timeout_ticks));
42 
43 	uint32_t timer_ctl = 1;
44 	asm volatile ("MCR p15, 0, %0, c14, c2, 1"
45 		: : "r"(timer_ctl));
46 }
47 
48 
49 void
Clear()50 ARMGenericTimer::Clear()
51 {
52 	uint32_t timer_ctl = 2;
53 	asm volatile ("MCR p15, 0, %0, c14, c2, 1"
54 		: : "r"(timer_ctl));
55 }
56 
57 
58 bigtime_t
Time()59 ARMGenericTimer::Time()
60 {
61 	return get_counter() / fTimerFrequencyMHz;
62 }
63 
64 
65 int32
_InterruptWrapper(void * data)66 ARMGenericTimer::_InterruptWrapper(void *data)
67 {
68 	return ((ARMGenericTimer*)data)->HandleInterrupt();
69 }
70 
71 
72 int32
HandleInterrupt()73 ARMGenericTimer::HandleInterrupt()
74 {
75 	return timer_interrupt();
76 }
77 
78 
ARMGenericTimer()79 ARMGenericTimer::ARMGenericTimer()
80 : HardwareTimer()
81 {
82 	Clear();
83 
84 	install_io_interrupt_handler(TIMER_IRQ,
85 		&ARMGenericTimer::_InterruptWrapper, this, 0);
86 
87 	fTimerFrequency = get_counter_freq();
88 	fTimerFrequencyMHz = fTimerFrequency / 1000000;
89 }
90 
91 
92 bool
IsAvailable()93 ARMGenericTimer::IsAvailable()
94 {
95 	uint32_t pfr1;
96 	asm volatile("MRC p15, 0, %0, c0, c1, 1": "=r" (pfr1));
97 	return (pfr1 & 0x000F0000) == 0x00010000;
98 }
99