Skip to content

Commit 107e386

Browse files
ppryga-nordicnordicjm
authored andcommitted
mpsl: clock_ctrl: Fix nRF52 LFCLK accuracy when LFSYNTH selected
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]>
1 parent 24798c4 commit 107e386

File tree

1 file changed

+60
-46
lines changed

1 file changed

+60
-46
lines changed

subsys/mpsl/clock_ctrl/mpsl_clock_ctrl.c

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,53 @@ static int32_t m_lfclk_wait(void)
105105

106106
#if defined(CONFIG_CLOCK_CONTROL_NRF)
107107

108+
static void m_hfclk_request(void)
109+
{
110+
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
111+
* it is caller responsibility handle requests and releases counting.
112+
*/
113+
if (atomic_inc(&m_hfclk_refcnt) > (atomic_val_t)0) {
114+
return;
115+
}
116+
117+
z_nrf_clock_bt_ctlr_hf_request();
118+
}
119+
120+
static void m_hfclk_release(void)
121+
{
122+
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
123+
* it is caller responsibility to not release the clock if there is
124+
* other request pending.
125+
*/
126+
if (atomic_get(&m_hfclk_refcnt) < (atomic_val_t)1) {
127+
LOG_WRN("Mismatch between HFCLK request/release");
128+
return;
129+
}
130+
131+
if (atomic_dec(&m_hfclk_refcnt) > (atomic_val_t)1) {
132+
return;
133+
}
134+
135+
z_nrf_clock_bt_ctlr_hf_release();
136+
}
137+
138+
static bool m_hfclk_is_running(void)
139+
{
140+
if (atomic_get(&m_hfclk_refcnt) > (atomic_val_t)0) {
141+
nrf_clock_hfclk_t type;
142+
143+
unsigned int key = irq_lock();
144+
145+
(void)nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &type);
146+
147+
irq_unlock(key);
148+
149+
return ((type == NRF_CLOCK_HFCLK_HIGH_ACCURACY) ? true : false);
150+
}
151+
152+
return false;
153+
}
154+
108155
static void m_lfclk_calibration_start(void)
109156
{
110157
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_DRIVER_CALIBRATION)) {
@@ -126,6 +173,13 @@ static int32_t m_lfclk_request(void)
126173
struct onoff_manager *mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF);
127174
int32_t err;
128175

176+
/* Workaround for NRFX-6865. The nrf clock control as well as nrfx_clock doesn't enable
177+
* HFXO when LFSYNTH is selected as LFCLK source. Remove the code when nrfx is fixed.
178+
*/
179+
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH)) {
180+
m_hfclk_request();
181+
}
182+
129183
sys_notify_init_callback(&m_lfclk_state.cli.notify, lfclk_request_cb);
130184
(void)k_sem_init(&m_lfclk_state.sem, 0, 1);
131185

@@ -150,56 +204,16 @@ static int32_t m_lfclk_release(void)
150204
return err;
151205
}
152206

153-
atomic_dec(&m_lfclk_state.m_clk_refcnt);
154-
155-
return 0;
156-
}
157-
158-
static void m_hfclk_request(void)
159-
{
160-
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
161-
* it is caller responsibility handle requests and releases counting.
207+
/* Workaround for NRFX-6865. The nrf clock control as well as nrfx_clock doesn't enable
208+
* HFXO when LFSYNTH is selected as LFCLK source. Remove the code when nrfx is fixed.
162209
*/
163-
if (atomic_inc(&m_hfclk_refcnt) > (atomic_val_t)0) {
164-
return;
210+
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH)) {
211+
m_hfclk_release();
165212
}
166213

167-
z_nrf_clock_bt_ctlr_hf_request();
168-
}
169-
170-
static void m_hfclk_release(void)
171-
{
172-
/* The z_nrf_clock_bt_ctlr_hf_request doesn't count references to HFCLK,
173-
* it is caller responsibility to not release the clock if there is
174-
* other request pending.
175-
*/
176-
if (atomic_get(&m_hfclk_refcnt) < (atomic_val_t)1) {
177-
LOG_WRN("Mismatch between HFCLK request/release");
178-
return;
179-
}
180-
181-
if (atomic_dec(&m_hfclk_refcnt) > (atomic_val_t)1) {
182-
return;
183-
}
184-
185-
z_nrf_clock_bt_ctlr_hf_release();
186-
}
187-
188-
static bool m_hfclk_is_running(void)
189-
{
190-
if (atomic_get(&m_hfclk_refcnt) > (atomic_val_t)0) {
191-
nrf_clock_hfclk_t type;
192-
193-
unsigned int key = irq_lock();
194-
195-
(void)nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &type);
196-
197-
irq_unlock(key);
198-
199-
return ((type == NRF_CLOCK_HFCLK_HIGH_ACCURACY) ? true : false);
200-
}
214+
atomic_dec(&m_lfclk_state.m_clk_refcnt);
201215

202-
return false;
216+
return 0;
203217
}
204218

205219
#elif defined(CONFIG_CLOCK_CONTROL_NRF2)

0 commit comments

Comments
 (0)