drivers: timer: nrf: Add configurable clock startup mode

Added configuration for approach to starting system clock source.
There are 3 options: no wait, wait untill available, wait until
stable.

Added support for those modes in clock control driver which handles
low frequency source clock.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2020-08-04 13:56:21 +02:00 committed by Carles Cufí
commit c69a27b789
5 changed files with 56 additions and 8 deletions

View file

@ -444,6 +444,7 @@ static void lfclk_spinwait(nrf_clock_lfclk_t t)
while (!(nrfx_clock_is_running(d, (void *)&type) && (type == t))) { while (!(nrfx_clock_is_running(d, (void *)&type) && (type == t))) {
/* empty */ /* empty */
/* k_cpu_idle(); */
} }
} }
@ -463,16 +464,21 @@ void z_nrf_clock_control_lf_on(enum nrf_lfclk_start_mode start_mode)
__ASSERT_NO_MSG(err >= 0); __ASSERT_NO_MSG(err >= 0);
} }
/* In case of simulated board leave immediately. */
if (IS_ENABLED(CONFIG_BOARD_NRF52_BSIM)) {
return;
}
switch (start_mode) { switch (start_mode) {
case NRF_LFCLK_START_MODE_SPINWAIT_STABLE: case CLOCK_CONTROL_NRF_LF_START_STABLE:
lfclk_spinwait(CLOCK_CONTROL_NRF_K32SRC); lfclk_spinwait(CLOCK_CONTROL_NRF_K32SRC);
break; break;
case NRF_LFCLK_START_MODE_SPINWAIT_RUNNING: case CLOCK_CONTROL_NRF_LF_START_AVAILABLE:
lfclk_spinwait(NRF_CLOCK_LFCLK_RC); lfclk_spinwait(NRF_CLOCK_LFCLK_RC);
break; break;
case NRF_LFCLK_START_MODE_NOWAIT: case CLOCK_CONTROL_NRF_LF_START_NOWAIT:
break; break;
default: default:

View file

@ -534,7 +534,7 @@ static int init_rtc(const struct device *dev, uint32_t prescaler)
NRF_RTC_Type *rtc = nrfx_config->rtc; NRF_RTC_Type *rtc = nrfx_config->rtc;
int err; int err;
z_nrf_clock_control_lf_on(NRF_LFCLK_START_MODE_NOWAIT); z_nrf_clock_control_lf_on(CLOCK_CONTROL_NRF_LF_START_NOWAIT);
nrf_rtc_prescaler_set(rtc, prescaler); nrf_rtc_prescaler_set(rtc, prescaler);

View file

@ -155,6 +155,42 @@ config NRF_RTC_TIMER
Counter NRF_RTC1 and provides the standard "system clock driver" Counter NRF_RTC1 and provides the standard "system clock driver"
interfaces. interfaces.
if NRF_RTC_TIMER
choice
prompt "Clock startup policy"
default SYSTEM_CLOCK_WAIT_FOR_STABILITY
config SYSTEM_CLOCK_NO_WAIT
bool "No wait"
help
System clock source is initiated but does not wait for clock readiness.
When this option is picked, system clock may not be ready when code relying
on kernel API is executed. Requested timeouts will be prolonged by the
remaining startup time.
config SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY
bool "Wait for availability"
help
System clock source initialization waits until clock is available. In some
systems, clock initially runs from less accurate source which has faster
startup time and then seamlessly switches to the target clock source when
it is ready. When this option is picked, system clock is available after
system clock driver initialization but it may be less accurate. Option is
equivalent to waiting for stability if clock source does not have
intermediate state.
config SYSTEM_CLOCK_WAIT_FOR_STABILITY
bool "Wait for stability"
help
System clock source initialization waits until clock is stable. When this
option is picked, system clock is available and stable after system clock
driver initialization.
endchoice
endif # NRF_RTC_TIMER
source "drivers/timer/Kconfig.stm32_lptim" source "drivers/timer/Kconfig.stm32_lptim"
config RISCV_MACHINE_TIMER config RISCV_MACHINE_TIMER

View file

@ -189,6 +189,12 @@ void rtc_nrf_isr(const void *arg)
int z_clock_driver_init(const struct device *device) int z_clock_driver_init(const struct device *device)
{ {
ARG_UNUSED(device); ARG_UNUSED(device);
static const enum nrf_lfclk_start_mode mode =
IS_ENABLED(CONFIG_SYSTEM_CLOCK_NO_WAIT) ?
CLOCK_CONTROL_NRF_LF_START_NOWAIT :
(IS_ENABLED(CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY) ?
CLOCK_CONTROL_NRF_LF_START_AVAILABLE :
CLOCK_CONTROL_NRF_LF_START_STABLE);
/* TODO: replace with counter driver to access RTC */ /* TODO: replace with counter driver to access RTC */
nrf_rtc_prescaler_set(RTC, 0); nrf_rtc_prescaler_set(RTC, 0);
@ -206,7 +212,7 @@ int z_clock_driver_init(const struct device *device)
set_comparator(counter() + CYC_PER_TICK); set_comparator(counter() + CYC_PER_TICK);
} }
z_nrf_clock_control_lf_on(NRF_LFCLK_START_MODE_NOWAIT); z_nrf_clock_control_lf_on(mode);
return 0; return 0;
} }

View file

@ -37,9 +37,9 @@ enum clock_control_nrf_type {
/** @brief LF clock start modes. */ /** @brief LF clock start modes. */
enum nrf_lfclk_start_mode { enum nrf_lfclk_start_mode {
NRF_LFCLK_START_MODE_NOWAIT, CLOCK_CONTROL_NRF_LF_START_NOWAIT,
NRF_LFCLK_START_MODE_SPINWAIT_RUNNING, CLOCK_CONTROL_NRF_LF_START_AVAILABLE,
NRF_LFCLK_START_MODE_SPINWAIT_STABLE, CLOCK_CONTROL_NRF_LF_START_STABLE,
}; };
/* Define 32KHz clock source */ /* Define 32KHz clock source */