Skip to content

Commit 39506f2

Browse files
committed
[nrf fromlist] modules: hal_nordic: nrf_802154: de-escalate to non-ZLI isr
Both the nrf_802154_clock_hfclk_start() and nrf_802154_clock_hfclk_stop() can potentially be called form ZLI and non-ZLI contexts and consecutive calls are not guaranteed to be alternating. Added an implementation that uses the EGU to de-escalate to a non-ZLI context from which it is safe to use the Zephyr API that enables/disables the HFXO. Upstream PR #: 94208 Signed-off-by: Rafał Kuźnia <[email protected]>
1 parent 63febf7 commit 39506f2

File tree

2 files changed

+128
-30
lines changed

2 files changed

+128
-30
lines changed

modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c

Lines changed: 127 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,35 @@
1313
#include <zephyr/kernel.h>
1414
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
1515
#include <nrf_sys_event.h>
16+
#include <hal/nrf_egu.h>
1617

17-
static bool hfclk_is_running;
18+
/**
19+
* The implementation uses EGU to de-escalate execution context from ZLI to a regular interrupt
20+
* to ensure that Zephyr APIs can be used safely.
21+
*
22+
* Both the nrf_802154_clock_hfclk_start() and nrf_802154_clock_hfclk_stop() can potentially be
23+
* called from ZLI and non-ZLI contexts and consecutive calls are not guaranteed to be alternating.
24+
*
25+
* For example, it is possible that _stop() may be called multiple times in succession and the
26+
* same thing applies to _start(). What is known however is that the last call always takes
27+
* the precedence.
28+
*/
29+
30+
#define SWI_INT NRFX_CONCAT_2(NRF_EGU_INT_TRIGGERED, NRF_802154_SL_EGU_CLOCK_CHANNEL_NO)
31+
#define SWI_TASK NRFX_CONCAT_2(NRF_EGU_TASK_TRIGGER, NRF_802154_SL_EGU_CLOCK_CHANNEL_NO)
32+
#define SWI_EVENT NRFX_CONCAT_2(NRF_EGU_EVENT_TRIGGERED, NRF_802154_SL_EGU_CLOCK_CHANNEL_NO)
33+
34+
#define CLOCK_NONE 0u
35+
#define CLOCK_REQUEST 1u
36+
#define CLOCK_RELEASE 2u
37+
38+
static bool hfclk_is_running = false;
39+
static bool enabled = false;
40+
static atomic_t request = CLOCK_NONE;
41+
42+
/* Forward declarations. */
43+
static void hfclk_start(void);
44+
static void hfclk_stop(void);
1845

1946
void nrf_802154_clock_init(void)
2047
{
@@ -23,11 +50,13 @@ void nrf_802154_clock_init(void)
2350

2451
nrf_802154_clock_hfclk_latency_set(clock_latency_us);
2552
#endif
53+
54+
nrf_egu_int_enable(NRF_802154_EGU_INSTANCE, SWI_INT);
2655
}
2756

2857
void nrf_802154_clock_deinit(void)
2958
{
30-
/* Intentionally empty. */
59+
nrf_egu_int_disable(NRF_802154_EGU_INSTANCE, SWI_INT);
3160
}
3261

3362
bool nrf_802154_clock_hfclk_is_running(void)
@@ -47,8 +76,45 @@ static void hfclk_on_callback(struct onoff_manager *mgr,
4776
nrf_802154_clock_hfclk_ready();
4877
}
4978

