1 /*
2  * Copyright (c) 2025 Croxel Inc.
3  * Copyright (c) 2025 CogniPilot Foundation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <platform/argus_timer.h>
9 #include <api/argus_status.h>
10 
11 #include <zephyr/kernel.h>
12 
13 #include <../drivers/sensor/broadcom/afbr_s50/platform.h>
14 
15 struct platform_argus_timer {
16 	struct k_timer *timer;
17 	uint32_t dt_microseconds;
18 	struct {
19 		timer_cb_t handler;
20 		void *param;
21 	} cb;
22 };
23 
24 static void argus_timer_handler(struct k_timer *timer);
25 
26 K_TIMER_DEFINE(argus_timer, argus_timer_handler, NULL);
27 
28 static struct platform_argus_timer platform_timer = {
29 	.timer = &argus_timer,
30 };
31 
argus_timer_handler(struct k_timer * timer)32 static void argus_timer_handler(struct k_timer *timer)
33 {
34 	struct platform_argus_timer *p_timer = &platform_timer;
35 	timer_cb_t handler = p_timer->cb.handler;
36 
37 	if (handler) {
38 		handler(p_timer->cb.param);
39 	}
40 }
41 
Timer_GetCounterValue(uint32_t * hct,uint32_t * lct)42 void Timer_GetCounterValue(uint32_t *hct, uint32_t *lct)
43 {
44 	int64_t uptime_ticks = k_uptime_ticks();
45 	uint64_t uptime_us = k_ticks_to_us_floor64((uint64_t)uptime_ticks);
46 
47 	/* hct in seconds, lct in microseconds */
48 	*hct = uptime_us / USEC_PER_SEC;
49 	*lct = uptime_us % USEC_PER_SEC;
50 }
51 
Timer_SetCallback(timer_cb_t f)52 status_t Timer_SetCallback(timer_cb_t f)
53 {
54 	platform_timer.cb.handler = f;
55 
56 	return STATUS_OK;
57 }
58 
59 /** The API description talks about multiple timers going on at once,
60  * distinguished by the parameter passed on, however there does not appear to
61  * be a mention on what's the requirement, neither do the other platform
62  * implementation in the upstream SDK follow a multi-timer pattern.
63  * For starters, this implementation just covers single-timer use case.
64  */
Timer_SetInterval(uint32_t dt_microseconds,void * param)65 status_t Timer_SetInterval(uint32_t dt_microseconds, void *param)
66 {
67 	if (dt_microseconds == 0) {
68 		k_timer_stop(platform_timer.timer);
69 		platform_timer.dt_microseconds = 0;
70 		platform_timer.cb.param = NULL;
71 	} else if (dt_microseconds != platform_timer.dt_microseconds) {
72 		platform_timer.dt_microseconds = dt_microseconds;
73 		platform_timer.cb.param = param;
74 		k_timer_start(platform_timer.timer,
75 			      K_USEC(platform_timer.dt_microseconds),
76 			      K_USEC(platform_timer.dt_microseconds));
77 	} else {
78 		platform_timer.cb.param = param;
79 	}
80 
81 	return STATUS_OK;
82 }
83 
timer_init(struct afbr_s50_platform_data * data)84 static int timer_init(struct afbr_s50_platform_data *data)
85 {
86 	ARG_UNUSED(data);
87 
88 	return 0;
89 }
90 
91 static struct afbr_s50_platform_init_node timer_init_node = {
92 	.init_fn = timer_init,
93 };
94 
timer_platform_init_hooks(void)95 static int timer_platform_init_hooks(void)
96 {
97 	afbr_s50_platform_init_hooks_add(&timer_init_node);
98 
99 	return 0;
100 }
101 
102 SYS_INIT(timer_platform_init_hooks, POST_KERNEL, 0);
103