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