Skip to content

Commit 0479f08

Browse files
ppryga-nordicnordicjm
authored andcommitted
mpsl: clock_ctrl: Fix wait for LFCLK if timeout returned earlier
There is a workaround implemented in the MPSL clock control integration layer for cases where nrf2 clock control doesn't get response from sysctrl for the LFCLK request. The workaround was incorrectly implemented. After clock driver returned -NRF_ETIMEDOUT new call to m_lfclk_wait() was done. The new call waits on a semaphore that also returns timeout error. The second m_lfclk_wait() call returns -NRF_EFAULT error code that causes an assert in later stage of initialization. The change done is to make sure if a clock driver returns -NRF_ETIMEDOUT error for m_lfclk_wait then next m_lfclk_wait call immediately returns 0 (as if the clock was ready). That is based on an assumption: - the sysctrl implicitly provides a LFCLK with accuracy that is the same or better than requested by MPSL, - there are not other LFLCK requests from Radio core FW - if there is another LFCLK request put, it is for a LFCLK with accuracy the same or better than required by radio protocols. The change also affects LFCLK request and response APIs, so that the new requests or released for the clock will return immediately until the mpsl_clock_ctrl_uninit() is executed, that resets the sate of the m_lflclk_req_timeout flag. There is added a KConfig option: CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ- _TIMEOUT_ALLOW that can be used to disable the workaround. Signed-off-by: Piotr Pryga <[email protected]>
1 parent 803c382 commit 0479f08

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

subsys/mpsl/clock_ctrl/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,16 @@ config MPSL_EXT_CLK_CTRL_NVM_CLOCK_REQUEST
3636
ensuring it operates at a frequency that prevents code execution being
3737
too slow. This is crucial to meet meet radio protocols requirements.
3838

39+
config MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW
40+
bool "Enables a workaround for LFCLK request timeout"
41+
depends on SOC_SERIES_NRF54HX
42+
default y
43+
help
44+
This option enables a workaround in MPSL external clock control
45+
integration layer, to ignore the -NRF_ETIMEDOUT response for LFCLK
46+
request. This workaround is safe to use for cases where there is no
47+
other clock requests in the radio core FW or available requests are
48+
for a clock with better accuracy than the one requested by the MPSL.
49+
It is user responsibility to make sure these requirements are fulfilled.
50+
3951
endif # MPSL_USE_EXTERNAL_CLOCK_CONTROL

subsys/mpsl/clock_ctrl/mpsl_clock_ctrl.c

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ struct clock_onoff_state {
3636
static struct clock_onoff_state m_lfclk_state = {
3737
.m_clock_request_release = m_lfclk_release
3838
};
39+
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW)
40+
/* Variable used temporarily until the NCSDK-31169 is fixed */
41+
static atomic_t m_lfclk_req_timeout;
42+
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW */
3943

4044
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_NVM_CLOCK_REQUEST)
4145
#define NVM_CLOCK_DT_LABEL DT_NODELABEL(hsfll120)
@@ -139,17 +143,37 @@ static int32_t m_lfclk_wait(void)
139143
{
140144
int err;
141145

146+
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW)
147+
/* Do not attempt to wait for the LFCLK if there was a timeout reported
148+
* for former requests. Due to NCSDK-31169, we allow for such case,
149+
* assuming there is a LFCLK source selected by sysctrl with accuracy
150+
* that meets radio protocols requirements.
151+
*/
152+
if (atomic_get(&m_lfclk_req_timeout) == (atomic_val_t) true) {
153+
return 0;
154+
}
155+
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW */
156+
142157
err = m_clock_request_wait(&m_lfclk_state,
143158
CONFIG_MPSL_EXT_CLK_CTRL_CLOCK_REQUEST_WAIT_TIMEOUT_MS);
144-
145-
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF2) && (err == -NRF_ETIMEDOUT)) {
159+
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW)
160+
if (err == -NRF_ETIMEDOUT) {
146161
/* Due to NCSDK-31169, temporarily allow for LFCLK request to timeout.
147162
* That doens't break anything now because the LFCLK requested clock is
148163
* 500PPM and such LFCLK should be running from boot of the radio core.
149164
*/
165+
atomic_set(&m_lfclk_req_timeout, (atomic_val_t) true);
166+
167+
/* Decrement the internal reference counter because the m_lfclk_req_timeout
168+
* takes priority in handling of future request and release calls until
169+
* mpsl_clock_ctrl_uninit() is called.
170+
*/
171+
atomic_dec(&m_lfclk_state.m_clk_refcnt);
172+
150173
LOG_WRN("LFCLK could not be started: %d", m_lfclk_state.clk_req_rsp);
151174
return 0;
152175
}
176+
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW */
153177

154178
return err;
155179
}
@@ -304,6 +328,17 @@ static int32_t m_lfclk_request(void)
304328
const struct device *lfclk_dev = DEVICE_DT_GET(DT_NODELABEL(lfclk));
305329
int err;
306330

331+
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW)
332+
/* Do not attempt request LFCLK again if there was a timeout resposne
333+
* for past request. Due to NCSDK-31169, we allow for such case
334+
* assuming there is a LFCLK source selected by sysctrl with accuracy
335+
* that meets radio protocols requirements.
336+
*/
337+
if (atomic_get(&m_lfclk_req_timeout) == (atomic_val_t) true) {
338+
return 0;
339+
}
340+
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW */
341+
307342
sys_notify_init_callback(&m_lfclk_state.cli.notify, m_clock_request_cb);
308343
k_sem_init(&m_lfclk_state.sem, 0, 1);
309344

@@ -322,9 +357,30 @@ static int32_t m_lfclk_release(void)
322357
const struct device *lfclk_dev = DEVICE_DT_GET(DT_NODELABEL(lfclk));
323358
int err;
324359

360+
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW)
361+
/* Do not attempt to release the LFCLK if there was a timeout reported
362+
* for a request. The clock driver hasn't got a request registered
363+
* because of the error.
364+
* Due to NCSDK-31169, we allow for such case assuming there is
365+
* a LFCLK source selected by sysctrl with accuracy that meets radio
366+
* protocols requirements.
367+
*/
368+
if (atomic_get(&m_lfclk_req_timeout) == (atomic_val_t) true) {
369+
return 0;
370+
}
371+
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW */
372+
373+
325374
err = nrf_clock_control_cancel_or_release(lfclk_dev, &m_lfclk_specs, &m_lfclk_state.cli);
326375
if (err < 0) {
327376
return err;
377+
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW)
378+
} else if (err == ONOFF_STATE_OFF) {
379+
/* Due to NCSDK-31169, clear the variable only in case all request are released.
380+
* This allows for full reinitialization.
381+
*/
382+
atomic_set(&m_lfclk_req_timeout, (atomic_val_t) false);
383+
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW */
328384
}
329385

330386
atomic_dec(&m_lfclk_state.m_clk_refcnt);
@@ -469,5 +525,10 @@ int32_t mpsl_clock_ctrl_uninit(void)
469525
}
470526
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_NVM_CLOCK_REQUEST */
471527

528+
#if defined(CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW)
529+
/* Reset the LFCLK timeout to allow for regular re-initialization of the MPSL.*/
530+
atomic_set(&m_lfclk_req_timeout, (atomic_val_t) false);
531+
#endif /* CONFIG_MPSL_EXT_CLK_CTRL_LFCLK_REQ_TIMEOUT_ALLOW */
532+
472533
return mpsl_clock_ctrl_source_unregister();
473534
}

0 commit comments

Comments
 (0)