Skip to content

Commit

Permalink
mpsl: clock_ctrl: Fix nRF52 LFCLK accuracy when LFSYNTH selected
Browse files Browse the repository at this point in the history
The nrf clock control driver doesn't enable HFXO when LFSYNTH is
selected as a source of LFCLK. That causes the accuracy of LFCLK
to be not within the expected by BT Core Specification range up
to 500 ppm.

To fix the problem the mpsl clock control integration layer has
to request the hfxo in case the lfclk is requested with LFSYNTH
as a source.

Use of z_nrf_clock_bt_ctlr_hf_release makes the call to be faster.
That unfortunately requires reference counting do avoid release of
HFXO later in runtime by MPSL. For that reason the m_hfclk_request
and m_hfclk_release are used.

Signed-off-by: Piotr Pryga <[email protected]>
  • Loading branch information
ppryga-nordic committed Feb 7, 2025
1 parent 368f3eb commit ab470a9
Showing 1 changed file with 59 additions and 45 deletions.
104 changes: 59 additions & 45 deletions subsys/mpsl/clock_ctrl/mpsl_clock_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,52 @@ static int32_t m_lfclk_wait(void)

#if defined(CONFIG_CLOCK_CONTROL_NRF)

static void m_hfclk_request(void)
{
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
* it is caller responsibility handle requests and releases counting.
*/
if (atomic_inc(&m_hfclk_refcnt) > (atomic_val_t)0) {
return;
}

z_nrf_clock_bt_ctlr_hf_request();
}

static void m_hfclk_release(void)
{
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
* it is caller responsibility to not release the clock if there is
* other request pending.
*/
if (atomic_get(&m_hfclk_refcnt) < (atomic_val_t)1) {
return;
}

if (atomic_dec(&m_hfclk_refcnt) > (atomic_val_t)1) {
return;
}

z_nrf_clock_bt_ctlr_hf_release();
}

static bool m_hfclk_is_running(void)
{
if (atomic_get(&m_hfclk_refcnt) > (atomic_val_t)0) {
nrf_clock_hfclk_t type;

unsigned int key = irq_lock();

(void)nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &type);

irq_unlock(key);

return ((type == NRF_CLOCK_HFCLK_HIGH_ACCURACY) ? true : false);
}

return false;
}

static void m_lfclk_calibration_start(void)
{
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_DRIVER_CALIBRATION)) {
Expand All @@ -126,6 +172,13 @@ static int32_t m_lfclk_request(void)
struct onoff_manager *mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF);
int32_t err;

/* Workaround for NRFX-6865. The nrf clock control as well as nrfx_clock doesn't enable
* HFXO when LFSYNTH is selected as LFCLK source. Remove the code when nrfx is fixed.
*/
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH)) {
m_hfclk_request();
}

sys_notify_init_callback(&m_lfclk_state.cli.notify, lfclk_request_cb);
(void)k_sem_init(&m_lfclk_state.sem, 0, 1);

Expand All @@ -150,55 +203,16 @@ static int32_t m_lfclk_release(void)
return err;
}

atomic_dec(&m_lfclk_state.m_clk_refcnt);

return 0;
}

static void m_hfclk_request(void)
{
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
* it is caller responsibility handle requests and releases counting.
*/
if (atomic_inc(&m_hfclk_refcnt) > (atomic_val_t)0) {
return;
}

z_nrf_clock_bt_ctlr_hf_request();
}

static void m_hfclk_release(void)
{
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
* it is caller responsibility to not release the clock if there is
* other request pending.
/* Workaround for NRFX-6865. The nrf clock control as well as nrfx_clock doesn't enable
* HFXO when LFSYNTH is selected as LFCLK source. Remove the code when nrfx is fixed.
*/
if (atomic_get(&m_hfclk_refcnt) < (atomic_val_t)1) {
return;
}

if (atomic_dec(&m_hfclk_refcnt) > (atomic_val_t)1) {
return;
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH)) {
m_hfclk_release();
}

z_nrf_clock_bt_ctlr_hf_release();
}

static bool m_hfclk_is_running(void)
{
if (atomic_get(&m_hfclk_refcnt) > (atomic_val_t)0) {
nrf_clock_hfclk_t type;

unsigned int key = irq_lock();

(void)nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &type);

irq_unlock(key);

return ((type == NRF_CLOCK_HFCLK_HIGH_ACCURACY) ? true : false);
}
atomic_dec(&m_lfclk_state.m_clk_refcnt);

return false;
return 0;
}

#elif defined(CONFIG_CLOCK_CONTROL_NRF2)
Expand Down

0 comments on commit ab470a9

Please sign in to comment.