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