Skip to content

Commit d56bdd4

Browse files
committed
drivers: grtc timer added support for system off for nrf54h20
Added option to use system channel for setup wakeup from soft off. In Lilium there is insuficcient grtc channels and no spare channel that can be used as wake up source. Added function to disable all grtc channels, except the one used for wake up to be able to enter soft off stated on local domain (disable uncexpected grtc wake ups). Signed-off-by: Łukasz Stępnicki <[email protected]>
1 parent 852da8d commit d56bdd4

File tree

4 files changed

+79
-103
lines changed

4 files changed

+79
-103
lines changed

drivers/timer/Kconfig.nrf_grtc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,11 @@ config NRF_GRTC_TIMER_AUTO_KEEP_ALIVE
5656
This feature prevents the SYSCOUNTER from sleeping when any core is in
5757
active state.
5858

59+
config NRF_GRTC_TIMER_USE_SYSTEM_CHANNEL_TO_WAKEUP_FROM_SYSTEMOFF
60+
bool
61+
depends on POWEROFF
62+
default y if SOC_NRF54H20
63+
help
64+
Use system channel to schedule wake up time.
65+
5966
endif # NRF_GRTC_TIMER

drivers/timer/nrf_grtc_timer.c

Lines changed: 49 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -365,17 +365,40 @@ uint64_t z_nrf_grtc_timer_startup_value_get(void)
365365
}
366366

