1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2018, Linaro Limited
4  */
5 
6 #include <arm64.h>
7 #include <kernel/spinlock.h>
8 #include <kernel/timer.h>
9 
10 static unsigned int timer_lock = SPINLOCK_UNLOCK;
11 static bool timer_running;
12 
generic_timer_start(uint32_t time_ms)13 void generic_timer_start(uint32_t time_ms)
14 {
15 	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
16 	uint32_t timer_ticks;
17 
18 	cpu_spin_lock(&timer_lock);
19 
20 	if (timer_running == true)
21 		goto exit;
22 
23 	/* The timer will fire time_ms from now */
24 	timer_ticks = (read_cntfrq() * time_ms) / 1000;
25 	write_cntps_tval(timer_ticks);
26 
27 	/* Enable the secure physical timer */
28 	write_cntps_ctl(1);
29 
30 	timer_running = true;
31 
32 exit:
33 	cpu_spin_unlock(&timer_lock);
34 	thread_set_exceptions(exceptions);
35 }
36 
generic_timer_stop(void)37 void generic_timer_stop(void)
38 {
39 	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
40 
41 	cpu_spin_lock(&timer_lock);
42 
43 	/* Disable the timer */
44 	write_cntps_ctl(0);
45 
46 	timer_running = false;
47 
48 	cpu_spin_unlock(&timer_lock);
49 	thread_set_exceptions(exceptions);
50 }
51 
generic_timer_handler(uint32_t time_ms)52 void generic_timer_handler(uint32_t time_ms)
53 {
54 	uint32_t timer_ticks;
55 
56 	/* Ensure that the timer did assert the interrupt */
57 	assert((read_cntps_ctl() >> 2));
58 
59 	/* Disable the timer */
60 	write_cntps_ctl(0);
61 
62 	/* Reconfigure timer to fire time_ms from now */
63 	timer_ticks = (read_cntfrq() * time_ms) / 1000;
64 	write_cntps_tval(timer_ticks);
65 
66 	/* Enable the secure physical timer */
67 	write_cntps_ctl(1);
68 }
69