From cac0da313b238a746acc2d998d40aac54ad040c3 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Tue, 19 Dec 2023 15:25:08 +0100 Subject: [PATCH] drivers: timer: grtc: Update GRTC driver This commit aligns the GRTC driver to changes introduced in hal_nordic. Some of the features regarding GRTC sleep/wakeup functionality has been modified and moved out to the nrfx driver's code. Signed-off-by: Adam Kondraciuk --- drivers/timer/Kconfig.nrf_grtc | 13 ++- drivers/timer/nrf_grtc_timer.c | 88 +++++-------------- include/zephyr/drivers/timer/nrf_grtc_timer.h | 1 + modules/hal_nordic/nrfx/CMakeLists.txt | 4 - modules/hal_nordic/nrfx/nrfx_config.h | 13 +++ 5 files changed, 48 insertions(+), 71 deletions(-) diff --git a/drivers/timer/Kconfig.nrf_grtc b/drivers/timer/Kconfig.nrf_grtc index 0436c071fa2..cda39ae8b1c 100644 --- a/drivers/timer/Kconfig.nrf_grtc +++ b/drivers/timer/Kconfig.nrf_grtc @@ -41,9 +41,20 @@ config NRF_GRTC_TIMER_CLOCK_MANAGEMENT the GRTC. Usually this is only needed by the processor that is starting the SYSCOUNTER, but can be shared by multiple processors in the system. -config NRF_GRTC_SLEEP_MINIMUM_LATENCY +config NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY int default 1000 depends on NRF_GRTC_SLEEP_ALLOWED + help + The value (in us) ensures that the wakeup event will not fire + too early. In other words, applying SYSCOUNTER sleep state for less than + NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY period makes no sense. + +config NRF_GRTC_TIMER_AUTO_KEEP_ALIVE + bool + default y if NRF_GRTC_START_SYSCOUNTER + help + This feature prevents the SYSCOUNTER to sleep when any core is in + active state. endif # NRF_GRTC_TIMER diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 45cd2212bc8..8c1c927b142 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -29,12 +29,6 @@ #define CHAN_COUNT NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS #define EXT_CHAN_COUNT (CHAN_COUNT - 1) -/* The reset value of waketime is 1, which doesn't seem to work. - * It's being looked into, but for the time being use 4. - * Timeout must always be higher than waketime, so setting that to 5. - */ -#define WAKETIME (4) -#define TIMEOUT (WAKETIME + 1) #ifndef GRTC_SYSCOUNTERL_VALUE_Msk #define GRTC_SYSCOUNTERL_VALUE_Msk GRTC_SYSCOUNTER_SYSCOUNTERL_VALUE_Msk @@ -55,8 +49,7 @@ #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) -/* The maximum SYSCOUNTERVALID settling time equals 1x32k cycles + 20x1MHz cycles. */ -#define GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US 51 +#define LFCLK_FREQUENCY_HZ 32768 #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); @@ -78,36 +71,6 @@ static nrfx_grtc_channel_t system_clock_channel_data = { __ASSERT_NO_MSG((NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK & (1UL << (chan))) && \ ((chan) != system_clock_channel_data.channel)) -static inline void grtc_active_set(void) -{ -#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1) - nrfy_grtc_sys_counter_active_set(NRF_GRTC, true); - while (!nrfy_grtc_sys_conter_ready_check(NRF_GRTC)) { - } -#else - nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, true); - k_busy_wait(GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US); -#endif -} - -static inline void grtc_wakeup(void) -{ - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - grtc_active_set(); - } -} - -static inline void grtc_sleep(void) -{ - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { -#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1) - nrfy_grtc_sys_counter_active_set(NRF_GRTC, false); -#else - nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, false); -#endif - } -} - static inline uint64_t counter_sub(uint64_t a, uint64_t b) { return (a - b); @@ -116,10 +79,7 @@ static inline uint64_t counter_sub(uint64_t a, uint64_t b) static inline uint64_t counter(void) { uint64_t now; - - grtc_wakeup(); nrfx_grtc_syscounter_get(&now); - grtc_sleep(); return now; } @@ -143,10 +103,8 @@ static inline int get_comparator(uint32_t chan, uint64_t *cc) static void system_timeout_set_relative(uint64_t value) { if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) { - grtc_wakeup(); nrfx_grtc_syscounter_cc_relative_set(&system_clock_channel_data, value, true, NRFX_GRTC_CC_RELATIVE_SYSCOUNTER); - grtc_sleep(); } else { nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value + counter(), true); @@ -386,6 +344,7 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) */ uint64_t capt_time; + nrfx_err_t result; IS_CHANNEL_ALLOWED_ASSERT(chan); @@ -396,8 +355,10 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) */ return -EBUSY; } - - capt_time = nrfy_grtc_sys_counter_cc_get(NRF_GRTC, chan); + result = nrfx_grtc_syscounter_cc_value_read(chan, &capt_time); + if (result != NRFX_SUCCESS) { + return -EPERM; + } __ASSERT_NO_MSG(capt_time < COUNTER_SPAN); @@ -412,16 +373,23 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) nrfx_err_t err_code; static uint8_t systemoff_channel; uint64_t now = counter(); + nrfx_grtc_sleep_config_t sleep_cfg; /* Minimum time that ensures valid execution of system-off procedure. */ - uint32_t minimum_latency_us = nrfy_grtc_waketime_get(NRF_GRTC) + - nrfy_grtc_timeout_get(NRF_GRTC) + - CONFIG_NRF_GRTC_SLEEP_MINIMUM_LATENCY; + uint32_t minimum_latency_us; uint32_t chan; int ret; + nrfx_grtc_sleep_configuration_get(&sleep_cfg); + minimum_latency_us = (sleep_cfg.waketime + sleep_cfg.timeout) * + USEC_PER_SEC / LFCLK_FREQUENCY_HZ + + CONFIG_NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY; + sleep_cfg.auto_mode = false; + nrfx_grtc_sleep_configure(&sleep_cfg); + if (minimum_latency_us > wake_time_us) { return -EINVAL; } + k_spinlock_key_t key = k_spin_lock(&lock); err_code = nrfx_grtc_channel_alloc(&systemoff_channel); @@ -430,7 +398,9 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) return -ENOMEM; } (void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel); - ret = compare_set(systemoff_channel, now + wake_time_us, NULL, NULL); + ret = compare_set(systemoff_channel, + now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC, NULL, + NULL); if (ret < 0) { k_spin_unlock(&lock, key); return ret; @@ -446,7 +416,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) } /* Make sure that wake_time_us was not triggered yet. */ - if (nrfy_grtc_sys_counter_compare_event_check(NRF_GRTC, systemoff_channel)) { + if (nrfx_grtc_syscounter_compare_event_check(systemoff_channel)) { k_spin_unlock(&lock, key); return -EINVAL; } @@ -457,7 +427,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) MAX_CC_LATCH_WAIT_TIME_US; k_busy_wait(wait_time); #if NRF_GRTC_HAS_CLKSEL - nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFXO); + nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFXO); #endif k_spin_unlock(&lock, key); return 0; @@ -498,16 +468,9 @@ static int sys_clock_driver_init(void) #if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) && \ (defined(NRF_GRTC_HAS_CLKSEL) && (NRF_GRTC_HAS_CLKSEL == 1)) /* Use System LFCLK as the low-frequency clock source. */ - nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFCLK); + nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFCLK); #endif -#if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER) - /* SYSCOUNTER needs to be turned off before initialization. */ - nrfy_grtc_sys_counter_set(NRF_GRTC, false); - nrfy_grtc_timeout_set(NRF_GRTC, TIMEOUT); - nrfy_grtc_waketime_set(NRF_GRTC, WAKETIME); -#endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ - IRQ_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), nrfx_isr, nrfx_grtc_irq_handler, 0); @@ -521,9 +484,6 @@ static int sys_clock_driver_init(void) if (err_code != NRFX_SUCCESS) { return err_code == NRFX_ERROR_NO_MEM ? -ENOMEM : -EPERM; } - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - nrfy_grtc_sys_counter_auto_mode_set(NRF_GRTC, false); - } #else err_code = nrfx_grtc_channel_alloc(&system_clock_channel_data.channel); if (err_code != NRFX_SUCCESS) { @@ -531,10 +491,6 @@ static int sys_clock_driver_init(void) } #endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ - if (!IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - grtc_active_set(); - } - int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { system_timeout_set_relative(CYC_PER_TICK); diff --git a/include/zephyr/drivers/timer/nrf_grtc_timer.h b/include/zephyr/drivers/timer/nrf_grtc_timer.h index 4cd3f8d14cb..f8b69d7ddf0 100644 --- a/include/zephyr/drivers/timer/nrf_grtc_timer.h +++ b/include/zephyr/drivers/timer/nrf_grtc_timer.h @@ -171,6 +171,7 @@ int z_nrf_grtc_timer_capture_prepare(int32_t chan); * * @retval 0 if the timestamp was successfully caught and read. * @retval -EBUSY if capturing has not been triggered. + * @retval -EPERM if either channel is unavailable or SYSCOUNTER is not running. */ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time); diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index e46e458ccab..5ad29dddc46 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -131,10 +131,6 @@ if(CONFIG_NRFX_TWI OR CONFIG_NRFX_TWIM) zephyr_library_sources(${SRC_DIR}/nrfx_twi_twim.c) endif() -if (CONFIG_NRF_GRTC_TIMER AND CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) - zephyr_compile_definitions(NRF_GRTC_HAS_EXTENDED=1) -endif() - # Inject HAL "CONFIG_NFCT_PINS_AS_GPIOS" definition if user requests to # configure the NFCT pins as GPIOS. Do the same with "CONFIG_GPIO_AS_PINRESET" # to configure the reset GPIO as nRESET. This way, the HAL will take care of diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 397d7b2a320..a0f2f481bc3 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -120,6 +120,19 @@ #define NRFX_GRTC_CONFIG_LOG_ENABLED 1 #endif +#ifdef CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT +#define NRF_GRTC_HAS_EXTENDED 1 +#endif +#ifdef CONFIG_NRF_GRTC_SLEEP_ALLOWED +#define NRFX_GRTC_CONFIG_SLEEP_ALLOWED 1 +#endif +#ifdef CONFIG_NRF_GRTC_TIMER_AUTO_KEEP_ALIVE +#define NRFX_GRTC_CONFIG_AUTOEN 1 +#endif +#ifdef CONFIG_NRF_GRTC_START_SYSCOUNTER +#define NRFX_GRTC_CONFIG_AUTOSTART 1 +#endif + #ifdef CONFIG_NRFX_GPIOTE #define NRFX_GPIOTE_ENABLED 1 #endif