367367
#if defined(CONFIG_POWEROFF)
368-
#if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER)
368+
static int32_t wakeup_channel = -1;
369+
370+
int32_t z_nrf_grtc_timer_wakeup_channel_get(void)
371+
{
372+
return wakeup_channel;
373+
}
374+
375+
void z_nrf_grtc_timer_disable_owned_cc_channels(int32_t reserved_channel)
376+
{
377+
uint32_t chan;
378+
379+
k_spinlock_key_t key = k_spin_lock(&lock);
380+
381+
for (uint32_t grtc_chan_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
382+
grtc_chan_mask > 0; grtc_chan_mask &= ~BIT(chan)) {
383+
/* Clear all GRTC channels except the reserved_channel. */
384+
chan = u32_count_trailing_zeros(grtc_chan_mask);
385+
if (chan != reserved_channel) {
386+
nrfx_grtc_syscounter_cc_disable(chan);
387+
}
388+
}
389+
k_spin_unlock(&lock, key);
390+
}
391+
369392
int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
370393
{
371-
nrfx_err_t err_code;
372394
static uint8_t systemoff_channel;
373395
uint64_t now = counter();
374-
nrfx_grtc_sleep_config_t sleep_cfg;
396+
int ret;
375397
/* Minimum time that ensures valid execution of system-off procedure. */
376398
uint32_t minimum_latency_us;
377-
uint32_t chan;
378-
int ret;
399+
400+
#if CONFIG_NRF_GRTC_START_SYSCOUNTER
401+
nrfx_grtc_sleep_config_t sleep_cfg;
379402

380403
nrfx_grtc_sleep_configuration_get(&sleep_cfg);
381404
minimum_latency_us = (sleep_cfg.waketime + sleep_cfg.timeout) *
@@ -384,34 +407,34 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
384407
sleep_cfg.auto_mode = false;
385408
nrfx_grtc_sleep_configure(&sleep_cfg);
386409

410+
#else
411+
minimum_latency_us = CONFIG_NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY;
412+
#endif
387413
if (minimum_latency_us > wake_time_us) {
388414
return -EINVAL;
389415
}
390416

391417
k_spinlock_key_t key = k_spin_lock(&lock);
392418

393-
err_code = nrfx_grtc_channel_alloc(&systemoff_channel);
419+
#if CONFIG_NRF_GRTC_TIMER_USE_SYSTEM_CHANNEL_TO_WAKEUP_FROM_SYSTEMOFF
420+
systemoff_channel = system_clock_channel_data.channel;
421+
#else
422+
nrfx_err_t err_code = nrfx_grtc_channel_alloc(&systemoff_channel);
394423
if (err_code != NRFX_SUCCESS) {
395424
k_spin_unlock(&lock, key);
396425
return -ENOMEM;
397426
}
398-
(void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel);
399-
ret = compare_set(systemoff_channel,
400-
now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC, NULL,
401-
NULL);
427+
#endif
428+
(void) nrfx_grtc_syscounter_cc_int_disable(systemoff_channel);
429+
int64_t delay = now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC;
430+
431+
ret = compare_set(systemoff_channel, delay, NULL, NULL);
402432
if (ret < 0) {
403433
k_spin_unlock(&lock, key);
404434
return ret;
405435
}
406436

407-
for (uint32_t grtc_chan_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
408-
grtc_chan_mask > 0; grtc_chan_mask &= ~BIT(chan)) {
409-
/* Clear all GRTC channels except the systemoff_channel. */
410-
chan = u32_count_trailing_zeros(grtc_chan_mask);
411-
if (chan != systemoff_channel) {
412-
nrfx_grtc_syscounter_cc_disable(chan);
413-
}
414-
}
437+
z_nrf_grtc_timer_disable_owned_cc_channels(systemoff_channel);
415438

416439
/* Make sure that wake_time_us was not triggered yet. */
417440
if (nrfx_grtc_syscounter_compare_event_check(systemoff_channel)) {
@@ -420,98 +443,21 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
420443
}
421444

422445
/* This mechanism ensures that stored CC value is latched. */
446+
#if CONFIG_NRF_GRTC_START_SYSCOUNTER
423447
uint32_t wait_time =
424448
nrfy_grtc_timeout_get(NRF_GRTC) * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 32768 +
425449
MAX_CC_LATCH_WAIT_TIME_US;
426-
k_busy_wait(wait_time);
427-
k_spin_unlock(&lock, key);
428-
return 0;
429-
}
430450
#else
431-
int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
432-
{
433-
//nrfx_err_t err_code;
434-
//static uint8_t systemoff_channel;
435-
//uint64_t now = counter();
436-
//nrfx_grtc_sleep_config_t sleep_cfg;
437-
/* Minimum time that ensures valid execution of system-off procedure. */
438-
//uint32_t minimum_latency_us;
439-
uint32_t chan;
440-
//int ret;
441-
442-
// nrfx_grtc_sleep_configuration_get(&sleep_cfg);
443-
// minimum_latency_us =
444-
// (sleep_cfg.waketime + sleep_cfg.timeout) * USEC_PER_SEC / LFCLK_FREQUENCY_HZ +
445-
// CONFIG_NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY;
446-
// sleep_cfg.auto_mode = false;
447-
// nrfx_grtc_sleep_configure(&sleep_cfg);
448-
449-
// if (minimum_latency_us > wake_time_us) {
450-
// return -EINVAL;
451-
// }
452-
453-
//k_spinlock_key_t key = k_spin_lock(&lock);
454-
455-
// err_code = nrfx_grtc_channel_alloc(&systemoff_channel);
456-
// if (err_code != NRFX_SUCCESS) {
457-
// k_spin_unlock(&lock, key);
458-
// return -ENOMEM;
459-
// }
460-
//(void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel);
461-
// ret = compare_set(systemoff_channel,
462-
// now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC, NULL,
463-
// NULL);
464-
// if (ret < 0) {
465-
// k_spin_unlock(&lock, key);
466-
// return ret;
467-
// }
468-
// for (uint32_t grtc_chan_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
469-
for (uint32_t grtc_chan_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
470-
grtc_chan_mask > 0; grtc_chan_mask &= ~BIT(chan)) {
471-
/* Clear all GRTC channels except the systemoff_channel. */
472-
chan = u32_count_trailing_zeros(grtc_chan_mask);
473-
// if (chan != systemoff_channel) {
474-
nrfx_grtc_syscounter_cc_disable(chan);
475-
//}
476-
}
477-
#if 0
478-
#if defined(CONFIG_SOC_NRF54H20_CPUAPP)
479-
for (uint32_t grtc_chan_mask = 0x70;
480-
grtc_chan_mask > 0; grtc_chan_mask &= ~BIT(chan)) {
481-
/* Clear all GRTC channels except the systemoff_channel. */
482-
chan = u32_count_trailing_zeros(grtc_chan_mask);
483-
// if (chan != systemoff_channel) {
484-
nrfx_grtc_syscounter_cc_disable(chan);
485-
// }
486-
}
487-
#endif
488-
#if defined(CONFIG_SOC_NRF54H20_CPURAD)
489-
//for (uint32_t grtc_chan_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
490-
for (uint32_t grtc_chan_mask = 0xFF80;
491-
grtc_chan_mask > 0; grtc_chan_mask &= ~BIT(chan)) {
492-
/* Clear all GRTC channels except the systemoff_channel. */
493-
chan = u32_count_trailing_zeros(grtc_chan_mask);
494-
//if (chan != systemoff_channel) {
495-
nrfx_grtc_syscounter_cc_disable(chan);
496-
//}
497-
}
451+
uint32_t wait_time = MAX_CC_LATCH_WAIT_TIME_US;
498452
#endif
499-
#endif
500-
// /* Make sure that wake_time_us was not triggered yet. */
501-
// if (nrfx_grtc_syscounter_compare_event_check(systemoff_channel)) {
502-
// k_spin_unlock(&lock, key);
503-
// return -EINVAL;
504-
// }
505-
506-
// /* This mechanism ensures that stored CC value is latched. */
507-
//uint32_t wait_time =
508-
// nrfy_grtc_timeout_get(NRF_GRTC) * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 32768 +
509-
// MAX_CC_LATCH_WAIT_TIME_US;
510-
k_busy_wait(1000);
511-
// k_spin_unlock(&lock, key);
453+
/* Wait until the CC value is latched. */
454+
k_busy_wait(wait_time);
455+
k_spin_unlock(&lock, key);
456+
457+
wakeup_channel = systemoff_channel;
458+
512459
return 0;
513460
}
514-
#endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */
515461
#endif /* CONFIG_POWEROFF */
516462

