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