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 <adam.kondraciuk@nordicsemi.no>
This commit is contained in:
Adam Kondraciuk 2023-12-19 15:25:08 +01:00 committed by Henrik Brix Andersen
commit cac0da313b
5 changed files with 48 additions and 71 deletions

View file

@ -41,9 +41,20 @@ config NRF_GRTC_TIMER_CLOCK_MANAGEMENT
the GRTC. Usually this is only needed by the processor that is starting 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. 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 int
default 1000 default 1000
depends on NRF_GRTC_SLEEP_ALLOWED 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 endif # NRF_GRTC_TIMER

View file

@ -29,12 +29,6 @@
#define CHAN_COUNT NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS #define CHAN_COUNT NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS
#define EXT_CHAN_COUNT (CHAN_COUNT - 1) #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 #ifndef GRTC_SYSCOUNTERL_VALUE_Msk
#define GRTC_SYSCOUNTERL_VALUE_Msk GRTC_SYSCOUNTER_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) #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK)
/* The maximum SYSCOUNTERVALID settling time equals 1x32k cycles + 20x1MHz cycles. */ #define LFCLK_FREQUENCY_HZ 32768
#define GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US 51
#if defined(CONFIG_TEST) #if defined(CONFIG_TEST)
const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); 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))) && \ __ASSERT_NO_MSG((NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK & (1UL << (chan))) && \
((chan) != system_clock_channel_data.channel)) ((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) static inline uint64_t counter_sub(uint64_t a, uint64_t b)
{ {
return (a - 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) static inline uint64_t counter(void)
{ {
uint64_t now; uint64_t now;
grtc_wakeup();
nrfx_grtc_syscounter_get(&now); nrfx_grtc_syscounter_get(&now);
grtc_sleep();
return now; 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) static void system_timeout_set_relative(uint64_t value)
{ {
if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) { if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) {
grtc_wakeup();
nrfx_grtc_syscounter_cc_relative_set(&system_clock_channel_data, value, true, nrfx_grtc_syscounter_cc_relative_set(&system_clock_channel_data, value, true,
NRFX_GRTC_CC_RELATIVE_SYSCOUNTER); NRFX_GRTC_CC_RELATIVE_SYSCOUNTER);
grtc_sleep();
} else { } else {
nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value + counter(), nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value + counter(),
true); true);
@ -386,6 +344,7 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time)
*/ */
uint64_t capt_time; uint64_t capt_time;
nrfx_err_t result;
IS_CHANNEL_ALLOWED_ASSERT(chan); 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; return -EBUSY;
} }
result = nrfx_grtc_syscounter_cc_value_read(chan, &capt_time);
capt_time = nrfy_grtc_sys_counter_cc_get(NRF_GRTC, chan); if (result != NRFX_SUCCESS) {
return -EPERM;
}
__ASSERT_NO_MSG(capt_time < COUNTER_SPAN); __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; nrfx_err_t err_code;
static uint8_t systemoff_channel; static uint8_t systemoff_channel;
uint64_t now = counter(); uint64_t now = counter();
nrfx_grtc_sleep_config_t sleep_cfg;
/* Minimum time that ensures valid execution of system-off procedure. */ /* Minimum time that ensures valid execution of system-off procedure. */
uint32_t minimum_latency_us = nrfy_grtc_waketime_get(NRF_GRTC) + uint32_t minimum_latency_us;
nrfy_grtc_timeout_get(NRF_GRTC) +
CONFIG_NRF_GRTC_SLEEP_MINIMUM_LATENCY;
uint32_t chan; uint32_t chan;
int ret; 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) { if (minimum_latency_us > wake_time_us) {
return -EINVAL; return -EINVAL;
} }
k_spinlock_key_t key = k_spin_lock(&lock); k_spinlock_key_t key = k_spin_lock(&lock);
err_code = nrfx_grtc_channel_alloc(&systemoff_channel); 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; return -ENOMEM;
} }
(void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel); (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) { if (ret < 0) {
k_spin_unlock(&lock, key); k_spin_unlock(&lock, key);
return ret; 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. */ /* 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); k_spin_unlock(&lock, key);
return -EINVAL; return -EINVAL;
} }
@ -457,7 +427,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
MAX_CC_LATCH_WAIT_TIME_US; MAX_CC_LATCH_WAIT_TIME_US;
k_busy_wait(wait_time); k_busy_wait(wait_time);
#if NRF_GRTC_HAS_CLKSEL #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 #endif
k_spin_unlock(&lock, key); k_spin_unlock(&lock, key);
return 0; return 0;
@ -498,16 +468,9 @@ static int sys_clock_driver_init(void)
#if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) && \ #if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) && \
(defined(NRF_GRTC_HAS_CLKSEL) && (NRF_GRTC_HAS_CLKSEL == 1)) (defined(NRF_GRTC_HAS_CLKSEL) && (NRF_GRTC_HAS_CLKSEL == 1))
/* Use System LFCLK as the low-frequency clock source. */ /* 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 #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, IRQ_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), nrfx_isr,
nrfx_grtc_irq_handler, 0); nrfx_grtc_irq_handler, 0);
@ -521,9 +484,6 @@ static int sys_clock_driver_init(void)
if (err_code != NRFX_SUCCESS) { if (err_code != NRFX_SUCCESS) {
return err_code == NRFX_ERROR_NO_MEM ? -ENOMEM : -EPERM; 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 #else
err_code = nrfx_grtc_channel_alloc(&system_clock_channel_data.channel); err_code = nrfx_grtc_channel_alloc(&system_clock_channel_data.channel);
if (err_code != NRFX_SUCCESS) { if (err_code != NRFX_SUCCESS) {
@ -531,10 +491,6 @@ static int sys_clock_driver_init(void)
} }
#endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ #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; int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK;
if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
system_timeout_set_relative(CYC_PER_TICK); system_timeout_set_relative(CYC_PER_TICK);

View file

@ -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 0 if the timestamp was successfully caught and read.
* @retval -EBUSY if capturing has not been triggered. * @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); int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time);

View file

@ -131,10 +131,6 @@ if(CONFIG_NRFX_TWI OR CONFIG_NRFX_TWIM)
zephyr_library_sources(${SRC_DIR}/nrfx_twi_twim.c) zephyr_library_sources(${SRC_DIR}/nrfx_twi_twim.c)
endif() 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 # 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" # 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 # to configure the reset GPIO as nRESET. This way, the HAL will take care of

View file

@ -120,6 +120,19 @@
#define NRFX_GRTC_CONFIG_LOG_ENABLED 1 #define NRFX_GRTC_CONFIG_LOG_ENABLED 1
#endif #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 #ifdef CONFIG_NRFX_GPIOTE
#define NRFX_GPIOTE_ENABLED 1 #define NRFX_GPIOTE_ENABLED 1
#endif #endif