1 /*
2  * Copyright (c) 2024 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.
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 
20 #ifdef NRF_WIFI_LOW_POWER
21 #ifdef NRF_WIFI_RPU_RECOVERY
did_rpu_had_sleep_opp(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)22 static void did_rpu_had_sleep_opp(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
23 {
24 	unsigned int deassert_time_diff_ms = nrf_wifi_osal_time_elapsed_ms(
25 		hal_dev_ctx->last_wakeup_now_deasserted_time_ms);
26 
27 	if (deassert_time_diff_ms > NRF_WIFI_RPU_MIN_TIME_TO_ENTER_SLEEP_MS) {
28 		hal_dev_ctx->last_rpu_sleep_opp_time_ms =
29 			hal_dev_ctx->last_wakeup_now_deasserted_time_ms;
30 	}
31 }
32 #endif /* NRF_WIFI_RPU_RECOVERY */
33 
hal_rpu_ps_wake(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)34 enum nrf_wifi_status hal_rpu_ps_wake(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
35 {
36 	unsigned int reg_val = 0;
37 	unsigned int rpu_ps_state_mask = 0;
38 	unsigned long start_time_us = 0;
39 	unsigned long idle_time_start_us = 0;
40 	unsigned long idle_time_us = 0;
41 	unsigned long elapsed_time_sec = 0;
42 	unsigned long elapsed_time_usec = 0;
43 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
44 
45 	if (!hal_dev_ctx) {
46 		nrf_wifi_osal_log_err("%s: Invalid parameters",
47 				      __func__);
48 		return status;
49 	}
50 
51 
52 	/* If the FW is not yet booted up (e.g. during the FW load stage of Host FW load)
53 	 * then skip the RPU wake attempt since RPU sleep/wake kicks in only after FW boot
54 	 */
55 	if (!hal_dev_ctx->rpu_fw_booted)
56 		return NRF_WIFI_STATUS_SUCCESS;
57 
58 	if (hal_dev_ctx->rpu_ps_state == RPU_PS_STATE_AWAKE) {
59 		status = NRF_WIFI_STATUS_SUCCESS;
60 
61 		goto out;
62 	}
63 
64 	nrf_wifi_bal_rpu_ps_wake(hal_dev_ctx->bal_dev_ctx);
65 #ifdef NRF_WIFI_RPU_RECOVERY
66 	hal_dev_ctx->is_wakeup_now_asserted = true;
67 	hal_dev_ctx->last_wakeup_now_asserted_time_ms =
68 		nrf_wifi_osal_time_get_curr_ms();
69 #endif /* NRF_WIFI_RPU_RECOVERY */
70 	start_time_us = nrf_wifi_osal_time_get_curr_us();
71 
72 	rpu_ps_state_mask = ((1 << RPU_REG_BIT_PS_STATE) |
73 			     (1 << RPU_REG_BIT_READY_STATE));
74 
75 	/* Add a delay to avoid a race condition in the RPU */
76 	/* TODO: Reduce to 200 us after sleep has been stabilized */
77 	nrf_wifi_osal_delay_us(1000);
78 
79 	do {
80 		/* Poll the RPU PS state */
81 		reg_val = nrf_wifi_bal_rpu_ps_status(hal_dev_ctx->bal_dev_ctx);
82 
83 		if ((reg_val & rpu_ps_state_mask) == rpu_ps_state_mask) {
84 			status = NRF_WIFI_STATUS_SUCCESS;
85 			break;
86 		}
87 
88 		idle_time_start_us = nrf_wifi_osal_time_get_curr_us();
89 
90 		do {
91 			idle_time_us = nrf_wifi_osal_time_elapsed_us(idle_time_start_us);
92 		} while ((idle_time_us / 1000) < RPU_PS_WAKE_INTERVAL_MS);
93 
94 		elapsed_time_usec = nrf_wifi_osal_time_elapsed_us(start_time_us);
95 		elapsed_time_sec = (elapsed_time_usec / 1000000);
96 	} while (elapsed_time_sec < RPU_PS_WAKE_TIMEOUT_S);
97 
98 	if (status != NRF_WIFI_STATUS_SUCCESS) {
99 		nrf_wifi_osal_log_err("%s: RPU is not ready for more than %d sec,"
100 				      "reg_val = 0x%X rpu_ps_state_mask = 0x%X",
101 				      __func__,
102 				      RPU_PS_WAKE_TIMEOUT_S,
103 				      reg_val,
104 				      rpu_ps_state_mask);
105 #ifdef NRF_WIFI_RPU_RECOVERY
106 		nrf_wifi_osal_tasklet_schedule(hal_dev_ctx->recovery_tasklet);
107 #endif /* NRF_WIFI_RPU_RECOVERY */
108 		goto out;
109 	}
110 	hal_dev_ctx->rpu_ps_state = RPU_PS_STATE_AWAKE;
111 #ifdef NRF_WIFI_RPU_RECOVERY
112 	did_rpu_had_sleep_opp(hal_dev_ctx);
113 #endif /* NRF_WIFI_RPU_RECOVERY */
114 #ifdef NRF_WIFI_RPU_RECOVERY_PS_STATE_DEBUG
115 	nrf_wifi_osal_log_info("%s: RPU PS state is AWAKE\n",
116 			       __func__);
117 #endif /* NRF_WIFI_RPU_RECOVERY_PS_STATE_DEBUG */
118 
119 out:
120 
121 	nrf_wifi_osal_timer_schedule(hal_dev_ctx->rpu_ps_timer,
122 		NRF70_RPU_PS_IDLE_TIMEOUT_MS);
123 	return status;
124 }
125 
126 
hal_rpu_ps_sleep(unsigned long data)127 static void hal_rpu_ps_sleep(unsigned long data)
128 {
129 	struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
130 	unsigned long flags = 0;
131 
132 	hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
133 
134 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->rpu_ps_lock,
135 					&flags);
136 
137 	nrf_wifi_bal_rpu_ps_sleep(hal_dev_ctx->bal_dev_ctx);
138 #ifdef NRF_WIFI_RPU_RECOVERY
139 	hal_dev_ctx->is_wakeup_now_asserted = false;
140 	hal_dev_ctx->last_wakeup_now_deasserted_time_ms =
141 		nrf_wifi_osal_time_get_curr_ms();
142 #endif /* NRF_WIFI_RPU_RECOVERY */
143 	hal_dev_ctx->rpu_ps_state = RPU_PS_STATE_ASLEEP;
144 
145 #ifdef NRF_WIFI_RPU_RECOVERY_PS_STATE_DEBUG
146 	nrf_wifi_osal_log_info("%s: RPU PS state is ASLEEP\n",
147 			       __func__);
148 #endif /* NRF_WIFI_RPU_RECOVERY_PS_STATE_DEBUG */
149 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->rpu_ps_lock,
150 				       &flags);
151 }
152 
153 
hal_rpu_ps_init(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)154 enum nrf_wifi_status hal_rpu_ps_init(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
155 {
156 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
157 
158 	hal_dev_ctx->rpu_ps_lock = nrf_wifi_osal_spinlock_alloc();
159 
160 	if (!hal_dev_ctx->rpu_ps_lock) {
161 		nrf_wifi_osal_log_err("%s: Unable to allocate lock",
162 				      __func__);
163 		goto out;
164 	}
165 
166 	nrf_wifi_osal_spinlock_init(hal_dev_ctx->rpu_ps_lock);
167 
168 	hal_dev_ctx->rpu_ps_timer = nrf_wifi_osal_timer_alloc();
169 
170 	if (!hal_dev_ctx->rpu_ps_timer) {
171 		nrf_wifi_osal_log_err("%s: Unable to allocate timer",
172 				      __func__);
173 		nrf_wifi_osal_spinlock_free(hal_dev_ctx->rpu_ps_lock);
174 		goto out;
175 	}
176 
177 	nrf_wifi_osal_timer_init(hal_dev_ctx->rpu_ps_timer,
178 				 hal_rpu_ps_sleep,
179 				 (unsigned long)hal_dev_ctx);
180 
181 	hal_dev_ctx->rpu_ps_state = RPU_PS_STATE_ASLEEP;
182 	hal_dev_ctx->dbg_enable = true;
183 
184 	status = NRF_WIFI_STATUS_SUCCESS;
185 out:
186 	return status;
187 }
188 
189 
hal_rpu_ps_deinit(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)190 static void hal_rpu_ps_deinit(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
191 {
192 	nrf_wifi_osal_timer_kill(hal_dev_ctx->rpu_ps_timer);
193 
194 	nrf_wifi_osal_timer_free(hal_dev_ctx->rpu_ps_timer);
195 
196 	nrf_wifi_osal_spinlock_free(hal_dev_ctx->rpu_ps_lock);
197 }
198 
nrf_wifi_hal_get_rpu_ps_state(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,int * rpu_ps_ctrl_state)199 enum nrf_wifi_status nrf_wifi_hal_get_rpu_ps_state(
200 				struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
201 				int *rpu_ps_ctrl_state)
202 {
203 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
204 
205 	if (!hal_dev_ctx) {
206 		nrf_wifi_osal_log_err("%s: Invalid parameters",
207 				      __func__);
208 		goto out;
209 	}
210 
211 	*rpu_ps_ctrl_state = hal_dev_ctx->rpu_ps_state;
212 
213 	return NRF_WIFI_STATUS_SUCCESS;
214 out:
215 	return status;
216 }
217 #endif /* NRF_WIFI_LOW_POWER */
218 
219 
hal_rpu_hpq_is_empty(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,struct host_rpu_hpq * hpq)220 static bool hal_rpu_hpq_is_empty(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
221 				 struct host_rpu_hpq *hpq)
222 {
223 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
224 	unsigned int val = 0;
225 
226 	status = hal_rpu_reg_read(hal_dev_ctx,
227 				  &val,
228 				  hpq->dequeue_addr);
229 
230 	if (status != NRF_WIFI_STATUS_SUCCESS) {
231 		nrf_wifi_osal_log_err("%s: Read from dequeue address failed, val (0x%X)",
232 				      __func__,
233 				      val);
234 		return true;
235 	}
236 
237 	if (val) {
238 		return false;
239 	}
240 
241 	return true;
242 }
243 
244 
hal_rpu_ready(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum NRF_WIFI_HAL_MSG_TYPE msg_type)245 static enum nrf_wifi_status hal_rpu_ready(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
246 					  enum NRF_WIFI_HAL_MSG_TYPE msg_type)
247 {
248 	bool is_empty = false;
249 	struct host_rpu_hpq *avl_buf_q = NULL;
250 
251 	if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) {
252 		avl_buf_q = &hal_dev_ctx->rpu_info.hpqm_info.cmd_avl_queue;
253 	} else {
254 		nrf_wifi_osal_log_err("%s: Invalid msg type %d",
255 				      __func__,
256 				      msg_type);
257 
258 		return NRF_WIFI_STATUS_FAIL;
259 	}
260 
261 	/* Check if any command pointers are available to post a message */
262 	is_empty = hal_rpu_hpq_is_empty(hal_dev_ctx,
263 					avl_buf_q);
264 
265 	if (is_empty == true) {
266 		return NRF_WIFI_STATUS_FAIL;
267 	}
268 
269 	return NRF_WIFI_STATUS_SUCCESS;
270 }
271 
272 
hal_rpu_ready_wait(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum NRF_WIFI_HAL_MSG_TYPE msg_type)273 static enum nrf_wifi_status hal_rpu_ready_wait(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
274 					       enum NRF_WIFI_HAL_MSG_TYPE msg_type)
275 {
276 	unsigned long start_time_us = 0;
277 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
278 
279 	start_time_us = nrf_wifi_osal_time_get_curr_us();
280 
281 	while (hal_rpu_ready(hal_dev_ctx, msg_type) != NRF_WIFI_STATUS_SUCCESS) {
282 		if (nrf_wifi_osal_time_elapsed_us(start_time_us) >= MAX_HAL_RPU_READY_WAIT) {
283 			nrf_wifi_osal_log_err("%s: Timed out waiting (msg_type = %d)",
284 					      __func__,
285 					      msg_type);
286 			goto out;
287 		}
288 	}
289 
290 	status = NRF_WIFI_STATUS_SUCCESS;
291 out:
292 	return status;
293 }
294 
295 
hal_rpu_msg_trigger(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)296 static enum nrf_wifi_status hal_rpu_msg_trigger(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
297 {
298 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
299 
300 	status = hal_rpu_reg_write(hal_dev_ctx,
301 				   RPU_REG_INT_TO_MCU_CTRL,
302 				   (hal_dev_ctx->num_cmds | 0x7fff0000));
303 
304 	if (status != NRF_WIFI_STATUS_SUCCESS) {
305 		nrf_wifi_osal_log_err("%s: Writing to MCU cmd register failed",
306 				      __func__);
307 		goto out;
308 	}
309 
310 	hal_dev_ctx->num_cmds++;
311 out:
312 	return status;
313 }
314 
315 
hal_rpu_msg_post(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum NRF_WIFI_HAL_MSG_TYPE msg_type,unsigned int queue_id,unsigned int msg_addr)316 enum nrf_wifi_status hal_rpu_msg_post(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
317 				      enum NRF_WIFI_HAL_MSG_TYPE msg_type,
318 				      unsigned int queue_id,
319 				      unsigned int msg_addr)
320 {
321 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
322 	struct host_rpu_hpq *busy_queue = NULL;
323 
324 	if (queue_id >= MAX_NUM_OF_RX_QUEUES) {
325 		nrf_wifi_osal_log_err("%s: Invalid queue_id (%d)",
326 				      __func__,
327 				      queue_id);
328 		goto out;
329 	}
330 
331 	if ((msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) ||
332 	    (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_TX)) {
333 		busy_queue = &hal_dev_ctx->rpu_info.hpqm_info.cmd_busy_queue;
334 	} else if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX) {
335 		busy_queue = &hal_dev_ctx->rpu_info.hpqm_info.rx_buf_busy_queue[queue_id];
336 	} else {
337 		nrf_wifi_osal_log_err("%s: Invalid msg_type (%d)",
338 				      __func__,
339 				      msg_type);
340 		goto out;
341 	}
342 
343 	/* Copy the address, to which information was posted,
344 	 * to the busy queue.
345 	 */
346 	status = hal_rpu_hpq_enqueue(hal_dev_ctx,
347 				     busy_queue,
348 				     msg_addr);
349 
350 	if (status != NRF_WIFI_STATUS_SUCCESS) {
351 		nrf_wifi_osal_log_err("%s: Queueing of message to RPU failed",
352 				      __func__);
353 		goto out;
354 	}
355 
356 	if (msg_type != NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX) {
357 		/* Indicate to the RPU that the information has been posted */
358 		status = hal_rpu_msg_trigger(hal_dev_ctx);
359 
360 		if (status != NRF_WIFI_STATUS_SUCCESS) {
361 			nrf_wifi_osal_log_err("%s: Posting command to RPU failed",
362 					      __func__);
363 			goto out;
364 		}
365 	}
366 out:
367 	return status;
368 }
369 
370 
hal_rpu_msg_get_addr(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum NRF_WIFI_HAL_MSG_TYPE msg_type,unsigned int * msg_addr)371 static enum nrf_wifi_status hal_rpu_msg_get_addr(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
372 						 enum NRF_WIFI_HAL_MSG_TYPE msg_type,
373 						 unsigned int *msg_addr)
374 {
375 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
376 	struct host_rpu_hpq *avl_queue = NULL;
377 
378 	if (msg_type == NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL) {
379 		avl_queue = &hal_dev_ctx->rpu_info.hpqm_info.cmd_avl_queue;
380 	} else {
381 		nrf_wifi_osal_log_err("%s: Invalid msg_type (%d)",
382 				      __func__,
383 				      msg_type);
384 		goto out;
385 	}
386 
387 	status = hal_rpu_hpq_dequeue(hal_dev_ctx,
388 				     avl_queue,
389 				     msg_addr);
390 
391 	if (status != NRF_WIFI_STATUS_SUCCESS) {
392 		nrf_wifi_osal_log_err("%s: Dequeue of address failed msg_addr 0x%X",
393 				      __func__,
394 				      *msg_addr);
395 		*msg_addr = 0;
396 		goto out;
397 	}
398 out:
399 	return status;
400 }
401 
402 
hal_rpu_msg_write(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum NRF_WIFI_HAL_MSG_TYPE msg_type,void * msg,unsigned int len)403 static enum nrf_wifi_status hal_rpu_msg_write(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
404 					      enum NRF_WIFI_HAL_MSG_TYPE msg_type,
405 					      void *msg,
406 					      unsigned int len)
407 {
408 	unsigned int msg_addr = 0;
409 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
410 
411 	/* Get the address from the RPU to which
412 	 * the command needs to be copied to
413 	 */
414 	status = hal_rpu_msg_get_addr(hal_dev_ctx,
415 				      msg_type,
416 				      &msg_addr);
417 
418 	if (status != NRF_WIFI_STATUS_SUCCESS) {
419 		nrf_wifi_osal_log_err("%s: Getting address (0x%X) to post message failed",
420 				      __func__,
421 				      msg_addr);
422 		goto out;
423 	}
424 
425 	/* Copy the information to the suggested address */
426 	status = hal_rpu_mem_write(hal_dev_ctx,
427 				   msg_addr,
428 				   msg,
429 				   len);
430 
431 	if (status != NRF_WIFI_STATUS_SUCCESS) {
432 		nrf_wifi_osal_log_err("%s: Copying information to RPU failed",
433 				      __func__);
434 		goto out;
435 	}
436 
437 	/* Post the updated information to the RPU */
438 	status = hal_rpu_msg_post(hal_dev_ctx,
439 				  msg_type,
440 				  0,
441 				  msg_addr);
442 
443 	if (status != NRF_WIFI_STATUS_SUCCESS) {
444 		nrf_wifi_osal_log_err("%s: Posting command to RPU failed",
445 				      __func__);
446 		goto out;
447 	}
448 
449 out:
450 	return status;
451 }
452 
453 
hal_rpu_cmd_process_queue(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)454 static enum nrf_wifi_status hal_rpu_cmd_process_queue(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
455 {
456 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
457 	struct nrf_wifi_hal_msg *cmd = NULL;
458 
459 	while ((cmd = nrf_wifi_utils_q_dequeue(hal_dev_ctx->cmd_q))) {
460 		status = hal_rpu_ready_wait(hal_dev_ctx,
461 					    NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL);
462 
463 		if (status != NRF_WIFI_STATUS_SUCCESS) {
464 			nrf_wifi_osal_log_err("%s: Timeout waiting to get free cmd buff from RPU",
465 					      __func__);
466 			nrf_wifi_osal_mem_free(cmd);
467 			cmd = NULL;
468 			continue;
469 		}
470 
471 		status = hal_rpu_msg_write(hal_dev_ctx,
472 					   NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL,
473 					   cmd->data,
474 					   cmd->len);
475 
476 		if (status != NRF_WIFI_STATUS_SUCCESS) {
477 			nrf_wifi_osal_log_err("%s: Writing command to RPU failed",
478 					      __func__);
479 			nrf_wifi_osal_mem_free(cmd);
480 			cmd = NULL;
481 			continue;
482 		}
483 
484 		/* Free the command data and command */
485 		nrf_wifi_osal_mem_free(cmd);
486 		cmd = NULL;
487 	}
488 
489 	return status;
490 }
491 
492 
hal_rpu_cmd_queue(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,void * cmd,unsigned int cmd_size)493 static enum nrf_wifi_status hal_rpu_cmd_queue(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
494 					      void *cmd,
495 					      unsigned int cmd_size)
496 {
497 	int len = 0;
498 	int size = 0;
499 	char *data = NULL;
500 	struct nrf_wifi_hal_msg *hal_msg = NULL;
501 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
502 
503 	len = cmd_size;
504 	data = cmd;
505 
506 	if (len > hal_dev_ctx->hpriv->cfg_params.max_cmd_size) {
507 		while (len > 0) {
508 			if (len > hal_dev_ctx->hpriv->cfg_params.max_cmd_size) {
509 				size = hal_dev_ctx->hpriv->cfg_params.max_cmd_size;
510 			} else {
511 				size = len;
512 			}
513 
514 			hal_msg = nrf_wifi_osal_mem_zalloc(sizeof(*hal_msg) + size);
515 
516 			if (!hal_msg) {
517 				nrf_wifi_osal_log_err("%s: Unable to alloc buff for frag HAL cmd",
518 						      __func__);
519 				status = NRF_WIFI_STATUS_FAIL;
520 				goto out;
521 			}
522 
523 			nrf_wifi_osal_mem_cpy(hal_msg->data,
524 					      data,
525 					      size);
526 
527 			hal_msg->len = size;
528 
529 			status = nrf_wifi_utils_q_enqueue(hal_dev_ctx->cmd_q,
530 							  hal_msg);
531 
532 			if (status != NRF_WIFI_STATUS_SUCCESS) {
533 				nrf_wifi_osal_log_err("%s: Unable to queue frag HAL cmd",
534 						      __func__);
535 				goto out;
536 			}
537 
538 			len -= size;
539 			data += size;
540 		}
541 	} else {
542 		hal_msg = nrf_wifi_osal_mem_zalloc(sizeof(*hal_msg) + len);
543 
544 		if (!hal_msg) {
545 			nrf_wifi_osal_log_err("%s: Unable to allocate buffer for HAL command",
546 					      __func__);
547 			status = NRF_WIFI_STATUS_FAIL;
548 			goto out;
549 		}
550 
551 		nrf_wifi_osal_mem_cpy(hal_msg->data,
552 				      cmd,
553 				      len);
554 
555 		hal_msg->len = len;
556 
557 		status = nrf_wifi_utils_q_enqueue(hal_dev_ctx->cmd_q,
558 						  hal_msg);
559 
560 		if (status != NRF_WIFI_STATUS_SUCCESS) {
561 			nrf_wifi_osal_log_err("%s: Unable to queue fragmented command",
562 					      __func__);
563 			goto out;
564 		}
565 	}
566 
567 	/* Free the original command data */
568 	nrf_wifi_osal_mem_free(cmd);
569 
570 out:
571 	return status;
572 }
573 
574 
nrf_wifi_hal_ctrl_cmd_send(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,void * cmd,unsigned int cmd_size)575 enum nrf_wifi_status nrf_wifi_hal_ctrl_cmd_send(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
576 						void *cmd,
577 						unsigned int cmd_size)
578 {
579 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
580 
581 
582 #ifdef CONFIG_NRF_WIFI_CMD_EVENT_LOG
583 	nrf_wifi_osal_log_info("%s: caller %p\n",
584 			      __func__,
585 			      __builtin_return_address(0));
586 #else
587 	nrf_wifi_osal_log_dbg("%s: caller %p\n",
588 			     __func__,
589 			     __builtin_return_address(0));
590 #endif
591 	nrf_wifi_osal_spinlock_take(hal_dev_ctx->lock_hal);
592 
593 	status = hal_rpu_cmd_queue(hal_dev_ctx,
594 				   cmd,
595 				   cmd_size);
596 
597 	if (status != NRF_WIFI_STATUS_SUCCESS) {
598 		nrf_wifi_osal_log_err("%s: Queueing of command failed",
599 				      __func__);
600 		goto out;
601 	}
602 
603 	status = hal_rpu_cmd_process_queue(hal_dev_ctx);
604 
605 out:
606 	nrf_wifi_osal_spinlock_rel(hal_dev_ctx->lock_hal);
607 
608 	return status;
609 }
610 
611 
hal_rpu_eventq_process(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)612 enum nrf_wifi_status hal_rpu_eventq_process(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
613 {
614 	enum nrf_wifi_status status = NRF_WIFI_STATUS_SUCCESS;
615 	struct nrf_wifi_hal_msg *event = NULL;
616 	void *event_data = NULL;
617 	unsigned int event_len = 0;
618 
619 	while (1) {
620 		event = nrf_wifi_utils_q_dequeue(hal_dev_ctx->event_q);
621 		if (!event) {
622 			goto out;
623 		}
624 
625 		event_data = event->data;
626 		event_len = event->len;
627 
628 		/* Process the event further */
629 		status = hal_dev_ctx->hpriv->intr_callbk_fn(hal_dev_ctx->mac_dev_ctx,
630 							    event_data,
631 							    event_len);
632 
633 		if (status != NRF_WIFI_STATUS_SUCCESS) {
634 			nrf_wifi_osal_log_err("%s: Interrupt callback failed",
635 					      __func__);
636 		}
637 
638 		/* Free up the local buffer */
639 		nrf_wifi_osal_mem_free(event);
640 		event = NULL;
641 	}
642 
643 out:
644 	return status;
645 }
646 
hal_rpu_eventq_drain(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)647 static void hal_rpu_eventq_drain(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
648 {
649 	struct nrf_wifi_hal_msg *event = NULL;
650 	unsigned long flags = 0;
651 
652 	while (1) {
653 		nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
654 						&flags);
655 
656 		event = nrf_wifi_utils_q_dequeue(hal_dev_ctx->event_q);
657 
658 		nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
659 					       &flags);
660 
661 		if (!event) {
662 			goto out;
663 		}
664 
665 		/* Free up the local buffer */
666 		nrf_wifi_osal_mem_free(event);
667 		event = NULL;
668 	}
669 
670 out:
671 	return;
672 }
673 
nrf_wifi_hal_proc_ctx_set(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum RPU_PROC_TYPE proc)674 void nrf_wifi_hal_proc_ctx_set(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
675 			       enum RPU_PROC_TYPE proc)
676 {
677 	hal_dev_ctx->curr_proc = proc;
678 }
679 
680 
nrf_wifi_hal_dev_rem(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)681 void nrf_wifi_hal_dev_rem(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
682 {
683 	unsigned int i = 0;
684 
685 	nrf_wifi_osal_tasklet_kill(hal_dev_ctx->recovery_tasklet);
686 	nrf_wifi_osal_tasklet_free(hal_dev_ctx->recovery_tasklet);
687 	nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_recovery);
688 
689 	nrf_wifi_osal_tasklet_kill(hal_dev_ctx->event_tasklet);
690 
691 	nrf_wifi_osal_tasklet_free(hal_dev_ctx->event_tasklet);
692 
693 	hal_rpu_eventq_drain(hal_dev_ctx);
694 
695 	nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_hal);
696 	nrf_wifi_osal_spinlock_free(hal_dev_ctx->lock_rx);
697 
698 	nrf_wifi_utils_q_free(hal_dev_ctx->event_q);
699 
700 	nrf_wifi_utils_q_free(hal_dev_ctx->cmd_q);
701 
702 #ifdef NRF_WIFI_LOW_POWER
703 	hal_rpu_ps_deinit(hal_dev_ctx);
704 #endif /* NRF_WIFI_LOW_POWER */
705 
706 	nrf_wifi_bal_dev_rem(hal_dev_ctx->bal_dev_ctx);
707 
708 	nrf_wifi_osal_mem_free(hal_dev_ctx->tx_buf_info);
709 	hal_dev_ctx->tx_buf_info = NULL;
710 
711 	for (i = 0; i < MAX_NUM_OF_RX_QUEUES; i++) {
712 		nrf_wifi_osal_mem_free(hal_dev_ctx->rx_buf_info[i]);
713 		hal_dev_ctx->rx_buf_info[i] = NULL;
714 	}
715 
716 	hal_dev_ctx->hpriv->num_devs--;
717 
718 	nrf_wifi_osal_mem_free(hal_dev_ctx);
719 }
720 
721 
nrf_wifi_hal_dev_init(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)722 enum nrf_wifi_status nrf_wifi_hal_dev_init(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
723 {
724 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
725 
726 #ifdef NRF_WIFI_LOW_POWER
727 	hal_dev_ctx->rpu_fw_booted = true;
728 #endif /* NRF_WIFI_LOW_POWER */
729 
730 	status = nrf_wifi_bal_dev_init(hal_dev_ctx->bal_dev_ctx);
731 
732 	if (status != NRF_WIFI_STATUS_SUCCESS) {
733 		nrf_wifi_osal_log_err("%s: nrf_wifi_bal_dev_init failed",
734 				      __func__);
735 		goto out;
736 	}
737 
738 	/* Read the HPQM info for all the queues provided by the RPU
739 	 * (like command, event, RX buf queues etc)
740 	 */
741 	status = hal_rpu_mem_read(hal_dev_ctx,
742 				  &hal_dev_ctx->rpu_info.hpqm_info,
743 				  RPU_MEM_HPQ_INFO,
744 				  sizeof(hal_dev_ctx->rpu_info.hpqm_info));
745 
746 	if (status != NRF_WIFI_STATUS_SUCCESS) {
747 		nrf_wifi_osal_log_err("%s: Failed to get the HPQ info",
748 				      __func__);
749 		goto out;
750 	}
751 
752 	status = hal_rpu_mem_read(hal_dev_ctx,
753 				  &hal_dev_ctx->rpu_info.rx_cmd_base,
754 				  RPU_MEM_RX_CMD_BASE,
755 				  sizeof(hal_dev_ctx->rpu_info.rx_cmd_base));
756 
757 	if (status != NRF_WIFI_STATUS_SUCCESS) {
758 		nrf_wifi_osal_log_err("%s: Reading the RX cmd base failed",
759 				      __func__);
760 		goto out;
761 	}
762 
763 	hal_dev_ctx->rpu_info.tx_cmd_base = RPU_MEM_TX_CMD_BASE;
764 	nrf_wifi_hal_enable(hal_dev_ctx);
765 out:
766 	return status;
767 }
768 
769 
nrf_wifi_hal_dev_deinit(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)770 void nrf_wifi_hal_dev_deinit(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
771 {
772 	nrf_wifi_hal_disable(hal_dev_ctx);
773 	nrf_wifi_bal_dev_deinit(hal_dev_ctx->bal_dev_ctx);
774 	hal_rpu_eventq_drain(hal_dev_ctx);
775 }
776 
777 
nrf_wifi_hal_irq_handler(void * data)778 enum nrf_wifi_status nrf_wifi_hal_irq_handler(void *data)
779 {
780 	struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL;
781 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
782 	unsigned long flags = 0;
783 	bool do_rpu_recovery = false;
784 
785 	hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data;
786 
787 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
788 					&flags);
789 
790 	if (hal_dev_ctx->hal_status != NRF_WIFI_HAL_STATUS_ENABLED) {
791 		/* Ignore the interrupt if the HAL is not enabled */
792 		status = NRF_WIFI_STATUS_SUCCESS;
793 		goto out;
794 	}
795 
796 
797 	status = hal_rpu_irq_process(hal_dev_ctx, &do_rpu_recovery);
798 
799 	if (status != NRF_WIFI_STATUS_SUCCESS) {
800 		goto out;
801 	}
802 
803 	if (do_rpu_recovery) {
804 		nrf_wifi_osal_tasklet_schedule(hal_dev_ctx->recovery_tasklet);
805 		goto out;
806 	}
807 
808 	nrf_wifi_osal_tasklet_schedule(hal_dev_ctx->event_tasklet);
809 
810 out:
811 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
812 				       &flags);
813 	return status;
814 }
815 
816 
nrf_wifi_hal_poll_reg(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int reg_addr,unsigned int mask,unsigned int req_value,unsigned int poll_delay)817 static int nrf_wifi_hal_poll_reg(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
818 				 unsigned int reg_addr,
819 				 unsigned int mask,
820 				 unsigned int req_value,
821 				 unsigned int poll_delay)
822 {
823 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
824 	unsigned int val = 0;
825 	unsigned int count = 50;
826 
827 	do {
828 		status = hal_rpu_reg_read(hal_dev_ctx,
829 					  &val,
830 					  reg_addr);
831 
832 		if (status != NRF_WIFI_STATUS_SUCCESS) {
833 			nrf_wifi_osal_log_err("%s: Read from address (0x%X) failed, val (0x%X)",
834 					      __func__,
835 					      reg_addr,
836 					      val);
837 		}
838 
839 		if ((val & mask) == req_value) {
840 			status = NRF_WIFI_STATUS_SUCCESS;
841 			break;
842 		}
843 
844 		nrf_wifi_osal_sleep_ms(poll_delay);
845 	} while (count-- > 0);
846 
847 	if (count == 0) {
848 		nrf_wifi_osal_log_err("%s: Timed out polling on (0x%X)",
849 				      __func__,
850 				      reg_addr);
851 
852 		status = NRF_WIFI_STATUS_FAIL;
853 		goto out;
854 	}
855 out:
856 	return status;
857 }
858 
859 
860 /* Perform MIPS reset */
nrf_wifi_hal_proc_reset(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum RPU_PROC_TYPE rpu_proc)861 enum nrf_wifi_status nrf_wifi_hal_proc_reset(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
862 					     enum RPU_PROC_TYPE rpu_proc)
863 {
864 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
865 
866 	if ((rpu_proc != RPU_PROC_TYPE_MCU_LMAC) &&
867 	    (rpu_proc != RPU_PROC_TYPE_MCU_UMAC)) {
868 		nrf_wifi_osal_log_err("%s: Unsupported RPU processor(%d)",
869 				      __func__,
870 				      rpu_proc);
871 		goto out;
872 	}
873 
874 	hal_dev_ctx->curr_proc = rpu_proc;
875 
876 	/* Perform pulsed soft reset of MIPS */
877 	if (rpu_proc == RPU_PROC_TYPE_MCU_LMAC) {
878 		status = hal_rpu_reg_write(hal_dev_ctx,
879 					   RPU_REG_MIPS_MCU_CONTROL,
880 					   0x1);
881 	} else {
882 		status = hal_rpu_reg_write(hal_dev_ctx,
883 					   RPU_REG_MIPS_MCU2_CONTROL,
884 					   0x1);
885 	}
886 
887 	if (status != NRF_WIFI_STATUS_SUCCESS) {
888 		nrf_wifi_osal_log_err("%s: Pulsed soft reset of MCU failed for (%d) processor",
889 				      __func__,
890 				      rpu_proc);
891 		goto out;
892 	}
893 
894 
895 	/* Wait for it to come out of reset */
896 	if (rpu_proc == RPU_PROC_TYPE_MCU_LMAC) {
897 		status = nrf_wifi_hal_poll_reg(hal_dev_ctx,
898 					       RPU_REG_MIPS_MCU_CONTROL,
899 					       0x1,
900 					       0,
901 					       10);
902 	} else {
903 		status = nrf_wifi_hal_poll_reg(hal_dev_ctx,
904 					       RPU_REG_MIPS_MCU2_CONTROL,
905 					       0x1,
906 					       0,
907 					       10);
908 	}
909 
910 	if (status != NRF_WIFI_STATUS_SUCCESS) {
911 		nrf_wifi_osal_log_err("%s: MCU (%d) failed to come out of reset",
912 				      __func__,
913 				      rpu_proc);
914 		goto out;
915 	}
916 
917 	/* MIPS will restart from it's boot exception registers
918 	 * and hit its default wait instruction
919 	 */
920 	if (rpu_proc == RPU_PROC_TYPE_MCU_LMAC) {
921 		status = nrf_wifi_hal_poll_reg(hal_dev_ctx,
922 					       0xA4000018,
923 					       0x1,
924 					       0x1,
925 					       10);
926 	} else {
927 		status = nrf_wifi_hal_poll_reg(hal_dev_ctx,
928 					       0xA4000118,
929 					       0x1,
930 					       0x1,
931 					       10);
932 	}
933 out:
934 	hal_dev_ctx->curr_proc = RPU_PROC_TYPE_MCU_LMAC;
935 	return status;
936 }
937 
938 #define MCU_FW_BOOT_TIMEOUT_MS 1000
nrf_wifi_hal_fw_chk_boot(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,enum RPU_PROC_TYPE rpu_proc)939 enum nrf_wifi_status nrf_wifi_hal_fw_chk_boot(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
940 					      enum RPU_PROC_TYPE rpu_proc)
941 {
942 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
943 	unsigned int addr = 0;
944 	unsigned int val = 0;
945 	unsigned int exp_val = 0;
946 	int mcu_ready_wait_count = MCU_FW_BOOT_TIMEOUT_MS / 10;
947 
948 	if (rpu_proc == RPU_PROC_TYPE_MCU_LMAC) {
949 		addr = RPU_MEM_LMAC_BOOT_SIG;
950 		exp_val = NRF_WIFI_LMAC_BOOT_SIG;
951 	} else if (rpu_proc == RPU_PROC_TYPE_MCU_UMAC) {
952 		addr = RPU_MEM_UMAC_BOOT_SIG;
953 		exp_val = NRF_WIFI_UMAC_BOOT_SIG;
954 	} else {
955 		nrf_wifi_osal_log_err("%s: Invalid RPU processor (%d)",
956 				      __func__,
957 				      rpu_proc);
958 	}
959 
960 	hal_dev_ctx->curr_proc = rpu_proc;
961 
962 	while (mcu_ready_wait_count-- > 0) {
963 		status = hal_rpu_mem_read(hal_dev_ctx,
964 					  (unsigned char *)&val,
965 					  addr,
966 					  sizeof(val));
967 
968 		if (status != NRF_WIFI_STATUS_SUCCESS) {
969 			nrf_wifi_osal_log_err("%s: Reading of boot signature failed for RPU(%d)",
970 					      __func__,
971 					      rpu_proc);
972 		}
973 
974 		if (val == exp_val) {
975 			break;
976 		}
977 
978 		/* Sleep for 10 ms */
979 		nrf_wifi_osal_sleep_ms(10);
980 	};
981 
982 	if (mcu_ready_wait_count <= 0) {
983 		nrf_wifi_osal_log_err("%s: Boot_sig check failed for RPU(%d), "
984 				      "Expected: 0x%X, Actual: 0x%X",
985 				      __func__,
986 				      rpu_proc,
987 				      exp_val,
988 				      val);
989 		status = NRF_WIFI_STATUS_FAIL;
990 		goto out;
991 	}
992 
993 	status = NRF_WIFI_STATUS_SUCCESS;
994 out:
995 	hal_dev_ctx->curr_proc = RPU_PROC_TYPE_MCU_LMAC;
996 
997 	return status;
998 }
999 
1000 
1001 struct nrf_wifi_hal_priv *
nrf_wifi_hal_init(struct nrf_wifi_hal_cfg_params * cfg_params,enum nrf_wifi_status (* intr_callbk_fn)(void * dev_ctx,void * event_data,unsigned int len),enum nrf_wifi_status (* rpu_recovery_callbk_fn)(void * mac_ctx,void * event_data,unsigned int len))1002 nrf_wifi_hal_init(struct nrf_wifi_hal_cfg_params *cfg_params,
1003 		  enum nrf_wifi_status (*intr_callbk_fn)(void *dev_ctx,
1004 							 void *event_data,
1005 							 unsigned int len),
1006 		  enum nrf_wifi_status (*rpu_recovery_callbk_fn)(void *mac_ctx,
1007 								 void *event_data,
1008 								 unsigned int len))
1009 {
1010 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1011 	struct nrf_wifi_hal_priv *hpriv = NULL;
1012 	struct nrf_wifi_bal_cfg_params bal_cfg_params;
1013 
1014 	hpriv = nrf_wifi_osal_mem_zalloc(sizeof(*hpriv));
1015 
1016 	if (!hpriv) {
1017 		nrf_wifi_osal_log_err("%s: Unable to allocate memory for hpriv",
1018 				      __func__);
1019 		goto out;
1020 	}
1021 
1022 	nrf_wifi_osal_mem_cpy(&hpriv->cfg_params,
1023 			      cfg_params,
1024 			      sizeof(hpriv->cfg_params));
1025 
1026 	hpriv->intr_callbk_fn = intr_callbk_fn;
1027 	hpriv->rpu_recovery_callbk_fn = rpu_recovery_callbk_fn;
1028 
1029 	status = pal_rpu_addr_offset_get(RPU_ADDR_PKTRAM_START,
1030 					 &hpriv->addr_pktram_base,
1031 					 RPU_PROC_TYPE_MAX);
1032 
1033 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1034 		nrf_wifi_osal_log_err("%s: pal_rpu_addr_offset_get failed",
1035 				      __func__);
1036 		goto out;
1037 	}
1038 
1039 	bal_cfg_params.addr_pktram_base = hpriv->addr_pktram_base;
1040 
1041 	hpriv->bpriv = nrf_wifi_bal_init(&bal_cfg_params,
1042 					 &nrf_wifi_hal_irq_handler);
1043 
1044 	if (!hpriv->bpriv) {
1045 		nrf_wifi_osal_log_err("%s: Failed",
1046 				      __func__);
1047 		nrf_wifi_osal_mem_free(hpriv);
1048 		hpriv = NULL;
1049 	}
1050 out:
1051 	return hpriv;
1052 }
1053 
1054 
nrf_wifi_hal_deinit(struct nrf_wifi_hal_priv * hpriv)1055 void nrf_wifi_hal_deinit(struct nrf_wifi_hal_priv *hpriv)
1056 {
1057 	nrf_wifi_bal_deinit(hpriv->bpriv);
1058 
1059 	nrf_wifi_osal_mem_free(hpriv);
1060 }
1061 
1062 
nrf_wifi_hal_otp_info_get(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,struct host_rpu_umac_info * otp_info,unsigned int * otp_flags)1063 enum nrf_wifi_status nrf_wifi_hal_otp_info_get(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
1064 					       struct host_rpu_umac_info *otp_info,
1065 					       unsigned int *otp_flags)
1066 {
1067 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1068 
1069 	if (!hal_dev_ctx || !otp_info) {
1070 		nrf_wifi_osal_log_err("%s: Invalid parameters",
1071 				      __func__);
1072 		goto out;
1073 	}
1074 
1075 	status = hal_rpu_mem_read(hal_dev_ctx,
1076 				  otp_info,
1077 				  RPU_MEM_UMAC_BOOT_SIG,
1078 				  sizeof(*otp_info));
1079 
1080 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1081 		nrf_wifi_osal_log_err("%s: OTP info get failed",
1082 				      __func__);
1083 		goto out;
1084 	}
1085 
1086 	status = hal_rpu_mem_read(hal_dev_ctx,
1087 				  otp_flags,
1088 				  RPU_MEM_OTP_INFO_FLAGS,
1089 				  sizeof(*otp_flags));
1090 
1091 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1092 		nrf_wifi_osal_log_err("%s: OTP flags get failed",
1093 				      __func__);
1094 		goto out;
1095 	}
1096 out:
1097 	return status;
1098 }
1099 
1100 
nrf_wifi_hal_otp_ft_prog_ver_get(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int * ft_prog_ver)1101 enum nrf_wifi_status nrf_wifi_hal_otp_ft_prog_ver_get(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
1102 						      unsigned int *ft_prog_ver)
1103 {
1104 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1105 
1106 	if (!hal_dev_ctx || !ft_prog_ver) {
1107 		nrf_wifi_osal_log_err("%s: Invalid parameters",
1108 				      __func__);
1109 		goto out;
1110 	}
1111 
1112 	status = hal_rpu_mem_read(hal_dev_ctx,
1113 				  ft_prog_ver,
1114 				  RPU_MEM_OTP_FT_PROG_VERSION,
1115 				  sizeof(*ft_prog_ver));
1116 
1117 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1118 		nrf_wifi_osal_log_err("%s: FT program version get failed",
1119 				      __func__);
1120 		goto out;
1121 	}
1122 out:
1123 	return status;
1124 }
1125 
nrf_wifi_hal_otp_pack_info_get(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx,unsigned int * package_info)1126 enum nrf_wifi_status nrf_wifi_hal_otp_pack_info_get(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx,
1127 						    unsigned int *package_info)
1128 {
1129 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1130 
1131 	if (!hal_dev_ctx || !package_info) {
1132 		nrf_wifi_osal_log_err("%s: Invalid parameters",
1133 				      __func__);
1134 		goto out;
1135 	}
1136 
1137 	status = hal_rpu_mem_read(hal_dev_ctx,
1138 				  package_info,
1139 				  RPU_MEM_OTP_PACKAGE_TYPE,
1140 				  sizeof(*package_info));
1141 
1142 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1143 		nrf_wifi_osal_log_err("%s: Package info get failed",
1144 				      __func__);
1145 		goto out;
1146 	}
1147 out:
1148 	return status;
1149 }
1150 
nrf_wifi_hal_enable(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)1151 void nrf_wifi_hal_enable(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
1152 {
1153 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
1154 					NULL);
1155 	hal_dev_ctx->hal_status = NRF_WIFI_HAL_STATUS_ENABLED;
1156 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
1157 				       NULL);
1158 }
1159 
nrf_wifi_hal_disable(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)1160 void nrf_wifi_hal_disable(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
1161 {
1162 	nrf_wifi_osal_spinlock_irq_take(hal_dev_ctx->lock_rx,
1163 					NULL);
1164 	hal_dev_ctx->hal_status = NRF_WIFI_HAL_STATUS_DISABLED;
1165 	nrf_wifi_osal_spinlock_irq_rel(hal_dev_ctx->lock_rx,
1166 				       NULL);
1167 }
1168 
nrf_wifi_hal_status_unlocked(struct nrf_wifi_hal_dev_ctx * hal_dev_ctx)1169 enum NRF_WIFI_HAL_STATUS nrf_wifi_hal_status_unlocked(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx)
1170 {
1171 	return hal_dev_ctx->hal_status;
1172 }
1173