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  * FMAC IF Layer of the Wi-Fi driver.
10  */
11 
12 #include "host_rpu_umac_if.h"
13 #include "radio_test/fmac_api.h"
14 #include "radio_test/hal_api.h"
15 #include "radio_test/fmac_structs.h"
16 #include "common/fmac_util.h"
17 #include "radio_test/fmac_cmd.h"
18 #include "radio_test/fmac_event.h"
19 #include "util.h"
20 
21 #define RADIO_CMD_STATUS_TIMEOUT 5000
22 
23 
nrf_wifi_rt_fmac_fw_init(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct nrf_wifi_phy_rf_params * rf_params,bool rf_params_valid,int sleep_type,unsigned int phy_calib,enum op_band op_band,bool beamforming,struct nrf_wifi_tx_pwr_ctrl_params * tx_pwr_ctrl,struct nrf_wifi_board_params * board_params,unsigned char * country_code)24 static enum nrf_wifi_status nrf_wifi_rt_fmac_fw_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
25 						     struct nrf_wifi_phy_rf_params *rf_params,
26 						     bool rf_params_valid,
27 #ifdef NRF_WIFI_LOW_POWER
28 						     int sleep_type,
29 #endif /* NRF_WIFI_LOW_POWER */
30 						     unsigned int phy_calib,
31 						     enum op_band op_band,
32 						     bool beamforming,
33 						     struct nrf_wifi_tx_pwr_ctrl_params *tx_pwr_ctrl,
34 						     struct nrf_wifi_board_params *board_params,
35 						     unsigned char *country_code)
36 {
37 	unsigned long start_time_us = 0;
38 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
39 
40 	if (!fmac_dev_ctx) {
41 		nrf_wifi_osal_log_err("%s: Invalid device context",
42 				      __func__);
43 		goto out;
44 	}
45 
46 	status = umac_cmd_rt_init(fmac_dev_ctx,
47 				  rf_params,
48 				  rf_params_valid,
49 #ifdef NRF_WIFI_LOW_POWER
50 				  sleep_type,
51 #endif /* NRF_WIFI_LOWPOWER */
52 				  phy_calib,
53 				  op_band,
54 				  beamforming,
55 				  tx_pwr_ctrl,
56 				  board_params,
57 				  country_code);
58 
59 	if (status != NRF_WIFI_STATUS_SUCCESS) {
60 		nrf_wifi_osal_log_err("%s: UMAC init failed",
61 				      __func__);
62 		goto out;
63 	}
64 	start_time_us = nrf_wifi_osal_time_get_curr_us();
65 	while (!fmac_dev_ctx->fw_init_done) {
66 		nrf_wifi_osal_sleep_ms(1);
67 #define MAX_INIT_WAIT (5 * 1000 * 1000)
68 		if (nrf_wifi_osal_time_elapsed_us(start_time_us) >= MAX_INIT_WAIT) {
69 			break;
70 		}
71 	}
72 
73 	if (!fmac_dev_ctx->fw_init_done) {
74 		nrf_wifi_osal_log_err("%s: UMAC init timed out",
75 				      __func__);
76 		status = NRF_WIFI_STATUS_FAIL;
77 		goto out;
78 	}
79 
80 	status = NRF_WIFI_STATUS_SUCCESS;
81 
82 out:
83 	return status;
84 }
85 
nrf_wifi_rt_fmac_fw_deinit(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)86 static void nrf_wifi_rt_fmac_fw_deinit(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
87 {
88 }
89 
nrf_wifi_rt_fmac_dev_add(struct nrf_wifi_fmac_priv * fpriv,void * os_dev_ctx)90 struct nrf_wifi_fmac_dev_ctx *nrf_wifi_rt_fmac_dev_add(struct nrf_wifi_fmac_priv *fpriv,
91 						       void *os_dev_ctx)
92 {
93 	struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
94 	struct nrf_wifi_rt_fmac_dev_ctx *rt_fmac_dev_ctx = NULL;
95 
96 
97 	if (!fpriv || !os_dev_ctx) {
98 		return NULL;
99 	}
100 
101 	if (fpriv->op_mode != NRF_WIFI_OP_MODE_RT) {
102 		nrf_wifi_osal_log_err("%s: Invalid op mode",
103 				      __func__);
104 		goto out;
105 	}
106 
107 	fmac_dev_ctx = nrf_wifi_osal_mem_zalloc(sizeof(*fmac_dev_ctx) + sizeof(*rt_fmac_dev_ctx));
108 
109 	if (!fmac_dev_ctx) {
110 		nrf_wifi_osal_log_err("%s: Unable to allocate fmac_dev_ctx",
111 				      __func__);
112 		goto out;
113 	}
114 
115 	fmac_dev_ctx->fpriv = fpriv;
116 	fmac_dev_ctx->os_dev_ctx = os_dev_ctx;
117 
118 	fmac_dev_ctx->hal_dev_ctx = nrf_wifi_rt_hal_dev_add(fpriv->hpriv,
119 							    fmac_dev_ctx);
120 
121 	if (!fmac_dev_ctx->hal_dev_ctx) {
122 		nrf_wifi_osal_log_err("%s: nrf_wifi_rt_hal_dev_add failed",
123 				      __func__);
124 
125 		nrf_wifi_osal_mem_free(fmac_dev_ctx);
126 		fmac_dev_ctx = NULL;
127 		goto out;
128 	}
129 
130 	fmac_dev_ctx->op_mode = NRF_WIFI_OP_MODE_RT;
131 
132 out:
133 	return fmac_dev_ctx;
134 }
135 
136 
nrf_wifi_rt_fmac_dev_init(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,int sleep_type,unsigned int phy_calib,enum op_band op_band,bool beamforming,struct nrf_wifi_tx_pwr_ctrl_params * tx_pwr_ctrl_params,struct nrf_wifi_tx_pwr_ceil_params * tx_pwr_ceil_params,struct nrf_wifi_board_params * board_params,unsigned char * country_code)137 enum nrf_wifi_status nrf_wifi_rt_fmac_dev_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
138 #ifdef NRF_WIFI_LOW_POWER
139 					       int sleep_type,
140 #endif /* NRF_WIFI_LOW_POWER */
141 					       unsigned int phy_calib,
142 					       enum op_band op_band,
143 					       bool beamforming,
144 					       struct nrf_wifi_tx_pwr_ctrl_params *tx_pwr_ctrl_params,
145 					       struct nrf_wifi_tx_pwr_ceil_params *tx_pwr_ceil_params,
146 					       struct nrf_wifi_board_params *board_params,
147 					       unsigned char *country_code)
148 {
149 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
150 	struct nrf_wifi_fmac_otp_info otp_info;
151 	struct nrf_wifi_phy_rf_params phy_rf_params;
152 
153 	if (!fmac_dev_ctx) {
154 		nrf_wifi_osal_log_err("%s: Invalid device context",
155 				      __func__);
156 		goto out;
157 	}
158 
159 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
160 		nrf_wifi_osal_log_err("%s: Invalid op mode",
161 				      __func__);
162 		goto out;
163 	}
164 
165 	status = nrf_wifi_hal_dev_init(fmac_dev_ctx->hal_dev_ctx);
166 
167 	if (status != NRF_WIFI_STATUS_SUCCESS) {
168 		nrf_wifi_osal_log_err("%s: nrf_wifi_hal_dev_init failed",
169 				      __func__);
170 		goto out;
171 	}
172 
173 	fmac_dev_ctx->tx_pwr_ceil_params = nrf_wifi_osal_mem_alloc(sizeof(*tx_pwr_ceil_params));
174 	nrf_wifi_osal_mem_cpy(fmac_dev_ctx->tx_pwr_ceil_params,
175 			      tx_pwr_ceil_params,
176 			      sizeof(*tx_pwr_ceil_params));
177 
178 	nrf_wifi_osal_mem_set(&otp_info,
179 			      0xFF,
180 			      sizeof(otp_info));
181 
182 	status = nrf_wifi_hal_otp_info_get(fmac_dev_ctx->hal_dev_ctx,
183 					   &otp_info.info,
184 					   &otp_info.flags);
185 
186 	if (status != NRF_WIFI_STATUS_SUCCESS) {
187 		nrf_wifi_osal_log_err("%s: Fetching of RPU OTP information failed",
188 				      __func__);
189 		goto out;
190 	}
191 
192 	status = nrf_wifi_rt_fmac_rf_params_get(fmac_dev_ctx,
193 						&phy_rf_params);
194 
195 	if (status != NRF_WIFI_STATUS_SUCCESS) {
196 		nrf_wifi_osal_log_err("%s: RF parameters get failed",
197 				     __func__);
198 		goto out;
199 	}
200 
201 	status = nrf_wifi_rt_fmac_fw_init(fmac_dev_ctx,
202 				          &phy_rf_params,
203 				          true,
204 #ifdef NRF_WIFI_LOW_POWER
205 					  sleep_type,
206 #endif /* NRF_WIFI_LOW_POWER */
207 					  phy_calib,
208 					  op_band,
209 					  beamforming,
210 					  tx_pwr_ctrl_params,
211 					  board_params,
212 					  country_code);
213 
214 	if (status == NRF_WIFI_STATUS_FAIL) {
215 		nrf_wifi_osal_log_err("%s: nrf_wifi_sys_fmac_fw_init failed",
216 				      __func__);
217 		goto out;
218 	}
219 out:
220 	return status;
221 }
222 
nrf_wifi_rt_fmac_dev_deinit(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)223 void nrf_wifi_rt_fmac_dev_deinit(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
224 {
225 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
226 		nrf_wifi_osal_log_err("%s: Invalid op mode",
227 				      __func__);
228 		return;
229 	}
230 
231 	nrf_wifi_osal_mem_free(fmac_dev_ctx->tx_pwr_ceil_params);
232 	nrf_wifi_rt_fmac_fw_deinit(fmac_dev_ctx);
233 }
234 
nrf_wifi_rt_fmac_init(void)235 struct nrf_wifi_fmac_priv *nrf_wifi_rt_fmac_init(void)
236 {
237 	struct nrf_wifi_fmac_priv *fpriv = NULL;
238 	struct nrf_wifi_hal_cfg_params hal_cfg_params;
239 
240 	fpriv = nrf_wifi_osal_mem_zalloc(sizeof(*fpriv));
241 
242 	if (!fpriv) {
243 		nrf_wifi_osal_log_err("%s: Unable to allocate fpriv",
244 				      __func__);
245 		goto out;
246 	}
247 
248 	nrf_wifi_osal_mem_set(&hal_cfg_params,
249 			      0,
250 			      sizeof(hal_cfg_params));
251 
252 
253 	hal_cfg_params.max_cmd_size = MAX_NRF_WIFI_UMAC_CMD_SIZE;
254 	hal_cfg_params.max_event_size = MAX_EVENT_POOL_LEN;
255 
256 	fpriv->hpriv = nrf_wifi_hal_init(&hal_cfg_params,
257 					 &nrf_wifi_rt_fmac_event_callback,
258 					 NULL);
259 
260 	if (!fpriv->hpriv) {
261 		nrf_wifi_osal_log_err("%s: Unable to do HAL init",
262 				      __func__);
263 		nrf_wifi_osal_mem_free(fpriv);
264 		fpriv = NULL;
265 		goto out;
266 	}
267 
268 	fpriv->op_mode = NRF_WIFI_OP_MODE_RT;
269 out:
270 	return fpriv;
271 }
272 
273 
wait_for_radio_cmd_status(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int timeout)274 static enum nrf_wifi_status wait_for_radio_cmd_status(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
275 						      unsigned int timeout)
276 {
277 	unsigned int count = 0;
278 	enum nrf_wifi_cmd_status radio_cmd_status;
279 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
280 
281 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
282 	do {
283 		nrf_wifi_osal_sleep_ms(1);
284 		count++;
285 	} while ((!rt_dev_ctx->radio_cmd_done) &&
286 		 (count < timeout));
287 
288 	if (count == timeout) {
289 		nrf_wifi_osal_log_err("%s: Timed out (%d secs)",
290 				      __func__,
291 					 timeout / 1000);
292 		goto out;
293 	}
294 
295 	radio_cmd_status = rt_dev_ctx->radio_cmd_status;
296 
297 	if (radio_cmd_status != NRF_WIFI_UMAC_CMD_SUCCESS) {
298 		nrf_wifi_osal_log_err("%s: Radio test command failed with status %d",
299 				      __func__,
300 				      radio_cmd_status);
301 		goto out;
302 	}
303 	return NRF_WIFI_STATUS_SUCCESS;
304 
305 out:
306 	return NRF_WIFI_STATUS_FAIL;
307 }
308 
nrf_wifi_rt_fmac_radio_test_init(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct rpu_conf_params * params)309 enum nrf_wifi_status nrf_wifi_rt_fmac_radio_test_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
310 						      struct rpu_conf_params *params)
311 {
312 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
313 	struct nrf_wifi_radio_test_init_info init_params;
314 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
315 
316 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
317 		nrf_wifi_osal_log_err("%s: Invalid op mode",
318 				      __func__);
319 		goto out;
320 	}
321 
322 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
323 
324 	nrf_wifi_osal_mem_set(&init_params,
325 			      0,
326 			      sizeof(init_params));
327 
328 	nrf_wifi_osal_mem_cpy(init_params.rf_params,
329 			      params->rf_params,
330 			      NRF_WIFI_RF_PARAMS_SIZE);
331 
332 	nrf_wifi_osal_mem_cpy(&init_params.chan,
333 			      &params->chan,
334 			      sizeof(init_params.chan));
335 
336 	init_params.phy_threshold = params->phy_threshold;
337 	init_params.phy_calib = params->phy_calib;
338 
339 	rt_dev_ctx->radio_cmd_done = false;
340 	status = umac_cmd_rt_prog_init(fmac_dev_ctx,
341 				       &init_params);
342 
343 	if (status != NRF_WIFI_STATUS_SUCCESS) {
344 		nrf_wifi_osal_log_err("%s: Unable to init radio test",
345 				      __func__);
346 		goto out;
347 	}
348 
349 	status = wait_for_radio_cmd_status(fmac_dev_ctx,
350 					   RADIO_CMD_STATUS_TIMEOUT);
351 	if (status != NRF_WIFI_STATUS_SUCCESS) {
352 		goto out;
353 	}
354 
355 out:
356 	return status;
357 }
358 
359 
nrf_wifi_rt_fmac_prog_tx(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct rpu_conf_params * params)360 enum nrf_wifi_status nrf_wifi_rt_fmac_prog_tx(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
361 					      struct rpu_conf_params *params)
362 {
363 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
364 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
365 
366 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
367 		nrf_wifi_osal_log_err("%s: Invalid op mode",
368 				      __func__);
369 		goto out;
370 	}
371 
372 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
373 
374 	rt_dev_ctx->radio_cmd_done = false;
375 	status = umac_cmd_rt_prog_tx(fmac_dev_ctx,
376 				     params);
377 
378 	if (status != NRF_WIFI_STATUS_SUCCESS) {
379 		nrf_wifi_osal_log_err("%s: Unable to program radio test TX",
380 				      __func__);
381 		goto out;
382 	}
383 
384 	status = wait_for_radio_cmd_status(fmac_dev_ctx,
385 					   RADIO_CMD_STATUS_TIMEOUT);
386 	if (status != NRF_WIFI_STATUS_SUCCESS) {
387 		goto out;
388 	}
389 out:
390 	return status;
391 }
392 
393 
nrf_wifi_rt_fmac_prog_rx(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct rpu_conf_params * params)394 enum nrf_wifi_status nrf_wifi_rt_fmac_prog_rx(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
395 					      struct rpu_conf_params *params)
396 {
397 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
398 	struct rpu_conf_rx_radio_test_params rx_params;
399 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
400 
401 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
402 		nrf_wifi_osal_log_err("%s: Invalid op mode",
403 				      __func__);
404 		goto out;
405 	}
406 
407 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
408 
409 	nrf_wifi_osal_mem_set(&rx_params,
410 			      0,
411 			      sizeof(rx_params));
412 
413 	rx_params.nss = params->nss;
414 
415 	nrf_wifi_osal_mem_cpy(rx_params.rf_params,
416 			      params->rf_params,
417 			      NRF_WIFI_RF_PARAMS_SIZE);
418 
419 	nrf_wifi_osal_mem_cpy(&rx_params.chan,
420 			      &params->chan,
421 			      sizeof(rx_params.chan));
422 
423 	rx_params.phy_threshold = params->phy_threshold;
424 	rx_params.phy_calib = params->phy_calib;
425 	rx_params.rx = params->rx;
426 
427 	rt_dev_ctx->radio_cmd_done = false;
428 	status = umac_cmd_rt_prog_rx(fmac_dev_ctx,
429 				     &rx_params);
430 
431 	if (status != NRF_WIFI_STATUS_SUCCESS) {
432 		nrf_wifi_osal_log_err("%s: Unable to program radio test RX",
433 				      __func__);
434 		goto out;
435 	}
436 
437 	status = wait_for_radio_cmd_status(fmac_dev_ctx,
438 					   RADIO_CMD_STATUS_TIMEOUT);
439 	if (status != NRF_WIFI_STATUS_SUCCESS) {
440 		goto out;
441 	}
442 out:
443 	return status;
444 }
445 
446 
nrf_wifi_rt_fmac_rf_test_rx_cap(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,enum nrf_wifi_rf_test rf_test_type,void * cap_data,unsigned short int num_samples,unsigned short int capture_timeout,unsigned char lna_gain,unsigned char bb_gain,unsigned char * capture_status)447 enum nrf_wifi_status nrf_wifi_rt_fmac_rf_test_rx_cap(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
448 						     enum nrf_wifi_rf_test rf_test_type,
449 						     void *cap_data,
450 						     unsigned short int num_samples,
451 						     unsigned short int capture_timeout ,
452 						     unsigned char lna_gain,
453 						     unsigned char bb_gain,
454 						     unsigned char *capture_status)
455 {
456 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
457 	struct nrf_wifi_rf_test_capture_params rf_test_cap_params;
458 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
459 	unsigned int count = 0;
460 
461 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
462 		nrf_wifi_osal_log_err("%s: Invalid op mode",
463 				      __func__);
464 		goto out;
465 	}
466 
467 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
468 
469 	nrf_wifi_osal_mem_set(&rf_test_cap_params,
470 			      0,
471 			      sizeof(rf_test_cap_params));
472 
473 	rf_test_cap_params.test = rf_test_type;
474 	rf_test_cap_params.cap_len = num_samples;
475 	rf_test_cap_params.cap_time = capture_timeout;
476 	rf_test_cap_params.lna_gain = lna_gain;
477 	rf_test_cap_params.bb_gain = bb_gain;
478 
479 	rt_dev_ctx->rf_test_type = rf_test_type;
480 	rt_dev_ctx->rf_test_cap_data = cap_data;
481 	rt_dev_ctx->rf_test_cap_sz = (num_samples * 3);
482 	rt_dev_ctx->capture_status = 0;
483 
484 	status = umac_cmd_rt_prog_rf_test(fmac_dev_ctx,
485 					  &rf_test_cap_params,
486 					  sizeof(rf_test_cap_params));
487 
488 	if (status != NRF_WIFI_STATUS_SUCCESS) {
489 		nrf_wifi_osal_log_err("%s: umac_cmd_rt_prog_rf_test_cap failed",
490 				      __func__);
491 
492 		goto out;
493 	}
494 
495 	do {
496 		nrf_wifi_osal_sleep_ms(100);
497 		count++;
498 	} while ((rt_dev_ctx->rf_test_type != NRF_WIFI_RF_TEST_MAX) &&
499 		 (count < (RX_CAPTURE_TIMEOUT_CONST * capture_timeout)));
500 
501 	if (count == (RX_CAPTURE_TIMEOUT_CONST * capture_timeout)) {
502 		nrf_wifi_osal_log_err("%s: Timed out",
503 				      __func__);
504 		rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
505 		rt_dev_ctx->rf_test_cap_data = NULL;
506 		status = NRF_WIFI_STATUS_FAIL;
507 		goto out;
508 	}
509 	*capture_status = rt_dev_ctx->capture_status;
510 
511 out:
512 	return status;
513 }
514 
515 
nrf_wifi_rt_fmac_rf_test_tx_tone(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char enable,signed char tone_freq,signed char tx_power)516 enum nrf_wifi_status nrf_wifi_rt_fmac_rf_test_tx_tone(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
517 						      unsigned char enable,
518 						      signed char tone_freq,
519 						      signed char tx_power)
520 {
521 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
522 	struct nrf_wifi_rf_test_tx_params rf_test_tx_params;
523 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
524 	unsigned int count = 0;
525 
526 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
527 		nrf_wifi_osal_log_err("%s: Invalid op mode",
528 				      __func__);
529 		goto out;
530 	}
531 
532 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
533 
534 	nrf_wifi_osal_mem_set(&rf_test_tx_params,
535 			      0,
536 			      sizeof(rf_test_tx_params));
537 
538 	rf_test_tx_params.test = NRF_WIFI_RF_TEST_TX_TONE;
539 	rf_test_tx_params.tone_freq = tone_freq;
540 	rf_test_tx_params.tx_pow = tx_power;
541 	rf_test_tx_params.enabled = enable;
542 
543 	rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_TX_TONE;
544 	rt_dev_ctx->rf_test_cap_data = NULL;
545 	rt_dev_ctx->rf_test_cap_sz = 0;
546 
547 	status = umac_cmd_rt_prog_rf_test(fmac_dev_ctx,
548 					  &rf_test_tx_params,
549 					  sizeof(rf_test_tx_params));
550 
551 	if (status != NRF_WIFI_STATUS_SUCCESS) {
552 		nrf_wifi_osal_log_err("%s: umac_cmd_rt_prog_rf_test_tx_tone failed",
553 				      __func__);
554 
555 		goto out;
556 	}
557 
558 	do {
559 		nrf_wifi_osal_sleep_ms(100);
560 		count++;
561 	} while ((rt_dev_ctx->rf_test_type != NRF_WIFI_RF_TEST_MAX) &&
562 		 (count < NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT));
563 
564 	if (count == NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT) {
565 		nrf_wifi_osal_log_err("%s: Timed out",
566 				      __func__);
567 		rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
568 		rt_dev_ctx->rf_test_cap_data = NULL;
569 		status = NRF_WIFI_STATUS_FAIL;
570 		goto out;
571 	}
572 
573 out:
574 	return status;
575 }
576 
577 
nrf_wifi_rt_fmac_rf_test_dpd(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char enable)578 enum nrf_wifi_status nrf_wifi_rt_fmac_rf_test_dpd(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
579 						  unsigned char enable)
580 {
581 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
582 	struct nrf_wifi_rf_test_dpd_params rf_test_dpd_params;
583 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
584 	unsigned int count = 0;
585 
586 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
587 		nrf_wifi_osal_log_err("%s: Invalid op mode",
588 				      __func__);
589 		goto out;
590 	}
591 
592 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
593 
594 	nrf_wifi_osal_mem_set(&rf_test_dpd_params,
595 			      0,
596 			      sizeof(rf_test_dpd_params));
597 
598 	rf_test_dpd_params.test = NRF_WIFI_RF_TEST_DPD;
599 	rf_test_dpd_params.enabled = enable;
600 
601 	rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_DPD;
602 	rt_dev_ctx->rf_test_cap_data = NULL;
603 	rt_dev_ctx->rf_test_cap_sz = 0;
604 
605 	status = umac_cmd_rt_prog_rf_test(fmac_dev_ctx,
606 					  &rf_test_dpd_params,
607 					  sizeof(rf_test_dpd_params));
608 
609 	if (status != NRF_WIFI_STATUS_SUCCESS) {
610 		nrf_wifi_osal_log_err("%s: umac_cmd_rt_prog_rf_test_dpd failed",
611 				      __func__);
612 
613 		goto out;
614 	}
615 
616 	do {
617 		nrf_wifi_osal_sleep_ms(100);
618 		count++;
619 	} while ((rt_dev_ctx->rf_test_type != NRF_WIFI_RF_TEST_MAX) &&
620 		 (count < NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT));
621 
622 	if (count == NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT) {
623 		nrf_wifi_osal_log_err("%s: Timed out",
624 				      __func__);
625 		rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
626 		rt_dev_ctx->rf_test_cap_data = NULL;
627 		status = NRF_WIFI_STATUS_FAIL;
628 		goto out;
629 	}
630 
631 out:
632 	return status;
633 }
634 
635 
nrf_wifi_rt_fmac_rf_get_temp(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)636 enum nrf_wifi_status nrf_wifi_rt_fmac_rf_get_temp(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
637 {
638 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
639 	struct nrf_wifi_temperature_params rf_test_get_temperature;
640 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
641 	unsigned int count = 0;
642 
643 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
644 		nrf_wifi_osal_log_err("%s: Invalid op mode",
645 				      __func__);
646 		goto out;
647 	}
648 
649 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
650 
651 	nrf_wifi_osal_mem_set(&rf_test_get_temperature,
652 			      0,
653 			      sizeof(rf_test_get_temperature));
654 
655 	rf_test_get_temperature.test = NRF_WIFI_RF_TEST_GET_TEMPERATURE;
656 
657 	rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_GET_TEMPERATURE;
658 	rt_dev_ctx->rf_test_cap_data = NULL;
659 	rt_dev_ctx->rf_test_cap_sz = 0;
660 
661 	status = umac_cmd_rt_prog_rf_test(fmac_dev_ctx,
662 					  &rf_test_get_temperature,
663 					  sizeof(rf_test_get_temperature));
664 
665 	if (status != NRF_WIFI_STATUS_SUCCESS) {
666 		nrf_wifi_osal_log_err("%s: umac_cmd_rt_prog_rf_get_temperature failed",
667 				      __func__);
668 
669 		goto out;
670 	}
671 
672 	do {
673 		nrf_wifi_osal_sleep_ms(100);
674 		count++;
675 	} while ((rt_dev_ctx->rf_test_type != NRF_WIFI_RF_TEST_MAX) &&
676 		 (count < NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT));
677 
678 	if (count == NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT) {
679 		nrf_wifi_osal_log_err("%s: Timed out",
680 				      __func__);
681 		rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
682 		rt_dev_ctx->rf_test_cap_data = NULL;
683 		status = NRF_WIFI_STATUS_FAIL;
684 		goto out;
685 	}
686 
687 out:
688 	return status;
689 }
690 
nrf_wifi_rt_fmac_rf_get_rf_rssi(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)691 enum nrf_wifi_status nrf_wifi_rt_fmac_rf_get_rf_rssi(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
692 {
693 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
694 	struct nrf_wifi_rf_get_rf_rssi rf_get_rf_rssi_params;
695 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
696 	unsigned int count = 0;
697 
698 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
699 		nrf_wifi_osal_log_err("%s: Invalid op mode",
700 				      __func__);
701 		goto out;
702 	}
703 
704 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
705 
706 	nrf_wifi_osal_mem_set(&rf_get_rf_rssi_params,
707 			      0,
708 			      sizeof(rf_get_rf_rssi_params));
709 
710 	rf_get_rf_rssi_params.test = NRF_WIFI_RF_TEST_RF_RSSI;
711 	rf_get_rf_rssi_params.lna_gain = 3;
712 	rf_get_rf_rssi_params.bb_gain = 10;
713 
714 	rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_RF_RSSI;
715 	rt_dev_ctx->rf_test_cap_data = NULL;
716 	rt_dev_ctx->rf_test_cap_sz = 0;
717 
718 	status = umac_cmd_rt_prog_rf_test(fmac_dev_ctx,
719 					  &rf_get_rf_rssi_params,
720 					  sizeof(rf_get_rf_rssi_params));
721 
722 	if (status != NRF_WIFI_STATUS_SUCCESS) {
723 		nrf_wifi_osal_log_err("%s: umac_cmd_rt_prog_rf_get_rf_rssi failed",
724 				      __func__);
725 
726 		goto out;
727 	}
728 
729 	do {
730 		nrf_wifi_osal_sleep_ms(100);
731 		count++;
732 	} while ((rt_dev_ctx->rf_test_type != NRF_WIFI_RF_TEST_MAX) &&
733 		 (count < NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT));
734 
735 	if (count == NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT) {
736 		nrf_wifi_osal_log_err("%s: Timed out",
737 				      __func__);
738 		rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
739 		rt_dev_ctx->rf_test_cap_data = NULL;
740 		status = NRF_WIFI_STATUS_FAIL;
741 		goto out;
742 	}
743 
744 out:
745 	return status;
746 }
747 
748 
nrf_wifi_rt_fmac_set_xo_val(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char value)749 enum nrf_wifi_status nrf_wifi_rt_fmac_set_xo_val(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
750 						 unsigned char value)
751 {
752 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
753 	struct nrf_wifi_rf_test_xo_calib nrf_wifi_rf_test_xo_calib_params;
754 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
755 	unsigned int count = 0;
756 
757 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
758 		nrf_wifi_osal_log_err("%s: Invalid op mode",
759 				      __func__);
760 		goto out;
761 	}
762 
763 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
764 
765 	nrf_wifi_osal_mem_set(&nrf_wifi_rf_test_xo_calib_params,
766 			      0,
767 			      sizeof(nrf_wifi_rf_test_xo_calib_params));
768 
769 	nrf_wifi_rf_test_xo_calib_params.test = NRF_WIFI_RF_TEST_XO_CALIB;
770 	nrf_wifi_rf_test_xo_calib_params.xo_val = value;
771 
772 
773 	rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_XO_CALIB;
774 	rt_dev_ctx->rf_test_cap_data = NULL;
775 	rt_dev_ctx->rf_test_cap_sz = 0;
776 
777 	status = umac_cmd_rt_prog_rf_test(fmac_dev_ctx,
778 					  &nrf_wifi_rf_test_xo_calib_params,
779 					  sizeof(nrf_wifi_rf_test_xo_calib_params));
780 
781 	if (status != NRF_WIFI_STATUS_SUCCESS) {
782 		nrf_wifi_osal_log_err("%s: umac_cmd_rt_prog_set_xo_val failed",
783 				      __func__);
784 
785 		goto out;
786 	}
787 
788 	do {
789 		nrf_wifi_osal_sleep_ms(100);
790 		count++;
791 	} while ((rt_dev_ctx->rf_test_type != NRF_WIFI_RF_TEST_MAX) &&
792 		 (count < NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT));
793 
794 	if (count == NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT) {
795 		nrf_wifi_osal_log_err("%s: Timed out",
796 				      __func__);
797 		rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
798 		rt_dev_ctx->rf_test_cap_data = NULL;
799 		status = NRF_WIFI_STATUS_FAIL;
800 		goto out;
801 	}
802 
803 out:
804 	return status;
805 }
806 
807 
nrf_wifi_rt_fmac_rf_test_compute_xo(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)808 enum nrf_wifi_status nrf_wifi_rt_fmac_rf_test_compute_xo(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
809 {
810 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
811 	struct nrf_wifi_rf_get_xo_value rf_get_xo_value_params;
812 	struct nrf_wifi_rt_fmac_dev_ctx *rt_dev_ctx = NULL;
813 	unsigned int count = 0;
814 
815 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
816 		nrf_wifi_osal_log_err("%s: Invalid op mode",
817 				      __func__);
818 		goto out;
819 	}
820 
821 	rt_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
822 
823 	nrf_wifi_osal_mem_set(&rf_get_xo_value_params,
824 			      0,
825 			      sizeof(rf_get_xo_value_params));
826 
827 	rf_get_xo_value_params.test = NRF_WIFI_RF_TEST_XO_TUNE;
828 
829 	rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_XO_TUNE;
830 	rt_dev_ctx->rf_test_cap_data = NULL;
831 	rt_dev_ctx->rf_test_cap_sz = 0;
832 
833 	status = umac_cmd_rt_prog_rf_test(fmac_dev_ctx,
834 					  &rf_get_xo_value_params,
835 					  sizeof(rf_get_xo_value_params));
836 
837 	if (status != NRF_WIFI_STATUS_SUCCESS) {
838 		nrf_wifi_osal_log_err("%s: umac_cmd_rt_prog_rf_get_xo_value failed",
839 				      __func__);
840 
841 		goto out;
842 	}
843 
844 	do {
845 		nrf_wifi_osal_sleep_ms(100);
846 		count++;
847 	} while ((rt_dev_ctx->rf_test_type != NRF_WIFI_RF_TEST_MAX) &&
848 		 (count < NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT));
849 
850 	if (count == NRF_WIFI_FMAC_RF_TEST_EVNT_TIMEOUT) {
851 		nrf_wifi_osal_log_err("%s: Timed out",
852 				      __func__);
853 		rt_dev_ctx->rf_test_type = NRF_WIFI_RF_TEST_MAX;
854 		rt_dev_ctx->rf_test_cap_data = NULL;
855 		status = NRF_WIFI_STATUS_FAIL;
856 		goto out;
857 	}
858 
859 out:
860 	return status;
861 }
862 
nrf_wifi_rt_fmac_stats_get(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,enum rpu_op_mode op_mode,struct rpu_rt_op_stats * stats)863 enum nrf_wifi_status nrf_wifi_rt_fmac_stats_get(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
864 						enum rpu_op_mode op_mode,
865 						struct rpu_rt_op_stats *stats)
866 {
867 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
868 	unsigned char count = 0;
869 
870 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
871 		nrf_wifi_osal_log_err("%s: Invalid op mode",
872 				      __func__);
873 		goto out;
874 	}
875 
876 	if (fmac_dev_ctx->stats_req == true) {
877 		nrf_wifi_osal_log_err("%s: Stats request already pending",
878 				      __func__);
879 		goto out;
880 	}
881 
882 	fmac_dev_ctx->stats_req = true;
883 	fmac_dev_ctx->fw_stats = &stats->fw;
884 
885 	status = umac_cmd_rt_prog_stats_get(fmac_dev_ctx,
886 					    op_mode);
887 
888 	if (status != NRF_WIFI_STATUS_SUCCESS) {
889 		goto out;
890 	}
891 
892 	do {
893 		nrf_wifi_osal_sleep_ms(1);
894 		count++;
895 	} while ((fmac_dev_ctx->stats_req == true) &&
896 		 (count < NRF_WIFI_FMAC_STATS_RECV_TIMEOUT));
897 
898 	if (count == NRF_WIFI_FMAC_STATS_RECV_TIMEOUT) {
899 		nrf_wifi_osal_log_err("%s: Timed out",
900 				      __func__);
901 		goto out;
902 	}
903 
904 	status = NRF_WIFI_STATUS_SUCCESS;
905 out:
906 	return status;
907 }
908 
nrf_wifi_rt_fmac_phy_rf_params_init(struct nrf_wifi_phy_rf_params * prf,unsigned int package_info,unsigned char * str)909 static int nrf_wifi_rt_fmac_phy_rf_params_init(struct nrf_wifi_phy_rf_params *prf,
910 					       unsigned int package_info,
911 					       unsigned char *str)
912 {
913 	int ret = -1;
914 	unsigned int rf_param_offset = BAND_2G_LW_ED_BKF_DSSS_OFST - NRF_WIFI_RF_PARAMS_CONF_SIZE;
915 	/* Initilaize reserved bytes */
916 	nrf_wifi_osal_mem_set(prf,
917 			      0x0,
918 			      sizeof(prf));
919 	/* Initialize PD adjust values for MCS7. Currently these 4 bytes are not being used */
920 	prf->pd_adjust_val.pd_adjt_lb_chan = PD_ADJUST_VAL;
921 	prf->pd_adjust_val.pd_adjt_hb_low_chan = PD_ADJUST_VAL;
922 	prf->pd_adjust_val.pd_adjt_hb_mid_chan = PD_ADJUST_VAL;
923 	prf->pd_adjust_val.pd_adjt_hb_high_chan = PD_ADJUST_VAL;
924 
925 	/* RX Gain offsets */
926 	prf->rx_gain_offset.rx_gain_lb_chan = CTRL_PWR_OPTIMIZATIONS;
927 	prf->rx_gain_offset.rx_gain_hb_low_chan = RX_GAIN_OFFSET_HB_LOW_CHAN;
928 	prf->rx_gain_offset.rx_gain_hb_mid_chan = RX_GAIN_OFFSET_HB_MID_CHAN;
929 	prf->rx_gain_offset.rx_gain_hb_high_chan = RX_GAIN_OFFSET_HB_HIGH_CHAN;
930 
931 	if (package_info == CSP_PACKAGE_INFO) {
932 		prf->xo_offset.xo_freq_offset = CSP_XO_VAL;
933 
934 		/* Configure systematic offset value */
935 		prf->syst_tx_pwr_offset.syst_off_lb_chan = CSP_SYSTEM_OFFSET_LB;
936 		prf->syst_tx_pwr_offset.syst_off_hb_low_chan = CSP_SYSTEM_OFFSET_HB_CHAN_LOW;
937 		prf->syst_tx_pwr_offset.syst_off_hb_mid_chan = CSP_SYSTEM_OFFSET_HB_CHAN_MID;
938 		prf->syst_tx_pwr_offset.syst_off_hb_high_chan = CSP_SYSTEM_OFFSET_HB_CHAN_HIGH;
939 
940 		/* TX power ceiling */
941 		prf->max_pwr_ceil.max_dsss_pwr = CSP_MAX_TX_PWR_DSSS;
942 		prf->max_pwr_ceil.max_lb_mcs7_pwr = CSP_MAX_TX_PWR_LB_MCS7;
943 		prf->max_pwr_ceil.max_lb_mcs0_pwr = CSP_MAX_TX_PWR_LB_MCS0;
944 		prf->max_pwr_ceil.max_hb_low_chan_mcs7_pwr = CSP_MAX_TX_PWR_HB_LOW_CHAN_MCS7;
945 		prf->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr = CSP_MAX_TX_PWR_HB_MID_CHAN_MCS7;
946 		prf->max_pwr_ceil.max_hb_high_chan_mcs7_pwr = CSP_MAX_TX_PWR_HB_HIGH_CHAN_MCS7;
947 		prf->max_pwr_ceil.max_hb_low_chan_mcs0_pwr = CSP_MAX_TX_PWR_HB_LOW_CHAN_MCS0;
948 		prf->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr = CSP_MAX_TX_PWR_HB_MID_CHAN_MCS0;
949 		prf->max_pwr_ceil.max_hb_high_chan_mcs0_pwr = CSP_MAX_TX_PWR_HB_HIGH_CHAN_MCS0;
950 	} else {
951 		/** If nothing is written to OTP field corresponding to package info byte
952 		 * or if the package info field is corrupted then the default package
953 		 * package is QFN.
954 		 */
955 
956 		/* Initialize XO */
957 		prf->xo_offset.xo_freq_offset = QFN_XO_VAL;
958 
959 		/* Configure systematic offset value */
960 		prf->syst_tx_pwr_offset.syst_off_lb_chan = QFN_SYSTEM_OFFSET_LB;
961 		prf->syst_tx_pwr_offset.syst_off_hb_low_chan = QFN_SYSTEM_OFFSET_HB_CHAN_LOW;
962 		prf->syst_tx_pwr_offset.syst_off_hb_mid_chan = QFN_SYSTEM_OFFSET_HB_CHAN_MID;
963 		prf->syst_tx_pwr_offset.syst_off_hb_high_chan = QFN_SYSTEM_OFFSET_HB_CHAN_HIGH;
964 
965 		/* TX power ceiling */
966 		prf->max_pwr_ceil.max_dsss_pwr = QFN_MAX_TX_PWR_DSSS;
967 		prf->max_pwr_ceil.max_lb_mcs7_pwr = QFN_MAX_TX_PWR_LB_MCS7;
968 		prf->max_pwr_ceil.max_lb_mcs0_pwr = QFN_MAX_TX_PWR_LB_MCS0;
969 		prf->max_pwr_ceil.max_hb_low_chan_mcs7_pwr = QFN_MAX_TX_PWR_HB_LOW_CHAN_MCS7;
970 		prf->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr = QFN_MAX_TX_PWR_HB_MID_CHAN_MCS7;
971 		prf->max_pwr_ceil.max_hb_high_chan_mcs7_pwr = QFN_MAX_TX_PWR_HB_HIGH_CHAN_MCS7;
972 		prf->max_pwr_ceil.max_hb_low_chan_mcs0_pwr = QFN_MAX_TX_PWR_HB_LOW_CHAN_MCS0;
973 		prf->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr = QFN_MAX_TX_PWR_HB_MID_CHAN_MCS0;
974 		prf->max_pwr_ceil.max_hb_high_chan_mcs0_pwr = QFN_MAX_TX_PWR_HB_HIGH_CHAN_MCS0;
975 	}
976 
977 	ret = nrf_wifi_utils_hex_str_to_val((unsigned char *)&prf->phy_params,
978 					    sizeof(prf->phy_params),
979 					    str);
980 
981 	prf->phy_params[rf_param_offset]  = NRF70_BAND_2G_LOWER_EDGE_BACKOFF_DSSS;
982 	prf->phy_params[rf_param_offset + 1]  = NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HT;
983 	prf->phy_params[rf_param_offset + 2]  = NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HE;
984 	prf->phy_params[rf_param_offset + 3]  = NRF70_BAND_2G_UPPER_EDGE_BACKOFF_DSSS;
985 	prf->phy_params[rf_param_offset + 4]  = NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HT;
986 	prf->phy_params[rf_param_offset + 5]  = NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HE;
987 	prf->phy_params[rf_param_offset + 6]  = NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HT;
988 	prf->phy_params[rf_param_offset + 7]  = NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HE;
989 	prf->phy_params[rf_param_offset + 8]  = NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HT;
990 	prf->phy_params[rf_param_offset + 9]  = NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HE;
991 	prf->phy_params[rf_param_offset + 10]  = NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HT;
992 	prf->phy_params[rf_param_offset + 11]  = NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HE;
993 	prf->phy_params[rf_param_offset + 12]  = NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HT;
994 	prf->phy_params[rf_param_offset + 13]  = NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HE;
995 	prf->phy_params[rf_param_offset + 14]  = NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HT;
996 	prf->phy_params[rf_param_offset + 15]  = NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HE;
997 	prf->phy_params[rf_param_offset + 16]  = NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HT;
998 	prf->phy_params[rf_param_offset + 17]  = NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HE;
999 	prf->phy_params[rf_param_offset + 18]  = NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HT;
1000 	prf->phy_params[rf_param_offset + 19]  = NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HE;
1001 	prf->phy_params[rf_param_offset + 20]  = NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HT;
1002 	prf->phy_params[rf_param_offset + 21]  = NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HE;
1003 	prf->phy_params[rf_param_offset + 22]  = NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HT;
1004 	prf->phy_params[rf_param_offset + 23]  = NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HE;
1005 	prf->phy_params[rf_param_offset + 24]  = NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HT;
1006 	prf->phy_params[rf_param_offset + 25]  = NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HE;
1007 	prf->phy_params[rf_param_offset + 26]  = NRF70_ANT_GAIN_2G;
1008 	prf->phy_params[rf_param_offset + 27]  = NRF70_ANT_GAIN_5G_BAND1;
1009 	prf->phy_params[rf_param_offset + 28]  = NRF70_ANT_GAIN_5G_BAND2;
1010 	prf->phy_params[rf_param_offset + 29]  = NRF70_ANT_GAIN_5G_BAND3;
1011 	prf->phy_params[rf_param_offset + 30]  = NRF70_PCB_LOSS_2G;
1012 	prf->phy_params[rf_param_offset + 31]  = NRF70_PCB_LOSS_5G_BAND1;
1013 	prf->phy_params[rf_param_offset + 32]  = NRF70_PCB_LOSS_5G_BAND2;
1014 	prf->phy_params[rf_param_offset + 33]  = NRF70_PCB_LOSS_5G_BAND3;
1015 
1016 	return(ret);
1017 }
1018 
1019 
nrf_wifi_rt_fmac_rf_params_get(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct nrf_wifi_phy_rf_params * phy_rf_params)1020 enum nrf_wifi_status nrf_wifi_rt_fmac_rf_params_get(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1021 						     struct nrf_wifi_phy_rf_params *phy_rf_params)
1022 {
1023 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1024 	struct nrf_wifi_fmac_otp_info otp_info;
1025 	unsigned int ft_prog_ver;
1026 	int ret = -1;
1027 	/* If package_info is not written to OTP then the default value will be 0xFF. */
1028 	unsigned int package_info = 0xFFFFFFFF;
1029 	struct nrf_wifi_tx_pwr_ceil_params *tx_pwr_ceil_params;
1030 	unsigned char backoff_2g_dsss = 0, backoff_2g_ofdm = 0;
1031 	unsigned char backoff_5g_lowband = 0, backoff_5g_midband = 0, backoff_5g_highband = 0;
1032 
1033 	if (!fmac_dev_ctx || !phy_rf_params) {
1034 		nrf_wifi_osal_log_err("%s: Invalid parameters",
1035 				      __func__);
1036 		goto out;
1037 	}
1038 
1039 	if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_RT) {
1040 		nrf_wifi_osal_log_err("%s: Invalid op mode",
1041 				      __func__);
1042 		goto out;
1043 	}
1044 
1045 	tx_pwr_ceil_params = fmac_dev_ctx->tx_pwr_ceil_params;
1046 
1047 	nrf_wifi_osal_mem_set(&otp_info,
1048 			      0xFF,
1049 			      sizeof(otp_info));
1050 
1051 	status = nrf_wifi_hal_otp_info_get(fmac_dev_ctx->hal_dev_ctx,
1052 					   &otp_info.info,
1053 					   &otp_info.flags);
1054 
1055 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1056 		nrf_wifi_osal_log_err("%s: Fetching of RPU OTP information failed",
1057 				      __func__);
1058 		goto out;
1059 	}
1060 
1061 	status = nrf_wifi_hal_otp_ft_prog_ver_get(fmac_dev_ctx->hal_dev_ctx,
1062 						  &ft_prog_ver);
1063 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1064 		nrf_wifi_osal_log_err("%s: Fetching of FT program version failed",
1065 				      __func__);
1066 		goto out;
1067 	}
1068 
1069 	status = nrf_wifi_hal_otp_pack_info_get(fmac_dev_ctx->hal_dev_ctx,
1070 						&package_info);
1071 	if (status != NRF_WIFI_STATUS_SUCCESS) {
1072 		nrf_wifi_osal_log_err("%s: Fetching of Package info failed",
1073 				      __func__);
1074 		goto out;
1075 	}
1076 
1077 	ret = nrf_wifi_rt_fmac_phy_rf_params_init(phy_rf_params,
1078 						  package_info,
1079 						  NRF_WIFI_RT_DEF_RF_PARAMS);
1080 
1081 	if (ret == -1) {
1082 		nrf_wifi_osal_log_err("%s: Initialization of RF params with default values failed",
1083 				      __func__);
1084 		status = NRF_WIFI_STATUS_FAIL;
1085 		goto out;
1086 	}
1087 	if (!(otp_info.flags & (~CALIB_XO_FLAG_MASK))) {
1088 		nrf_wifi_osal_mem_cpy(&phy_rf_params->xo_offset.xo_freq_offset,
1089 				      (char *)otp_info.info.calib + OTP_OFF_CALIB_XO,
1090 				      OTP_SZ_CALIB_XO);
1091 
1092 	}
1093 
1094 	ft_prog_ver = (ft_prog_ver & FT_PROG_VER_MASK) >> 16;
1095 
1096 	if (ft_prog_ver == FT_PROG_VER1) {
1097 		backoff_2g_dsss = FT_PROG_VER1_2G_DSSS_TXCEIL_BKOFF;
1098 		backoff_2g_ofdm = FT_PROG_VER1_2G_OFDM_TXCEIL_BKOFF;
1099 		backoff_5g_lowband = FT_PROG_VER1_5G_LOW_OFDM_TXCEIL_BKOFF;
1100 		backoff_5g_midband = FT_PROG_VER1_5G_MID_OFDM_TXCEIL_BKOFF;
1101 		backoff_5g_highband = FT_PROG_VER1_5G_HIGH_OFDM_TXCEIL_BKOFF;
1102 	} else if (ft_prog_ver == FT_PROG_VER2) {
1103 		backoff_2g_dsss = FT_PROG_VER2_2G_DSSS_TXCEIL_BKOFF;
1104 		backoff_2g_ofdm = FT_PROG_VER2_2G_OFDM_TXCEIL_BKOFF;
1105 		backoff_5g_lowband = FT_PROG_VER2_5G_LOW_OFDM_TXCEIL_BKOFF;
1106 		backoff_5g_midband = FT_PROG_VER2_5G_MID_OFDM_TXCEIL_BKOFF;
1107 		backoff_5g_highband = FT_PROG_VER2_5G_HIGH_OFDM_TXCEIL_BKOFF;
1108 	} else if (ft_prog_ver == FT_PROG_VER3) {
1109 		backoff_2g_dsss = FT_PROG_VER3_2G_DSSS_TXCEIL_BKOFF;
1110 		backoff_2g_ofdm = FT_PROG_VER3_2G_OFDM_TXCEIL_BKOFF;
1111 		backoff_5g_lowband = FT_PROG_VER3_5G_LOW_OFDM_TXCEIL_BKOFF;
1112 		backoff_5g_midband = FT_PROG_VER3_5G_MID_OFDM_TXCEIL_BKOFF;
1113 		backoff_5g_highband = FT_PROG_VER3_5G_HIGH_OFDM_TXCEIL_BKOFF;
1114 	}
1115 	phy_rf_params->max_pwr_ceil.max_dsss_pwr =
1116 	MIN(tx_pwr_ceil_params->max_pwr_2g_dsss, phy_rf_params->max_pwr_ceil.max_dsss_pwr)
1117 	- backoff_2g_dsss;
1118 	phy_rf_params->max_pwr_ceil.max_lb_mcs7_pwr =
1119 	MIN(tx_pwr_ceil_params->max_pwr_2g_mcs7, phy_rf_params->max_pwr_ceil.max_lb_mcs7_pwr)
1120 	- backoff_2g_ofdm;
1121 	phy_rf_params->max_pwr_ceil.max_lb_mcs0_pwr =
1122 	MIN(tx_pwr_ceil_params->max_pwr_2g_mcs0, phy_rf_params->max_pwr_ceil.max_lb_mcs0_pwr)
1123 	- backoff_2g_ofdm;
1124 #ifndef NRF70_2_4G_ONLY
1125 	phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs7_pwr =
1126 	MIN(tx_pwr_ceil_params->max_pwr_5g_low_mcs7,
1127 		phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs7_pwr) - backoff_5g_lowband;
1128 	phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr =
1129 	MIN(tx_pwr_ceil_params->max_pwr_5g_mid_mcs7,
1130 		phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr) - backoff_5g_midband;
1131 	phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs7_pwr =
1132 	MIN(tx_pwr_ceil_params->max_pwr_5g_high_mcs7,
1133 		phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs7_pwr) - backoff_5g_highband;
1134 	phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs0_pwr =
1135 	MIN(tx_pwr_ceil_params->max_pwr_5g_low_mcs0,
1136 		phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs0_pwr) - backoff_5g_lowband;
1137 	phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr =
1138 	MIN(tx_pwr_ceil_params->max_pwr_5g_mid_mcs0,
1139 	        phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr) - backoff_5g_midband;
1140 	phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs0_pwr =
1141 	MIN(tx_pwr_ceil_params->max_pwr_5g_high_mcs0,
1142 	        phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs0_pwr) - backoff_5g_highband;
1143 #endif /* NRF70_2_4G_ONLY */
1144 
1145 	status = NRF_WIFI_STATUS_SUCCESS;
1146 out:
1147 	return status;
1148 }