517463
uint32_t sys_clock_cycle_get_32(void)

include/zephyr/drivers/timer/nrf_grtc_timer.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,24 @@ int z_nrf_grtc_timer_capture_prepare(int32_t chan);
175175
*/
176176
int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time);
177177

178+
/** @brief Get the channel used for wakeup from system-off.
179+
*
180+
* @return Channel ID or -1 if no channel is reserved for that purpose.
181+
*/
182+
int32_t z_nrf_grtc_timer_wakeup_channel_get(void);
183+
184+
/** @brief Disable all owned compare channels except the one specified.
185+
*
186+
* This function is used when preparing the system to enter system-off mode.
187+
* It disables all compare channels owned by the driver except the one
188+
* specified by @p reserved_channel. The reserved channel is typically used
189+
* for wake-up from system-off.
190+
* @param reserved_channel Channel ID to remain enabled.
191+
*
192+
* @note Set @p reserved_channel to -1 to disable all owned channels.
193+
*/
194+
void z_nrf_grtc_timer_disable_owned_cc_channels(int32_t reserved_channel);
195+
178196
/** @brief Prepare GRTC as a source of wake up event and set the wake up time.
179197
*
180198
* @note Calling this function should be immediately followed by low-power mode enter

soc/nordic/nrf54h/power.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <zephyr/toolchain.h>
99
#include <zephyr/pm/policy.h>
1010
#include <zephyr/arch/common/pm_s2ram.h>
11+
#include <zephyr/drivers/timer/nrf_grtc_timer.h>
1112
#include <hal/nrf_resetinfo.h>
1213
#include <hal/nrf_memconf.h>
1314
#include <zephyr/cache.h>
@@ -82,6 +83,10 @@ void nrf_poweroff(void)
8283
#endif
8384
common_suspend();
8485

86+
/* Disable all owned compare channels except the one used for wakeup from system-off. */
87+
z_nrf_grtc_timer_disable_owned_cc_channels(z_nrf_grtc_timer_wakeup_channel_get());
88+
89+
/* Indicate that we are ready for system off. */
8590
nrf_lrcconf_task_trigger(NRF_LRCCONF010, NRF_LRCCONF_TASK_SYSTEMOFFREADY);
8691

8792
__set_BASEPRI(0);

0 commit comments

Comments
 (0)