50-
#if defined(CONFIG_CLOCK_CONTROL_NRF)
79+
void nrf_802154_sl_clock_swi_irq_handler(void)
80+
{
81+
if (nrf_egu_event_check(NRF_802154_EGU_INSTANCE, SWI_EVENT))
82+
{
83+
nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, SWI_EVENT);
84+
85+
atomic_val_t previous = atomic_set(&request, CLOCK_NONE);
86+
87+
__ASSERT_NO_MSG(previous == CLOCK_REQUEST || previous == CLOCK_RELEASE);
88+
89+
switch (previous) {
90+
case CLOCK_REQUEST:
91+
hfclk_start();
92+
break;
93+
94+
case CLOCK_RELEASE:
95+
hfclk_stop();
96+
break;
97+
98+
default:
99+
break;
100+
}
101+
}
102+
}
103+
51104
void nrf_802154_clock_hfclk_start(void)
105+
{
106+
atomic_set(&request, CLOCK_REQUEST);
107+
nrf_egu_task_trigger(NRF_802154_EGU_INSTANCE, SWI_TASK);
108+
}
109+
110+
void nrf_802154_clock_hfclk_stop(void)
111+
{
112+
atomic_set(&request, CLOCK_RELEASE);
113+
nrf_egu_task_trigger(NRF_802154_EGU_INSTANCE, SWI_TASK);
114+
}
115+
116+
#if defined(CONFIG_CLOCK_CONTROL_NRF)
117+
static void hfclk_start(void)
52118
{
53119
struct onoff_manager *mgr =
54120
z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
@@ -57,56 +123,88 @@ void nrf_802154_clock_hfclk_start(void)
57123

58124
sys_notify_init_callback(&hfclk_cli.notify, hfclk_on_callback);
59125

60-
/*
61-
* todo: replace constlat request with PM policy API when
62-
* controlling the event latency becomes possible.
63-
*/
64-
if (IS_ENABLED(CONFIG_NRF_802154_CONSTLAT_CONTROL)) {
65-
nrf_sys_event_request_global_constlat();
126+
if (!enabled) {
127+
unsigned int key = irq_lock();
128+
129+
/*
130+
* todo: replace constlat request with PM policy API when
131+
* controlling the event latency becomes possible.
132+
*/
133+
if (IS_ENABLED(CONFIG_NRF_802154_CONSTLAT_CONTROL)) {
134+
nrf_sys_event_request_global_constlat();
135+
}
136+
137+
int ret = onoff_request(mgr, &hfclk_cli);
138+
__ASSERT_NO_MSG(ret >= 0);
139+
(void)ret;
140+
141+
irq_unlock(key);
66142
}
67143

68-
int ret = onoff_request(mgr, &hfclk_cli);
69-
__ASSERT_NO_MSG(ret >= 0);
70-
(void)ret;
144+
enabled = true;
71145
}
72146

73-
void nrf_802154_clock_hfclk_stop(void)
147+
static void hfclk_stop(void)
74148
{
75149
struct onoff_manager *mgr =
76150
z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
77151

78152
__ASSERT_NO_MSG(mgr != NULL);
79153

80-
int ret = onoff_cancel_or_release(mgr, &hfclk_cli);
81-
__ASSERT_NO_MSG(ret >= 0);
82-
(void)ret;
154+
if (enabled) {
155+
unsigned int key = irq_lock();
156+
157+
int ret = onoff_cancel_or_release(mgr, &hfclk_cli);
158+
__ASSERT_NO_MSG(ret >= 0);
159+
(void)ret;
160+
161+
if (IS_ENABLED(CONFIG_NRF_802154_CONSTLAT_CONTROL)) {
162+
nrf_sys_event_release_global_constlat();
163+
}
164+
165+
hfclk_is_running = false;
83166

84-
if (IS_ENABLED(CONFIG_NRF_802154_CONSTLAT_CONTROL)) {
85-
nrf_sys_event_release_global_constlat();
167+
irq_unlock(key);
86168
}
87169

88-
hfclk_is_running = false;
170+
enabled = false;
89171
}
90172

91173
#elif DT_NODE_HAS_STATUS(DT_NODELABEL(hfxo), okay) && \
92174
DT_NODE_HAS_COMPAT(DT_NODELABEL(hfxo), nordic_nrf54h_hfxo)
93175

94-
void nrf_802154_clock_hfclk_start(void)
176+
static void hfclk_start(void)
95177
{
96-
sys_notify_init_callback(&hfclk_cli.notify, hfclk_on_callback);
97-
int ret = nrf_clock_control_request(DEVICE_DT_GET(DT_NODELABEL(hfxo)), NULL, &hfclk_cli);
178+
if (!enabled) {
179+
unsigned int key = irq_lock();
180+
181+
sys_notify_init_callback(&hfclk_cli.notify, hfclk_on_callback);
182+
int ret = nrf_clock_control_request(DEVICE_DT_GET(DT_NODELABEL(hfxo)), NULL, &hfclk_cli);
183+
184+
__ASSERT_NO_MSG(ret >= 0);
185+
(void)ret;
186+
187+
irq_unlock(key);
188+
}
98189

99-
__ASSERT_NO_MSG(ret >= 0);
100-
(void)ret;
190+
enabled = true;
101191
}
102192

103-
void nrf_802154_clock_hfclk_stop(void)
193+
static void hfclk_stop(void)
104194
{
105-
int ret = nrf_clock_control_cancel_or_release(DEVICE_DT_GET(DT_NODELABEL(hfxo)),
106-
NULL, &hfclk_cli);
195+
if (enabled) {
196+
unsigned int key = irq_lock();
197+
198+
int ret = nrf_clock_control_cancel_or_release(DEVICE_DT_GET(DT_NODELABEL(hfxo)),
199+
NULL, &hfclk_cli);
200+
201+
__ASSERT_NO_MSG(ret >= 0);
202+
(void)ret;
203+
204+
irq_unlock(key);
205+
}
107206

108-
__ASSERT_NO_MSG(ret >= 0);
109-
(void)ret;
207+
enabled = false;
110208
}
111209

112210
#endif

west.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ manifest:
200200
groups:
201201
- hal
202202
- name: hal_nordic
203-
revision: 2f5d4e5868ab573eac932fa4bc142565073c3c04
203+
revision: pull/313/head
204204
path: modules/hal/nordic
205205
groups:
206206
- hal

0 commit comments

Comments
 (0)