1 /*
2 * Copyright (c) 2025 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /**
8 * @brief File containing API definitions for the
9 * HAL Layer of the Wi-Fi driver in the radio test mode of operation.
10 */
11
12 #include "queue.h"
13 #include "common/hal_structs_common.h"
14 #include "common/hal_common.h"
15 #include "common/hal_reg.h"
16 #include "common/hal_mem.h"
17 #include "common/hal_interrupt.h"
18 #include "common/pal.h"
19 #include "radio_test/hal_api.h"
20
event_tasklet_fn(unsigned long data)21 static void event_tasklet_fn(unsigned long data)
22 {
23 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
24 struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
25 unsigned long flags = 0;
26
27 hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
28
29 nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
30 &flags);
31
32 if (hal_dev_ctx->hal_status != NRF_WIFI_HAL_STATUS_ENABLED) {
33 /* Ignore the interrupt if the HAL is not enabled */
34 status = NRF_WIFI_STATUS_SUCCESS;
35 goto out;
36 }
37
38 status = hal_rpu_eventq_process(hal_dev_ctx);
39
40 if (status != NRF_WIFI_STATUS_SUCCESS) {
41 nrf_wifi_osal_log_err("%s: Event queue processing failed",
42 __func__);
43 }
44
45 out:
46 nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
47 &flags);
48 }
49
50
hal_rpu_recovery(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)51 static enum nrf_wifi_status hal_rpu_recovery(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
52 {
53 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
54
55 if (!hal_dev_ctx->hpriv->rpu_recovery_callbk_fn) {
56 nrf_wifi_osal_log_dbg("%s: RPU recovery callback not registered",
57 __func__);
58 goto out;
59 }
60
61 status = hal_dev_ctx->hpriv->rpu_recovery_callbk_fn(hal_dev_ctx->mac_dev_ctx, NULL, 0);
62 if (status != NRF_WIFI_STATUS_SUCCESS) {
63 nrf_wifi_osal_log_err("%s: RPU recovery failed",
64 __func__);
65 goto out;
66 }
67
68 out:
69 return status;
70 }
71
recovery_tasklet_fn(unsigned long data)72 static void recovery_tasklet_fn(unsigned long data)
73 {
74 struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
75 unsigned long flags = 0;
76
77 hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
78 if (!hal_dev_ctx) {
79 nrf_wifi_osal_log_err("%s: Invalid hal_dev_ctx",
80 __func__);
81 return;
82 }
83
84 nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_recovery,
85 &flags);
86 hal_rpu_recovery(hal_dev_ctx);
87 nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_recovery,
88 &flags);
89 }
90
91
nrf_wifi_rt_hal_dev_add(struct nrf_wifi_hal_priv * hpriv,void * mac_dev_ctx)92 struct nrf_wifi_hal_dev_ctx *nrf_wifi_rt_hal_dev_add(struct nrf_wifi_hal_priv *hpriv,
93 void *mac_dev_ctx)
94 {
95 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
96 struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
97
98 hal_dev_ctx = nrf_wifi_osal_mem_zalloc(sizeof(*hal_dev_ctx));
99
100 if (!hal_dev_ctx) {
101 nrf_wifi_osal_log_err("%s: Unable to allocate hal_dev_ctx",
102 __func__);
103 goto err;
104 }
105
106 hal_dev_ctx->hpriv = hpriv;
107 hal_dev_ctx->mac_dev_ctx = mac_dev_ctx;
108 hal_dev_ctx->idx = hpriv->num_devs++;
109
110 hal_dev_ctx->num_cmds = RPU_CMD_START_MAGIC;
111
112 hal_dev_ctx->cmd_q = nrf_wifi_utils_q_alloc();
113
114 if (!hal_dev_ctx->cmd_q) {
115 nrf_wifi_osal_log_err("%s: Unable to allocate command queue",
116 __func__);
117 goto hal_dev_free;
118 }
119
120 hal_dev_ctx->event_q = nrf_wifi_utils_q_alloc();
121
122 if (!hal_dev_ctx->event_q) {
123 nrf_wifi_osal_log_err("%s: Unable to allocate event queue",
124 __func__);
125 goto cmd_q_free;
126 }
127
128 hal_dev_ctx->lock_hal = nrf_wifi_osal_spinlock_alloc();
129
130 if (!hal_dev_ctx->lock_hal) {
131 nrf_wifi_osal_log_err("%s: Unable to allocate HAL lock", __func__);
132 hal_dev_ctx = NULL;
133 goto event_q_free;
134 }
135
136 nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_hal);
137
138 hal_dev_ctx->lock_rx = nrf_wifi_osal_spinlock_alloc();
139
140 if (!hal_dev_ctx->lock_rx) {
141 nrf_wifi_osal_log_err("%s: Unable to allocate HAL lock",
142 __func__);
143 goto lock_hal_free;
144 }
145
146 nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_rx);
147
148 hal_dev_ctx->event_tasklet = nrf_wifi_osal_tasklet_alloc(NRF_WIFI_TASKLET_TYPE_BH);
149
150 if (!hal_dev_ctx->event_tasklet) {
151 nrf_wifi_osal_log_err("%s: Unable to allocate event_tasklet",
152 __func__);
153 goto lock_rx_free;
154 }
155
156 nrf_wifi_osal_tasklet_init(hal_dev_ctx->event_tasklet,
157 event_tasklet_fn,
158 (unsigned long)hal_dev_ctx);
159
160 hal_dev_ctx->recovery_tasklet = nrf_wifi_osal_tasklet_alloc(NRF_WIFI_TASKLET_TYPE_BH);
161 if (!hal_dev_ctx->recovery_tasklet) {
162 nrf_wifi_osal_log_err("%s: Unable to allocate recovery_tasklet",
163 __func__);
164 goto event_tasklet_free;
165 }
166 nrf_wifi_osal_tasklet_init(hal_dev_ctx->recovery_tasklet,
167 recovery_tasklet_fn,
168 (unsigned long)hal_dev_ctx);
169
170 hal_dev_ctx->lock_recovery = nrf_wifi_osal_spinlock_alloc();
171 if (!hal_dev_ctx->lock_recovery) {
172 nrf_wifi_osal_log_err("%s: Unable to allocate recovery lock",
173 __func__);
174 goto recovery_tasklet_free;
175 }
176
177 nrf_wifi_osal_spinlock_init(hal_dev_ctx->lock_recovery);
178 #ifdef NRF_WIFI_LOW_POWER
179 status = hal_rpu_ps_init(hal_dev_ctx);
180
181 if (status != NRF_WIFI_STATUS_SUCCESS) {
182 nrf_wifi_osal_log_err("%s: hal_rpu_ps_init failed",
183 __func__);
184 goto lock_recovery_free;
185 }
186 #endif /* NRF_WIFI_LOW_POWER */
187
188 hal_dev_ctx->bal_dev_ctx = nrf_wifi_bal_dev_add(hpriv->bpriv,
189 hal_dev_ctx);
190
191 if (!hal_dev_ctx->bal_dev_ctx) {
192 nrf_wifi_osal_log_err("%s: nrf_wifi_bal_dev_add failed",
193 __func__);
194 goto lock_recovery_free;
195 }
196
197 status = hal_rpu_irq_enable(hal_dev_ctx);
198
199 if (status != NRF_WIFI_STATUS_SUCCESS) {
200 nrf_wifi_osal_log_err("%s: hal_rpu_irq_enable failed",
201 __func__);
202 goto bal_dev_free;
203 }
204
205 return hal_dev_ctx;
206 bal_dev_free:
207 nrf_wifi_bal_dev_rem(hal_dev_ctx->bal_dev_ctx);
208 lock_recovery_free:
209 nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_recovery);
210 recovery_tasklet_free:
211 nrf_wifi_osal_tasklet_free(hal_dev_ctx->recovery_tasklet);
212 event_tasklet_free:
213 nrf_wifi_osal_tasklet_free(hal_dev_ctx->event_tasklet);
214 lock_rx_free:
215 nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_rx);
216 lock_hal_free:
217 nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_hal);
218 event_q_free:
219 nrf_wifi_utils_q_free(hal_dev_ctx->event_q);
220 cmd_q_free:
221 nrf_wifi_utils_q_free(hal_dev_ctx->cmd_q);
222 hal_dev_free:
223 nrf_wifi_osal_mem_free(hal_dev_ctx);
224 hal_dev_ctx = NULL;
225 err:
226 return NULL;
227 }