• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2016 - 2019 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 
16 #include "halmac_mimo_88xx.h"
17 #include "halmac_88xx_cfg.h"
18 #include "halmac_common_88xx.h"
19 #include "halmac_init_88xx.h"
20 
21 #if HALMAC_88XX_SUPPORT
22 
23 #define TXBF_CTRL_CFG	(BIT_R_ENABLE_NDPA | BIT_USE_NDPA_PARAMETER | \
24 			 BIT_R_EN_NDPA_INT | BIT_DIS_NDP_BFEN)
25 #define CSI_RATE_MAP	0x55
26 
27 static void
28 cfg_mu_bfee_88xx(struct halmac_adapter *adapter,
29 		 struct halmac_cfg_mumimo_para *param);
30 
31 static void
32 cfg_mu_bfer_88xx(struct halmac_adapter *adapter,
33 		 struct halmac_cfg_mumimo_para *param);
34 
35 static enum halmac_cmd_construct_state
36 fw_snding_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
37 
38 static enum halmac_ret_status
39 cnv_fw_snding_state_88xx(struct halmac_adapter *adapter,
40 			 enum halmac_cmd_construct_state dest_state);
41 
42 static u8
43 snding_pkt_chk_88xx(struct halmac_adapter *adapter, u8 *pkt);
44 
45 /**
46  * cfg_txbf_88xx() - enable/disable specific user's txbf
47  * @adapter : the adapter of halmac
48  * @userid : su bfee userid = 0 or 1 to apply TXBF
49  * @bw : the sounding bandwidth
50  * @txbf_en : 0: disable TXBF, 1: enable TXBF
51  * Author : chunchu
52  * Return : enum halmac_ret_status
53  * More details of status code can be found in prototype document
54  */
55 enum halmac_ret_status
cfg_txbf_88xx(struct halmac_adapter * adapter,u8 userid,enum halmac_bw bw,u8 txbf_en)56 cfg_txbf_88xx(struct halmac_adapter *adapter, u8 userid, enum halmac_bw bw,
57 	      u8 txbf_en)
58 {
59 	u16 tmp42c = 0;
60 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
61 
62 	if (txbf_en) {
63 		switch (bw) {
64 		case HALMAC_BW_80:
65 			tmp42c |= BIT_R_TXBF0_80M;
66 			fallthrough;
67 		case HALMAC_BW_40:
68 			tmp42c |= BIT_R_TXBF0_40M;
69 			fallthrough;
70 		case HALMAC_BW_20:
71 			tmp42c |= BIT_R_TXBF0_20M;
72 			break;
73 		default:
74 			return HALMAC_RET_INVALID_SOUNDING_SETTING;
75 		}
76 	}
77 
78 	switch (userid) {
79 	case 0:
80 		tmp42c |= HALMAC_REG_R16(REG_TXBF_CTRL) &
81 			~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
82 		HALMAC_REG_W16(REG_TXBF_CTRL, tmp42c);
83 		break;
84 	case 1:
85 		tmp42c |= HALMAC_REG_R16(REG_TXBF_CTRL + 2) &
86 			~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
87 		HALMAC_REG_W16(REG_TXBF_CTRL + 2, tmp42c);
88 		break;
89 	default:
90 		return HALMAC_RET_INVALID_SOUNDING_SETTING;
91 	}
92 
93 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
94 
95 	return HALMAC_RET_SUCCESS;
96 }
97 
98 /**
99  * cfg_mumimo_88xx() -config mumimo
100  * @adapter : the adapter of halmac
101  * @param : parameters to configure MU PPDU Tx/Rx
102  * Author : chunchu
103  * Return : enum halmac_ret_status
104  * More details of status code can be found in prototype document
105  */
106 enum halmac_ret_status
cfg_mumimo_88xx(struct halmac_adapter * adapter,struct halmac_cfg_mumimo_para * param)107 cfg_mumimo_88xx(struct halmac_adapter *adapter,
108 		struct halmac_cfg_mumimo_para *param)
109 {
110 	if (param->role == HAL_BFEE)
111 		cfg_mu_bfee_88xx(adapter, param);
112 	else
113 		cfg_mu_bfer_88xx(adapter, param);
114 
115 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
116 
117 	return HALMAC_RET_SUCCESS;
118 }
119 
120 static void
cfg_mu_bfee_88xx(struct halmac_adapter * adapter,struct halmac_cfg_mumimo_para * param)121 cfg_mu_bfee_88xx(struct halmac_adapter *adapter,
122 		 struct halmac_cfg_mumimo_para *param)
123 {
124 	u8 mu_tbl_sel;
125 	u8 tmp14c0;
126 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
127 
128 	tmp14c0 = HALMAC_REG_R8(REG_MU_TX_CTL) & ~BIT_MASK_R_MU_TABLE_VALID;
129 	HALMAC_REG_W8(REG_MU_TX_CTL, (tmp14c0 | BIT(0) | BIT(1)) & ~(BIT(7)));
130 
131 	/*config GID valid table and user position table*/
132 	mu_tbl_sel = HALMAC_REG_R8(REG_MU_TX_CTL + 1) & 0xF8;
133 
134 	HALMAC_REG_W8(REG_MU_TX_CTL + 1, mu_tbl_sel);
135 	HALMAC_REG_W32(REG_MU_STA_GID_VLD, param->given_gid_tab[0]);
136 	HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO, param->given_user_pos[0]);
137 	HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO + 4, param->given_user_pos[1]);
138 
139 	HALMAC_REG_W8(REG_MU_TX_CTL + 1, mu_tbl_sel | 1);
140 	HALMAC_REG_W32(REG_MU_STA_GID_VLD, param->given_gid_tab[1]);
141 	HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO, param->given_user_pos[2]);
142 	HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO + 4, param->given_user_pos[3]);
143 }
144 
145 static void
cfg_mu_bfer_88xx(struct halmac_adapter * adapter,struct halmac_cfg_mumimo_para * param)146 cfg_mu_bfer_88xx(struct halmac_adapter *adapter,
147 		 struct halmac_cfg_mumimo_para *param)
148 {
149 	u8 i;
150 	u8 idx;
151 	u8 id0;
152 	u8 id1;
153 	u8 gid;
154 	u8 mu_tbl_sel;
155 	u8 mu_tbl_valid = 0;
156 	u32 gid_valid[6] = {0};
157 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
158 
159 	if (param->mu_tx_en == 0) {
160 		HALMAC_REG_W8(REG_MU_TX_CTL,
161 			      HALMAC_REG_R8(REG_MU_TX_CTL) & ~(BIT(7)));
162 		return;
163 	}
164 
165 	for (idx = 0; idx < 15; idx++) {
166 		if (idx < 5) {
167 			/*grouping_bitmap bit0~4, MU_STA0 with MUSTA1~5*/
168 			id0 = 0;
169 			id1 = (u8)(idx + 1);
170 		} else if (idx < 9) {
171 			/*grouping_bitmap bit5~8, MU_STA1 with MUSTA2~5*/
172 			id0 = 1;
173 			id1 = (u8)(idx - 3);
174 		} else if (idx < 12) {
175 			/*grouping_bitmap bit9~11, MU_STA2 with MUSTA3~5*/
176 			id0 = 2;
177 			id1 = (u8)(idx - 6);
178 		} else if (idx < 14) {
179 			/*grouping_bitmap bit12~13, MU_STA3 with MUSTA4~5*/
180 			id0 = 3;
181 			id1 = (u8)(idx - 8);
182 		} else {
183 			/*grouping_bitmap bit14, MU_STA4 with MUSTA5*/
184 			id0 = 4;
185 			id1 = (u8)(idx - 9);
186 		}
187 		if (param->grouping_bitmap & BIT(idx)) {
188 			/*Pair 1*/
189 			gid = (idx << 1) + 1;
190 			gid_valid[id0] |= (BIT(gid));
191 			gid_valid[id1] |= (BIT(gid));
192 			/*Pair 2*/
193 			gid += 1;
194 			gid_valid[id0] |= (BIT(gid));
195 			gid_valid[id1] |= (BIT(gid));
196 		} else {
197 			/*Pair 1*/
198 			gid = (idx << 1) + 1;
199 			gid_valid[id0] &= ~(BIT(gid));
200 			gid_valid[id1] &= ~(BIT(gid));
201 			/*Pair 2*/
202 			gid += 1;
203 			gid_valid[id0] &= ~(BIT(gid));
204 			gid_valid[id1] &= ~(BIT(gid));
205 		}
206 	}
207 
208 	/*set MU STA GID valid TABLE*/
209 	mu_tbl_sel = HALMAC_REG_R8(REG_MU_TX_CTL + 1) & 0xF8;
210 	for (idx = 0; idx < 6; idx++) {
211 		HALMAC_REG_W8(REG_MU_TX_CTL + 1, idx | mu_tbl_sel);
212 		HALMAC_REG_W32(REG_MU_STA_GID_VLD, gid_valid[idx]);
213 	}
214 
215 	/*To validate the sounding successful MU STA and enable MU TX*/
216 	for (i = 0; i < 6; i++) {
217 		if (param->sounding_sts[i] == 1)
218 			mu_tbl_valid |= BIT(i);
219 	}
220 	HALMAC_REG_W8(REG_MU_TX_CTL, mu_tbl_valid | BIT(7));
221 }
222 
223 /**
224  * cfg_sounding_88xx() - configure general sounding
225  * @adapter : the adapter of halmac
226  * @role : driver's role, BFer or BFee
227  * @rate : set ndpa tx rate if driver is BFer,
228  * or set csi response rate if driver is BFee
229  * Author : chunchu
230  * Return : enum halmac_ret_status
231  * More details of status code can be found in prototype document
232  */
233 enum halmac_ret_status
cfg_sounding_88xx(struct halmac_adapter * adapter,enum halmac_snd_role role,enum halmac_data_rate rate)234 cfg_sounding_88xx(struct halmac_adapter *adapter, enum halmac_snd_role role,
235 		  enum halmac_data_rate rate)
236 {
237 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
238 	u32 tmp6dc = 0;
239 	u8 csi_rsc = 0x0;
240 
241 	/*use ndpa rx rate to decide csi rate*/
242 	tmp6dc = HALMAC_REG_R32(REG_BBPSF_CTRL) | BIT_WMAC_USE_NDPARATE
243 							| (csi_rsc << 13);
244 
245 	switch (role) {
246 	case HAL_BFER:
247 		HALMAC_REG_W32_SET(REG_TXBF_CTRL, TXBF_CTRL_CFG);
248 		HALMAC_REG_W8(REG_NDPA_RATE, rate);
249 		HALMAC_REG_W8(REG_SND_PTCL_CTRL + 1, 0x2 | BIT(7));
250 		HALMAC_REG_W8(REG_SND_PTCL_CTRL + 2, 0x2);
251 		break;
252 	case HAL_BFEE:
253 		HALMAC_REG_W8(REG_SND_PTCL_CTRL, 0xDB);
254 		HALMAC_REG_W8(REG_SND_PTCL_CTRL + 3, 0x3A);
255 		HALMAC_REG_W8_CLR(REG_RXFLTMAP1, BIT(4));
256 		HALMAC_REG_W8_CLR(REG_RXFLTMAP4, BIT(4));
257 		#if (HALMAC_8822C_SUPPORT || HALMAC_8812F_SUPPORT)
258 		if (adapter->chip_id == HALMAC_CHIP_ID_8822C)
259 			HALMAC_REG_W32(REG_CSI_RRSR,
260 				       BIT_CSI_RRSC_BITMAP(CSI_RATE_MAP) |
261 				       BIT_OFDM_LEN_TH(0));
262 		else if (adapter->chip_id == HALMAC_CHIP_ID_8812F)
263 			HALMAC_REG_W32(REG_CSI_RRSR,
264 				       BIT_CSI_RRSC_BITMAP(CSI_RATE_MAP) |
265 				       BIT_OFDM_LEN_TH(3));
266 		#endif
267 		break;
268 	default:
269 		return HALMAC_RET_INVALID_SOUNDING_SETTING;
270 	}
271 
272 	/*AP mode set tx gid to 63*/
273 	/*STA mode set tx gid to 0*/
274 	if (BIT_GET_NETYPE0(HALMAC_REG_R32(REG_CR)) == 0x3)
275 		HALMAC_REG_W32(REG_BBPSF_CTRL, tmp6dc | BIT(12));
276 	else
277 		HALMAC_REG_W32(REG_BBPSF_CTRL, tmp6dc & ~(BIT(12)));
278 
279 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
280 
281 	return HALMAC_RET_SUCCESS;
282 }
283 
284 /**
285  * del_sounding_88xx() - reset general sounding
286  * @adapter : the adapter of halmac
287  * @role : driver's role, BFer or BFee
288  * Author : chunchu
289  * Return : enum halmac_ret_status
290  * More details of status code can be found in prototype document
291  */
292 enum halmac_ret_status
del_sounding_88xx(struct halmac_adapter * adapter,enum halmac_snd_role role)293 del_sounding_88xx(struct halmac_adapter *adapter, enum halmac_snd_role role)
294 {
295 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
296 
297 	switch (role) {
298 	case HAL_BFER:
299 		HALMAC_REG_W8(REG_TXBF_CTRL + 3, 0);
300 		break;
301 	case HAL_BFEE:
302 		HALMAC_REG_W8(REG_SND_PTCL_CTRL, 0);
303 		break;
304 	default:
305 		return HALMAC_RET_INVALID_SOUNDING_SETTING;
306 	}
307 
308 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
309 
310 	return HALMAC_RET_SUCCESS;
311 }
312 
313 /**
314  * su_bfee_entry_init_88xx() - config SU beamformee's registers
315  * @adapter : the adapter of halmac
316  * @userid : SU bfee userid = 0 or 1 to be added
317  * @paid : partial AID of this bfee
318  * Author : chunchu
319  * Return : enum halmac_ret_status
320  * More details of status code can be found in prototype document
321  */
322 enum halmac_ret_status
su_bfee_entry_init_88xx(struct halmac_adapter * adapter,u8 userid,u16 paid)323 su_bfee_entry_init_88xx(struct halmac_adapter *adapter, u8 userid, u16 paid)
324 {
325 	u16 tmp42c = 0;
326 	u16 tmp168x = 0;
327 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
328 
329 	switch (userid) {
330 	case 0:
331 		tmp42c = HALMAC_REG_R16(REG_TXBF_CTRL) &
332 				~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
333 				BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
334 		HALMAC_REG_W16(REG_TXBF_CTRL, tmp42c | paid);
335 		HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL, paid);
336 		#if HALMAC_8822C_SUPPORT
337 		if (adapter->chip_id == HALMAC_CHIP_ID_8822C)
338 			HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL, paid | BIT(9));
339 		#endif
340 		break;
341 	case 1:
342 		tmp42c = HALMAC_REG_R16(REG_TXBF_CTRL + 2) &
343 				~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
344 				BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
345 		HALMAC_REG_W16(REG_TXBF_CTRL + 2, tmp42c | paid);
346 		HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL + 2, paid | BIT(9));
347 		break;
348 	case 2:
349 		tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE2);
350 		tmp168x = BIT_CLEAR_WMAC_MU_BFEE2_AID(tmp168x);
351 		tmp168x |= (paid | BIT(9));
352 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE2, tmp168x);
353 		break;
354 	case 3:
355 		tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE3);
356 		tmp168x = BIT_CLEAR_WMAC_MU_BFEE3_AID(tmp168x);
357 		tmp168x |= (paid | BIT(9));
358 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE3, tmp168x);
359 		break;
360 	case 4:
361 		tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE4);
362 		tmp168x = BIT_CLEAR_WMAC_MU_BFEE4_AID(tmp168x);
363 		tmp168x |= (paid | BIT(9));
364 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE4, tmp168x);
365 		break;
366 	case 5:
367 		tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE5);
368 		tmp168x = BIT_CLEAR_WMAC_MU_BFEE5_AID(tmp168x);
369 		tmp168x |= (paid | BIT(9));
370 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE5, tmp168x);
371 		break;
372 	default:
373 		return HALMAC_RET_INVALID_SOUNDING_SETTING;
374 	}
375 
376 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
377 
378 	return HALMAC_RET_SUCCESS;
379 }
380 
381 /**
382  * su_bfee_entry_init_88xx() - config SU beamformer's registers
383  * @adapter : the adapter of halmac
384  * @param : parameters to configure SU BFER entry
385  * Author : chunchu
386  * Return : enum halmac_ret_status
387  * More details of status code can be found in prototype document
388  */
389 enum halmac_ret_status
su_bfer_entry_init_88xx(struct halmac_adapter * adapter,struct halmac_su_bfer_init_para * param)390 su_bfer_entry_init_88xx(struct halmac_adapter *adapter,
391 			struct halmac_su_bfer_init_para *param)
392 {
393 	u16 mac_addr_h;
394 	u32 mac_addr_l;
395 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
396 
397 	mac_addr_l = rtk_le32_to_cpu(param->bfer_address.addr_l_h.low);
398 	mac_addr_h = rtk_le16_to_cpu(param->bfer_address.addr_l_h.high);
399 
400 	switch (param->userid) {
401 	case 0:
402 		HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, mac_addr_l);
403 		HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 4, mac_addr_h);
404 		HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 6, param->paid);
405 		HALMAC_REG_W16(REG_TX_CSI_RPT_PARAM_BW20, param->csi_para);
406 		break;
407 	case 1:
408 		HALMAC_REG_W32(REG_ASSOCIATED_BFMER1_INFO, mac_addr_l);
409 		HALMAC_REG_W16(REG_ASSOCIATED_BFMER1_INFO + 4, mac_addr_h);
410 		HALMAC_REG_W16(REG_ASSOCIATED_BFMER1_INFO + 6, param->paid);
411 		HALMAC_REG_W16(REG_TX_CSI_RPT_PARAM_BW20 + 2, param->csi_para);
412 		break;
413 	default:
414 		return HALMAC_RET_INVALID_SOUNDING_SETTING;
415 	}
416 
417 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
418 
419 	return HALMAC_RET_SUCCESS;
420 }
421 
422 /**
423  * mu_bfee_entry_init_88xx() - config MU beamformee's registers
424  * @adapter : the adapter of halmac
425  * @param : parameters to configure MU BFEE entry
426  * Author : chunchu
427  * Return : enum halmac_ret_status
428  * More details of status code can be found in prototype document
429  */
430 enum halmac_ret_status
mu_bfee_entry_init_88xx(struct halmac_adapter * adapter,struct halmac_mu_bfee_init_para * param)431 mu_bfee_entry_init_88xx(struct halmac_adapter *adapter,
432 			struct halmac_mu_bfee_init_para *param)
433 {
434 	u16 tmp168x = 0;
435 	u16 tmp14c0;
436 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
437 
438 	tmp168x |= param->paid | BIT(9);
439 	HALMAC_REG_W16((0x1680 + param->userid * 2), tmp168x);
440 
441 	tmp14c0 = HALMAC_REG_R16(REG_MU_TX_CTL) & ~(BIT(8) | BIT(9) | BIT(10));
442 	HALMAC_REG_W16(REG_MU_TX_CTL, tmp14c0 | ((param->userid - 2) << 8));
443 	HALMAC_REG_W32(REG_MU_STA_GID_VLD, 0);
444 	HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO, param->user_position_l);
445 	HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO + 4, param->user_position_h);
446 
447 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
448 
449 	return HALMAC_RET_SUCCESS;
450 }
451 
452 /**
453  * mu_bfer_entry_init_88xx() - config MU beamformer's registers
454  * @adapter : the adapter of halmac
455  * @param : parameters to configure MU BFER entry
456  * Author : chunchu
457  * Return : enum halmac_ret_status
458  * More details of status code can be found in prototype document
459  */
460 enum halmac_ret_status
mu_bfer_entry_init_88xx(struct halmac_adapter * adapter,struct halmac_mu_bfer_init_para * param)461 mu_bfer_entry_init_88xx(struct halmac_adapter *adapter,
462 			struct halmac_mu_bfer_init_para *param)
463 {
464 	u16 tmp1680 = 0;
465 	u16 mac_addr_h;
466 	u32 mac_addr_l;
467 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
468 
469 	mac_addr_l = rtk_le32_to_cpu(param->bfer_address.addr_l_h.low);
470 	mac_addr_h = rtk_le16_to_cpu(param->bfer_address.addr_l_h.high);
471 
472 	HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, mac_addr_l);
473 	HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 4, mac_addr_h);
474 	HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 6, param->paid);
475 	HALMAC_REG_W16(REG_TX_CSI_RPT_PARAM_BW20, param->csi_para);
476 
477 	tmp1680 = HALMAC_REG_R16(0x1680) & 0xC000;
478 	tmp1680 |= param->my_aid | (param->csi_length_sel << 12);
479 	HALMAC_REG_W16(0x1680, tmp1680);
480 
481 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
482 
483 	return HALMAC_RET_SUCCESS;
484 }
485 
486 /**
487  * su_bfee_entry_del_88xx() - reset SU beamformee's registers
488  * @adapter : the adapter of halmac
489  * @userid : the SU BFee userid to be deleted
490  * Author : chunchu
491  * Return : enum halmac_ret_status
492  * More details of status code can be found in prototype document
493  */
494 enum halmac_ret_status
su_bfee_entry_del_88xx(struct halmac_adapter * adapter,u8 userid)495 su_bfee_entry_del_88xx(struct halmac_adapter *adapter, u8 userid)
496 {
497 	u16 value16;
498 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
499 
500 	switch (userid) {
501 	case 0:
502 		value16 = HALMAC_REG_R16(REG_TXBF_CTRL);
503 		value16 &= ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
504 					BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
505 		HALMAC_REG_W16(REG_TXBF_CTRL, value16);
506 		HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL, 0);
507 		break;
508 	case 1:
509 		value16 = HALMAC_REG_R16(REG_TXBF_CTRL + 2);
510 		value16 &= ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
511 					BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
512 		HALMAC_REG_W16(REG_TXBF_CTRL + 2, value16);
513 		HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL + 2, 0);
514 		break;
515 	case 2:
516 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE2, 0);
517 		break;
518 	case 3:
519 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE3, 0);
520 		break;
521 	case 4:
522 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE4, 0);
523 		break;
524 	case 5:
525 		HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE5, 0);
526 		break;
527 	default:
528 		return HALMAC_RET_INVALID_SOUNDING_SETTING;
529 	}
530 
531 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
532 
533 	return HALMAC_RET_SUCCESS;
534 }
535 
536 /**
537  * su_bfee_entry_del_88xx() - reset SU beamformer's registers
538  * @adapter : the adapter of halmac
539  * @userid : the SU BFer userid to be deleted
540  * Author : chunchu
541  * Return : enum halmac_ret_status
542  * More details of status code can be found in prototype document
543  */
544 enum halmac_ret_status
su_bfer_entry_del_88xx(struct halmac_adapter * adapter,u8 userid)545 su_bfer_entry_del_88xx(struct halmac_adapter *adapter, u8 userid)
546 {
547 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
548 
549 	switch (userid) {
550 	case 0:
551 		HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, 0);
552 		HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO + 4, 0);
553 		break;
554 	case 1:
555 		HALMAC_REG_W32(REG_ASSOCIATED_BFMER1_INFO, 0);
556 		HALMAC_REG_W32(REG_ASSOCIATED_BFMER1_INFO + 4, 0);
557 		break;
558 	default:
559 		return HALMAC_RET_INVALID_SOUNDING_SETTING;
560 	}
561 
562 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
563 
564 	return HALMAC_RET_SUCCESS;
565 }
566 
567 /**
568  * mu_bfee_entry_del_88xx() - reset MU beamformee's registers
569  * @adapter : the adapter of halmac
570  * @userid : the MU STA userid to be deleted
571  * Author : chunchu
572  * Return : enum halmac_ret_status
573  * More details of status code can be found in prototype document
574  */
575 enum halmac_ret_status
mu_bfee_entry_del_88xx(struct halmac_adapter * adapter,u8 userid)576 mu_bfee_entry_del_88xx(struct halmac_adapter *adapter, u8 userid)
577 {
578 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
579 
580 	HALMAC_REG_W16(0x1680 + userid * 2, 0);
581 	HALMAC_REG_W8_CLR(REG_MU_TX_CTL, BIT(userid - 2));
582 
583 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
584 
585 	return HALMAC_RET_SUCCESS;
586 }
587 
588 /**
589  * mu_bfer_entry_del_88xx() -reset MU beamformer's registers
590  * @adapter : the adapter of halmac
591  * Author : chunchu
592  * Return : enum halmac_ret_status
593  * More details of status code can be found in prototype document
594  */
595 enum halmac_ret_status
mu_bfer_entry_del_88xx(struct halmac_adapter * adapter)596 mu_bfer_entry_del_88xx(struct halmac_adapter *adapter)
597 {
598 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
599 
600 	HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, 0);
601 	HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO + 4, 0);
602 	HALMAC_REG_W16(0x1680, 0);
603 	HALMAC_REG_W8(REG_MU_TX_CTL, 0);
604 
605 	PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
606 
607 	return HALMAC_RET_SUCCESS;
608 }
609 
610 /**
611  * cfg_csi_rate_88xx() - config CSI frame Tx rate
612  * @adapter : the adapter of halmac
613  * @rssi : rssi in decimal value
614  * @cur_rate : current CSI frame rate
615  * @fixrate_en : enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate
616  * @new_rate : API returns the final CSI frame rate
617  * Author : chunchu
618  * Return : enum halmac_ret_status
619  * More details of status code can be found in prototype document
620  */
621 enum halmac_ret_status
cfg_csi_rate_88xx(struct halmac_adapter * adapter,u8 rssi,u8 cur_rate,u8 fixrate_en,u8 * new_rate,u8 * bmp_ofdm54)622 cfg_csi_rate_88xx(struct halmac_adapter *adapter, u8 rssi, u8 cur_rate,
623 		  u8 fixrate_en, u8 *new_rate, u8 *bmp_ofdm54)
624 {
625 	u32 csi_cfg;
626 	struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
627 
628 	PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
629 
630 	*bmp_ofdm54 = 0xFF;
631 
632 #if HALMAC_8821C_SUPPORT
633 	if (adapter->chip_id == HALMAC_CHIP_ID_8821C && fixrate_en) {
634 		csi_cfg = HALMAC_REG_R32(REG_BBPSF_CTRL) & ~BITS_WMAC_CSI_RATE;
635 		HALMAC_REG_W32(REG_BBPSF_CTRL,
636 			       csi_cfg | BIT_CSI_FORCE_RATE_EN |
637 			       BIT_CSI_RSC(1) |
638 			       BIT_WMAC_CSI_RATE(HALMAC_VHT_NSS1_MCS3));
639 		*new_rate = HALMAC_VHT_NSS1_MCS3;
640 		return HALMAC_RET_SUCCESS;
641 	}
642 	csi_cfg = HALMAC_REG_R32(REG_BBPSF_CTRL) & ~BITS_WMAC_CSI_RATE &
643 							~BIT_CSI_FORCE_RATE_EN;
644 #else
645 	csi_cfg = HALMAC_REG_R32(REG_BBPSF_CTRL) & ~BITS_WMAC_CSI_RATE;
646 #endif
647 
648 #if (HALMAC_8822C_SUPPORT || HALMAC_8812F_SUPPORT)
649 	if (adapter->chip_id == HALMAC_CHIP_ID_8822C ||
650 	    adapter->chip_id == HALMAC_CHIP_ID_8812F)
651 		HALMAC_REG_W32_SET(REG_BBPSF_CTRL, BIT(15));
652 #endif
653 
654 	if (rssi >= 40) {
655 		if (cur_rate != HALMAC_OFDM54) {
656 			csi_cfg |= BIT_WMAC_CSI_RATE(HALMAC_OFDM54);
657 			HALMAC_REG_W32(REG_BBPSF_CTRL, csi_cfg);
658 			*bmp_ofdm54 = 1;
659 		}
660 		*new_rate = HALMAC_OFDM54;
661 	} else {
662 		if (cur_rate != HALMAC_OFDM24) {
663 			csi_cfg |= BIT_WMAC_CSI_RATE(HALMAC_OFDM24);
664 			HALMAC_REG_W32(REG_BBPSF_CTRL, csi_cfg);
665 			*bmp_ofdm54 = 0;
666 		}
667 		*new_rate = HALMAC_OFDM24;
668 	}
669 
670 	return HALMAC_RET_SUCCESS;
671 }
672 
673 /**
674  * fw_snding_88xx() - fw sounding control
675  * @adapter : the adapter of halmac
676  * @su_info :
677  *	su0_en : enable/disable fw sounding
678  *	su0_ndpa_pkt : ndpa pkt, shall include txdesc
679  *	su0_pkt_sz : ndpa pkt size, shall include txdesc
680  * @mu_info : currently not in use, input NULL is acceptable
681  * @period : sounding period, unit is 5ms
682  * Author : Ivan Lin
683  * Return : enum halmac_ret_status
684  * More details of status code can be found in prototype document
685  */
686 enum halmac_ret_status
fw_snding_88xx(struct halmac_adapter * adapter,struct halmac_su_snding_info * su_info,struct halmac_mu_snding_info * mu_info,u8 period)687 fw_snding_88xx(struct halmac_adapter *adapter,
688 	       struct halmac_su_snding_info *su_info,
689 	       struct halmac_mu_snding_info *mu_info, u8 period)
690 {
691 	u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
692 	u16 seq_num;
693 	u16 snding_info_addr;
694 	struct halmac_h2c_header_info hdr_info;
695 	enum halmac_cmd_process_status *proc_status;
696 	enum halmac_ret_status status;
697 
698 	proc_status = &adapter->halmac_state.fw_snding_state.proc_status;
699 
700 	if (adapter->chip_id == HALMAC_CHIP_ID_8821C)
701 		return HALMAC_RET_NOT_SUPPORT;
702 
703 	if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
704 		return HALMAC_RET_NO_DLFW;
705 
706 	if (adapter->fw_ver.h2c_version < 9)
707 		return HALMAC_RET_FW_NO_SUPPORT;
708 
709 	if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
710 		PLTFM_MSG_TRACE("[TRACE]Wait event(snd)\n");
711 		return HALMAC_RET_BUSY_STATE;
712 	}
713 
714 	if (su_info->su0_en == 1) {
715 		if (!su_info->su0_ndpa_pkt)
716 			return HALMAC_RET_NULL_POINTER;
717 
718 		if (su_info->su0_pkt_sz > (u32)SU0_SNDING_PKT_RSVDPG_SIZE -
719 		    adapter->hw_cfg_info.txdesc_size)
720 			return HALMAC_RET_DATA_SIZE_INCORRECT;
721 
722 		if (!snding_pkt_chk_88xx(adapter, su_info->su0_ndpa_pkt))
723 			return HALMAC_RET_TXDESC_SET_FAIL;
724 
725 		if (fw_snding_cmd_cnstr_state_88xx(adapter) !=
726 		    HALMAC_CMD_CNSTR_IDLE) {
727 			PLTFM_MSG_ERR("[ERR]Not idle(snd)\n");
728 			return HALMAC_RET_ERROR_STATE;
729 		}
730 
731 		snding_info_addr = adapter->txff_alloc.rsvd_h2c_sta_info_addr +
732 				   SU0_SNDING_PKT_OFFSET;
733 		status = dl_rsvd_page_88xx(adapter, snding_info_addr,
734 					   su_info->su0_ndpa_pkt,
735 					   su_info->su0_pkt_sz);
736 		if (status != HALMAC_RET_SUCCESS) {
737 			PLTFM_MSG_ERR("[ERR]dl rsvd page\n");
738 			return status;
739 		}
740 
741 		FW_SNDING_SET_SU0(h2c_buf, 1);
742 		FW_SNDING_SET_PERIOD(h2c_buf, period);
743 		FW_SNDING_SET_NDPA0_HEAD_PG(h2c_buf, snding_info_addr -
744 					    adapter->txff_alloc.rsvd_boundary);
745 	} else {
746 		if (fw_snding_cmd_cnstr_state_88xx(adapter) !=
747 		    HALMAC_CMD_CNSTR_BUSY) {
748 			PLTFM_MSG_ERR("[ERR]Not snd(snd)\n");
749 			return HALMAC_RET_ERROR_STATE;
750 		}
751 		FW_SNDING_SET_SU0(h2c_buf, 0);
752 	}
753 
754 	*proc_status = HALMAC_CMD_PROCESS_SENDING;
755 
756 	hdr_info.sub_cmd_id = SUB_CMD_ID_FW_SNDING;
757 	hdr_info.content_size = 8;
758 	hdr_info.ack = 1;
759 	set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
760 	adapter->halmac_state.fw_snding_state.seq_num = seq_num;
761 
762 	status = send_h2c_pkt_88xx(adapter, h2c_buf);
763 	if (status != HALMAC_RET_SUCCESS) {
764 		PLTFM_MSG_ERR("[ERR]send h2c\n");
765 		reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_FW_SNDING);
766 		return status;
767 	}
768 
769 	if (cnv_fw_snding_state_88xx(adapter, su_info->su0_en == 1 ?
770 				     HALMAC_CMD_CNSTR_BUSY :
771 				     HALMAC_CMD_CNSTR_IDLE)
772 				     != HALMAC_RET_SUCCESS)
773 		return HALMAC_RET_ERROR_STATE;
774 
775 	return HALMAC_RET_SUCCESS;
776 }
777 
778 static u8
snding_pkt_chk_88xx(struct halmac_adapter * adapter,u8 * pkt)779 snding_pkt_chk_88xx(struct halmac_adapter *adapter, u8 *pkt)
780 {
781 	u8 data_rate;
782 
783 	if (GET_TX_DESC_NDPA(pkt) == 0) {
784 		PLTFM_MSG_ERR("[ERR]txdesc ndpa = 0\n");
785 		return 0;
786 	}
787 
788 	data_rate = (u8)GET_TX_DESC_DATARATE(pkt);
789 	if (!(data_rate >= HALMAC_VHT_NSS2_MCS0 &&
790 	      data_rate <= HALMAC_VHT_NSS2_MCS9)) {
791 		if (!(data_rate >= HALMAC_MCS8 && data_rate <= HALMAC_MCS15)) {
792 			PLTFM_MSG_ERR("[ERR]txdesc rate\n");
793 			return 0;
794 		}
795 	}
796 
797 	if (GET_TX_DESC_NAVUSEHDR(pkt) == 0) {
798 		PLTFM_MSG_ERR("[ERR]txdesc navusehdr = 0\n");
799 		return 0;
800 	}
801 
802 	if (GET_TX_DESC_USE_RATE(pkt) == 0) {
803 		PLTFM_MSG_ERR("[ERR]txdesc userate = 0\n");
804 		return 0;
805 	}
806 
807 	return 1;
808 }
809 
810 static enum halmac_cmd_construct_state
fw_snding_cmd_cnstr_state_88xx(struct halmac_adapter * adapter)811 fw_snding_cmd_cnstr_state_88xx(struct halmac_adapter *adapter)
812 {
813 	return adapter->halmac_state.fw_snding_state.cmd_cnstr_state;
814 }
815 
816 enum halmac_ret_status
get_h2c_ack_fw_snding_88xx(struct halmac_adapter * adapter,u8 * buf,u32 size)817 get_h2c_ack_fw_snding_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
818 {
819 	u8 seq_num = 0;
820 	u8 fw_rc;
821 	struct halmac_fw_snding_state *state;
822 	enum halmac_cmd_process_status proc_status;
823 
824 	state = &adapter->halmac_state.fw_snding_state;
825 
826 	seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
827 	PLTFM_MSG_TRACE("[TRACE]Seq num:h2c->%d c2h->%d\n",
828 			state->seq_num, seq_num);
829 	if (seq_num != state->seq_num) {
830 		PLTFM_MSG_ERR("[ERR]Seq num mismatch:h2c->%d c2h->%d\n",
831 			      state->seq_num, seq_num);
832 		return HALMAC_RET_SUCCESS;
833 	}
834 
835 	if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
836 		PLTFM_MSG_ERR("[ERR]not sending(snd)\n");
837 		return HALMAC_RET_SUCCESS;
838 	}
839 
840 	fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
841 	state->fw_rc = fw_rc;
842 
843 	if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS) {
844 		proc_status = HALMAC_CMD_PROCESS_DONE;
845 		state->proc_status = proc_status;
846 		PLTFM_EVENT_SIG(HALMAC_FEATURE_FW_SNDING, proc_status,
847 				NULL, 0);
848 	} else {
849 		proc_status = HALMAC_CMD_PROCESS_ERROR;
850 		state->proc_status = proc_status;
851 		PLTFM_EVENT_SIG(HALMAC_FEATURE_FW_SNDING, proc_status,
852 				&fw_rc, 1);
853 	}
854 
855 	return HALMAC_RET_SUCCESS;
856 }
857 
858 enum halmac_ret_status
get_fw_snding_status_88xx(struct halmac_adapter * adapter,enum halmac_cmd_process_status * proc_status)859 get_fw_snding_status_88xx(struct halmac_adapter *adapter,
860 			  enum halmac_cmd_process_status *proc_status)
861 {
862 	*proc_status = adapter->halmac_state.fw_snding_state.proc_status;
863 
864 	return HALMAC_RET_SUCCESS;
865 }
866 
867 static enum halmac_ret_status
cnv_fw_snding_state_88xx(struct halmac_adapter * adapter,enum halmac_cmd_construct_state dest_state)868 cnv_fw_snding_state_88xx(struct halmac_adapter *adapter,
869 			 enum halmac_cmd_construct_state dest_state)
870 {
871 	struct halmac_fw_snding_state *state;
872 
873 	state = &adapter->halmac_state.fw_snding_state;
874 
875 	if (state->cmd_cnstr_state != HALMAC_CMD_CNSTR_IDLE &&
876 	    state->cmd_cnstr_state != HALMAC_CMD_CNSTR_BUSY)
877 		return HALMAC_RET_ERROR_STATE;
878 
879 	if (dest_state == HALMAC_CMD_CNSTR_IDLE) {
880 		if (state->cmd_cnstr_state == HALMAC_CMD_CNSTR_IDLE)
881 			return HALMAC_RET_ERROR_STATE;
882 	} else if (dest_state == HALMAC_CMD_CNSTR_BUSY) {
883 		if (state->cmd_cnstr_state == HALMAC_CMD_CNSTR_BUSY)
884 			return HALMAC_RET_ERROR_STATE;
885 	}
886 
887 	state->cmd_cnstr_state = dest_state;
888 
889 	return HALMAC_RET_SUCCESS;
890 }
891 #endif /* HALMAC_88XX_SUPPORT */
892