clock_control: nRF5x: Non-blocking 32KHz crystal oscillator startup

Added Kconfig option and implementation to support a
non-blocking startup of 32KHz crystal oscillator.

This will reduce the time from boot to application start
while the crystal startup happens in background.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2018-07-09 11:15:48 +02:00 committed by Carles Cufí
parent 76320d2142
commit 23c92100ac
2 changed files with 32 additions and 11 deletions

View File

@ -12,10 +12,11 @@ menuconfig CLOCK_CONTROL_NRF5
Enable support for the Nordic Semiconductor nRF5x series SoC clock
driver.
if CLOCK_CONTROL_NRF5
config CLOCK_CONTROL_NRF5_IRQ_PRIORITY
int
prompt "Power Clock Interrupt Priority"
depends on CLOCK_CONTROL_NRF5
range 0 7
default 1
help
@ -24,19 +25,16 @@ config CLOCK_CONTROL_NRF5_IRQ_PRIORITY
config CLOCK_CONTROL_NRF5_M16SRC_DRV_NAME
string
prompt "NRF5 16MHz clock device name"
depends on CLOCK_CONTROL_NRF5
default "clk_m16src"
config CLOCK_CONTROL_NRF5_K32SRC_DRV_NAME
string
prompt "NRF5 32KHz clock device name"
depends on CLOCK_CONTROL_NRF5
default "clk_k32src"
choice
prompt "32KHz clock source"
default CLOCK_CONTROL_NRF5_K32SRC_XTAL
depends on CLOCK_CONTROL_NRF5
config CLOCK_CONTROL_NRF5_K32SRC_RC
bool
@ -48,11 +46,20 @@ config CLOCK_CONTROL_NRF5_K32SRC_XTAL
endchoice
config CLOCK_CONTROL_NRF5_K32SRC_BLOCKING
bool
prompt "Blocking 32KHz crystal oscillator startup"
depends on CLOCK_CONTROL_NRF5_K32SRC_XTAL
help
Clock control driver will spin wait in CPU sleep until 32KHz
crystal oscillator starts up. If not enabled, RC oscillator will
initially start running and automatically switch to crystal when
ready.
choice
prompt "32KHz clock accuracy"
default CLOCK_CONTROL_NRF5_K32SRC_500PPM if CLOCK_CONTROL_NRF5_K32SRC_RC
default CLOCK_CONTROL_NRF5_K32SRC_20PPM
depends on CLOCK_CONTROL_NRF5
config CLOCK_CONTROL_NRF5_K32SRC_500PPM
bool
@ -87,3 +94,5 @@ config CLOCK_CONTROL_NRF5_K32SRC_20PPM
prompt "0 ppm to 20 ppm"
endchoice
endif # CLOCK_CONTROL_NRF5

View File

@ -145,9 +145,12 @@ static int _m16src_stop(struct device *dev, clock_control_subsys_t sub_system)
static int _k32src_start(struct device *dev, clock_control_subsys_t sub_system)
{
u32_t lf_clk_src;
u32_t intenset;
u32_t imask;
#if defined(CONFIG_CLOCK_CONTROL_NRF5_K32SRC_BLOCKING)
u32_t intenset;
#endif /* CONFIG_CLOCK_CONTROL_NRF5_K32SRC_BLOCKING */
/* If the LF clock is already started, but wasn't initialized with
* this function, allow it to run once. This is needed because if a
* soft reset is triggered while watchdog is active, the LF clock will
@ -170,17 +173,19 @@ static int _k32src_start(struct device *dev, clock_control_subsys_t sub_system)
irq_unlock(imask);
irq_disable(POWER_CLOCK_IRQn);
/* Clear events if any */
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
intenset = NRF_CLOCK->INTENSET;
nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK);
/* Set LF Clock Source */
lf_clk_src = POINTER_TO_UINT(sub_system);
NRF_CLOCK->LFCLKSRC = lf_clk_src;
#if defined(CONFIG_CLOCK_CONTROL_NRF5_K32SRC_BLOCKING)
irq_disable(POWER_CLOCK_IRQn);
intenset = NRF_CLOCK->INTENSET;
nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK);
/* Start and spin-wait until clock settles */
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
@ -200,6 +205,13 @@ static int _k32src_start(struct device *dev, clock_control_subsys_t sub_system)
irq_enable(POWER_CLOCK_IRQn);
#else /* !CONFIG_CLOCK_CONTROL_NRF5_K32SRC_BLOCKING */
/* NOTE: LFCLK will initially start running from the LFRC if LFXO is
* selected.
*/
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
#endif /* !CONFIG_CLOCK_CONTROL_NRF5_K32SRC_BLOCKING */
/* If RC selected, calibrate and start timer for consecutive
* calibrations.
*/