Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions drivers/clock_control/Kconfig.nrf5
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -87,3 +94,5 @@ config CLOCK_CONTROL_NRF5_K32SRC_20PPM
prompt "0 ppm to 20 ppm"

endchoice

endif # CLOCK_CONTROL_NRF5
35 changes: 26 additions & 9 deletions drivers/clock_control/nrf5_power_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ static u8_t k32src_initialized;

static int _m16src_start(struct device *dev, clock_control_subsys_t sub_system)
{
u32_t imask;
bool blocking;
u32_t imask;
u32_t stat;

/* If the clock is already started then just increment refcount.
* If the start and stop don't happen in pairs, a rollover will
Expand Down Expand Up @@ -94,7 +95,8 @@ static int _m16src_start(struct device *dev, clock_control_subsys_t sub_system)
*/
__ASSERT_NO_MSG(m16src_ref);

if (NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk) {
stat = CLOCK_HFCLKSTAT_SRC_Xtal | CLOCK_HFCLKSTAT_STATE_Msk;
if ((NRF_CLOCK->HFCLKSTAT & stat) == stat) {
return 0;
} else {
return -EINPROGRESS;
Expand Down Expand Up @@ -145,8 +147,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;
u32_t stat;

#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
Expand All @@ -170,17 +176,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);

Expand All @@ -200,6 +208,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.
*/
Expand Down Expand Up @@ -234,7 +249,9 @@ static int _k32src_start(struct device *dev, clock_control_subsys_t sub_system)
}

lf_already_started:
if (NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_STATE_Msk) {
stat = (NRF_CLOCK->LFCLKSRCCOPY & CLOCK_LFCLKSRCCOPY_SRC_Msk) |
CLOCK_LFCLKSTAT_STATE_Msk;
if ((NRF_CLOCK->LFCLKSTAT & stat) == stat) {
return 0;
} else {
return -EINPROGRESS;
Expand Down
31 changes: 31 additions & 0 deletions subsys/bluetooth/controller/ll_sw/ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "ll.h"

#if defined(CONFIG_SOC_FAMILY_NRF)
#include <drivers/clock_control/nrf5_clock_control.h>
#include <drivers/entropy/nrf5_entropy.h>
#endif /* CONFIG_SOC_FAMILY_NRF */

Expand Down Expand Up @@ -161,6 +162,8 @@ static struct {
u32_t ticks_anchor;
u32_t remainder_anchor;

u8_t is_k32src_stable;

u8_t volatile ticker_id_prepare;
u8_t volatile ticker_id_event;
u8_t volatile ticker_id_stop;
Expand Down Expand Up @@ -4614,6 +4617,28 @@ static void mayfly_xtal_stop(void *params)
DEBUG_RADIO_CLOSE(0);
}

#define DRV_NAME CONFIG_CLOCK_CONTROL_NRF5_K32SRC_DRV_NAME
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this will behave on non-Nordic chips?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current upstream controller is nRF specific, the newer architecture in development separates vendor specifics in lower layer modules.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

#define K32SRC CLOCK_CONTROL_NRF5_K32SRC
static void k32src_wait(void)
{
if (!_radio.is_k32src_stable) {
struct device *clk_k32;

_radio.is_k32src_stable = 1;

clk_k32 = device_get_binding(DRV_NAME);
LL_ASSERT(clk_k32);

while (clock_control_on(clk_k32, (void *)K32SRC)) {
DEBUG_CPU_SLEEP(1);
cpu_sleep();
DEBUG_CPU_SLEEP(0);
}
}
}
#undef K32SRC
#undef DRV_NAME

#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
#define XON_BITMASK BIT(31) /* XTAL has been retained from previous prepare */

Expand Down Expand Up @@ -10070,6 +10095,9 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
conn->rssi_sample_count = 0;
#endif /* CONFIG_BT_CTLR_CONN_RSSI */

/* wait for stable 32KHz clock */
k32src_wait();

_radio.advertiser.conn = conn;
} else {
conn = NULL;
Expand Down Expand Up @@ -10549,6 +10577,9 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
conn->rssi_sample_count = 0;
#endif /* CONFIG_BT_CTLR_CONN_RSSI */

/* wait for stable 32KHz clock */
k32src_wait();

_radio.scanner.conn = conn;

return 0;
Expand Down