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 Dec 17, 2024
1 parent 3768cf3 commit 0aeca76
Showing 1 changed file with 49 additions and 35 deletions.
84 changes: 49 additions & 35 deletions subsys/mpsl/clock_ctrl/mpsl_clock_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,41 @@ 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) > 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 do not release the clock if there is
* other request pending.
*/
if (m_hfclk_refcnt < 1) {
return;
}

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

z_nrf_clock_bt_ctlr_hf_release();
}

static bool m_hfclk_is_running(void)
{
/* As of now assume the HFCLK is runnig after the request was put */
return ((m_hfclk_refcnt > 0) ? true : false);
}

static void m_lfclk_calibration_start(void)
{
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_DRIVER_CALIBRATION)) {
Expand All @@ -94,6 +129,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_spinwait(&m_lfclk_state.cli.notify);
err = onoff_request(mgr, &m_lfclk_state.cli);
if (err < 0) {
Expand All @@ -116,46 +158,18 @@ static int32_t m_lfclk_release(void)
return 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_release();
}

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) > 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 do not release the clock if there is
* other request pending.
*/
if (m_hfclk_refcnt < 1) {
return;
}

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

z_nrf_clock_bt_ctlr_hf_release();
}

static bool m_hfclk_is_running(void)
{
/* As of now assume the HFCLK is runnig after the request was put */
return ((m_hfclk_refcnt > 0) ? true : false);
}

#elif defined(CONFIG_CLOCK_CONTROL_NRF2)

/* Temporary macro because there is no system level configuration of LFCLK source and its accuracy
Expand Down

0 comments on commit 0aeca76

Please sign in to comment.