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 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 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 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 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 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 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