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 "offload_raw_tx/phy_rf_params.h"
14 #include "offload_raw_tx/hal_api.h"
15 #include "offload_raw_tx/fmac_api.h"
16 #include "offload_raw_tx/fmac_cmd.h"
17 #include "offload_raw_tx/fmac_event.h"
18 #include "offload_raw_tx/fmac_structs.h"
19 #include "common/fmac_util.h"
20 #include <stdio.h>
21
nrf_wifi_fmac_off_raw_tx_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)22 static enum nrf_wifi_status nrf_wifi_fmac_off_raw_tx_fw_init(
23 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
24 struct nrf_wifi_phy_rf_params *rf_params,
25 bool rf_params_valid,
26 #ifdef NRF_WIFI_LOW_POWER
27 int sleep_type,
28 #endif /* NRF_WIFI_LOW_POWER */
29 unsigned int phy_calib,
30 enum op_band op_band,
31 bool beamforming,
32 struct nrf_wifi_tx_pwr_ctrl_params *tx_pwr_ctrl,
33 struct nrf_wifi_board_params *board_params,
34 unsigned char *country_code)
35 {
36 unsigned long start_time_us = 0;
37 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
38
39 if (!fmac_dev_ctx) {
40 nrf_wifi_osal_log_err("%s: Invalid device context",
41 __func__);
42 goto out;
43 }
44
45 status = umac_cmd_off_raw_tx_init(fmac_dev_ctx,
46 rf_params,
47 rf_params_valid,
48 #ifdef NRF_WIFI_LOW_POWER
49 sleep_type,
50 #endif /* NRF_WIFI_LOW_POWER */
51 phy_calib,
52 op_band,
53 beamforming,
54 tx_pwr_ctrl,
55 board_params,
56 country_code);
57
58 if (status != NRF_WIFI_STATUS_SUCCESS) {
59 nrf_wifi_osal_log_err("%s: UMAC init failed",
60 __func__);
61 goto out;
62 }
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 out:
82 return status;
83 }
84
85
nrf_wifi_off_raw_tx_fmac_init(void)86 struct nrf_wifi_fmac_priv *nrf_wifi_off_raw_tx_fmac_init(void)
87 {
88 struct nrf_wifi_fmac_priv *fpriv = NULL;
89 struct nrf_wifi_hal_cfg_params hal_cfg_params;
90
91 fpriv = nrf_wifi_osal_mem_zalloc(sizeof(*fpriv));
92 if (!fpriv) {
93 nrf_wifi_osal_log_err("%s: Unable to allocate fpriv",
94 __func__);
95 goto out;
96 }
97
98 nrf_wifi_osal_mem_set(&hal_cfg_params,
99 0,
100 sizeof(hal_cfg_params));
101
102 hal_cfg_params.max_cmd_size = MAX_NRF_WIFI_UMAC_CMD_SIZE;
103 hal_cfg_params.max_event_size = MAX_EVENT_POOL_LEN;
104
105 fpriv->hpriv = nrf_wifi_hal_init(&hal_cfg_params,
106 &nrf_wifi_off_raw_tx_fmac_event_callback,
107 NULL);
108 if (!fpriv->hpriv) {
109 nrf_wifi_osal_log_err("%s: Unable to do HAL init",
110 __func__);
111 nrf_wifi_osal_mem_free(fpriv);
112 fpriv = NULL;
113 goto out;
114 }
115
116 fpriv->op_mode = NRF_WIFI_OP_MODE_OFF_RAW_TX;
117 out:
118 return fpriv;
119 }
120
121
nrf_wifi_off_raw_tx_fmac_dev_add(struct nrf_wifi_fmac_priv * fpriv,void * os_dev_ctx)122 struct nrf_wifi_fmac_dev_ctx *nrf_wifi_off_raw_tx_fmac_dev_add(struct nrf_wifi_fmac_priv *fpriv,
123 void *os_dev_ctx)
124 {
125 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
126 struct nrf_wifi_off_raw_tx_fmac_dev_ctx *off_raw_tx_fmac_dev_ctx;
127
128 if (!fpriv || !os_dev_ctx) {
129 return NULL;
130 }
131
132 if (fpriv->op_mode != NRF_WIFI_OP_MODE_OFF_RAW_TX) {
133 nrf_wifi_osal_log_err("%s: Invalid op mode",
134 __func__);
135 goto out;
136 }
137
138 fmac_dev_ctx = nrf_wifi_osal_mem_zalloc(sizeof(*fmac_dev_ctx) + sizeof(*off_raw_tx_fmac_dev_ctx));
139
140 if (!fmac_dev_ctx) {
141 nrf_wifi_osal_log_err("%s: Unable to allocate fmac_dev_ctx",
142 __func__);
143 goto out;
144 }
145
146 fmac_dev_ctx->fpriv = fpriv;
147 fmac_dev_ctx->os_dev_ctx = os_dev_ctx;
148
149 fmac_dev_ctx->hal_dev_ctx = nrf_wifi_off_raw_tx_hal_dev_add(fpriv->hpriv,
150 fmac_dev_ctx);
151
152 if (!fmac_dev_ctx->hal_dev_ctx) {
153 nrf_wifi_osal_log_err("%s: nrf_wifi_off_raw_tx_hal_dev_add failed",
154 __func__);
155
156 nrf_wifi_osal_mem_free(fmac_dev_ctx);
157 fmac_dev_ctx = NULL;
158 goto out;
159 }
160
161 fmac_dev_ctx->op_mode = NRF_WIFI_OP_MODE_OFF_RAW_TX;
162 out:
163 return fmac_dev_ctx;
164 }
165
166
nrf_wifi_off_raw_tx_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)167 enum nrf_wifi_status nrf_wifi_off_raw_tx_fmac_dev_init(
168 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
169 #ifdef NRF_WIFI_LOW_POWER
170 int sleep_type,
171 #endif /* NRF_WIFI_LOW_POWER */
172 unsigned int phy_calib,
173 enum op_band op_band,
174 bool beamforming,
175 struct nrf_wifi_tx_pwr_ctrl_params *tx_pwr_ctrl_params,
176 struct nrf_wifi_tx_pwr_ceil_params *tx_pwr_ceil_params,
177 struct nrf_wifi_board_params *board_params,
178 unsigned char *country_code)
179 {
180 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
181 struct nrf_wifi_fmac_otp_info otp_info;
182 struct nrf_wifi_phy_rf_params phy_rf_params;
183
184 if (!fmac_dev_ctx) {
185 nrf_wifi_osal_log_err("%s: Invalid device context",
186 __func__);
187 goto out;
188 }
189
190 if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_OFF_RAW_TX) {
191 nrf_wifi_osal_log_err("%s: Invalid op mode",
192 __func__);
193 goto out;
194 }
195
196 status = nrf_wifi_hal_dev_init(fmac_dev_ctx->hal_dev_ctx);
197 if (status != NRF_WIFI_STATUS_SUCCESS) {
198 nrf_wifi_osal_log_err("%s: nrf_wifi_hal_dev_init failed",
199 __func__);
200 goto out;
201 }
202
203 fmac_dev_ctx->tx_pwr_ceil_params = nrf_wifi_osal_mem_alloc(sizeof(*tx_pwr_ceil_params));
204 nrf_wifi_osal_mem_cpy(fmac_dev_ctx->tx_pwr_ceil_params,
205 tx_pwr_ceil_params,
206 sizeof(*tx_pwr_ceil_params));
207
208 nrf_wifi_osal_mem_set(&otp_info,
209 0xFF,
210 sizeof(otp_info));
211
212 status = nrf_wifi_hal_otp_info_get(fmac_dev_ctx->hal_dev_ctx,
213 &otp_info.info,
214 &otp_info.flags);
215 if (status != NRF_WIFI_STATUS_SUCCESS) {
216 nrf_wifi_osal_log_err("%s: Fetching of RPU OTP information failed",
217 __func__);
218 goto out;
219 }
220
221 status = nrf_wifi_off_raw_tx_fmac_rf_params_get(fmac_dev_ctx,
222 &phy_rf_params);
223
224 if (status != NRF_WIFI_STATUS_SUCCESS) {
225 nrf_wifi_osal_log_err("%s: RF parameters get failed",
226 __func__);
227 goto out;
228 }
229
230 status = nrf_wifi_fmac_off_raw_tx_fw_init(fmac_dev_ctx,
231 &phy_rf_params,
232 true,
233 #ifdef NRF_WIFI_LOW_POWER
234 sleep_type,
235 #endif /* NRF_WIFI_LOW_POWER */
236 phy_calib,
237 op_band,
238 beamforming,
239 tx_pwr_ctrl_params,
240 board_params,
241 country_code);
242
243 if (status == NRF_WIFI_STATUS_FAIL) {
244 nrf_wifi_osal_log_err("%s: nrf_wifi_fmac_off_raw_tx_fw_init failed",
245 __func__);
246 goto out;
247 }
248 out:
249 return status;
250 }
251
252
nrf_wifi_off_raw_tx_fmac_conf(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct nrf_wifi_offload_ctrl_params * off_ctrl_params,struct nrf_wifi_offload_tx_ctrl * off_tx_params)253 enum nrf_wifi_status nrf_wifi_off_raw_tx_fmac_conf(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
254 struct nrf_wifi_offload_ctrl_params *off_ctrl_params,
255 struct nrf_wifi_offload_tx_ctrl *off_tx_params)
256 {
257 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
258 struct nrf_wifi_off_raw_tx_fmac_dev_ctx *dev_ctx_off_raw_tx;
259 struct nrf_wifi_fmac_reg_info reg_domain_info = {0};
260 unsigned char count = 0;
261
262 if (!fmac_dev_ctx) {
263 nrf_wifi_osal_log_err("%s: Invalid device context",
264 __func__);
265 goto out;
266 }
267
268 if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_OFF_RAW_TX) {
269 nrf_wifi_osal_log_err("%s: Invalid op mode",
270 __func__);
271 goto out;
272 }
273
274 dev_ctx_off_raw_tx = wifi_dev_priv(fmac_dev_ctx);
275 dev_ctx_off_raw_tx->off_raw_tx_cmd_done = true;
276
277 if (!off_ctrl_params || !off_tx_params) {
278 nrf_wifi_osal_log_err("%s: Invalid offloaded raw tx params",
279 __func__);
280 goto out;
281 }
282
283 status = umac_cmd_off_raw_tx_conf(fmac_dev_ctx,
284 off_ctrl_params,
285 off_tx_params);
286
287 if (status != NRF_WIFI_STATUS_SUCCESS) {
288 nrf_wifi_osal_log_err("%s: umac_cmd_offload_raw_tx_conf failed", __func__);
289 goto out;
290 }
291
292 do {
293 nrf_wifi_osal_sleep_ms(1);
294 count++;
295 } while ((dev_ctx_off_raw_tx->off_raw_tx_cmd_done == true) &&
296 (count < NRF_WIFI_FMAC_PARAMS_RECV_TIMEOUT));
297
298 if (count == NRF_WIFI_FMAC_PARAMS_RECV_TIMEOUT) {
299 nrf_wifi_osal_log_err("%s: Timed out",
300 __func__);
301 goto out;
302 }
303
304 if (dev_ctx_off_raw_tx->off_raw_tx_cmd_status != NRF_WIFI_UMAC_CMD_SUCCESS) {
305 status = nrf_wifi_fmac_get_reg(fmac_dev_ctx, ®_domain_info);
306 if (status != NRF_WIFI_STATUS_SUCCESS) {
307 nrf_wifi_osal_log_err("%s: Failed to get regulatory domain",
308 __func__);
309 goto out;
310 }
311
312 nrf_wifi_osal_log_err("%s: Failed to set configuration, check config against %.2s regulatory domain rules",
313 __func__,
314 dev_ctx_off_raw_tx->country_code);
315 status = NRF_WIFI_STATUS_FAIL;
316 goto out;
317 }
318
319 status = NRF_WIFI_STATUS_SUCCESS;
320 out:
321 return status;
322 }
323
nrf_wifi_off_raw_tx_fmac_start(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)324 enum nrf_wifi_status nrf_wifi_off_raw_tx_fmac_start(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
325 {
326 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
327
328 if (!fmac_dev_ctx) {
329 nrf_wifi_osal_log_err("%s: Invalid device context",
330 __func__);
331 goto out;
332 }
333
334 if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_OFF_RAW_TX) {
335 nrf_wifi_osal_log_err("%s: Invalid op mode",
336 __func__);
337 goto out;
338 }
339
340 status = umac_cmd_off_raw_tx_ctrl(fmac_dev_ctx, 1);
341
342 if (status != NRF_WIFI_STATUS_SUCCESS) {
343 nrf_wifi_osal_log_err("%s: umac_cmd_off_raw_tx_ctrl failed", __func__);
344 goto out;
345 }
346 out:
347 return status;
348 }
349
nrf_wifi_off_raw_tx_fmac_stop(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)350 enum nrf_wifi_status nrf_wifi_off_raw_tx_fmac_stop(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
351 {
352 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
353
354 if (!fmac_dev_ctx) {
355 nrf_wifi_osal_log_err("%s: Invalid device context",
356 __func__);
357 goto out;
358 }
359
360 if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_OFF_RAW_TX) {
361 nrf_wifi_osal_log_err("%s: Invalid op mode",
362 __func__);
363 goto out;
364 }
365
366 status = umac_cmd_off_raw_tx_ctrl(fmac_dev_ctx, 0);
367
368 if (status != NRF_WIFI_STATUS_SUCCESS) {
369 nrf_wifi_osal_log_err("%s: umac_cmd_offload_raw_tx_ctrl failed", __func__);
370 goto out;
371 }
372 out:
373 return status;
374 }
375
376
nrf_wifi_off_raw_tx_fmac_stats_get(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,enum rpu_op_mode op_mode,struct rpu_off_raw_tx_op_stats * stats)377 enum nrf_wifi_status nrf_wifi_off_raw_tx_fmac_stats_get(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
378 enum rpu_op_mode op_mode,
379 struct rpu_off_raw_tx_op_stats *stats)
380 {
381 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
382 unsigned char count = 0;
383
384 if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_OFF_RAW_TX) {
385 nrf_wifi_osal_log_err("%s: Invalid op mode",
386 __func__);
387 goto out;
388 }
389
390 if (fmac_dev_ctx->stats_req == true) {
391 nrf_wifi_osal_log_err("%s: Stats request already pending",
392 __func__);
393 goto out;
394 }
395
396 fmac_dev_ctx->stats_req = true;
397 fmac_dev_ctx->fw_stats = &stats->fw;
398
399 status = umac_cmd_off_raw_tx_prog_stats_get(fmac_dev_ctx);
400
401 if (status != NRF_WIFI_STATUS_SUCCESS) {
402 goto out;
403 }
404
405 do {
406 nrf_wifi_osal_sleep_ms(1);
407 count++;
408 } while ((fmac_dev_ctx->stats_req == true) &&
409 (count < NRF_WIFI_FMAC_STATS_RECV_TIMEOUT));
410
411 if (count == NRF_WIFI_FMAC_STATS_RECV_TIMEOUT) {
412 nrf_wifi_osal_log_err("%s: Timed out",
413 __func__);
414 goto out;
415 }
416
417 status = NRF_WIFI_STATUS_SUCCESS;
418 out:
419 return status;
420 }
421
nrf_wifi_off_raw_tx_fmac_phy_rf_params_init(struct nrf_wifi_phy_rf_params * prf,unsigned int package_info,unsigned char * str)422 static int nrf_wifi_off_raw_tx_fmac_phy_rf_params_init(struct nrf_wifi_phy_rf_params *prf,
423 unsigned int package_info,
424 unsigned char *str)
425 {
426 int ret = -1;
427 unsigned int rf_param_offset = BAND_2G_LW_ED_BKF_DSSS_OFST - NRF_WIFI_RF_PARAMS_CONF_SIZE;
428 /* Initilaize reserved bytes */
429 nrf_wifi_osal_mem_set(prf,
430 0x0,
431 sizeof(prf));
432 /* Initialize PD adjust values for MCS7. Currently these 4 bytes are not being used */
433 prf->pd_adjust_val.pd_adjt_lb_chan = PD_ADJUST_VAL;
434 prf->pd_adjust_val.pd_adjt_hb_low_chan = PD_ADJUST_VAL;
435 prf->pd_adjust_val.pd_adjt_hb_mid_chan = PD_ADJUST_VAL;
436 prf->pd_adjust_val.pd_adjt_hb_high_chan = PD_ADJUST_VAL;
437
438 /* RX Gain offsets */
439 prf->rx_gain_offset.rx_gain_lb_chan = CTRL_PWR_OPTIMIZATIONS;
440 prf->rx_gain_offset.rx_gain_hb_low_chan = RX_GAIN_OFFSET_HB_LOW_CHAN;
441 prf->rx_gain_offset.rx_gain_hb_mid_chan = RX_GAIN_OFFSET_HB_MID_CHAN;
442 prf->rx_gain_offset.rx_gain_hb_high_chan = RX_GAIN_OFFSET_HB_HIGH_CHAN;
443
444 if (package_info == CSP_PACKAGE_INFO) {
445 prf->xo_offset.xo_freq_offset = CSP_XO_VAL;
446
447 /* Configure systematic offset value */
448 prf->syst_tx_pwr_offset.syst_off_lb_chan = CSP_SYSTEM_OFFSET_LB;
449 prf->syst_tx_pwr_offset.syst_off_hb_low_chan = CSP_SYSTEM_OFFSET_HB_CHAN_LOW;
450 prf->syst_tx_pwr_offset.syst_off_hb_mid_chan = CSP_SYSTEM_OFFSET_HB_CHAN_MID;
451 prf->syst_tx_pwr_offset.syst_off_hb_high_chan = CSP_SYSTEM_OFFSET_HB_CHAN_HIGH;
452
453 /* TX power ceiling */
454 prf->max_pwr_ceil.max_dsss_pwr = CSP_MAX_TX_PWR_DSSS;
455 prf->max_pwr_ceil.max_lb_mcs7_pwr = CSP_MAX_TX_PWR_LB_MCS7;
456 prf->max_pwr_ceil.max_lb_mcs0_pwr = CSP_MAX_TX_PWR_LB_MCS0;
457 prf->max_pwr_ceil.max_hb_low_chan_mcs7_pwr = CSP_MAX_TX_PWR_HB_LOW_CHAN_MCS7;
458 prf->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr = CSP_MAX_TX_PWR_HB_MID_CHAN_MCS7;
459 prf->max_pwr_ceil.max_hb_high_chan_mcs7_pwr = CSP_MAX_TX_PWR_HB_HIGH_CHAN_MCS7;
460 prf->max_pwr_ceil.max_hb_low_chan_mcs0_pwr = CSP_MAX_TX_PWR_HB_LOW_CHAN_MCS0;
461 prf->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr = CSP_MAX_TX_PWR_HB_MID_CHAN_MCS0;
462 prf->max_pwr_ceil.max_hb_high_chan_mcs0_pwr = CSP_MAX_TX_PWR_HB_HIGH_CHAN_MCS0;
463 } else {
464 /** If nothing is written to OTP field corresponding to package info byte
465 * or if the package info field is corrupted then the default package
466 * package is QFN.
467 */
468
469 /* Initialize XO */
470 prf->xo_offset.xo_freq_offset = QFN_XO_VAL;
471
472 /* Configure systematic offset value */
473 prf->syst_tx_pwr_offset.syst_off_lb_chan = QFN_SYSTEM_OFFSET_LB;
474 prf->syst_tx_pwr_offset.syst_off_hb_low_chan = QFN_SYSTEM_OFFSET_HB_CHAN_LOW;
475 prf->syst_tx_pwr_offset.syst_off_hb_mid_chan = QFN_SYSTEM_OFFSET_HB_CHAN_MID;
476 prf->syst_tx_pwr_offset.syst_off_hb_high_chan = QFN_SYSTEM_OFFSET_HB_CHAN_HIGH;
477
478 /* TX power ceiling */
479 prf->max_pwr_ceil.max_dsss_pwr = QFN_MAX_TX_PWR_DSSS;
480 prf->max_pwr_ceil.max_lb_mcs7_pwr = QFN_MAX_TX_PWR_LB_MCS7;
481 prf->max_pwr_ceil.max_lb_mcs0_pwr = QFN_MAX_TX_PWR_LB_MCS0;
482 prf->max_pwr_ceil.max_hb_low_chan_mcs7_pwr = QFN_MAX_TX_PWR_HB_LOW_CHAN_MCS7;
483 prf->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr = QFN_MAX_TX_PWR_HB_MID_CHAN_MCS7;
484 prf->max_pwr_ceil.max_hb_high_chan_mcs7_pwr = QFN_MAX_TX_PWR_HB_HIGH_CHAN_MCS7;
485 prf->max_pwr_ceil.max_hb_low_chan_mcs0_pwr = QFN_MAX_TX_PWR_HB_LOW_CHAN_MCS0;
486 prf->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr = QFN_MAX_TX_PWR_HB_MID_CHAN_MCS0;
487 prf->max_pwr_ceil.max_hb_high_chan_mcs0_pwr = QFN_MAX_TX_PWR_HB_HIGH_CHAN_MCS0;
488 }
489
490 ret = nrf_wifi_utils_hex_str_to_val((unsigned char *)&prf->phy_params,
491 sizeof(prf->phy_params),
492 str);
493
494 prf->phy_params[rf_param_offset] = NRF70_BAND_2G_LOWER_EDGE_BACKOFF_DSSS;
495 prf->phy_params[rf_param_offset + 1] = NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HT;
496 prf->phy_params[rf_param_offset + 2] = NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HE;
497 prf->phy_params[rf_param_offset + 3] = NRF70_BAND_2G_UPPER_EDGE_BACKOFF_DSSS;
498 prf->phy_params[rf_param_offset + 4] = NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HT;
499 prf->phy_params[rf_param_offset + 5] = NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HE;
500 prf->phy_params[rf_param_offset + 6] = NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HT;
501 prf->phy_params[rf_param_offset + 7] = NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HE;
502 prf->phy_params[rf_param_offset + 8] = NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HT;
503 prf->phy_params[rf_param_offset + 9] = NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HE;
504 prf->phy_params[rf_param_offset + 10] = NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HT;
505 prf->phy_params[rf_param_offset + 11] = NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HE;
506 prf->phy_params[rf_param_offset + 12] = NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HT;
507 prf->phy_params[rf_param_offset + 13] = NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HE;
508 prf->phy_params[rf_param_offset + 14] = NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HT;
509 prf->phy_params[rf_param_offset + 15] = NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HE;
510 prf->phy_params[rf_param_offset + 16] = NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HT;
511 prf->phy_params[rf_param_offset + 17] = NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HE;
512 prf->phy_params[rf_param_offset + 18] = NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HT;
513 prf->phy_params[rf_param_offset + 19] = NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HE;
514 prf->phy_params[rf_param_offset + 20] = NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HT;
515 prf->phy_params[rf_param_offset + 21] = NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HE;
516 prf->phy_params[rf_param_offset + 22] = NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HT;
517 prf->phy_params[rf_param_offset + 23] = NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HE;
518 prf->phy_params[rf_param_offset + 24] = NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HT;
519 prf->phy_params[rf_param_offset + 25] = NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HE;
520 prf->phy_params[rf_param_offset + 26] = NRF70_ANT_GAIN_2G;
521 prf->phy_params[rf_param_offset + 27] = NRF70_ANT_GAIN_5G_BAND1;
522 prf->phy_params[rf_param_offset + 28] = NRF70_ANT_GAIN_5G_BAND2;
523 prf->phy_params[rf_param_offset + 29] = NRF70_ANT_GAIN_5G_BAND3;
524 prf->phy_params[rf_param_offset + 30] = NRF70_PCB_LOSS_2G;
525 prf->phy_params[rf_param_offset + 31] = NRF70_PCB_LOSS_5G_BAND1;
526 prf->phy_params[rf_param_offset + 32] = NRF70_PCB_LOSS_5G_BAND2;
527 prf->phy_params[rf_param_offset + 33] = NRF70_PCB_LOSS_5G_BAND3;
528
529 return(ret);
530 }
531
532
nrf_wifi_off_raw_tx_fmac_rf_params_get(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct nrf_wifi_phy_rf_params * phy_rf_params)533 enum nrf_wifi_status nrf_wifi_off_raw_tx_fmac_rf_params_get(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
534 struct nrf_wifi_phy_rf_params *phy_rf_params)
535 {
536 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
537 struct nrf_wifi_fmac_otp_info otp_info;
538 unsigned int ft_prog_ver;
539 int ret = -1;
540 /* If package_info is not written to OTP then the default value will be 0xFF. */
541 unsigned int package_info = 0xFFFFFFFF;
542 struct nrf_wifi_tx_pwr_ceil_params *tx_pwr_ceil_params;
543 unsigned char backoff_2g_dsss = 0, backoff_2g_ofdm = 0;
544 unsigned char backoff_5g_lowband = 0, backoff_5g_midband = 0, backoff_5g_highband = 0;
545
546 if (!fmac_dev_ctx || !phy_rf_params) {
547 nrf_wifi_osal_log_err("%s: Invalid parameters",
548 __func__);
549 goto out;
550 }
551
552 if (!fmac_dev_ctx->op_mode == NRF_WIFI_OP_MODE_OFF_RAW_TX) {
553 nrf_wifi_osal_log_err("%s: Invalid op mode",
554 __func__);
555 goto out;
556 }
557
558 tx_pwr_ceil_params = fmac_dev_ctx->tx_pwr_ceil_params;
559
560 nrf_wifi_osal_mem_set(&otp_info,
561 0xFF,
562 sizeof(otp_info));
563
564 status = nrf_wifi_hal_otp_info_get(fmac_dev_ctx->hal_dev_ctx,
565 &otp_info.info,
566 &otp_info.flags);
567
568 if (status != NRF_WIFI_STATUS_SUCCESS) {
569 nrf_wifi_osal_log_err("%s: Fetching of RPU OTP information failed",
570 __func__);
571 goto out;
572 }
573
574 status = nrf_wifi_hal_otp_ft_prog_ver_get(fmac_dev_ctx->hal_dev_ctx,
575 &ft_prog_ver);
576 if (status != NRF_WIFI_STATUS_SUCCESS) {
577 nrf_wifi_osal_log_err("%s: Fetching of FT program version failed",
578 __func__);
579 goto out;
580 }
581
582 status = nrf_wifi_hal_otp_pack_info_get(fmac_dev_ctx->hal_dev_ctx,
583 &package_info);
584 if (status != NRF_WIFI_STATUS_SUCCESS) {
585 nrf_wifi_osal_log_err("%s: Fetching of Package info failed",
586 __func__);
587 goto out;
588 }
589
590 ret = nrf_wifi_off_raw_tx_fmac_phy_rf_params_init(phy_rf_params,
591 package_info,
592 NRF_WIFI_OFF_RAW_TX_DEF_RF_PARAMS);
593
594 if (ret == -1) {
595 nrf_wifi_osal_log_err("%s: Initialization of RF params with default values failed",
596 __func__);
597 status = NRF_WIFI_STATUS_FAIL;
598 goto out;
599 }
600 if (!(otp_info.flags & (~CALIB_XO_FLAG_MASK))) {
601 nrf_wifi_osal_mem_cpy(&phy_rf_params->xo_offset.xo_freq_offset,
602 (char *)otp_info.info.calib + OTP_OFF_CALIB_XO,
603 OTP_SZ_CALIB_XO);
604
605 }
606
607 ft_prog_ver = (ft_prog_ver & FT_PROG_VER_MASK) >> 16;
608
609 if (ft_prog_ver == FT_PROG_VER1) {
610 backoff_2g_dsss = FT_PROG_VER1_2G_DSSS_TXCEIL_BKOFF;
611 backoff_2g_ofdm = FT_PROG_VER1_2G_OFDM_TXCEIL_BKOFF;
612 backoff_5g_lowband = FT_PROG_VER1_5G_LOW_OFDM_TXCEIL_BKOFF;
613 backoff_5g_midband = FT_PROG_VER1_5G_MID_OFDM_TXCEIL_BKOFF;
614 backoff_5g_highband = FT_PROG_VER1_5G_HIGH_OFDM_TXCEIL_BKOFF;
615 } else if (ft_prog_ver == FT_PROG_VER2) {
616 backoff_2g_dsss = FT_PROG_VER2_2G_DSSS_TXCEIL_BKOFF;
617 backoff_2g_ofdm = FT_PROG_VER2_2G_OFDM_TXCEIL_BKOFF;
618 backoff_5g_lowband = FT_PROG_VER2_5G_LOW_OFDM_TXCEIL_BKOFF;
619 backoff_5g_midband = FT_PROG_VER2_5G_MID_OFDM_TXCEIL_BKOFF;
620 backoff_5g_highband = FT_PROG_VER2_5G_HIGH_OFDM_TXCEIL_BKOFF;
621 } else if (ft_prog_ver == FT_PROG_VER3) {
622 backoff_2g_dsss = FT_PROG_VER3_2G_DSSS_TXCEIL_BKOFF;
623 backoff_2g_ofdm = FT_PROG_VER3_2G_OFDM_TXCEIL_BKOFF;
624 backoff_5g_lowband = FT_PROG_VER3_5G_LOW_OFDM_TXCEIL_BKOFF;
625 backoff_5g_midband = FT_PROG_VER3_5G_MID_OFDM_TXCEIL_BKOFF;
626 backoff_5g_highband = FT_PROG_VER3_5G_HIGH_OFDM_TXCEIL_BKOFF;
627 }
628 phy_rf_params->max_pwr_ceil.max_dsss_pwr =
629 MIN(tx_pwr_ceil_params->max_pwr_2g_dsss, phy_rf_params->max_pwr_ceil.max_dsss_pwr)
630 - backoff_2g_dsss;
631 phy_rf_params->max_pwr_ceil.max_lb_mcs7_pwr =
632 MIN(tx_pwr_ceil_params->max_pwr_2g_mcs7, phy_rf_params->max_pwr_ceil.max_lb_mcs7_pwr)
633 - backoff_2g_ofdm;
634 phy_rf_params->max_pwr_ceil.max_lb_mcs0_pwr =
635 MIN(tx_pwr_ceil_params->max_pwr_2g_mcs0, phy_rf_params->max_pwr_ceil.max_lb_mcs0_pwr)
636 - backoff_2g_ofdm;
637 #ifndef NRF70_2_4G_ONLY
638 phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs7_pwr =
639 MIN(tx_pwr_ceil_params->max_pwr_5g_low_mcs7,
640 phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs7_pwr) - backoff_5g_lowband;
641 phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr =
642 MIN(tx_pwr_ceil_params->max_pwr_5g_mid_mcs7,
643 phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs7_pwr) - backoff_5g_midband;
644 phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs7_pwr =
645 MIN(tx_pwr_ceil_params->max_pwr_5g_high_mcs7,
646 phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs7_pwr) - backoff_5g_highband;
647 phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs0_pwr =
648 MIN(tx_pwr_ceil_params->max_pwr_5g_low_mcs0,
649 phy_rf_params->max_pwr_ceil.max_hb_low_chan_mcs0_pwr) - backoff_5g_lowband;
650 phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr =
651 MIN(tx_pwr_ceil_params->max_pwr_5g_mid_mcs0,
652 phy_rf_params->max_pwr_ceil.max_hb_mid_chan_mcs0_pwr) - backoff_5g_midband;
653 phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs0_pwr =
654 MIN(tx_pwr_ceil_params->max_pwr_5g_high_mcs0,
655 phy_rf_params->max_pwr_ceil.max_hb_high_chan_mcs0_pwr) - backoff_5g_highband;
656 #endif /* NRF70_2_4G_ONLY */
657
658 status = NRF_WIFI_STATUS_SUCCESS;
659 out:
660 return status;
661 }
662