xref: /optee_os/core/arch/arm/kernel/generic_timer.c (revision cdffc82e89a254562407eac1a37df8f4eacf51e3)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2024, Linaro Limited
4  */
5 
6 #include <arm.h>
7 #include <kernel/callout.h>
8 #include <kernel/timer.h>
9 
timer_disable(const struct callout_timer_desc * desc __unused)10 static void timer_disable(const struct callout_timer_desc *desc __unused)
11 {
12 	if (IS_ENABLED(CFG_CORE_SEL2_SPMC))
13 		write_cntp_ctl(0);
14 	else
15 		write_cntps_ctl(0);
16 }
17 
timer_set_next(const struct callout_timer_desc * desc __unused,uint64_t ctrval)18 static void timer_set_next(const struct callout_timer_desc *desc __unused,
19 			   uint64_t ctrval)
20 {
21 	if (IS_ENABLED(CFG_CORE_SEL2_SPMC)) {
22 		write_cntp_cval(ctrval);
23 		write_cntp_ctl(1);
24 	} else {
25 		write_cntps_cval(ctrval);
26 		write_cntps_ctl(1);
27 	}
28 }
29 
30 static uint64_t
timer_ms_to_ticks(const struct callout_timer_desc * desc __unused,uint32_t timeout_ms)31 timer_ms_to_ticks(const struct callout_timer_desc *desc __unused,
32 		  uint32_t timeout_ms)
33 {
34 	uint64_t freq = read_cntfrq();
35 
36 	return (freq * timeout_ms) / 1000;
37 }
38 
timer_now(const struct callout_timer_desc * desc __unused)39 static uint64_t timer_now(const struct callout_timer_desc *desc __unused)
40 {
41 	return barrier_read_counter_timer();
42 }
43 
44 static struct itr_handler timer_itr __nex_bss;
45 static const struct callout_timer_desc timer_desc
46 __relrodata_unpaged("timer_desc") = {
47 	.disable_timeout = timer_disable,
48 	.set_next_timeout = timer_set_next,
49 	.ms_to_ticks = timer_ms_to_ticks,
50 	.get_now = timer_now,
51 	.is_per_cpu = true,
52 };
53 DECLARE_KEEP_PAGER(timer_desc);
54 
timer_itr_cb(struct itr_handler * h __unused)55 static enum itr_return timer_itr_cb(struct itr_handler *h __unused)
56 {
57 	callout_service_cb();
58 
59 	return ITRR_HANDLED;
60 }
61 DECLARE_KEEP_PAGER(timer_itr_cb);
62 
timer_init_callout_service(struct itr_chip * itr_chip,size_t itr_number)63 void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number)
64 {
65 	timer_itr = (struct itr_handler){
66 		.it = itr_number,
67 		.flags = ITRF_TRIGGER_LEVEL,
68 		.handler = timer_itr_cb,
69 	};
70 
71 	if (interrupt_add_handler_with_chip(itr_chip, &timer_itr))
72 		panic();
73 
74 	interrupt_enable(timer_itr.chip, timer_itr.it);
75 	callout_service_init(&timer_desc);
76 }
77