Skip to content

Commit f444dbd

Browse files
e-rkjukkar
authored andcommitted
[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]> (cherry picked from commit 568a8ad)
1 parent e5acb17 commit f444dbd

File tree

2 files changed

+129
-29
lines changed

2 files changed

+129
-29
lines changed

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

Lines changed: 128 additions & 28 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>
17+
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
1637

1738
static bool hfclk_is_running;
39+
static bool enabled;
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,44 @@ 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+
nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, SWI_EVENT);
83+
84+
atomic_val_t previous = atomic_set(&request, CLOCK_NONE);
85+
86+
__ASSERT_NO_MSG(previous == CLOCK_REQUEST || previous == CLOCK_RELEASE);
87+
88+
switch (previous) {
89+
case CLOCK_REQUEST:
90+
hfclk_start();
91+
break;
92+
93+
case CLOCK_RELEASE:
94+
hfclk_stop();
95+
break;
96+
97+
default:
98+
break;
99+
}
100+
}
101+
}
102+
51103
void nrf_802154_clock_hfclk_start(void)
104+
{
105+
atomic_set(&request, CLOCK_REQUEST);
106+
nrf_egu_task_trigger(NRF_802154_EGU_INSTANCE, SWI_TASK);
107+
}
108+
109+
void nrf_802154_clock_hfclk_stop(void)
110+
{
111+
atomic_set(&request, CLOCK_RELEASE);
112+
nrf_egu_task_trigger(NRF_802154_EGU_INSTANCE, SWI_TASK);
113+
}
114+
115+
#if defined(CONFIG_CLOCK_CONTROL_NRF)
116+
static void hfclk_start(void)
52117
{
53118
struct onoff_manager *mgr =
54119
z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
@@ -57,56 +122,91 @@ void nrf_802154_clock_hfclk_start(void)
57122

58123
sys_notify_init_callback(&hfclk_cli.notify, hfclk_on_callback);
59124

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();
125+
if (!enabled) {
126+
unsigned int key = irq_lock();
127+
128+
/*
129+
* todo: replace constlat request with PM policy API when
130+
* controlling the event latency becomes possible.
131+
*/
132+
if (IS_ENABLED(CONFIG_NRF_802154_CONSTLAT_CONTROL)) {
133+
nrf_sys_event_request_global_constlat();
134+
}
135+
136+
int ret = onoff_request(mgr, &hfclk_cli);
137+
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+
159+
__ASSERT_NO_MSG(ret >= 0);
160+
(void)ret;
161+
162+
if (IS_ENABLED(CONFIG_NRF_802154_CONSTLAT_CONTROL)) {
163+
nrf_sys_event_release_global_constlat();
164+
}
165+
166+
hfclk_is_running = false;
83167

84-
if (IS_ENABLED(CONFIG_NRF_802154_CONSTLAT_CONTROL)) {
85-
nrf_sys_event_release_global_constlat();
168+
irq_unlock(key);
86169
}
87170

88-
hfclk_is_running = false;
171+
enabled = false;
89172
}
90173

91174
#elif DT_NODE_HAS_STATUS(DT_NODELABEL(hfxo), okay) && \
92175
DT_NODE_HAS_COMPAT(DT_NODELABEL(hfxo), nordic_nrf54h_hfxo)
93176

94-
void nrf_802154_clock_hfclk_start(void)
177+
static void hfclk_start(void)
95178
{
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);
179+
if (!enabled) {
180+
unsigned int key = irq_lock();
181+
182+
sys_notify_init_callback(&hfclk_cli.notify, hfclk_on_callback);
183+
int ret = nrf_clock_control_request(DEVICE_DT_GET(DT_NODELABEL(hfxo)),
184+
NULL, &hfclk_cli);
185+
186+
__ASSERT_NO_MSG(ret >= 0);
187+
(void)ret;
188+
189+
irq_unlock(key);
190+
}
98191

99-
__ASSERT_NO_MSG(ret >= 0);
100-
(void)ret;
192+
enabled = true;
101193
}
102194

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

108-
__ASSERT_NO_MSG(ret >= 0);
109-
(void)ret;
209+
enabled = false;
110210
}
111211

112212
#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: 9e1bc32436a71adf1aa55937046d659a2db9e74f
204204
path: modules/hal/nordic
205205
groups:
206206
- hal

0 commit comments

Comments
 (0)