// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024, Linaro Limited */ #include #include #include static void timer_disable(const struct callout_timer_desc *desc __unused) { if (IS_ENABLED(CFG_CORE_SEL2_SPMC)) write_cntp_ctl(0); else write_cntps_ctl(0); } static void timer_set_next(const struct callout_timer_desc *desc __unused, uint64_t ctrval) { if (IS_ENABLED(CFG_CORE_SEL2_SPMC)) { write_cntp_cval(ctrval); write_cntp_ctl(1); } else { write_cntps_cval(ctrval); write_cntps_ctl(1); } } static uint64_t timer_ms_to_ticks(const struct callout_timer_desc *desc __unused, uint32_t timeout_ms) { uint64_t freq = read_cntfrq(); return (freq * timeout_ms) / 1000; } static uint64_t timer_now(const struct callout_timer_desc *desc __unused) { return barrier_read_counter_timer(); } static struct itr_handler timer_itr __nex_bss; static const struct callout_timer_desc timer_desc __relrodata_unpaged("timer_desc") = { .disable_timeout = timer_disable, .set_next_timeout = timer_set_next, .ms_to_ticks = timer_ms_to_ticks, .get_now = timer_now, .is_per_cpu = true, }; DECLARE_KEEP_PAGER(timer_desc); static enum itr_return timer_itr_cb(struct itr_handler *h __unused) { callout_service_cb(); return ITRR_HANDLED; } DECLARE_KEEP_PAGER(timer_itr_cb); void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number) { timer_itr = (struct itr_handler){ .it = itr_number, .flags = ITRF_TRIGGER_LEVEL, .handler = timer_itr_cb, }; if (interrupt_add_handler_with_chip(itr_chip, &timer_itr)) panic(); interrupt_enable(timer_itr.chip, timer_itr.it); callout_service_init(&timer_desc); }