15b7afacfSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
25b7afacfSJens Wiklander /*
35b7afacfSJens Wiklander * Copyright (c) 2024, Linaro Limited
45b7afacfSJens Wiklander */
55b7afacfSJens Wiklander
65b7afacfSJens Wiklander #include <arm.h>
75b7afacfSJens Wiklander #include <kernel/callout.h>
85b7afacfSJens Wiklander #include <kernel/timer.h>
95b7afacfSJens Wiklander
timer_disable(const struct callout_timer_desc * desc __unused)105b7afacfSJens Wiklander static void timer_disable(const struct callout_timer_desc *desc __unused)
115b7afacfSJens Wiklander {
12*cdffc82eSJens Wiklander if (IS_ENABLED(CFG_CORE_SEL2_SPMC))
13*cdffc82eSJens Wiklander write_cntp_ctl(0);
14*cdffc82eSJens Wiklander else
155b7afacfSJens Wiklander write_cntps_ctl(0);
165b7afacfSJens Wiklander }
175b7afacfSJens Wiklander
timer_set_next(const struct callout_timer_desc * desc __unused,uint64_t ctrval)185b7afacfSJens Wiklander static void timer_set_next(const struct callout_timer_desc *desc __unused,
195b7afacfSJens Wiklander uint64_t ctrval)
205b7afacfSJens Wiklander {
21*cdffc82eSJens Wiklander if (IS_ENABLED(CFG_CORE_SEL2_SPMC)) {
22*cdffc82eSJens Wiklander write_cntp_cval(ctrval);
23*cdffc82eSJens Wiklander write_cntp_ctl(1);
24*cdffc82eSJens Wiklander } else {
255b7afacfSJens Wiklander write_cntps_cval(ctrval);
265b7afacfSJens Wiklander write_cntps_ctl(1);
275b7afacfSJens Wiklander }
28*cdffc82eSJens Wiklander }
295b7afacfSJens Wiklander
305b7afacfSJens Wiklander static uint64_t
timer_ms_to_ticks(const struct callout_timer_desc * desc __unused,uint32_t timeout_ms)315b7afacfSJens Wiklander timer_ms_to_ticks(const struct callout_timer_desc *desc __unused,
325b7afacfSJens Wiklander uint32_t timeout_ms)
335b7afacfSJens Wiklander {
345b7afacfSJens Wiklander uint64_t freq = read_cntfrq();
355b7afacfSJens Wiklander
365b7afacfSJens Wiklander return (freq * timeout_ms) / 1000;
375b7afacfSJens Wiklander }
385b7afacfSJens Wiklander
timer_now(const struct callout_timer_desc * desc __unused)395b7afacfSJens Wiklander static uint64_t timer_now(const struct callout_timer_desc *desc __unused)
405b7afacfSJens Wiklander {
415b7afacfSJens Wiklander return barrier_read_counter_timer();
425b7afacfSJens Wiklander }
435b7afacfSJens Wiklander
445b7afacfSJens Wiklander static struct itr_handler timer_itr __nex_bss;
455b7afacfSJens Wiklander static const struct callout_timer_desc timer_desc
465b7afacfSJens Wiklander __relrodata_unpaged("timer_desc") = {
475b7afacfSJens Wiklander .disable_timeout = timer_disable,
485b7afacfSJens Wiklander .set_next_timeout = timer_set_next,
495b7afacfSJens Wiklander .ms_to_ticks = timer_ms_to_ticks,
505b7afacfSJens Wiklander .get_now = timer_now,
515b7afacfSJens Wiklander .is_per_cpu = true,
525b7afacfSJens Wiklander };
53fd3f2d69SJens Wiklander DECLARE_KEEP_PAGER(timer_desc);
545b7afacfSJens Wiklander
timer_itr_cb(struct itr_handler * h __unused)555b7afacfSJens Wiklander static enum itr_return timer_itr_cb(struct itr_handler *h __unused)
565b7afacfSJens Wiklander {
575b7afacfSJens Wiklander callout_service_cb();
585b7afacfSJens Wiklander
595b7afacfSJens Wiklander return ITRR_HANDLED;
605b7afacfSJens Wiklander }
61fd3f2d69SJens Wiklander DECLARE_KEEP_PAGER(timer_itr_cb);
625b7afacfSJens Wiklander
timer_init_callout_service(struct itr_chip * itr_chip,size_t itr_number)635b7afacfSJens Wiklander void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number)
645b7afacfSJens Wiklander {
655b7afacfSJens Wiklander timer_itr = (struct itr_handler){
665b7afacfSJens Wiklander .it = itr_number,
675b7afacfSJens Wiklander .flags = ITRF_TRIGGER_LEVEL,
685b7afacfSJens Wiklander .handler = timer_itr_cb,
695b7afacfSJens Wiklander };
705b7afacfSJens Wiklander
715b7afacfSJens Wiklander if (interrupt_add_handler_with_chip(itr_chip, &timer_itr))
725b7afacfSJens Wiklander panic();
735b7afacfSJens Wiklander
745b7afacfSJens Wiklander interrupt_enable(timer_itr.chip, timer_itr.it);
755b7afacfSJens Wiklander callout_service_init(&timer_desc);
765b7afacfSJens Wiklander }
77