1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9 #include <zephyr/irq.h>
10 #if defined(CONFIG_CLOCK_CONTROL_NRF)
11 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
12 #endif
13 #include <zephyr/drivers/timer/system_timer.h>
14 #include <zephyr/drivers/timer/nrf_grtc_timer.h>
15 #include <nrfx_grtc.h>
16 #include <zephyr/sys/math_extras.h>
17 
18 #define GRTC_NODE DT_NODELABEL(grtc)
19 
20 /* Ensure that GRTC properties in devicetree are defined correctly. */
21 #if !DT_NODE_HAS_PROP(GRTC_NODE, owned_channels)
22 #error GRTC owned-channels DT property is not defined
23 #endif
24 #define OWNED_CHANNELS_MASK       NRFX_CONFIG_GRTC_MASK_DT(owned_channels)
25 #define CHILD_OWNED_CHANNELS_MASK NRFX_CONFIG_GRTC_MASK_DT(child_owned_channels)
26 #if ((OWNED_CHANNELS_MASK | CHILD_OWNED_CHANNELS_MASK) != OWNED_CHANNELS_MASK)
27 #error GRTC child-owned-channels DT property must be a subset of owned-channels
28 #endif
29 
30 #define CHAN_COUNT     NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS
31 #define EXT_CHAN_COUNT (CHAN_COUNT - 1)
32 /* The reset value of waketime is 1, which doesn't seem to work.
33  * It's being looked into, but for the time being use 4.
34  * Timeout must always be higher than waketime, so setting that to 5.
35  */
36 #define WAKETIME       (4)
37 #define TIMEOUT        (WAKETIME + 1)
38 
39 #ifndef GRTC_SYSCOUNTERL_VALUE_Msk
40 #define GRTC_SYSCOUNTERL_VALUE_Msk GRTC_SYSCOUNTER_SYSCOUNTERL_VALUE_Msk
41 #endif
42 
43 #ifndef GRTC_SYSCOUNTERH_VALUE_Msk
44 #define GRTC_SYSCOUNTERH_VALUE_Msk GRTC_SYSCOUNTER_SYSCOUNTERH_VALUE_Msk
45 #endif
46 
47 #define MAX_CC_LATCH_WAIT_TIME_US 77
48 
49 #define CYC_PER_TICK                                                                               \
50 	((uint64_t)sys_clock_hw_cycles_per_sec() / (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC)
51 
52 #define COUNTER_SPAN (GRTC_SYSCOUNTERL_VALUE_Msk | ((uint64_t)GRTC_SYSCOUNTERH_VALUE_Msk << 32))
53 #define MAX_TICKS                                                                                  \
54 	(((COUNTER_SPAN / CYC_PER_TICK) > INT_MAX) ? INT_MAX : (COUNTER_SPAN / CYC_PER_TICK))
55 
56 #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK)
57 
58 /* The maximum SYSCOUNTERVALID settling time equals 1x32k cycles + 20x1MHz cycles. */
59 #define GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US 51
60 
61 #if defined(CONFIG_TEST)
62 const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE);
63 #endif
64 
65 static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_context);
66 
67 static struct k_spinlock lock;
68 static uint64_t last_count;
69 static atomic_t int_mask;
70 static uint8_t ext_channels_allocated;
71 static nrfx_grtc_channel_t system_clock_channel_data = {
72 	.handler = sys_clock_timeout_handler,
73 	.p_context = NULL,
74 	.channel = (uint8_t)-1,
75 };
76 
77 #define IS_CHANNEL_ALLOWED_ASSERT(chan)                                                            \
78 	__ASSERT_NO_MSG((NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK & (1UL << (chan))) &&           \
79 			((chan) != system_clock_channel_data.channel))
80 
grtc_active_set(void)81 static inline void grtc_active_set(void)
82 {
83 #if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1)
84 	nrfy_grtc_sys_counter_active_set(NRF_GRTC, true);
85 	while (!nrfy_grtc_sys_conter_ready_check(NRF_GRTC)) {
86 	}
87 #else
88 	nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, true);
89 	k_busy_wait(GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US);
90 #endif
91 }
92 
grtc_wakeup(void)93 static inline void grtc_wakeup(void)
94 {
95 	if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
96 		grtc_active_set();
97 	}
98 }
99 
grtc_sleep(void)100 static inline void grtc_sleep(void)
101 {
102 	if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
103 #if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1)
104 		nrfy_grtc_sys_counter_active_set(NRF_GRTC, false);
105 #else
106 		nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, false);
107 #endif
108 	}
109 }
110 
counter_sub(uint64_t a,uint64_t b)111 static inline uint64_t counter_sub(uint64_t a, uint64_t b)
112 {
113 	return (a - b);
114 }
115 
counter(void)116 static inline uint64_t counter(void)
117 {
118 	uint64_t now;
119 
120 	grtc_wakeup();
121 	nrfx_grtc_syscounter_get(&now);
122 	grtc_sleep();
123 	return now;
124 }
125 
get_comparator(uint32_t chan)126 static inline uint64_t get_comparator(uint32_t chan)
127 {
128 	uint64_t cc;
129 	nrfx_err_t result;
130 
131 	result = nrfx_grtc_syscounter_cc_value_read(chan, &cc);
132 	if (result != NRFX_SUCCESS) {
133 		if (result != NRFX_ERROR_INVALID_PARAM) {
134 			return -EAGAIN;
135 		}
136 		return -EPERM;
137 	}
138 	return cc;
139 }
140 
system_timeout_set(uint64_t value)141 static void system_timeout_set(uint64_t value)
142 {
143 	if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) {
144 		grtc_wakeup();
145 		nrfx_grtc_syscounter_cc_relative_set(&system_clock_channel_data, value, true,
146 						     NRFX_GRTC_CC_RELATIVE_SYSCOUNTER);
147 		grtc_sleep();
148 	} else {
149 		nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value + counter(),
150 						     true);
151 	}
152 }
153 
compare_int_lock(int32_t chan)154 static bool compare_int_lock(int32_t chan)
155 {
156 	atomic_val_t prev = atomic_and(&int_mask, ~BIT(chan));
157 
158 	nrfx_grtc_syscounter_cc_int_disable(chan);
159 
160 	return prev & BIT(chan);
161 }
162 
compare_int_unlock(int32_t chan,bool key)163 static void compare_int_unlock(int32_t chan, bool key)
164 {
165 	if (key) {
166 		atomic_or(&int_mask, BIT(chan));
167 		nrfx_grtc_syscounter_cc_int_enable(chan);
168 	}
169 }
170 
sys_clock_timeout_handler(int32_t id,uint64_t cc_val,void * p_context)171 static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_context)
172 {
173 	ARG_UNUSED(id);
174 	ARG_UNUSED(p_context);
175 	uint64_t dticks;
176 	uint64_t now = counter();
177 
178 	if (unlikely(now < cc_val)) {
179 		return;
180 	}
181 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
182 		/* protection is not needed because we are in the GRTC interrupt
183 		 * so it won't get preempted by the interrupt.
184 		 */
185 		system_timeout_set(CYC_PER_TICK);
186 	}
187 
188 	dticks = counter_sub(now, last_count) / CYC_PER_TICK;
189 
190 	last_count += dticks * CYC_PER_TICK;
191 	sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? (int32_t)dticks : (dticks > 0));
192 }
193 
z_nrf_grtc_timer_chan_alloc(void)194 int32_t z_nrf_grtc_timer_chan_alloc(void)
195 {
196 	uint8_t chan;
197 	nrfx_err_t err_code;
198 
199 	/* Prevent allocating all available channels - one must be left for system purposes. */
200 	if (ext_channels_allocated >= EXT_CHAN_COUNT) {
201 		return -ENOMEM;
202 	}
203 	err_code = nrfx_grtc_channel_alloc(&chan);
204 	if (err_code != NRFX_SUCCESS) {
205 		return -ENOMEM;
206 	}
207 	ext_channels_allocated++;
208 	return (int32_t)chan;
209 }
210 
z_nrf_grtc_timer_chan_free(int32_t chan)211 void z_nrf_grtc_timer_chan_free(int32_t chan)
212 {
213 	IS_CHANNEL_ALLOWED_ASSERT(chan);
214 	nrfx_err_t err_code = nrfx_grtc_channel_free(chan);
215 
216 	if (err_code == NRFX_SUCCESS) {
217 		ext_channels_allocated--;
218 	}
219 }
220 
z_nrf_grtc_timer_compare_evt_check(int32_t chan)221 bool z_nrf_grtc_timer_compare_evt_check(int32_t chan)
222 {
223 	IS_CHANNEL_ALLOWED_ASSERT(chan);
224 
225 	uint32_t event_address = nrfx_grtc_event_compare_address_get(chan);
226 
227 	return *(volatile uint32_t *)event_address != 0;
228 }
229 
z_nrf_grtc_timer_compare_evt_address_get(int32_t chan)230 uint32_t z_nrf_grtc_timer_compare_evt_address_get(int32_t chan)
231 {
232 	IS_CHANNEL_ALLOWED_ASSERT(chan);
233 
234 	return nrfx_grtc_event_compare_address_get(chan);
235 }
236 
z_nrf_grtc_timer_capture_task_address_get(int32_t chan)237 uint32_t z_nrf_grtc_timer_capture_task_address_get(int32_t chan)
238 {
239 	IS_CHANNEL_ALLOWED_ASSERT(chan);
240 
241 	return nrfx_grtc_capture_task_address_get(chan);
242 }
243 
z_nrf_grtc_timer_read(void)244 uint64_t z_nrf_grtc_timer_read(void)
245 {
246 	return counter();
247 }
248 
z_nrf_grtc_timer_compare_int_lock(int32_t chan)249 bool z_nrf_grtc_timer_compare_int_lock(int32_t chan)
250 {
251 	IS_CHANNEL_ALLOWED_ASSERT(chan);
252 
253 	return compare_int_lock(chan);
254 }
255 
z_nrf_grtc_timer_compare_int_unlock(int32_t chan,bool key)256 void z_nrf_grtc_timer_compare_int_unlock(int32_t chan, bool key)
257 {
258 	IS_CHANNEL_ALLOWED_ASSERT(chan);
259 
260 	compare_int_unlock(chan, key);
261 }
262 
z_nrf_grtc_timer_compare_read(int32_t chan)263 uint64_t z_nrf_grtc_timer_compare_read(int32_t chan)
264 {
265 	IS_CHANNEL_ALLOWED_ASSERT(chan);
266 
267 	return get_comparator(chan);
268 }
269 
compare_set_nolocks(int32_t chan,uint64_t target_time,z_nrf_grtc_timer_compare_handler_t handler,void * user_data)270 static int compare_set_nolocks(int32_t chan, uint64_t target_time,
271 			       z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
272 {
273 	nrfx_err_t result;
274 
275 	__ASSERT_NO_MSG(target_time < COUNTER_SPAN);
276 	nrfx_grtc_channel_t user_channel_data = {
277 		.handler = handler,
278 		.p_context = user_data,
279 		.channel = chan,
280 	};
281 	result = nrfx_grtc_syscounter_cc_absolute_set(&user_channel_data, target_time, true);
282 	if (result != NRFX_SUCCESS) {
283 		return -EPERM;
284 	}
285 	return 0;
286 }
287 
compare_set(int32_t chan,uint64_t target_time,z_nrf_grtc_timer_compare_handler_t handler,void * user_data)288 static int compare_set(int32_t chan, uint64_t target_time,
289 		       z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
290 {
291 	bool key = compare_int_lock(chan);
292 	int ret = compare_set_nolocks(chan, target_time, handler, user_data);
293 
294 	compare_int_unlock(chan, key);
295 
296 	return ret;
297 }
298 
z_nrf_grtc_timer_set(int32_t chan,uint64_t target_time,z_nrf_grtc_timer_compare_handler_t handler,void * user_data)299 int z_nrf_grtc_timer_set(int32_t chan, uint64_t target_time,
300 			 z_nrf_grtc_timer_compare_handler_t handler, void *user_data)
301 {
302 	IS_CHANNEL_ALLOWED_ASSERT(chan);
303 
304 	return compare_set(chan, target_time, (nrfx_grtc_cc_handler_t)handler, user_data);
305 }
306 
z_nrf_grtc_timer_abort(int32_t chan)307 void z_nrf_grtc_timer_abort(int32_t chan)
308 {
309 	IS_CHANNEL_ALLOWED_ASSERT(chan);
310 
311 	bool key = compare_int_lock(chan);
312 	(void)nrfx_grtc_syscounter_cc_disable(chan);
313 	compare_int_unlock(chan, key);
314 }
315 
z_nrf_grtc_timer_get_ticks(k_timeout_t t)316 uint64_t z_nrf_grtc_timer_get_ticks(k_timeout_t t)
317 {
318 	uint64_t curr_time;
319 	int64_t curr_tick;
320 	int64_t result;
321 	int64_t abs_ticks;
322 
323 	curr_time = counter();
324 	curr_tick = sys_clock_tick_get();
325 
326 	abs_ticks = Z_TICK_ABS(t.ticks);
327 	if (abs_ticks < 0) {
328 		/* relative timeout */
329 		return (t.ticks > (int64_t)COUNTER_SPAN) ? -EINVAL : (curr_time + t.ticks);
330 	}
331 
332 	/* absolute timeout */
333 	result = abs_ticks - curr_tick;
334 
335 	if (result > (int64_t)COUNTER_SPAN) {
336 		return -EINVAL;
337 	}
338 
339 	return curr_time + result;
340 }
341 
z_nrf_grtc_timer_capture_prepare(int32_t chan)342 int z_nrf_grtc_timer_capture_prepare(int32_t chan)
343 {
344 	nrfx_grtc_channel_t user_channel_data = {
345 		.handler = NULL,
346 		.p_context = NULL,
347 		.channel = chan,
348 	};
349 	nrfx_err_t result;
350 
351 	IS_CHANNEL_ALLOWED_ASSERT(chan);
352 
353 	/* Set the CC value to mark channel as not triggered and also to enable it
354 	 * (makes CCEN=1). COUNTER_SPAN is used so as not to fire an event unnecessarily
355 	 * - it can be assumed that such a large value will never be reached.
356 	 */
357 	result = nrfx_grtc_syscounter_cc_absolute_set(&user_channel_data, COUNTER_SPAN, false);
358 
359 	if (result != NRFX_SUCCESS) {
360 		return -EPERM;
361 	}
362 
363 	return 0;
364 }
365 
z_nrf_grtc_timer_capture_read(int32_t chan,uint64_t * captured_time)366 int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time)
367 {
368 	/* TODO: The implementation should probably go to nrfx_grtc and this
369 	 *       should be just a wrapper for some nrfx_grtc_syscounter_capture_read.
370 	 */
371 
372 	uint64_t capt_time;
373 
374 	IS_CHANNEL_ALLOWED_ASSERT(chan);
375 
376 	/* TODO: Use `nrfy_grtc_sys_counter_enable_check` when available (NRFX-2480) */
377 	if (NRF_GRTC->CC[chan].CCEN == GRTC_CC_CCEN_ACTIVE_Enable) {
378 		/* If the channel is enabled (.CCEN), it means that there was no capture
379 		 * triggering event.
380 		 */
381 		return -EBUSY;
382 	}
383 
384 	capt_time = nrfy_grtc_sys_counter_cc_get(NRF_GRTC, chan);
385 
386 	__ASSERT_NO_MSG(capt_time < COUNTER_SPAN);
387 
388 	*captured_time = capt_time;
389 
390 	return 0;
391 }
392 
393 #if defined(CONFIG_NRF_GRTC_SLEEP_ALLOWED)
z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)394 int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
395 {
396 	nrfx_err_t err_code;
397 	static uint8_t systemoff_channel;
398 	uint64_t now = counter();
399 	/* Minimum time that ensures valid execution of system-off procedure. */
400 	uint32_t minimum_latency_us = nrfy_grtc_waketime_get(NRF_GRTC) +
401 				      nrfy_grtc_timeout_get(NRF_GRTC) +
402 				      CONFIG_NRF_GRTC_SLEEP_MINIMUM_LATENCY;
403 	uint32_t chan;
404 	int ret;
405 
406 	if (minimum_latency_us > wake_time_us) {
407 		return -EINVAL;
408 	}
409 	k_spinlock_key_t key = k_spin_lock(&lock);
410 
411 	err_code = nrfx_grtc_channel_alloc(&systemoff_channel);
412 	if (err_code != NRFX_SUCCESS) {
413 		k_spin_unlock(&lock, key);
414 		return -ENOMEM;
415 	}
416 	(void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel);
417 	ret = compare_set(systemoff_channel, now + wake_time_us, NULL, NULL);
418 	if (ret < 0) {
419 		k_spin_unlock(&lock, key);
420 		return ret;
421 	}
422 
423 	for (uint32_t grtc_chan_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
424 	     grtc_chan_mask > 0; grtc_chan_mask &= ~BIT(chan)) {
425 		/* Clear all GRTC channels except the systemoff_channel. */
426 		chan = u32_count_trailing_zeros(grtc_chan_mask);
427 		if (chan != systemoff_channel) {
428 			nrfx_grtc_syscounter_cc_disable(chan);
429 		}
430 	}
431 
432 	/* Make sure that wake_time_us was not triggered yet. */
433 	if (nrfy_grtc_sys_counter_compare_event_check(NRF_GRTC, systemoff_channel)) {
434 		k_spin_unlock(&lock, key);
435 		return -EINVAL;
436 	}
437 
438 	/* This mechanism ensures that stored CC value is latched. */
439 	uint32_t wait_time =
440 		nrfy_grtc_timeout_get(NRF_GRTC) * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 32768 +
441 		MAX_CC_LATCH_WAIT_TIME_US;
442 	k_busy_wait(wait_time);
443 #if NRF_GRTC_HAS_CLKSEL
444 	nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFXO);
445 #endif
446 	k_spin_unlock(&lock, key);
447 	return 0;
448 }
449 #endif /* CONFIG_NRF_GRTC_SLEEP_ALLOWED */
450 
sys_clock_cycle_get_32(void)451 uint32_t sys_clock_cycle_get_32(void)
452 {
453 	k_spinlock_key_t key = k_spin_lock(&lock);
454 	uint32_t ret = (uint32_t)counter();
455 
456 	k_spin_unlock(&lock, key);
457 	return ret;
458 }
459 
sys_clock_cycle_get_64(void)460 uint64_t sys_clock_cycle_get_64(void)
461 {
462 	k_spinlock_key_t key = k_spin_lock(&lock);
463 	uint64_t ret = counter();
464 
465 	k_spin_unlock(&lock, key);
466 	return ret;
467 }
468 
sys_clock_elapsed(void)469 uint32_t sys_clock_elapsed(void)
470 {
471 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
472 		return 0;
473 	}
474 
475 	return (uint32_t)(counter_sub(counter(), last_count) / CYC_PER_TICK);
476 }
477 
sys_clock_driver_init(void)478 static int sys_clock_driver_init(void)
479 {
480 	nrfx_err_t err_code;
481 
482 #if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) &&                                             \
483 	(defined(NRF_GRTC_HAS_CLKSEL) && (NRF_GRTC_HAS_CLKSEL == 1))
484 	/* Use System LFCLK as the low-frequency clock source. */
485 	nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFCLK);
486 #endif
487 
488 #if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER)
489 	/* SYSCOUNTER needs to be turned off before initialization. */
490 	nrfy_grtc_sys_counter_set(NRF_GRTC, false);
491 	nrfy_grtc_timeout_set(NRF_GRTC, TIMEOUT);
492 	nrfy_grtc_waketime_set(NRF_GRTC, WAKETIME);
493 #endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */
494 
495 	IRQ_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), nrfx_grtc_irq_handler, 0, 0);
496 
497 	err_code = nrfx_grtc_init(0);
498 	if (err_code != NRFX_SUCCESS) {
499 		return -EPERM;
500 	}
501 
502 #if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER)
503 	err_code = nrfx_grtc_syscounter_start(true, &system_clock_channel_data.channel);
504 	if (err_code != NRFX_SUCCESS) {
505 		return err_code == NRFX_ERROR_NO_MEM ? -ENOMEM : -EPERM;
506 	}
507 	if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
508 		nrfy_grtc_sys_counter_auto_mode_set(NRF_GRTC, false);
509 	}
510 #else
511 	err_code = nrfx_grtc_channel_alloc(&system_clock_channel_data.channel);
512 	if (err_code != NRFX_SUCCESS) {
513 		return -ENOMEM;
514 	}
515 #endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */
516 
517 	if (!IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) {
518 		grtc_active_set();
519 	}
520 
521 	int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
522 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
523 		system_timeout_set(CYC_PER_TICK);
524 	}
525 
526 #if defined(CONFIG_CLOCK_CONTROL_NRF)
527 	static const enum nrf_lfclk_start_mode mode =
528 		IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT)
529 			? CLOCK_CONTROL_NRF_LF_START_NOWAIT
530 			: (IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY)
531 				   ? CLOCK_CONTROL_NRF_LF_START_AVAILABLE
532 				   : CLOCK_CONTROL_NRF_LF_START_STABLE);
533 
534 	z_nrf_clock_control_lf_on(mode);
535 #endif
536 
537 	return 0;
538 }
539 
sys_clock_set_timeout(int32_t ticks,bool idle)540 void sys_clock_set_timeout(int32_t ticks, bool idle)
541 {
542 	ARG_UNUSED(idle);
543 	uint64_t cyc, off, now;
544 
545 	if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
546 		return;
547 	}
548 
549 	ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : MIN(MAX_TICKS, MAX(ticks - 1, 0));
550 
551 	now = counter();
552 
553 	/* Round up to the next tick boundary */
554 	off = (now - last_count) + (CYC_PER_TICK - 1);
555 	off = (off / CYC_PER_TICK) * CYC_PER_TICK;
556 
557 	/* Get the offset with respect to now */
558 	off -= (now - last_count);
559 
560 	/* Add the offset to get to the next tick boundary */
561 	cyc = (uint64_t)ticks * CYC_PER_TICK + off;
562 
563 	/* Due to elapsed time the calculation above might produce a
564 	 * duration that laps the counter.  Don't let it.
565 	 */
566 	if (cyc > MAX_CYCLES) {
567 		cyc = MAX_CYCLES;
568 	}
569 
570 	system_timeout_set(cyc == 0 ? 1 : cyc);
571 }
572 
573 #if defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT)
nrf_grtc_timer_clock_driver_init(void)574 int nrf_grtc_timer_clock_driver_init(void)
575 {
576 	return sys_clock_driver_init();
577 }
578 #else
579 SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
580 #endif
581