Skip to content

Commit 87abca1

Browse files
lstnlmeijemac
authored andcommitted
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 a81e33b commit 87abca1

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
@@ -369,17 +369,40 @@ uint64_t z_nrf_grtc_timer_startup_value_get(void)
369369
}
370370

371371
#if defined(CONFIG_POWEROFF)
372-
#if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER)
372+
static int32_t wakeup_channel = -1;
373+
374+
int32_t z_nrf_grtc_timer_wakeup_channel_get(void)
375+
{
376+
return wakeup_channel;
377+
}
378+
379+
void z_nrf_grtc_timer_disable_owned_cc_channels(int32_t reserved_channel)
380+
{
381+
uint32_t chan;
382+
383+
k_spinlock_key_t key = k_spin_lock(&lock);
384+
385+
for (uint32_t grtc_chan_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
386+
grtc_chan_mask > 0; grtc_chan_mask &= ~BIT(chan)) {
387+
/* Clear all GRTC channels except the reserved_channel. */
388+
chan = u32_count_trailing_zeros(grtc_chan_mask);
389+
if (chan != reserved_channel) {
390+
nrfx_grtc_syscounter_cc_disable(chan);
391+
}
392+
}
393+
k_spin_unlock(&lock, key);
394+
}
395+
373396
int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
374397
{
375-
nrfx_err_t err_code;
376398
static uint8_t systemoff_channel;
377399
uint64_t now = counter();
378-
nrfx_grtc_sleep_config_t sleep_cfg;
400+
int ret;
379401
/* Minimum time that ensures valid execution of system-off procedure. */
380402
uint32_t minimum_latency_us;
381-
uint32_t chan;
382-
int ret;
403+
404+
#if CONFIG_NRF_GRTC_START_SYSCOUNTER
405+
nrfx_grtc_sleep_config_t sleep_cfg;
383406

384407
nrfx_grtc_sleep_configuration_get(&sleep_cfg);
385408
minimum_latency_us = (sleep_cfg.waketime + sleep_cfg.timeout) *
@@ -388,34 +411,34 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
388411
sleep_cfg.auto_mode = false;
389412
nrfx_grtc_sleep_configure(&sleep_cfg);
390413

414+
#else
415+
minimum_latency_us = CONFIG_NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY;
416+
#endif
391417
if (minimum_latency_us > wake_time_us) {
392418
return -EINVAL;
393419
}
394420

395421
k_spinlock_key_t key = k_spin_lock(&lock);
396422

397-
err_code = nrfx_grtc_channel_alloc(&systemoff_channel);
423+
#if CONFIG_NRF_GRTC_TIMER_USE_SYSTEM_CHANNEL_TO_WAKEUP_FROM_SYSTEMOFF
424+
systemoff_channel = system_clock_channel_data.channel;
425+
#else
426+
nrfx_err_t err_code = nrfx_grtc_channel_alloc(&systemoff_channel);
398427
if (err_code != NRFX_SUCCESS) {
399428
k_spin_unlock(&lock, key);
400429
return -ENOMEM;
401430
}
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);
431+
#endif
432+
(void) nrfx_grtc_syscounter_cc_int_disable(systemoff_channel);
433+
int64_t delay = now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC;
434+
435+
ret = compare_set(systemoff_channel, delay, NULL, NULL);
406436
if (ret < 0) {
407437
k_spin_unlock(&lock, key);
408438
return ret;
409439
}
410440

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-
}
441+
z_nrf_grtc_timer_disable_owned_cc_channels(systemoff_channel);
419442

420443
/* Make sure that wake_time_us was not triggered yet. */
421444
if (nrfx_grtc_syscounter_compare_event_check(systemoff_channel)) {
@@ -424,98 +447,21 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
424447
}
425448

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

521467
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)