1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019  Realtek Corporation
3  */
4 
5 #include "main.h"
6 #include "coex.h"
7 #include "fw.h"
8 #include "ps.h"
9 #include "debug.h"
10 #include "reg.h"
11 #include "phy.h"
12 
rtw_coex_next_rssi_state(struct rtw_dev * rtwdev,u8 pre_state,u8 rssi,u8 rssi_thresh)13 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
14 				   u8 rssi, u8 rssi_thresh)
15 {
16 	struct rtw_chip_info *chip = rtwdev->chip;
17 	u8 tol = chip->rssi_tolerance;
18 	u8 next_state;
19 
20 	if (pre_state == COEX_RSSI_STATE_LOW ||
21 	    pre_state == COEX_RSSI_STATE_STAY_LOW) {
22 		if (rssi >= (rssi_thresh + tol))
23 			next_state = COEX_RSSI_STATE_HIGH;
24 		else
25 			next_state = COEX_RSSI_STATE_STAY_LOW;
26 	} else {
27 		if (rssi < rssi_thresh)
28 			next_state = COEX_RSSI_STATE_LOW;
29 		else
30 			next_state = COEX_RSSI_STATE_STAY_HIGH;
31 	}
32 
33 	return next_state;
34 }
35 
rtw_coex_limited_tx(struct rtw_dev * rtwdev,bool tx_limit_en,bool ampdu_limit_en)36 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
37 				bool tx_limit_en, bool ampdu_limit_en)
38 {
39 	struct rtw_chip_info *chip = rtwdev->chip;
40 	struct rtw_coex *coex = &rtwdev->coex;
41 	struct rtw_coex_stat *coex_stat = &coex->stat;
42 	u8 num_of_active_port = 1;
43 
44 	if (!chip->scbd_support)
45 		return;
46 
47 	/* force max tx retry limit = 8 */
48 	if (coex_stat->wl_tx_limit_en == tx_limit_en &&
49 	    coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
50 		return;
51 
52 	if (!coex_stat->wl_tx_limit_en) {
53 		coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
54 		coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
55 		coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
56 	}
57 
58 	if (!coex_stat->wl_ampdu_limit_en)
59 		coex_stat->ampdu_max_time =
60 				rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
61 
62 	coex_stat->wl_tx_limit_en = tx_limit_en;
63 	coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
64 
65 	if (tx_limit_en) {
66 		/* set BT polluted packet on for tx rate adaptive,
67 		 * not including tx retry broken by PTA
68 		 */
69 		rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
70 
71 		/* set queue life time to avoid can't reach tx retry limit
72 		 * if tx is always broken by GNT_BT
73 		 */
74 		if (num_of_active_port <= 1)
75 			rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
76 		rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
77 
78 		/* auto rate fallback step within 8 retries */
79 		rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
80 		rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
81 	} else {
82 		rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
83 		rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
84 
85 		rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
86 		rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
87 		rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
88 	}
89 
90 	if (ampdu_limit_en)
91 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
92 	else
93 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
94 			   coex_stat->ampdu_max_time);
95 }
96 
rtw_coex_limited_wl(struct rtw_dev * rtwdev)97 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
98 {
99 	struct rtw_coex *coex = &rtwdev->coex;
100 	struct rtw_coex_dm *coex_dm = &coex->dm;
101 	bool tx_limit = false;
102 	bool tx_agg_ctrl = false;
103 
104 	if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) {
105 		tx_limit = true;
106 		tx_agg_ctrl = true;
107 	}
108 
109 	rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
110 }
111 
rtw_coex_freerun_check(struct rtw_dev * rtwdev)112 static bool rtw_coex_freerun_check(struct rtw_dev *rtwdev)
113 {
114 	struct rtw_coex *coex = &rtwdev->coex;
115 	struct rtw_coex_dm *coex_dm = &coex->dm;
116 	struct rtw_coex_stat *coex_stat = &coex->stat;
117 	struct rtw_efuse *efuse = &rtwdev->efuse;
118 	u8 bt_rssi;
119 	u8 ant_distance = 10;
120 
121 	if (coex_stat->bt_disabled)
122 		return false;
123 
124 	if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy)
125 		return false;
126 
127 	if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2)
128 		return true;
129 
130 	/* ant_distance = 5 ~ 40  */
131 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]) &&
132 	    COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0]))
133 		return true;
134 
135 	if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
136 		bt_rssi = coex_dm->bt_rssi_state[0];
137 	else
138 		bt_rssi = coex_dm->bt_rssi_state[1];
139 
140 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
141 	    COEX_RSSI_HIGH(bt_rssi) &&
142 	    coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
143 		return true;
144 
145 	return false;
146 }
147 
rtw_coex_wl_slot_extend(struct rtw_dev * rtwdev,bool enable)148 static void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable)
149 {
150 	struct rtw_coex *coex = &rtwdev->coex;
151 	struct rtw_coex_stat *coex_stat = &coex->stat;
152 	u8 para[6] = {0};
153 
154 	para[0] = COEX_H2C69_WL_LEAKAP;
155 	para[1] = PARA1_H2C69_DIS_5MS;
156 
157 	if (enable)
158 		para[1] = PARA1_H2C69_EN_5MS;
159 	else
160 		coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
161 
162 	coex_stat->wl_slot_extend = enable;
163 	rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
164 }
165 
rtw_coex_wl_ccklock_action(struct rtw_dev * rtwdev)166 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
167 {
168 	struct rtw_coex *coex = &rtwdev->coex;
169 	struct rtw_coex_stat *coex_stat = &coex->stat;
170 
171 	if (coex->manual_control || coex->stop_dm)
172 		return;
173 
174 
175 	if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
176 		rtw_dbg(rtwdev, RTW_DBG_COEX,
177 			"[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
178 		rtw_coex_wl_slot_extend(rtwdev, false);
179 		return;
180 	}
181 
182 	if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
183 	    !coex_stat->wl_cck_lock_ever) {
184 		if (coex_stat->wl_fw_dbg_info[7] <= 5)
185 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
186 		else
187 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
188 
189 		rtw_dbg(rtwdev, RTW_DBG_COEX,
190 			"[BTCoex], 5ms WL slot extend cnt = %d!!\n",
191 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]);
192 
193 		if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
194 			rtw_dbg(rtwdev, RTW_DBG_COEX,
195 				"[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
196 			rtw_coex_wl_slot_extend(rtwdev, false);
197 		}
198 	} else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
199 		rtw_dbg(rtwdev, RTW_DBG_COEX,
200 			"[BTCoex], set h2c 0x69 opcode 12 to turn on 5ms WL slot extend!!\n");
201 
202 		rtw_coex_wl_slot_extend(rtwdev, true);
203 	}
204 }
205 
rtw_coex_wl_ccklock_detect(struct rtw_dev * rtwdev)206 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
207 {
208 	struct rtw_coex *coex = &rtwdev->coex;
209 	struct rtw_coex_stat *coex_stat = &coex->stat;
210 	struct rtw_coex_dm *coex_dm = &coex->dm;
211 
212 	bool is_cck_lock_rate = false;
213 
214 	if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE ||
215 	    coex_stat->bt_setup_link) {
216 		coex_stat->wl_cck_lock = false;
217 		coex_stat->wl_cck_lock_pre = false;
218 		return;
219 	}
220 
221 	if (coex_stat->wl_rx_rate <= COEX_CCK_2 ||
222 	    coex_stat->wl_rts_rx_rate <= COEX_CCK_2)
223 		is_cck_lock_rate = true;
224 
225 	if (coex_stat->wl_connected && coex_stat->wl_gl_busy &&
226 	    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
227 	    (coex_dm->bt_status == COEX_BTSTATUS_ACL_BUSY ||
228 	     coex_dm->bt_status == COEX_BTSTATUS_ACL_SCO_BUSY ||
229 	     coex_dm->bt_status == COEX_BTSTATUS_SCO_BUSY)) {
230 		if (is_cck_lock_rate) {
231 			coex_stat->wl_cck_lock = true;
232 
233 			rtw_dbg(rtwdev, RTW_DBG_COEX,
234 				"[BTCoex], cck locking...\n");
235 
236 		} else {
237 			coex_stat->wl_cck_lock = false;
238 
239 			rtw_dbg(rtwdev, RTW_DBG_COEX,
240 				"[BTCoex], cck unlock...\n");
241 		}
242 	} else {
243 		coex_stat->wl_cck_lock = false;
244 	}
245 
246 	/* CCK lock identification */
247 	if (coex_stat->wl_cck_lock && !coex_stat->wl_cck_lock_pre)
248 		ieee80211_queue_delayed_work(rtwdev->hw, &coex->wl_ccklock_work,
249 					     3 * HZ);
250 
251 	coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock;
252 }
253 
rtw_coex_wl_noisy_detect(struct rtw_dev * rtwdev)254 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
255 {
256 	struct rtw_coex *coex = &rtwdev->coex;
257 	struct rtw_coex_stat *coex_stat = &coex->stat;
258 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
259 	u32 cnt_cck;
260 	bool wl_cck_lock = false;
261 
262 	/* wifi noisy environment identification */
263 	cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
264 
265 	if (!coex_stat->wl_gl_busy && !wl_cck_lock) {
266 		if (cnt_cck > 250) {
267 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
268 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
269 
270 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
271 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
272 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
273 			}
274 		} else if (cnt_cck < 100) {
275 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
276 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
277 
278 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
279 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
280 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
281 			}
282 		} else {
283 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
284 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
285 
286 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
287 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
288 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
289 			}
290 		}
291 
292 		if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
293 			coex_stat->wl_noisy_level = 2;
294 		else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
295 			coex_stat->wl_noisy_level = 1;
296 		else
297 			coex_stat->wl_noisy_level = 0;
298 
299 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n",
300 			coex_stat->wl_noisy_level);
301 	}
302 }
303 
rtw_coex_tdma_timer_base(struct rtw_dev * rtwdev,u8 type)304 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
305 {
306 	struct rtw_coex *coex = &rtwdev->coex;
307 	struct rtw_coex_stat *coex_stat = &coex->stat;
308 	u8 para[2] = {0};
309 	u8 times;
310 	u16 tbtt_interval = coex_stat->wl_beacon_interval;
311 
312 	if (coex_stat->tdma_timer_base == type)
313 		return;
314 
315 	coex_stat->tdma_timer_base = type;
316 
317 	para[0] = COEX_H2C69_TDMA_SLOT;
318 
319 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n",
320 		tbtt_interval);
321 
322 	if (type == TDMA_TIMER_TYPE_4SLOT && tbtt_interval < 120) {
323 		para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */
324 	} else if (tbtt_interval < 80 && tbtt_interval > 0) {
325 		times = 100 / tbtt_interval;
326 		if (100 % tbtt_interval != 0)
327 			times++;
328 
329 		para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times);
330 	} else if (tbtt_interval >= 180) {
331 		times = tbtt_interval / 100;
332 		if (tbtt_interval % 100 <= 80)
333 			times--;
334 
335 		para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) |
336 			  FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1);
337 	} else {
338 		para[1] = PARA1_H2C69_TDMA_2SLOT;
339 	}
340 
341 	rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
342 
343 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n",
344 		__func__, para[1]);
345 
346 	/* no 5ms_wl_slot_extend for 4-slot mode  */
347 	if (coex_stat->tdma_timer_base == 3)
348 		rtw_coex_wl_ccklock_action(rtwdev);
349 }
350 
rtw_coex_set_wl_pri_mask(struct rtw_dev * rtwdev,u8 bitmap,u8 data)351 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
352 				     u8 data)
353 {
354 	u32 addr;
355 
356 	addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
357 	bitmap = bitmap % 8;
358 
359 	rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
360 }
361 
rtw_coex_write_scbd(struct rtw_dev * rtwdev,u16 bitpos,bool set)362 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
363 {
364 	struct rtw_chip_info *chip = rtwdev->chip;
365 	struct rtw_coex *coex = &rtwdev->coex;
366 	struct rtw_coex_stat *coex_stat = &coex->stat;
367 	u16 val = 0x2;
368 
369 	if (!chip->scbd_support)
370 		return;
371 
372 	val |= coex_stat->score_board;
373 
374 	/* for 8822b, scbd[10] is CQDDR on
375 	 * for 8822c, scbd[10] is no fix 2M
376 	 */
377 	if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
378 		if (set)
379 			val &= ~COEX_SCBD_FIX2M;
380 		else
381 			val |= COEX_SCBD_FIX2M;
382 	} else {
383 		if (set)
384 			val |= bitpos;
385 		else
386 			val &= ~bitpos;
387 	}
388 
389 	if (val != coex_stat->score_board) {
390 		coex_stat->score_board = val;
391 		val |= BIT_BT_INT_EN;
392 		rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
393 	}
394 }
395 EXPORT_SYMBOL(rtw_coex_write_scbd);
396 
rtw_coex_read_scbd(struct rtw_dev * rtwdev)397 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
398 {
399 	struct rtw_chip_info *chip = rtwdev->chip;
400 
401 	if (!chip->scbd_support)
402 		return 0;
403 
404 	return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
405 }
406 
rtw_coex_check_rfk(struct rtw_dev * rtwdev)407 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
408 {
409 	struct rtw_chip_info *chip = rtwdev->chip;
410 	struct rtw_coex *coex = &rtwdev->coex;
411 	struct rtw_coex_stat *coex_stat = &coex->stat;
412 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
413 	u8 cnt = 0;
414 	u32 wait_cnt;
415 	bool btk, wlk;
416 
417 	if (coex_rfe->wlg_at_btg && chip->scbd_support &&
418 	    coex_stat->bt_iqk_state != 0xff) {
419 		rtw_dbg(rtwdev, RTW_DBG_COEX,
420 			"[BTCoex], (Before Ant Setup) Delay by IQK\n");
421 
422 		wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
423 		do {
424 			/* BT RFK */
425 			btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
426 
427 			/* WL RFK */
428 			wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
429 
430 			if (!btk && !wlk)
431 				break;
432 
433 			rtw_dbg(rtwdev, RTW_DBG_COEX,
434 				"[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n",
435 				wlk, btk);
436 
437 			mdelay(COEX_MIN_DELAY);
438 		} while (++cnt < wait_cnt);
439 
440 		if (cnt >= wait_cnt)
441 			coex_stat->bt_iqk_state = 0xff;
442 	}
443 }
444 
rtw_coex_query_bt_info(struct rtw_dev * rtwdev)445 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
446 {
447 	struct rtw_coex *coex = &rtwdev->coex;
448 	struct rtw_coex_stat *coex_stat = &coex->stat;
449 
450 	if (coex_stat->bt_disabled)
451 		return;
452 
453 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
454 
455 	rtw_fw_query_bt_info(rtwdev);
456 }
457 
rtw_coex_gnt_workaround(struct rtw_dev * rtwdev,bool force,u8 mode)458 static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode)
459 {
460 	rtw_coex_set_gnt_fix(rtwdev);
461 }
462 
rtw_coex_monitor_bt_enable(struct rtw_dev * rtwdev)463 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
464 {
465 	struct rtw_chip_info *chip = rtwdev->chip;
466 	struct rtw_coex *coex = &rtwdev->coex;
467 	struct rtw_coex_stat *coex_stat = &coex->stat;
468 	struct rtw_coex_dm *coex_dm = &coex->dm;
469 	bool bt_disabled = false;
470 	u16 score_board;
471 
472 	if (chip->scbd_support) {
473 		score_board = rtw_coex_read_scbd(rtwdev);
474 		bt_disabled = !(score_board & COEX_SCBD_ONOFF);
475 	}
476 
477 	if (coex_stat->bt_disabled != bt_disabled) {
478 		rtw_dbg(rtwdev, RTW_DBG_COEX,
479 			"[BTCoex], BT state changed (%d) -> (%d)\n",
480 			coex_stat->bt_disabled, bt_disabled);
481 
482 		coex_stat->bt_disabled = bt_disabled;
483 		coex_stat->bt_ble_scan_type = 0;
484 		coex_dm->cur_bt_lna_lvl = 0;
485 
486 		if (!coex_stat->bt_disabled) {
487 			coex_stat->bt_reenable = true;
488 			ieee80211_queue_delayed_work(rtwdev->hw,
489 						     &coex->bt_reenable_work,
490 						     15 * HZ);
491 		} else {
492 			coex_stat->bt_mailbox_reply = false;
493 			coex_stat->bt_reenable = false;
494 		}
495 	}
496 }
497 
rtw_coex_update_wl_link_info(struct rtw_dev * rtwdev,u8 reason)498 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
499 {
500 	struct rtw_coex *coex = &rtwdev->coex;
501 	struct rtw_coex_stat *coex_stat = &coex->stat;
502 	struct rtw_coex_dm *coex_dm = &coex->dm;
503 	struct rtw_chip_info *chip = rtwdev->chip;
504 	struct rtw_traffic_stats *stats = &rtwdev->stats;
505 	bool is_5G = false;
506 	bool wl_busy = false;
507 	bool scan = false, link = false;
508 	int i;
509 	u8 rssi_state;
510 	u8 rssi_step;
511 	u8 rssi;
512 
513 	scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
514 	coex_stat->wl_connected = !!rtwdev->sta_cnt;
515 
516 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
517 	if (wl_busy != coex_stat->wl_gl_busy) {
518 		if (wl_busy)
519 			coex_stat->wl_gl_busy = true;
520 		else
521 			ieee80211_queue_delayed_work(rtwdev->hw,
522 						     &coex->wl_remain_work,
523 						     12 * HZ);
524 	}
525 
526 	if (stats->tx_throughput > stats->rx_throughput)
527 		coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
528 	else
529 		coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
530 
531 	if (scan || link || reason == COEX_RSN_2GCONSTART ||
532 	    reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
533 		coex_stat->wl_linkscan_proc = true;
534 	else
535 		coex_stat->wl_linkscan_proc = false;
536 
537 	rtw_coex_wl_noisy_detect(rtwdev);
538 
539 	for (i = 0; i < 4; i++) {
540 		rssi_state = coex_dm->wl_rssi_state[i];
541 		rssi_step = chip->wl_rssi_step[i];
542 		rssi = rtwdev->dm_info.min_rssi;
543 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
544 						      rssi, rssi_step);
545 		coex_dm->wl_rssi_state[i] = rssi_state;
546 	}
547 
548 	if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
549 	    coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
550 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
551 	else
552 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
553 
554 	switch (reason) {
555 	case COEX_RSN_5GSCANSTART:
556 	case COEX_RSN_5GSWITCHBAND:
557 	case COEX_RSN_5GCONSTART:
558 
559 		is_5G = true;
560 		break;
561 	case COEX_RSN_2GSCANSTART:
562 	case COEX_RSN_2GSWITCHBAND:
563 	case COEX_RSN_2GCONSTART:
564 
565 		is_5G = false;
566 		break;
567 	default:
568 		if (rtwdev->hal.current_band_type == RTW_BAND_5G)
569 			is_5G = true;
570 		else
571 			is_5G = false;
572 		break;
573 	}
574 
575 	coex->under_5g = is_5G;
576 }
577 
get_payload_from_coex_resp(struct sk_buff * resp)578 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
579 {
580 	struct rtw_c2h_cmd *c2h;
581 	u32 pkt_offset;
582 
583 	pkt_offset = *((u32 *)resp->cb);
584 	c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
585 
586 	return c2h->payload;
587 }
588 
rtw_coex_info_response(struct rtw_dev * rtwdev,struct sk_buff * skb)589 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
590 {
591 	struct rtw_coex *coex = &rtwdev->coex;
592 	u8 *payload = get_payload_from_coex_resp(skb);
593 
594 	if (payload[0] != COEX_RESP_ACK_BY_WL_FW)
595 		return;
596 
597 	skb_queue_tail(&coex->queue, skb);
598 	wake_up(&coex->wait);
599 }
600 
rtw_coex_info_request(struct rtw_dev * rtwdev,struct rtw_coex_info_req * req)601 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
602 					     struct rtw_coex_info_req *req)
603 {
604 	struct rtw_coex *coex = &rtwdev->coex;
605 	struct sk_buff *skb_resp = NULL;
606 
607 	mutex_lock(&coex->mutex);
608 
609 	rtw_fw_query_bt_mp_info(rtwdev, req);
610 
611 	if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
612 				COEX_REQUEST_TIMEOUT)) {
613 		rtw_err(rtwdev, "coex request time out\n");
614 		goto out;
615 	}
616 
617 	skb_resp = skb_dequeue(&coex->queue);
618 	if (!skb_resp) {
619 		rtw_err(rtwdev, "failed to get coex info response\n");
620 		goto out;
621 	}
622 
623 out:
624 	mutex_unlock(&coex->mutex);
625 	return skb_resp;
626 }
627 
rtw_coex_get_bt_scan_type(struct rtw_dev * rtwdev,u8 * scan_type)628 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
629 {
630 	struct rtw_coex_info_req req = {0};
631 	struct sk_buff *skb;
632 	u8 *payload;
633 	bool ret = false;
634 
635 	req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
636 	skb = rtw_coex_info_request(rtwdev, &req);
637 	if (!skb)
638 		goto out;
639 
640 	payload = get_payload_from_coex_resp(skb);
641 	*scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
642 	dev_kfree_skb_any(skb);
643 	ret = true;
644 
645 out:
646 	return ret;
647 }
648 
rtw_coex_set_lna_constrain_level(struct rtw_dev * rtwdev,u8 lna_constrain_level)649 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
650 					     u8 lna_constrain_level)
651 {
652 	struct rtw_coex_info_req req = {0};
653 	struct sk_buff *skb;
654 	bool ret = false;
655 
656 	req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
657 	req.para1 = lna_constrain_level;
658 	skb = rtw_coex_info_request(rtwdev, &req);
659 	if (!skb)
660 		goto out;
661 
662 	dev_kfree_skb_any(skb);
663 	ret = true;
664 
665 out:
666 	return ret;
667 }
668 
669 #define case_BTSTATUS(src) \
670 	case COEX_BTSTATUS_##src: return #src
671 
rtw_coex_get_bt_status_string(u8 bt_status)672 static const char *rtw_coex_get_bt_status_string(u8 bt_status)
673 {
674 	switch (bt_status) {
675 	case_BTSTATUS(NCON_IDLE);
676 	case_BTSTATUS(CON_IDLE);
677 	case_BTSTATUS(INQ_PAGE);
678 	case_BTSTATUS(ACL_BUSY);
679 	case_BTSTATUS(SCO_BUSY);
680 	case_BTSTATUS(ACL_SCO_BUSY);
681 	default:
682 		return "Unknown";
683 	}
684 }
685 
rtw_coex_update_bt_link_info(struct rtw_dev * rtwdev)686 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
687 {
688 	struct rtw_coex *coex = &rtwdev->coex;
689 	struct rtw_coex_stat *coex_stat = &coex->stat;
690 	struct rtw_coex_dm *coex_dm = &coex->dm;
691 	struct rtw_chip_info *chip = rtwdev->chip;
692 	u8 i;
693 	u8 rssi_state;
694 	u8 rssi_step;
695 	u8 rssi;
696 
697 	/* update wl/bt rssi by btinfo */
698 	for (i = 0; i < COEX_RSSI_STEP; i++) {
699 		rssi_state = coex_dm->bt_rssi_state[i];
700 		rssi_step = chip->bt_rssi_step[i];
701 		rssi = coex_stat->bt_rssi;
702 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi,
703 						      rssi_step);
704 		coex_dm->bt_rssi_state[i] = rssi_state;
705 	}
706 
707 	if (coex_stat->bt_ble_scan_en &&
708 	    coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
709 		u8 scan_type;
710 
711 		if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
712 			coex_stat->bt_ble_scan_type = scan_type;
713 			if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
714 				coex_stat->bt_init_scan = true;
715 			else
716 				coex_stat->bt_init_scan = false;
717 		}
718 	}
719 
720 	coex_stat->bt_profile_num = 0;
721 
722 	/* set link exist status */
723 	if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
724 		coex_stat->bt_link_exist = false;
725 		coex_stat->bt_pan_exist = false;
726 		coex_stat->bt_a2dp_exist = false;
727 		coex_stat->bt_hid_exist = false;
728 		coex_stat->bt_hfp_exist = false;
729 	} else {
730 		/* connection exists */
731 		coex_stat->bt_link_exist = true;
732 		if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
733 			coex_stat->bt_pan_exist = true;
734 			coex_stat->bt_profile_num++;
735 		} else {
736 			coex_stat->bt_pan_exist = false;
737 		}
738 
739 		if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
740 			coex_stat->bt_a2dp_exist = true;
741 			coex_stat->bt_profile_num++;
742 		} else {
743 			coex_stat->bt_a2dp_exist = false;
744 		}
745 
746 		if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
747 			coex_stat->bt_hid_exist = true;
748 			coex_stat->bt_profile_num++;
749 		} else {
750 			coex_stat->bt_hid_exist = false;
751 		}
752 
753 		if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
754 			coex_stat->bt_hfp_exist = true;
755 			coex_stat->bt_profile_num++;
756 		} else {
757 			coex_stat->bt_hfp_exist = false;
758 		}
759 	}
760 
761 	if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
762 		coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
763 	} else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
764 		coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
765 		coex_stat->bt_multi_link_remain = false;
766 	} else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
767 		coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
768 	} else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
769 		   (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
770 		if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
771 			coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
772 		else
773 			coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
774 	} else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
775 		coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
776 	} else {
777 		coex_dm->bt_status = COEX_BTSTATUS_MAX;
778 	}
779 
780 	coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
781 
782 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__,
783 		rtw_coex_get_bt_status_string(coex_dm->bt_status));
784 }
785 
rtw_coex_update_wl_ch_info(struct rtw_dev * rtwdev,u8 type)786 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
787 {
788 	struct rtw_chip_info *chip = rtwdev->chip;
789 	struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
790 	u8 link = 0;
791 	u8 center_chan = 0;
792 	u8 bw;
793 	int i;
794 
795 	bw = rtwdev->hal.current_band_width;
796 
797 	if (type != COEX_MEDIA_DISCONNECT)
798 		center_chan = rtwdev->hal.current_channel;
799 
800 	if (center_chan == 0) {
801 		link = 0;
802 		center_chan = 0;
803 		bw = 0;
804 	} else if (center_chan <= 14) {
805 		link = 0x1;
806 
807 		if (bw == RTW_CHANNEL_WIDTH_40)
808 			bw = chip->bt_afh_span_bw40;
809 		else
810 			bw = chip->bt_afh_span_bw20;
811 	} else if (chip->afh_5g_num > 1) {
812 		for (i = 0; i < chip->afh_5g_num; i++) {
813 			if (center_chan == chip->afh_5g[i].wl_5g_ch) {
814 				link = 0x3;
815 				center_chan = chip->afh_5g[i].bt_skip_ch;
816 				bw = chip->afh_5g[i].bt_skip_span;
817 				break;
818 			}
819 		}
820 	}
821 
822 	coex_dm->wl_ch_info[0] = link;
823 	coex_dm->wl_ch_info[1] = center_chan;
824 	coex_dm->wl_ch_info[2] = bw;
825 
826 	rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
827 	rtw_dbg(rtwdev, RTW_DBG_COEX,
828 		"[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link,
829 		center_chan, bw);
830 }
831 
rtw_coex_set_bt_tx_power(struct rtw_dev * rtwdev,u8 bt_pwr_dec_lvl)832 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
833 {
834 	struct rtw_coex *coex = &rtwdev->coex;
835 	struct rtw_coex_dm *coex_dm = &coex->dm;
836 
837 	if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
838 		return;
839 
840 	coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
841 
842 	rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
843 }
844 
rtw_coex_set_bt_rx_gain(struct rtw_dev * rtwdev,u8 bt_lna_lvl)845 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
846 {
847 	struct rtw_coex *coex = &rtwdev->coex;
848 	struct rtw_coex_dm *coex_dm = &coex->dm;
849 
850 	if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
851 		return;
852 
853 	coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
854 
855 	/* notify BT rx gain table changed */
856 	if (bt_lna_lvl < 7) {
857 		rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
858 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
859 	} else {
860 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
861 	}
862 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n",
863 		__func__, bt_lna_lvl);
864 }
865 
rtw_coex_set_rf_para(struct rtw_dev * rtwdev,struct coex_rf_para para)866 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
867 				 struct coex_rf_para para)
868 {
869 	struct rtw_coex *coex = &rtwdev->coex;
870 	struct rtw_coex_stat *coex_stat = &coex->stat;
871 	u8 offset = 0;
872 
873 	if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
874 		offset = 3;
875 
876 	rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
877 	rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
878 	rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
879 	rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
880 }
881 
rtw_coex_read_indirect_reg(struct rtw_dev * rtwdev,u16 addr)882 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
883 {
884 	u32 val;
885 
886 	if (!ltecoex_read_reg(rtwdev, addr, &val)) {
887 		rtw_err(rtwdev, "failed to read indirect register\n");
888 		return 0;
889 	}
890 
891 	return val;
892 }
893 EXPORT_SYMBOL(rtw_coex_read_indirect_reg);
894 
rtw_coex_write_indirect_reg(struct rtw_dev * rtwdev,u16 addr,u32 mask,u32 val)895 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
896 				 u32 mask, u32 val)
897 {
898 	u32 shift = __ffs(mask);
899 	u32 tmp;
900 
901 	tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
902 	tmp = (tmp & (~mask)) | ((val << shift) & mask);
903 
904 	if (!ltecoex_reg_write(rtwdev, addr, tmp))
905 		rtw_err(rtwdev, "failed to write indirect register\n");
906 }
907 EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
908 
rtw_coex_coex_ctrl_owner(struct rtw_dev * rtwdev,bool wifi_control)909 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
910 {
911 	struct rtw_chip_info *chip = rtwdev->chip;
912 	const struct rtw_hw_reg *btg_reg = chip->btg_reg;
913 
914 	if (wifi_control) {
915 		rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3,
916 			       BIT_LTE_MUX_CTRL_PATH >> 24);
917 		if (btg_reg)
918 			rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
919 	} else {
920 		rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3,
921 			       BIT_LTE_MUX_CTRL_PATH >> 24);
922 		if (btg_reg)
923 			rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
924 	}
925 }
926 
rtw_coex_set_gnt_bt(struct rtw_dev * rtwdev,u8 state)927 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
928 {
929 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);
930 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);
931 }
932 
rtw_coex_set_gnt_wl(struct rtw_dev * rtwdev,u8 state)933 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
934 {
935 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);
936 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
937 }
938 
rtw_btc_wltoggle_table_a(struct rtw_dev * rtwdev,bool force,u8 table_case)939 static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,
940 				     u8 table_case)
941 {
942 	struct rtw_chip_info *chip = rtwdev->chip;
943 	struct rtw_efuse *efuse = &rtwdev->efuse;
944 	u8 h2c_para[6] = {0};
945 	u32 table_wl = 0x5a5a5a5a;
946 
947 	h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A;
948 	/* no definition */
949 	h2c_para[1] = 0x1;
950 
951 	if (efuse->share_ant) {
952 		if (table_case < chip->table_sant_num)
953 			table_wl = chip->table_sant[table_case].wl;
954 	} else {
955 		if (table_case < chip->table_nsant_num)
956 			table_wl = chip->table_nsant[table_case].wl;
957 	}
958 
959 	/* tell WL FW WL slot toggle table-A*/
960 	h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0));
961 	h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8));
962 	h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16));
963 	h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24));
964 
965 	rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]);
966 
967 	rtw_dbg(rtwdev, RTW_DBG_COEX,
968 		"[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
969 		__func__, h2c_para[0], h2c_para[1], h2c_para[2],
970 		h2c_para[3], h2c_para[4], h2c_para[5]);
971 }
972 
973 #define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa
rtw_btc_wltoggle_table_b(struct rtw_dev * rtwdev,bool force,u8 interval,u32 table)974 static void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force,
975 				     u8 interval, u32 table)
976 {
977 	struct rtw_coex *coex = &rtwdev->coex;
978 	struct rtw_coex_stat *coex_stat = &coex->stat;
979 	u8 cur_h2c_para[6] = {0};
980 	u8 i;
981 
982 	cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B;
983 	cur_h2c_para[1] = interval;
984 	cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0));
985 	cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8));
986 	cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16));
987 	cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24));
988 
989 	coex_stat->wl_toggle_interval = interval;
990 
991 	for (i = 0; i <= 5; i++)
992 		coex_stat->wl_toggle_para[i] = cur_h2c_para[i];
993 
994 	rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]);
995 
996 	rtw_dbg(rtwdev, RTW_DBG_COEX,
997 		"[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
998 		__func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2],
999 		cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]);
1000 }
1001 
rtw_coex_set_table(struct rtw_dev * rtwdev,bool force,u32 table0,u32 table1)1002 static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,
1003 			       u32 table1)
1004 {
1005 #define DEF_BRK_TABLE_VAL 0xf0ffffff
1006 	struct rtw_coex *coex = &rtwdev->coex;
1007 	struct rtw_coex_dm *coex_dm = &coex->dm;
1008 
1009 	/* If last tdma is wl slot toggle, force write table*/
1010 	if (!force && coex_dm->reason != COEX_RSN_LPS) {
1011 		if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) &&
1012 		    table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1))
1013 			return;
1014 	}
1015 	rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
1016 	rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
1017 	rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
1018 
1019 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1020 		"[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0,
1021 		table1);
1022 }
1023 
rtw_coex_table(struct rtw_dev * rtwdev,bool force,u8 type)1024 static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)
1025 {
1026 	struct rtw_coex *coex = &rtwdev->coex;
1027 	struct rtw_coex_dm *coex_dm = &coex->dm;
1028 	struct rtw_chip_info *chip = rtwdev->chip;
1029 	struct rtw_efuse *efuse = &rtwdev->efuse;
1030 	struct rtw_coex_stat *coex_stat = &coex->stat;
1031 
1032 	coex_dm->cur_table = type;
1033 
1034 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type);
1035 
1036 	if (efuse->share_ant) {
1037 		if (type < chip->table_sant_num)
1038 			rtw_coex_set_table(rtwdev, force,
1039 					   chip->table_sant[type].bt,
1040 					   chip->table_sant[type].wl);
1041 	} else {
1042 		type = type - 100;
1043 		if (type < chip->table_nsant_num)
1044 			rtw_coex_set_table(rtwdev, force,
1045 					   chip->table_nsant[type].bt,
1046 					   chip->table_nsant[type].wl);
1047 	}
1048 	if (coex_stat->wl_slot_toggle_change)
1049 		rtw_btc_wltoggle_table_a(rtwdev, true, type);
1050 }
1051 
rtw_coex_ignore_wlan_act(struct rtw_dev * rtwdev,bool enable)1052 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
1053 {
1054 	struct rtw_coex *coex = &rtwdev->coex;
1055 
1056 	if (coex->manual_control || coex->stop_dm)
1057 		return;
1058 
1059 	rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
1060 }
1061 
rtw_coex_power_save_state(struct rtw_dev * rtwdev,u8 ps_type,u8 lps_val,u8 rpwm_val)1062 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
1063 				      u8 lps_val, u8 rpwm_val)
1064 {
1065 	struct rtw_coex *coex = &rtwdev->coex;
1066 	struct rtw_coex_stat *coex_stat = &coex->stat;
1067 	u8 lps_mode = 0x0;
1068 
1069 	lps_mode = rtwdev->lps_conf.mode;
1070 
1071 	switch (ps_type) {
1072 	case COEX_PS_WIFI_NATIVE:
1073 		/* recover to original 32k low power setting */
1074 		coex_stat->wl_force_lps_ctrl = false;
1075 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1076 			"[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__);
1077 		rtw_leave_lps(rtwdev);
1078 		break;
1079 	case COEX_PS_LPS_OFF:
1080 		coex_stat->wl_force_lps_ctrl = true;
1081 		if (lps_mode)
1082 			rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0);
1083 
1084 		rtw_leave_lps(rtwdev);
1085 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1086 			"[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__);
1087 		break;
1088 	default:
1089 		break;
1090 	}
1091 }
1092 
rtw_coex_set_tdma(struct rtw_dev * rtwdev,u8 byte1,u8 byte2,u8 byte3,u8 byte4,u8 byte5)1093 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
1094 			      u8 byte3, u8 byte4, u8 byte5)
1095 {
1096 	struct rtw_coex *coex = &rtwdev->coex;
1097 	struct rtw_coex_dm *coex_dm = &coex->dm;
1098 	struct rtw_chip_info *chip = rtwdev->chip;
1099 	struct rtw_coex_stat *coex_stat = &coex->stat;
1100 	u8 ps_type = COEX_PS_WIFI_NATIVE;
1101 	bool ap_enable = false;
1102 
1103 	if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
1104 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n",
1105 			__func__);
1106 
1107 		byte1 &= ~BIT(4);
1108 		byte1 |= BIT(5);
1109 
1110 		byte5 |= BIT(5);
1111 		byte5 &= ~BIT(6);
1112 
1113 		ps_type = COEX_PS_WIFI_NATIVE;
1114 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1115 	} else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
1116 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1117 			"[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__,
1118 			byte1);
1119 
1120 		if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
1121 			ps_type = COEX_PS_LPS_OFF;
1122 		else
1123 			ps_type = COEX_PS_LPS_ON;
1124 		rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
1125 	} else {
1126 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1127 			"[BTCoex], %s(): native power save (byte1 = 0x%x)\n",
1128 			__func__, byte1);
1129 
1130 		ps_type = COEX_PS_WIFI_NATIVE;
1131 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1132 	}
1133 
1134 	coex_dm->ps_tdma_para[0] = byte1;
1135 	coex_dm->ps_tdma_para[1] = byte2;
1136 	coex_dm->ps_tdma_para[2] = byte3;
1137 	coex_dm->ps_tdma_para[3] = byte4;
1138 	coex_dm->ps_tdma_para[4] = byte5;
1139 
1140 	rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
1141 
1142 	if (byte1 & BIT(2)) {
1143 		coex_stat->wl_slot_toggle = true;
1144 		coex_stat->wl_slot_toggle_change = false;
1145 	} else {
1146 		coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle;
1147 		coex_stat->wl_slot_toggle = false;
1148 	}
1149 }
1150 
rtw_coex_tdma(struct rtw_dev * rtwdev,bool force,u32 tcase)1151 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
1152 {
1153 	struct rtw_coex *coex = &rtwdev->coex;
1154 	struct rtw_coex_dm *coex_dm = &coex->dm;
1155 	struct rtw_coex_stat *coex_stat = &coex->stat;
1156 	struct rtw_chip_info *chip = rtwdev->chip;
1157 	struct rtw_efuse *efuse = &rtwdev->efuse;
1158 	u8 n, type;
1159 	bool turn_on;
1160 	bool wl_busy = false;
1161 
1162 	if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */
1163 		rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT);
1164 	else
1165 		rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT);
1166 
1167 	type = (u8)(tcase & 0xff);
1168 
1169 	turn_on = (type == 0 || type == 100) ? false : true;
1170 
1171 	if (!force && turn_on == coex_dm->cur_ps_tdma_on &&
1172 	    type == coex_dm->cur_ps_tdma) {
1173 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1174 			"[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n",
1175 			(coex_dm->cur_ps_tdma_on ? "on" : "off"),
1176 			coex_dm->cur_ps_tdma);
1177 
1178 		return;
1179 	}
1180 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
1181 
1182 	if ((coex_stat->bt_a2dp_exist &&
1183 	     (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||
1184 	    !wl_busy)
1185 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
1186 	else
1187 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
1188 
1189 	/* update pre state */
1190 	coex_dm->cur_ps_tdma_on = turn_on;
1191 	coex_dm->cur_ps_tdma = type;
1192 
1193 	if (efuse->share_ant) {
1194 		if (type < chip->tdma_sant_num)
1195 			rtw_coex_set_tdma(rtwdev,
1196 					  chip->tdma_sant[type].para[0],
1197 					  chip->tdma_sant[type].para[1],
1198 					  chip->tdma_sant[type].para[2],
1199 					  chip->tdma_sant[type].para[3],
1200 					  chip->tdma_sant[type].para[4]);
1201 	} else {
1202 		n = type - 100;
1203 		if (n < chip->tdma_nsant_num)
1204 			rtw_coex_set_tdma(rtwdev,
1205 					  chip->tdma_nsant[n].para[0],
1206 					  chip->tdma_nsant[n].para[1],
1207 					  chip->tdma_nsant[n].para[2],
1208 					  chip->tdma_nsant[n].para[3],
1209 					  chip->tdma_nsant[n].para[4]);
1210 	}
1211 
1212 
1213 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n",
1214 		turn_on ? "on" : "off", type);
1215 }
1216 
rtw_coex_set_ant_path(struct rtw_dev * rtwdev,bool force,u8 phase)1217 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
1218 {
1219 	struct rtw_coex *coex = &rtwdev->coex;
1220 	struct rtw_coex_stat *coex_stat = &coex->stat;
1221 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1222 	struct rtw_coex_dm *coex_dm = &coex->dm;
1223 	u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
1224 	u8 pos_type = COEX_SWITCH_TO_MAX;
1225 
1226 	if (!force && coex_dm->cur_ant_pos_type == phase)
1227 		return;
1228 
1229 	coex_dm->cur_ant_pos_type = phase;
1230 
1231 	/* avoid switch coex_ctrl_owner during BT IQK */
1232 	rtw_coex_check_rfk(rtwdev);
1233 
1234 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1235 		"[BTCoex],  coex_stat->bt_disabled = 0x%x\n",
1236 		coex_stat->bt_disabled);
1237 
1238 	switch (phase) {
1239 	case COEX_SET_ANT_POWERON:
1240 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1241 			"[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__);
1242 		/* set path control owner to BT at power-on */
1243 		if (coex_stat->bt_disabled)
1244 			rtw_coex_coex_ctrl_owner(rtwdev, true);
1245 		else
1246 			rtw_coex_coex_ctrl_owner(rtwdev, false);
1247 
1248 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1249 		pos_type = COEX_SWITCH_TO_BT;
1250 		break;
1251 	case COEX_SET_ANT_INIT:
1252 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1253 			"[BTCoex], %s() - PHASE_COEX_INIT\n", __func__);
1254 		if (coex_stat->bt_disabled) {
1255 			/* set GNT_BT to SW low */
1256 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1257 
1258 			/* set GNT_WL to SW high */
1259 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1260 		} else {
1261 			/* set GNT_BT to SW high */
1262 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1263 
1264 			/* set GNT_WL to SW low */
1265 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
1266 		}
1267 
1268 		/* set path control owner to wl at initial step */
1269 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1270 
1271 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1272 		pos_type = COEX_SWITCH_TO_BT;
1273 		break;
1274 	case COEX_SET_ANT_WONLY:
1275 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1276 			"[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__);
1277 		/* set GNT_BT to SW Low */
1278 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1279 
1280 		/* set GNT_WL to SW high */
1281 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1282 
1283 		/* set path control owner to wl at initial step */
1284 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1285 
1286 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1287 		pos_type = COEX_SWITCH_TO_WLG;
1288 		break;
1289 	case COEX_SET_ANT_WOFF:
1290 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1291 			"[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__);
1292 		/* set path control owner to BT */
1293 		rtw_coex_coex_ctrl_owner(rtwdev, false);
1294 
1295 		ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1296 		pos_type = COEX_SWITCH_TO_NOCARE;
1297 		break;
1298 	case COEX_SET_ANT_2G:
1299 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1300 			"[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__);
1301 		/* set GNT_BT to PTA */
1302 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1303 
1304 		/* set GNT_WL to PTA */
1305 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1306 
1307 		/* set path control owner to wl at runtime step */
1308 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1309 
1310 		ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1311 		pos_type = COEX_SWITCH_TO_NOCARE;
1312 		break;
1313 	case COEX_SET_ANT_5G:
1314 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1315 			"[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__);
1316 
1317 		/* set GNT_BT to HW PTA */
1318 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1319 
1320 		/* set GNT_WL to SW high */
1321 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1322 
1323 		/* set path control owner to wl at runtime step */
1324 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1325 
1326 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1327 		pos_type = COEX_SWITCH_TO_WLA;
1328 		break;
1329 	case COEX_SET_ANT_2G_FREERUN:
1330 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1331 			"[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__);
1332 
1333 		/* set GNT_BT to HW PTA */
1334 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1335 
1336 		/* Set GNT_WL to SW high */
1337 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1338 
1339 		/* set path control owner to wl at runtime step */
1340 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1341 
1342 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1343 		pos_type = COEX_SWITCH_TO_WLG_BT;
1344 		break;
1345 	case COEX_SET_ANT_2G_WLBT:
1346 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1347 			"[BTCoex], %s() - PHASE_2G_WLBT\n", __func__);
1348 		/* set GNT_BT to HW PTA */
1349 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1350 
1351 		/* Set GNT_WL to HW PTA */
1352 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1353 
1354 		/* set path control owner to wl at runtime step */
1355 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1356 
1357 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1358 		pos_type = COEX_SWITCH_TO_WLG_BT;
1359 		break;
1360 	default:
1361 		WARN(1, "unknown phase when setting antenna path\n");
1362 		return;
1363 	}
1364 
1365 	if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX &&
1366 	    coex_rfe->ant_switch_exist)
1367 		rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1368 }
1369 
1370 #define case_ALGO(src) \
1371 	case COEX_ALGO_##src: return #src
1372 
rtw_coex_get_algo_string(u8 algo)1373 static const char *rtw_coex_get_algo_string(u8 algo)
1374 {
1375 	switch (algo) {
1376 	case_ALGO(NOPROFILE);
1377 	case_ALGO(HFP);
1378 	case_ALGO(HID);
1379 	case_ALGO(A2DP);
1380 	case_ALGO(PAN);
1381 	case_ALGO(A2DP_HID);
1382 	case_ALGO(A2DP_PAN);
1383 	case_ALGO(PAN_HID);
1384 	case_ALGO(A2DP_PAN_HID);
1385 	default:
1386 		return "Unknown";
1387 	}
1388 }
1389 
1390 #define case_BT_PROFILE(src) \
1391 	case BPM_##src: return #src
1392 
rtw_coex_get_bt_profile_string(u8 bt_profile)1393 static const char *rtw_coex_get_bt_profile_string(u8 bt_profile)
1394 {
1395 	switch (bt_profile) {
1396 	case_BT_PROFILE(NOPROFILE);
1397 	case_BT_PROFILE(HFP);
1398 	case_BT_PROFILE(HID);
1399 	case_BT_PROFILE(A2DP);
1400 	case_BT_PROFILE(PAN);
1401 	case_BT_PROFILE(HID_HFP);
1402 	case_BT_PROFILE(A2DP_HFP);
1403 	case_BT_PROFILE(A2DP_HID);
1404 	case_BT_PROFILE(A2DP_HID_HFP);
1405 	case_BT_PROFILE(PAN_HFP);
1406 	case_BT_PROFILE(PAN_HID);
1407 	case_BT_PROFILE(PAN_HID_HFP);
1408 	case_BT_PROFILE(PAN_A2DP);
1409 	case_BT_PROFILE(PAN_A2DP_HFP);
1410 	case_BT_PROFILE(PAN_A2DP_HID);
1411 	case_BT_PROFILE(PAN_A2DP_HID_HFP);
1412 	default:
1413 		return "Unknown";
1414 	}
1415 }
1416 
rtw_coex_algorithm(struct rtw_dev * rtwdev)1417 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1418 {
1419 	struct rtw_coex *coex = &rtwdev->coex;
1420 	struct rtw_coex_stat *coex_stat = &coex->stat;
1421 	u8 algorithm = COEX_ALGO_NOPROFILE;
1422 	u8 profile_map = 0;
1423 
1424 	if (coex_stat->bt_hfp_exist)
1425 		profile_map |= BPM_HFP;
1426 	if (coex_stat->bt_hid_exist)
1427 		profile_map |= BPM_HID;
1428 	if (coex_stat->bt_a2dp_exist)
1429 		profile_map |= BPM_A2DP;
1430 	if (coex_stat->bt_pan_exist)
1431 		profile_map |= BPM_PAN;
1432 
1433 	switch (profile_map) {
1434 	case BPM_HFP:
1435 		algorithm = COEX_ALGO_HFP;
1436 		break;
1437 	case           BPM_HID:
1438 	case BPM_HFP + BPM_HID:
1439 		algorithm = COEX_ALGO_HID;
1440 		break;
1441 	case BPM_HFP           + BPM_A2DP:
1442 	case           BPM_HID + BPM_A2DP:
1443 	case BPM_HFP + BPM_HID + BPM_A2DP:
1444 		algorithm = COEX_ALGO_A2DP_HID;
1445 		break;
1446 	case BPM_HFP                      + BPM_PAN:
1447 	case           BPM_HID            + BPM_PAN:
1448 	case BPM_HFP + BPM_HID            + BPM_PAN:
1449 		algorithm = COEX_ALGO_PAN_HID;
1450 		break;
1451 	case BPM_HFP           + BPM_A2DP + BPM_PAN:
1452 	case           BPM_HID + BPM_A2DP + BPM_PAN:
1453 	case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
1454 		algorithm = COEX_ALGO_A2DP_PAN_HID;
1455 		break;
1456 	case                                BPM_PAN:
1457 		algorithm = COEX_ALGO_PAN;
1458 		break;
1459 	case                     BPM_A2DP + BPM_PAN:
1460 		algorithm = COEX_ALGO_A2DP_PAN;
1461 		break;
1462 	case                     BPM_A2DP:
1463 		if (coex_stat->bt_multi_link) {
1464 			if (coex_stat->bt_hid_pair_num > 0)
1465 				algorithm = COEX_ALGO_A2DP_HID;
1466 			else
1467 				algorithm = COEX_ALGO_A2DP_PAN;
1468 		} else {
1469 			algorithm = COEX_ALGO_A2DP;
1470 		}
1471 		break;
1472 	default:
1473 		algorithm = COEX_ALGO_NOPROFILE;
1474 		break;
1475 	}
1476 
1477 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1478 		"[BTCoex], BT Profile = %s => Algorithm = %s\n",
1479 		rtw_coex_get_bt_profile_string(profile_map),
1480 		rtw_coex_get_algo_string(algorithm));
1481 	return algorithm;
1482 }
1483 
rtw_coex_action_coex_all_off(struct rtw_dev * rtwdev)1484 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1485 {
1486 	struct rtw_efuse *efuse = &rtwdev->efuse;
1487 	struct rtw_chip_info *chip = rtwdev->chip;
1488 	u8 table_case, tdma_case;
1489 
1490 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1491 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1492 
1493 	if (efuse->share_ant) {
1494 		/* Shared-Ant */
1495 		table_case = 2;
1496 		tdma_case = 0;
1497 	} else {
1498 		/* Non-Shared-Ant */
1499 		table_case = 100;
1500 		tdma_case = 100;
1501 	}
1502 
1503 	rtw_coex_table(rtwdev, false, table_case);
1504 	rtw_coex_tdma(rtwdev, false, tdma_case);
1505 }
1506 
rtw_coex_action_freerun(struct rtw_dev * rtwdev)1507 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1508 {
1509 	struct rtw_coex *coex = &rtwdev->coex;
1510 	struct rtw_coex_stat *coex_stat = &coex->stat;
1511 	struct rtw_coex_dm *coex_dm = &coex->dm;
1512 	struct rtw_efuse *efuse = &rtwdev->efuse;
1513 	struct rtw_chip_info *chip = rtwdev->chip;
1514 	u8 level = 0;
1515 	bool bt_afh_loss = true;
1516 
1517 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1518 
1519 	if (efuse->share_ant)
1520 		return;
1521 
1522 	coex->freerun = true;
1523 
1524 	if (bt_afh_loss)
1525 		rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1526 
1527 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1528 
1529 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1530 
1531 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1532 		level = 2;
1533 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1534 		level = 3;
1535 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1536 		level = 4;
1537 	else
1538 		level = 5;
1539 
1540 	if (level > chip->wl_rf_para_num - 1)
1541 		level = chip->wl_rf_para_num - 1;
1542 
1543 	if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1544 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1545 	else
1546 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1547 
1548 	rtw_coex_table(rtwdev, false, 100);
1549 	rtw_coex_tdma(rtwdev, false, 100);
1550 }
1551 
rtw_coex_action_rf4ce(struct rtw_dev * rtwdev)1552 static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
1553 {
1554 	struct rtw_efuse *efuse = &rtwdev->efuse;
1555 	struct rtw_chip_info *chip = rtwdev->chip;
1556 	u8 table_case, tdma_case;
1557 
1558 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1559 
1560 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1561 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1562 
1563 	if (efuse->share_ant) {
1564 		/* Shared-Ant */
1565 		table_case = 9;
1566 		tdma_case = 16;
1567 	} else {
1568 		/* Non-Shared-Ant */
1569 		table_case = 100;
1570 		tdma_case = 100;
1571 	}
1572 
1573 	rtw_coex_table(rtwdev, false, table_case);
1574 	rtw_coex_tdma(rtwdev, false, tdma_case);
1575 }
1576 
rtw_coex_action_bt_whql_test(struct rtw_dev * rtwdev)1577 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1578 {
1579 	struct rtw_efuse *efuse = &rtwdev->efuse;
1580 	struct rtw_chip_info *chip = rtwdev->chip;
1581 	u8 table_case, tdma_case;
1582 
1583 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1584 
1585 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1586 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1587 
1588 	if (efuse->share_ant) {
1589 		/* Shared-Ant */
1590 		table_case = 2;
1591 		tdma_case = 0;
1592 	} else {
1593 		/* Non-Shared-Ant */
1594 		table_case = 100;
1595 		tdma_case = 100;
1596 	}
1597 
1598 	rtw_coex_table(rtwdev, false, table_case);
1599 	rtw_coex_tdma(rtwdev, false, tdma_case);
1600 }
1601 
rtw_coex_action_bt_relink(struct rtw_dev * rtwdev)1602 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1603 {
1604 	struct rtw_coex *coex = &rtwdev->coex;
1605 	struct rtw_coex_stat *coex_stat = &coex->stat;
1606 	struct rtw_efuse *efuse = &rtwdev->efuse;
1607 	struct rtw_chip_info *chip = rtwdev->chip;
1608 	u8 table_case, tdma_case;
1609 	u32 slot_type = 0;
1610 
1611 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1612 
1613 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1614 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1615 
1616 	if (efuse->share_ant) { /* Shared-Ant */
1617 		if (coex_stat->wl_gl_busy) {
1618 			table_case = 26;
1619 			if (coex_stat->bt_hid_exist &&
1620 			    coex_stat->bt_profile_num == 1) {
1621 				slot_type = TDMA_4SLOT;
1622 				tdma_case = 20;
1623 			} else {
1624 				tdma_case = 20;
1625 			}
1626 		} else {
1627 			table_case = 1;
1628 			tdma_case = 0;
1629 		}
1630 	} else { /* Non-Shared-Ant */
1631 		if (coex_stat->wl_gl_busy)
1632 			table_case = 115;
1633 		else
1634 			table_case = 100;
1635 		tdma_case = 100;
1636 	}
1637 
1638 	rtw_coex_table(rtwdev, false, table_case);
1639 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1640 }
1641 
rtw_coex_action_bt_idle(struct rtw_dev * rtwdev)1642 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1643 {
1644 	struct rtw_coex *coex = &rtwdev->coex;
1645 	struct rtw_coex_stat *coex_stat = &coex->stat;
1646 	struct rtw_coex_dm *coex_dm = &coex->dm;
1647 	struct rtw_efuse *efuse = &rtwdev->efuse;
1648 	struct rtw_chip_info *chip = rtwdev->chip;
1649 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1650 	u8 table_case = 0xff, tdma_case = 0xff;
1651 
1652 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1653 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1654 
1655 	if (coex_rfe->ant_switch_with_bt &&
1656 	    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1657 		if (efuse->share_ant &&
1658 		    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1659 		    coex_stat->wl_gl_busy) {
1660 			table_case = 0;
1661 			tdma_case = 0;
1662 		} else if (!efuse->share_ant) {
1663 			table_case = 100;
1664 			tdma_case = 100;
1665 		}
1666 	}
1667 
1668 	if (table_case != 0xff && tdma_case != 0xff) {
1669 		rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1670 		goto exit;
1671 	}
1672 
1673 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1674 
1675 	if (efuse->share_ant) {
1676 		/* Shared-Ant */
1677 		if (!coex_stat->wl_gl_busy) {
1678 			table_case = 10;
1679 			tdma_case = 3;
1680 		} else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1681 			table_case = 11;
1682 
1683 			if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250)
1684 				tdma_case = 17;
1685 			else
1686 				tdma_case = 7;
1687 		} else {
1688 			table_case = 12;
1689 			tdma_case = 7;
1690 		}
1691 	} else {
1692 		/* Non-Shared-Ant */
1693 		if (!coex_stat->wl_gl_busy) {
1694 			table_case = 112;
1695 			tdma_case = 104;
1696 		} else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1697 			   coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1698 			table_case = 114;
1699 			tdma_case = 103;
1700 		} else {
1701 			table_case = 112;
1702 			tdma_case = 103;
1703 		}
1704 	}
1705 
1706 exit:
1707 	rtw_coex_table(rtwdev, false, table_case);
1708 	rtw_coex_tdma(rtwdev, false, tdma_case);
1709 }
1710 
rtw_coex_action_bt_inquiry(struct rtw_dev * rtwdev)1711 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1712 {
1713 	struct rtw_coex *coex = &rtwdev->coex;
1714 	struct rtw_coex_stat *coex_stat = &coex->stat;
1715 	struct rtw_efuse *efuse = &rtwdev->efuse;
1716 	struct rtw_chip_info *chip = rtwdev->chip;
1717 	bool wl_hi_pri = false;
1718 	u8 table_case, tdma_case;
1719 	u32 slot_type = 0;
1720 
1721 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1722 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1723 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1724 
1725 	if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1726 	    coex_stat->wl_hi_pri_task2)
1727 		wl_hi_pri = true;
1728 
1729 	if (efuse->share_ant) {
1730 		/* Shared-Ant */
1731 		if (wl_hi_pri) {
1732 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1733 				"[BTCoex], bt inq/page +  wifi hi-pri task\n");
1734 			table_case = 15;
1735 
1736 			if (coex_stat->bt_profile_num > 0)
1737 				tdma_case = 10;
1738 			else if (coex_stat->wl_hi_pri_task1)
1739 				tdma_case = 6;
1740 			else if (!coex_stat->bt_page)
1741 				tdma_case = 8;
1742 			else
1743 				tdma_case = 9;
1744 		} else if (coex_stat->wl_gl_busy) {
1745 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1746 				"[BTCoex], bt inq/page + wifi busy\n");
1747 			if (coex_stat->bt_profile_num == 0) {
1748 				table_case = 12;
1749 				tdma_case = 18;
1750 			} else if (coex_stat->bt_profile_num == 1 &&
1751 				   !coex_stat->bt_a2dp_exist) {
1752 				slot_type = TDMA_4SLOT;
1753 				table_case = 12;
1754 				tdma_case = 20;
1755 			} else {
1756 				slot_type = TDMA_4SLOT;
1757 				table_case = 12;
1758 				tdma_case = 26;
1759 			}
1760 		} else if (coex_stat->wl_connected) {
1761 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1762 				"[BTCoex], bt inq/page + wifi connected\n");
1763 			table_case = 9;
1764 			tdma_case = 27;
1765 		} else {
1766 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1767 				"[BTCoex], bt inq/page + wifi not-connected\n");
1768 			table_case = 1;
1769 			tdma_case = 0;
1770 		}
1771 	} else {
1772 		/* Non_Shared-Ant */
1773 		if (wl_hi_pri) {
1774 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1775 				"[BTCoex], bt inq/page +  wifi hi-pri task\n");
1776 			table_case = 114;
1777 
1778 			if (coex_stat->bt_profile_num > 0)
1779 				tdma_case = 110;
1780 			else if (coex_stat->wl_hi_pri_task1)
1781 				tdma_case = 106;
1782 			else if (!coex_stat->bt_page)
1783 				tdma_case = 108;
1784 			else
1785 				tdma_case = 109;
1786 		}  else if (coex_stat->wl_gl_busy) {
1787 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1788 				"[BTCoex], bt inq/page + wifi busy\n");
1789 			table_case = 114;
1790 			tdma_case = 121;
1791 		} else if (coex_stat->wl_connected) {
1792 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1793 				"[BTCoex], bt inq/page +  wifi connected\n");
1794 			table_case = 101;
1795 			tdma_case = 100;
1796 		} else {
1797 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1798 				"[BTCoex], bt inq/page +  wifi not-connected\n");
1799 			table_case = 101;
1800 			tdma_case = 100;
1801 		}
1802 	}
1803 
1804 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n",
1805 		wl_hi_pri, coex_stat->bt_page);
1806 
1807 	rtw_coex_table(rtwdev, false, table_case);
1808 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1809 }
1810 
rtw_coex_action_bt_hfp(struct rtw_dev * rtwdev)1811 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1812 {
1813 	struct rtw_coex *coex = &rtwdev->coex;
1814 	struct rtw_coex_stat *coex_stat = &coex->stat;
1815 	struct rtw_efuse *efuse = &rtwdev->efuse;
1816 	struct rtw_chip_info *chip = rtwdev->chip;
1817 	u8 table_case, tdma_case;
1818 
1819 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1820 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1821 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1822 
1823 	if (efuse->share_ant) {
1824 		/* Shared-Ant */
1825 		if (coex_stat->bt_multi_link) {
1826 			table_case = 10;
1827 			tdma_case = 17;
1828 		} else {
1829 			table_case = 10;
1830 			tdma_case = 5;
1831 		}
1832 	} else {
1833 		/* Non-Shared-Ant */
1834 		if (coex_stat->bt_multi_link) {
1835 			table_case = 112;
1836 			tdma_case = 117;
1837 		} else {
1838 			table_case = 105;
1839 			tdma_case = 100;
1840 		}
1841 	}
1842 
1843 	rtw_coex_table(rtwdev, false, table_case);
1844 	rtw_coex_tdma(rtwdev, false, tdma_case);
1845 }
1846 
rtw_coex_action_bt_hid(struct rtw_dev * rtwdev)1847 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1848 {
1849 	struct rtw_coex *coex = &rtwdev->coex;
1850 	struct rtw_coex_stat *coex_stat = &coex->stat;
1851 	struct rtw_efuse *efuse = &rtwdev->efuse;
1852 	struct rtw_chip_info *chip = rtwdev->chip;
1853 	u8 table_case, tdma_case;
1854 	u32 slot_type = 0;
1855 	bool bt_multi_link_remain = false, is_toggle_table = false;
1856 
1857 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1858 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1859 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1860 
1861 	if (efuse->share_ant) {
1862 		/* Shared-Ant */
1863 		if (coex_stat->bt_ble_exist) {
1864 			/* RCU */
1865 			if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
1866 				table_case = 26;
1867 				tdma_case = 2;
1868 			} else {
1869 				table_case = 27;
1870 				tdma_case = 9;
1871 			}
1872 		} else {
1873 			/* Legacy HID  */
1874 			if (coex_stat->bt_profile_num == 1 &&
1875 			    (coex_stat->bt_multi_link ||
1876 			    (coex_stat->lo_pri_rx +
1877 			     coex_stat->lo_pri_tx > 360) ||
1878 			     coex_stat->bt_slave ||
1879 			     bt_multi_link_remain)) {
1880 				slot_type = TDMA_4SLOT;
1881 				table_case = 12;
1882 				tdma_case = 20;
1883 			} else if (coex_stat->bt_a2dp_active) {
1884 				table_case = 9;
1885 				tdma_case = 18;
1886 			} else if (coex_stat->bt_418_hid_exist &&
1887 				   coex_stat->wl_gl_busy) {
1888 				is_toggle_table = true;
1889 				slot_type = TDMA_4SLOT;
1890 				table_case = 9;
1891 				tdma_case = 24;
1892 			} else if (coex_stat->bt_ble_hid_exist &&
1893 				   coex_stat->wl_gl_busy) {
1894 				table_case = 32;
1895 				tdma_case = 9;
1896 			} else {
1897 				table_case = 9;
1898 				tdma_case = 9;
1899 			}
1900 		}
1901 	} else {
1902 		/* Non-Shared-Ant */
1903 		if (coex_stat->bt_ble_exist) {
1904 			/* BLE */
1905 			if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
1906 				table_case = 121;
1907 				tdma_case = 102;
1908 			} else {
1909 				table_case = 122;
1910 				tdma_case = 109;
1911 			}
1912 		} else if (coex_stat->bt_a2dp_active) {
1913 			table_case = 113;
1914 			tdma_case = 118;
1915 		} else {
1916 			table_case = 113;
1917 			tdma_case = 104;
1918 		}
1919 	}
1920 
1921 	rtw_coex_table(rtwdev, false, table_case);
1922 	if (is_toggle_table) {
1923 		rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
1924 		rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE);
1925 	}
1926 
1927 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1928 }
1929 
rtw_coex_action_bt_a2dp(struct rtw_dev * rtwdev)1930 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
1931 {
1932 	struct rtw_coex *coex = &rtwdev->coex;
1933 	struct rtw_coex_stat *coex_stat = &coex->stat;
1934 	struct rtw_coex_dm *coex_dm = &coex->dm;
1935 	struct rtw_efuse *efuse = &rtwdev->efuse;
1936 	struct rtw_chip_info *chip = rtwdev->chip;
1937 	u8 table_case, tdma_case;
1938 	u32 slot_type = 0;
1939 
1940 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1941 
1942 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1943 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1944 
1945 	slot_type = TDMA_4SLOT;
1946 
1947 	if (efuse->share_ant) {
1948 		/* Shared-Ant */
1949 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1950 			table_case = 12;
1951 		else
1952 			table_case = 9;
1953 
1954 		if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy)
1955 			tdma_case = 14;
1956 		else
1957 			tdma_case = 13;
1958 	} else {
1959 		/* Non-Shared-Ant */
1960 		table_case = 112;
1961 
1962 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1963 			tdma_case = 112;
1964 		else
1965 			tdma_case = 113;
1966 	}
1967 
1968 	rtw_coex_table(rtwdev, false, table_case);
1969 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1970 }
1971 
rtw_coex_action_bt_a2dpsink(struct rtw_dev * rtwdev)1972 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
1973 {
1974 	struct rtw_coex *coex = &rtwdev->coex;
1975 	struct rtw_coex_stat *coex_stat = &coex->stat;
1976 	struct rtw_efuse *efuse = &rtwdev->efuse;
1977 	struct rtw_chip_info *chip = rtwdev->chip;
1978 	u8 table_case, tdma_case;
1979 	bool ap_enable = false;
1980 
1981 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1982 
1983 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1984 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1985 
1986 	if (efuse->share_ant) { /* Shared-Ant */
1987 		if (ap_enable) {
1988 			table_case = 2;
1989 			tdma_case = 0;
1990 		} else if (coex_stat->wl_gl_busy) {
1991 			table_case = 28;
1992 			tdma_case = 20;
1993 		} else {
1994 			table_case = 28;
1995 			tdma_case = 26;
1996 		}
1997 	} else { /* Non-Shared-Ant */
1998 		if (ap_enable) {
1999 			table_case = 100;
2000 			tdma_case = 100;
2001 		} else {
2002 			table_case = 119;
2003 			tdma_case = 120;
2004 		}
2005 	}
2006 
2007 	rtw_coex_table(rtwdev, false, table_case);
2008 	rtw_coex_tdma(rtwdev, false, tdma_case);
2009 }
2010 
rtw_coex_action_bt_pan(struct rtw_dev * rtwdev)2011 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
2012 {
2013 	struct rtw_coex *coex = &rtwdev->coex;
2014 	struct rtw_coex_stat *coex_stat = &coex->stat;
2015 	struct rtw_efuse *efuse = &rtwdev->efuse;
2016 	struct rtw_chip_info *chip = rtwdev->chip;
2017 	u8 table_case, tdma_case;
2018 
2019 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2020 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2021 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2022 
2023 	if (efuse->share_ant) {
2024 		/* Shared-Ant */
2025 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
2026 			table_case = 14;
2027 		else
2028 			table_case = 10;
2029 
2030 		if (coex_stat->wl_gl_busy)
2031 			tdma_case = 17;
2032 		else
2033 			tdma_case = 20;
2034 	} else {
2035 		/* Non-Shared-Ant */
2036 		table_case = 112;
2037 
2038 		if (coex_stat->wl_gl_busy)
2039 			tdma_case = 117;
2040 		else
2041 			tdma_case = 119;
2042 	}
2043 
2044 	rtw_coex_table(rtwdev, false, table_case);
2045 	rtw_coex_tdma(rtwdev, false, tdma_case);
2046 }
2047 
rtw_coex_action_bt_a2dp_hid(struct rtw_dev * rtwdev)2048 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
2049 {
2050 	struct rtw_coex *coex = &rtwdev->coex;
2051 	struct rtw_coex_stat *coex_stat = &coex->stat;
2052 	struct rtw_coex_dm *coex_dm = &coex->dm;
2053 	struct rtw_efuse *efuse = &rtwdev->efuse;
2054 	struct rtw_chip_info *chip = rtwdev->chip;
2055 	u8 table_case, tdma_case, interval = 0;
2056 	u32 slot_type = 0;
2057 	bool is_toggle_table = false;
2058 
2059 	slot_type = TDMA_4SLOT;
2060 
2061 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2062 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2063 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2064 
2065 	if (efuse->share_ant) {
2066 		/* Shared-Ant */
2067 		if (coex_stat->bt_ble_exist) {
2068 			table_case = 26; /* for RCU */
2069 		} else if (coex_stat->bt_418_hid_exist) {
2070 			table_case = 9;
2071 			interval = 1;
2072 		} else {
2073 			table_case = 9;
2074 		}
2075 
2076 		if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) {
2077 			tdma_case = 14;
2078 		} else if (coex_stat->bt_418_hid_exist) {
2079 			is_toggle_table = true;
2080 			tdma_case = 23;
2081 		} else {
2082 			tdma_case = 13;
2083 		}
2084 	} else {
2085 		/* Non-Shared-Ant */
2086 		if (coex_stat->bt_ble_exist)
2087 			table_case = 121;
2088 		else
2089 			table_case = 113;
2090 
2091 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
2092 			tdma_case = 112;
2093 		else
2094 			tdma_case = 113;
2095 	}
2096 
2097 	rtw_coex_table(rtwdev, false, table_case);
2098 	if (is_toggle_table) {
2099 		rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
2100 		rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE);
2101 	}
2102 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2103 }
2104 
rtw_coex_action_bt_a2dp_pan(struct rtw_dev * rtwdev)2105 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
2106 {
2107 	struct rtw_coex *coex = &rtwdev->coex;
2108 	struct rtw_coex_stat *coex_stat = &coex->stat;
2109 	struct rtw_efuse *efuse = &rtwdev->efuse;
2110 	struct rtw_chip_info *chip = rtwdev->chip;
2111 	u8 table_case, tdma_case;
2112 	bool wl_cpt_test = false, bt_cpt_test = false;
2113 
2114 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2115 
2116 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2117 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2118 	if (efuse->share_ant) {
2119 		/* Shared-Ant */
2120 		if (wl_cpt_test) {
2121 			if (coex_stat->wl_gl_busy) {
2122 				table_case = 20;
2123 				tdma_case = 17;
2124 			} else {
2125 				table_case = 10;
2126 				tdma_case = 15;
2127 			}
2128 		} else if (bt_cpt_test) {
2129 			table_case = 26;
2130 			tdma_case = 26;
2131 		} else {
2132 			if (coex_stat->wl_gl_busy &&
2133 			    coex_stat->wl_noisy_level == 0)
2134 				table_case = 14;
2135 			else
2136 				table_case = 10;
2137 
2138 			if (coex_stat->wl_gl_busy)
2139 				tdma_case = 15;
2140 			else
2141 				tdma_case = 20;
2142 		}
2143 	} else {
2144 		/* Non-Shared-Ant */
2145 		table_case = 112;
2146 
2147 		if (coex_stat->wl_gl_busy)
2148 			tdma_case = 115;
2149 		else
2150 			tdma_case = 120;
2151 	}
2152 
2153 	if (wl_cpt_test)
2154 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[1]);
2155 	else
2156 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2157 
2158 	rtw_coex_table(rtwdev, false, table_case);
2159 	rtw_coex_tdma(rtwdev, false, tdma_case);
2160 }
2161 
rtw_coex_action_bt_pan_hid(struct rtw_dev * rtwdev)2162 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
2163 {
2164 	struct rtw_coex *coex = &rtwdev->coex;
2165 	struct rtw_coex_stat *coex_stat = &coex->stat;
2166 	struct rtw_efuse *efuse = &rtwdev->efuse;
2167 	struct rtw_chip_info *chip = rtwdev->chip;
2168 	u8 table_case, tdma_case;
2169 
2170 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2171 
2172 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2173 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2174 
2175 	if (efuse->share_ant) {
2176 		/* Shared-Ant */
2177 		table_case = 9;
2178 
2179 		if (coex_stat->wl_gl_busy)
2180 			tdma_case = 18;
2181 		else
2182 			tdma_case = 19;
2183 	} else {
2184 		/* Non-Shared-Ant */
2185 		table_case = 113;
2186 
2187 		if (coex_stat->wl_gl_busy)
2188 			tdma_case = 117;
2189 		else
2190 			tdma_case = 119;
2191 	}
2192 
2193 	rtw_coex_table(rtwdev, false, table_case);
2194 	rtw_coex_tdma(rtwdev, false, tdma_case);
2195 }
2196 
rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev * rtwdev)2197 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
2198 {
2199 	struct rtw_coex *coex = &rtwdev->coex;
2200 	struct rtw_coex_stat *coex_stat = &coex->stat;
2201 	struct rtw_efuse *efuse = &rtwdev->efuse;
2202 	struct rtw_chip_info *chip = rtwdev->chip;
2203 	u8 table_case, tdma_case;
2204 
2205 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2206 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2207 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2208 
2209 	if (efuse->share_ant) {
2210 		/* Shared-Ant */
2211 		table_case = 10;
2212 
2213 		if (coex_stat->wl_gl_busy)
2214 			tdma_case = 15;
2215 		else
2216 			tdma_case = 20;
2217 	} else {
2218 		/* Non-Shared-Ant */
2219 		table_case = 113;
2220 
2221 		if (coex_stat->wl_gl_busy)
2222 			tdma_case = 115;
2223 		else
2224 			tdma_case = 120;
2225 	}
2226 
2227 	rtw_coex_table(rtwdev, false, table_case);
2228 	rtw_coex_tdma(rtwdev, false, tdma_case);
2229 }
2230 
rtw_coex_action_wl_under5g(struct rtw_dev * rtwdev)2231 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
2232 {
2233 	struct rtw_efuse *efuse = &rtwdev->efuse;
2234 	struct rtw_chip_info *chip = rtwdev->chip;
2235 	u8 table_case, tdma_case;
2236 
2237 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2238 
2239 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2240 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2241 
2242 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
2243 
2244 	if (efuse->share_ant) {
2245 		/* Shared-Ant */
2246 		table_case = 0;
2247 		tdma_case = 0;
2248 	} else {
2249 		/* Non-Shared-Ant */
2250 		table_case = 100;
2251 		tdma_case = 100;
2252 	}
2253 
2254 	rtw_coex_table(rtwdev, false, table_case);
2255 	rtw_coex_tdma(rtwdev, false, tdma_case);
2256 }
2257 
rtw_coex_action_wl_only(struct rtw_dev * rtwdev)2258 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
2259 {
2260 	struct rtw_efuse *efuse = &rtwdev->efuse;
2261 	struct rtw_chip_info *chip = rtwdev->chip;
2262 	u8 table_case, tdma_case;
2263 
2264 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2265 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2266 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2267 
2268 	if (efuse->share_ant) {
2269 		/* Shared-Ant */
2270 		table_case = 2;
2271 		tdma_case = 0;
2272 	} else {
2273 		/* Non-Shared-Ant */
2274 		table_case = 100;
2275 		tdma_case = 100;
2276 	}
2277 
2278 	rtw_coex_table(rtwdev, false, table_case);
2279 	rtw_coex_tdma(rtwdev, false, tdma_case);
2280 }
2281 
rtw_coex_action_wl_native_lps(struct rtw_dev * rtwdev)2282 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
2283 {
2284 	struct rtw_coex *coex = &rtwdev->coex;
2285 	struct rtw_efuse *efuse = &rtwdev->efuse;
2286 	struct rtw_chip_info *chip = rtwdev->chip;
2287 	u8 table_case, tdma_case;
2288 
2289 	if (coex->under_5g)
2290 		return;
2291 
2292 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2293 
2294 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2295 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2296 
2297 	if (efuse->share_ant) {
2298 		/* Shared-Ant */
2299 		table_case = 28;
2300 		tdma_case = 0;
2301 	} else {
2302 		/* Non-Shared-Ant */
2303 		table_case = 100;
2304 		tdma_case = 100;
2305 	}
2306 
2307 	rtw_coex_table(rtwdev, false, table_case);
2308 	rtw_coex_tdma(rtwdev, false, tdma_case);
2309 }
2310 
rtw_coex_action_wl_linkscan(struct rtw_dev * rtwdev)2311 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
2312 {
2313 	struct rtw_coex *coex = &rtwdev->coex;
2314 	struct rtw_coex_stat *coex_stat = &coex->stat;
2315 	struct rtw_efuse *efuse = &rtwdev->efuse;
2316 	struct rtw_chip_info *chip = rtwdev->chip;
2317 	u8 table_case, tdma_case;
2318 	u32 slot_type = 0;
2319 
2320 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2321 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2322 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2323 
2324 	if (efuse->share_ant) { /* Shared-Ant */
2325 		if (coex_stat->bt_a2dp_exist) {
2326 			slot_type = TDMA_4SLOT;
2327 			tdma_case = 11;
2328 			if (coex_stat->wl_gl_busy)
2329 				table_case = 26;
2330 			else
2331 				table_case = 9;
2332 		} else {
2333 			table_case = 9;
2334 			tdma_case = 7;
2335 		}
2336 	} else { /* Non-Shared-Ant */
2337 		if (coex_stat->bt_a2dp_exist) {
2338 			slot_type = TDMA_4SLOT;
2339 			table_case = 112;
2340 			tdma_case = 111;
2341 		} else {
2342 			table_case = 112;
2343 			tdma_case = 107;
2344 		}
2345 	}
2346 
2347 	rtw_coex_table(rtwdev, false, table_case);
2348 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2349 }
2350 
rtw_coex_action_wl_not_connected(struct rtw_dev * rtwdev)2351 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
2352 {
2353 	struct rtw_efuse *efuse = &rtwdev->efuse;
2354 	struct rtw_chip_info *chip = rtwdev->chip;
2355 	u8 table_case, tdma_case;
2356 
2357 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2358 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2359 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2360 
2361 	if (efuse->share_ant) {
2362 		/* Shared-Ant */
2363 		table_case = 1;
2364 		tdma_case = 0;
2365 	} else {
2366 		/* Non-Shared-Ant */
2367 		table_case = 100;
2368 		tdma_case = 100;
2369 	}
2370 
2371 	rtw_coex_table(rtwdev, false, table_case);
2372 	rtw_coex_tdma(rtwdev, false, tdma_case);
2373 }
2374 
rtw_coex_action_wl_connected(struct rtw_dev * rtwdev)2375 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
2376 {
2377 	struct rtw_coex *coex = &rtwdev->coex;
2378 	struct rtw_coex_stat *coex_stat = &coex->stat;
2379 	u8 algorithm;
2380 
2381 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2382 
2383 	algorithm = rtw_coex_algorithm(rtwdev);
2384 
2385 	switch (algorithm) {
2386 	case COEX_ALGO_HFP:
2387 		rtw_coex_action_bt_hfp(rtwdev);
2388 		break;
2389 	case COEX_ALGO_HID:
2390 		if (rtw_coex_freerun_check(rtwdev))
2391 			rtw_coex_action_freerun(rtwdev);
2392 		else
2393 			rtw_coex_action_bt_hid(rtwdev);
2394 		break;
2395 	case COEX_ALGO_A2DP:
2396 		if (rtw_coex_freerun_check(rtwdev))
2397 			rtw_coex_action_freerun(rtwdev);
2398 		else if (coex_stat->bt_a2dp_sink)
2399 			rtw_coex_action_bt_a2dpsink(rtwdev);
2400 		else
2401 			rtw_coex_action_bt_a2dp(rtwdev);
2402 		break;
2403 	case COEX_ALGO_PAN:
2404 		rtw_coex_action_bt_pan(rtwdev);
2405 		break;
2406 	case COEX_ALGO_A2DP_HID:
2407 		if (rtw_coex_freerun_check(rtwdev))
2408 			rtw_coex_action_freerun(rtwdev);
2409 		else
2410 			rtw_coex_action_bt_a2dp_hid(rtwdev);
2411 		break;
2412 	case COEX_ALGO_A2DP_PAN:
2413 		rtw_coex_action_bt_a2dp_pan(rtwdev);
2414 		break;
2415 	case COEX_ALGO_PAN_HID:
2416 		rtw_coex_action_bt_pan_hid(rtwdev);
2417 		break;
2418 	case COEX_ALGO_A2DP_PAN_HID:
2419 		rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
2420 		break;
2421 	default:
2422 	case COEX_ALGO_NOPROFILE:
2423 		rtw_coex_action_bt_idle(rtwdev);
2424 		break;
2425 	}
2426 }
2427 
rtw_coex_run_coex(struct rtw_dev * rtwdev,u8 reason)2428 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
2429 {
2430 	struct rtw_coex *coex = &rtwdev->coex;
2431 	struct rtw_coex_dm *coex_dm = &coex->dm;
2432 	struct rtw_coex_stat *coex_stat = &coex->stat;
2433 	bool rf4ce_en = false;
2434 
2435 	lockdep_assert_held(&rtwdev->mutex);
2436 
2437 	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
2438 		return;
2439 
2440 	coex_dm->reason = reason;
2441 
2442 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__,
2443 		reason);
2444 
2445 	/* update wifi_link_info_ext variable */
2446 	rtw_coex_update_wl_link_info(rtwdev, reason);
2447 
2448 	rtw_coex_monitor_bt_enable(rtwdev);
2449 
2450 	if (coex->manual_control) {
2451 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2452 			"[BTCoex], return for Manual CTRL!!\n");
2453 		return;
2454 	}
2455 
2456 	if (coex->stop_dm) {
2457 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2458 			"[BTCoex], return for Stop Coex DM!!\n");
2459 		return;
2460 	}
2461 
2462 	if (coex_stat->wl_under_ips) {
2463 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2464 			"[BTCoex], return for wifi is under IPS!!\n");
2465 		return;
2466 	}
2467 
2468 	if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
2469 	    !coex_stat->bt_setup_link) {
2470 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2471 			"[BTCoex], return for coex_freeze!!\n");
2472 		return;
2473 	}
2474 
2475 	coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
2476 	coex->freerun = false;
2477 
2478 	/* Pure-5G Coex Process */
2479 	if (coex->under_5g) {
2480 		coex_stat->wl_coex_mode = COEX_WLINK_5G;
2481 		rtw_coex_action_wl_under5g(rtwdev);
2482 		goto exit;
2483 	}
2484 
2485 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n");
2486 	coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
2487 
2488 	if (coex_stat->bt_disabled) {
2489 		if (coex_stat->wl_connected && rf4ce_en)
2490 			rtw_coex_action_rf4ce(rtwdev);
2491 		else if (!coex_stat->wl_connected)
2492 			rtw_coex_action_wl_not_connected(rtwdev);
2493 		else
2494 			rtw_coex_action_wl_only(rtwdev);
2495 		goto exit;
2496 	}
2497 
2498 	if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
2499 		rtw_coex_action_wl_native_lps(rtwdev);
2500 		goto exit;
2501 	}
2502 
2503 	if (coex_stat->bt_whck_test) {
2504 		rtw_coex_action_bt_whql_test(rtwdev);
2505 		goto exit;
2506 	}
2507 
2508 	if (coex_stat->bt_setup_link) {
2509 		rtw_coex_action_bt_relink(rtwdev);
2510 		goto exit;
2511 	}
2512 
2513 	if (coex_stat->bt_inq_page) {
2514 		rtw_coex_action_bt_inquiry(rtwdev);
2515 		goto exit;
2516 	}
2517 
2518 	if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
2519 	     coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
2520 	     coex_stat->wl_connected) {
2521 		rtw_coex_action_bt_idle(rtwdev);
2522 		goto exit;
2523 	}
2524 
2525 	if (coex_stat->wl_linkscan_proc && !coex->freerun) {
2526 		rtw_coex_action_wl_linkscan(rtwdev);
2527 		goto exit;
2528 	}
2529 
2530 	if (coex_stat->wl_connected) {
2531 		rtw_coex_action_wl_connected(rtwdev);
2532 		goto exit;
2533 	} else {
2534 		rtw_coex_action_wl_not_connected(rtwdev);
2535 		goto exit;
2536 	}
2537 
2538 exit:
2539 	rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode);
2540 	rtw_coex_limited_wl(rtwdev);
2541 }
2542 
rtw_coex_init_coex_var(struct rtw_dev * rtwdev)2543 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
2544 {
2545 	struct rtw_coex *coex = &rtwdev->coex;
2546 	struct rtw_coex_stat *coex_stat = &coex->stat;
2547 	struct rtw_coex_dm *coex_dm = &coex->dm;
2548 	u8 i;
2549 
2550 	memset(coex_dm, 0, sizeof(*coex_dm));
2551 	memset(coex_stat, 0, sizeof(*coex_stat));
2552 
2553 	for (i = 0; i < COEX_CNT_WL_MAX; i++)
2554 		coex_stat->cnt_wl[i] = 0;
2555 
2556 	for (i = 0; i < COEX_CNT_BT_MAX; i++)
2557 		coex_stat->cnt_bt[i] = 0;
2558 
2559 	for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2560 		coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2561 
2562 	for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2563 		coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2564 
2565 	coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2566 	coex_stat->wl_rx_rate = DESC_RATE5_5M;
2567 	coex_stat->wl_rts_rx_rate = DESC_RATE5_5M;
2568 }
2569 
__rtw_coex_init_hw_config(struct rtw_dev * rtwdev,bool wifi_only)2570 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2571 {
2572 	struct rtw_coex *coex = &rtwdev->coex;
2573 	struct rtw_coex_stat *coex_stat = &coex->stat;
2574 
2575 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2576 
2577 	rtw_coex_init_coex_var(rtwdev);
2578 
2579 	coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4));
2580 
2581 	rtw_coex_monitor_bt_enable(rtwdev);
2582 	rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend);
2583 
2584 	rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
2585 
2586 	rtw_coex_set_rfe_type(rtwdev);
2587 	rtw_coex_set_init(rtwdev);
2588 
2589 	/* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2590 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2591 
2592 	/* set Tx beacon = Hi-Pri */
2593 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2594 
2595 	/* set Tx beacon queue = Hi-Pri */
2596 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2597 
2598 	/* antenna config */
2599 	if (coex->wl_rf_off) {
2600 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2601 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2602 		coex->stop_dm = true;
2603 
2604 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n",
2605 			__func__);
2606 	} else if (wifi_only) {
2607 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2608 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2609 				    true);
2610 		coex->stop_dm = true;
2611 	} else {
2612 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2613 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2614 				    true);
2615 		coex->stop_dm = false;
2616 		coex->freeze = true;
2617 	}
2618 
2619 	/* PTA parameter */
2620 	rtw_coex_table(rtwdev, true, 1);
2621 	rtw_coex_tdma(rtwdev, true, 0);
2622 	rtw_coex_query_bt_info(rtwdev);
2623 }
2624 
rtw_coex_power_on_setting(struct rtw_dev * rtwdev)2625 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2626 {
2627 	struct rtw_coex *coex = &rtwdev->coex;
2628 	u8 table_case = 1;
2629 
2630 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2631 
2632 	coex->stop_dm = true;
2633 	coex->wl_rf_off = false;
2634 
2635 	/* enable BB, we can write 0x948 */
2636 	rtw_write8_set(rtwdev, REG_SYS_FUNC_EN,
2637 		       BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB);
2638 
2639 	rtw_coex_monitor_bt_enable(rtwdev);
2640 	rtw_coex_set_rfe_type(rtwdev);
2641 
2642 	/* set antenna path to BT */
2643 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2644 
2645 	rtw_coex_table(rtwdev, true, table_case);
2646 	/* red x issue */
2647 	rtw_write8(rtwdev, 0xff1a, 0x0);
2648 	rtw_coex_set_gnt_debug(rtwdev);
2649 }
2650 
rtw_coex_power_off_setting(struct rtw_dev * rtwdev)2651 void rtw_coex_power_off_setting(struct rtw_dev *rtwdev)
2652 {
2653 	rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN);
2654 }
2655 
rtw_coex_init_hw_config(struct rtw_dev * rtwdev,bool wifi_only)2656 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2657 {
2658 	__rtw_coex_init_hw_config(rtwdev, wifi_only);
2659 }
2660 
rtw_coex_ips_notify(struct rtw_dev * rtwdev,u8 type)2661 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2662 {
2663 	struct rtw_coex *coex = &rtwdev->coex;
2664 	struct rtw_coex_stat *coex_stat = &coex->stat;
2665 
2666 	if (coex->manual_control || coex->stop_dm)
2667 		return;
2668 
2669 	if (type == COEX_IPS_ENTER) {
2670 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n");
2671 
2672 		coex_stat->wl_under_ips = true;
2673 
2674 		/* for lps off */
2675 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2676 
2677 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2678 		rtw_coex_action_coex_all_off(rtwdev);
2679 	} else if (type == COEX_IPS_LEAVE) {
2680 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n");
2681 
2682 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2683 		/* run init hw config (exclude wifi only) */
2684 		__rtw_coex_init_hw_config(rtwdev, false);
2685 
2686 		coex_stat->wl_under_ips = false;
2687 	}
2688 }
2689 
rtw_coex_lps_notify(struct rtw_dev * rtwdev,u8 type)2690 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2691 {
2692 	struct rtw_coex *coex = &rtwdev->coex;
2693 	struct rtw_coex_stat *coex_stat = &coex->stat;
2694 
2695 	if (coex->manual_control || coex->stop_dm)
2696 		return;
2697 
2698 	if (type == COEX_LPS_ENABLE) {
2699 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n");
2700 
2701 		coex_stat->wl_under_lps = true;
2702 
2703 		if (coex_stat->wl_force_lps_ctrl) {
2704 			/* for ps-tdma */
2705 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2706 		} else {
2707 			/* for native ps */
2708 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2709 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false);
2710 
2711 			rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2712 		}
2713 	} else if (type == COEX_LPS_DISABLE) {
2714 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n");
2715 
2716 		coex_stat->wl_under_lps = false;
2717 
2718 		/* for lps off */
2719 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2720 
2721 		if (!coex_stat->wl_force_lps_ctrl)
2722 			rtw_coex_query_bt_info(rtwdev);
2723 
2724 		rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2725 	}
2726 }
2727 
rtw_coex_scan_notify(struct rtw_dev * rtwdev,u8 type)2728 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2729 {
2730 	struct rtw_coex *coex = &rtwdev->coex;
2731 	struct rtw_coex_stat *coex_stat = &coex->stat;
2732 
2733 	if (coex->manual_control || coex->stop_dm)
2734 		return;
2735 
2736 	coex->freeze = false;
2737 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2738 
2739 	if (type == COEX_SCAN_START_5G) {
2740 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2741 			"[BTCoex], SCAN START notify (5G)\n");
2742 
2743 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2744 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2745 	} else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2746 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2747 			"[BTCoex], SCAN START notify (2G)\n");
2748 
2749 		coex_stat->wl_hi_pri_task2 = true;
2750 
2751 		/* Force antenna setup for no scan result issue */
2752 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2753 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2754 	} else {
2755 		coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */
2756 
2757 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2758 			"[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n",
2759 			coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]);
2760 
2761 		coex_stat->wl_hi_pri_task2 = false;
2762 		rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2763 	}
2764 }
2765 
rtw_coex_switchband_notify(struct rtw_dev * rtwdev,u8 type)2766 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2767 {
2768 	struct rtw_coex *coex = &rtwdev->coex;
2769 
2770 	if (coex->manual_control || coex->stop_dm)
2771 		return;
2772 
2773 	if (type == COEX_SWITCH_TO_5G) {
2774 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n",
2775 			__func__);
2776 	} else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) {
2777 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2778 			"[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__);
2779 	} else {
2780 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n",
2781 			__func__);
2782 	}
2783 
2784 	if (type == COEX_SWITCH_TO_5G)
2785 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2786 	else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2787 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2788 	else
2789 		rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2790 }
2791 
rtw_coex_connect_notify(struct rtw_dev * rtwdev,u8 type)2792 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2793 {
2794 	struct rtw_coex *coex = &rtwdev->coex;
2795 	struct rtw_coex_stat *coex_stat = &coex->stat;
2796 
2797 	if (coex->manual_control || coex->stop_dm)
2798 		return;
2799 
2800 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2801 
2802 	if (type == COEX_ASSOCIATE_5G_START) {
2803 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n",
2804 			__func__);
2805 
2806 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2807 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2808 	} else if (type == COEX_ASSOCIATE_5G_FINISH) {
2809 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n",
2810 			__func__);
2811 
2812 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2813 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2814 	} else if (type == COEX_ASSOCIATE_START) {
2815 		coex_stat->wl_hi_pri_task1 = true;
2816 		coex_stat->wl_connecting = true;
2817 		coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2818 		coex_stat->wl_connecting = true;
2819 		ieee80211_queue_delayed_work(rtwdev->hw,
2820 					     &coex->wl_connecting_work, 2 * HZ);
2821 
2822 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n",
2823 			__func__);
2824 		/* Force antenna setup for no scan result issue */
2825 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2826 
2827 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2828 
2829 		/* To keep TDMA case during connect process,
2830 		 * to avoid changed by Btinfo and runcoexmechanism
2831 		 */
2832 		coex->freeze = true;
2833 		ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2834 					     5 * HZ);
2835 	} else {
2836 		coex_stat->wl_hi_pri_task1 = false;
2837 		coex->freeze = false;
2838 		coex_stat->wl_connecting = false;
2839 
2840 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n",
2841 			__func__);
2842 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2843 	}
2844 }
2845 
rtw_coex_media_status_notify(struct rtw_dev * rtwdev,u8 type)2846 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2847 {
2848 	struct rtw_coex *coex = &rtwdev->coex;
2849 	struct rtw_coex_stat *coex_stat = &coex->stat;
2850 
2851 	if (coex->manual_control || coex->stop_dm)
2852 		return;
2853 
2854 	if (type == COEX_MEDIA_CONNECT_5G) {
2855 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__);
2856 
2857 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2858 
2859 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2860 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2861 	} else if (type == COEX_MEDIA_CONNECT) {
2862 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__);
2863 
2864 		coex_stat->wl_connecting = false;
2865 
2866 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2867 
2868 		/* Force antenna setup for no scan result issue */
2869 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2870 
2871 		/* Set CCK Rx high Pri */
2872 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2873 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2874 	} else {
2875 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n",
2876 			__func__);
2877 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2878 		rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2879 	}
2880 
2881 	rtw_coex_update_wl_ch_info(rtwdev, type);
2882 }
2883 
rtw_coex_bt_info_notify(struct rtw_dev * rtwdev,u8 * buf,u8 length)2884 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2885 {
2886 	struct rtw_coex *coex = &rtwdev->coex;
2887 	struct rtw_coex_stat *coex_stat = &coex->stat;
2888 	struct rtw_chip_info *chip = rtwdev->chip;
2889 	struct rtw_coex_dm *coex_dm = &coex->dm;
2890 	u32 bt_relink_time;
2891 	u8 i, rsp_source = 0, type;
2892 	bool inq_page = false;
2893 
2894 	rsp_source = buf[0] & 0xf;
2895 	if (rsp_source >= COEX_BTINFO_SRC_MAX)
2896 		return;
2897 	coex_stat->cnt_bt_info_c2h[rsp_source]++;
2898 
2899 	if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
2900 		coex_stat->bt_iqk_state = buf[1];
2901 		if (coex_stat->bt_iqk_state == 0)
2902 			coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
2903 		else if (coex_stat->bt_iqk_state == 2)
2904 			coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
2905 
2906 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2907 			"[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n",
2908 			buf[1]);
2909 
2910 		return;
2911 	}
2912 
2913 	if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
2914 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2915 			"[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n",
2916 			buf[1], buf[2]);
2917 
2918 		rtw_coex_monitor_bt_enable(rtwdev);
2919 		if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
2920 			coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
2921 			rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2922 		}
2923 		return;
2924 	}
2925 
2926 	if (rsp_source == COEX_BTINFO_SRC_H2C60) {
2927 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2928 			"[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n",
2929 			buf[1], buf[2], buf[3], buf[4], buf[5]);
2930 
2931 		for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++)
2932 			coex_dm->fw_tdma_para[i - 1] = buf[i];
2933 		return;
2934 	}
2935 
2936 	if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
2937 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2938 			"[BTCoex], bt_info reply by WL FW\n");
2939 
2940 		rtw_coex_update_bt_link_info(rtwdev);
2941 		return;
2942 	}
2943 
2944 	if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
2945 	    rsp_source == COEX_BTINFO_SRC_BT_ACT) {
2946 		if (coex_stat->bt_disabled) {
2947 			coex_stat->bt_disabled = false;
2948 			coex_stat->bt_reenable = true;
2949 			ieee80211_queue_delayed_work(rtwdev->hw,
2950 						     &coex->bt_reenable_work,
2951 						     15 * HZ);
2952 			rtw_dbg(rtwdev, RTW_DBG_COEX,
2953 				"[BTCoex], BT enable detected by bt_info\n");
2954 		}
2955 	}
2956 
2957 	if (length != COEX_BTINFO_LENGTH) {
2958 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2959 			"[BTCoex], Bt_info length = %d invalid!!\n", length);
2960 
2961 		return;
2962 	}
2963 
2964 	rtw_dbg(rtwdev, RTW_DBG_COEX,
2965 		"[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n",
2966 		buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
2967 
2968 	for (i = 0; i < COEX_BTINFO_LENGTH; i++)
2969 		coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
2970 
2971 	/* get the same info from bt, skip it */
2972 	if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
2973 	    coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
2974 	    coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
2975 	    coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
2976 	    coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
2977 	    coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) {
2978 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2979 			"[BTCoex], Return because Btinfo duplicate!!\n");
2980 		return;
2981 	}
2982 
2983 	coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
2984 	coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
2985 	coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
2986 	coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
2987 	coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
2988 	coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
2989 
2990 	/* 0xff means BT is under WHCK test */
2991 	coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
2992 
2993 	inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
2994 
2995 	if (inq_page != coex_stat->bt_inq_page) {
2996 		cancel_delayed_work_sync(&coex->bt_remain_work);
2997 		coex_stat->bt_inq_page = inq_page;
2998 
2999 		if (inq_page)
3000 			coex_stat->bt_inq_remain = true;
3001 		else
3002 			ieee80211_queue_delayed_work(rtwdev->hw,
3003 						     &coex->bt_remain_work,
3004 						     4 * HZ);
3005 	}
3006 	coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
3007 	if (chip->ble_hid_profile_support) {
3008 		if (coex_stat->bt_info_lb2 & BIT(5)) {
3009 			if (coex_stat->bt_info_hb1 & BIT(0)) {
3010 				/*BLE HID*/
3011 				coex_stat->bt_ble_hid_exist = true;
3012 			} else {
3013 				coex_stat->bt_ble_hid_exist = false;
3014 			}
3015 			coex_stat->bt_ble_exist = false;
3016 		} else if (coex_stat->bt_info_hb1 & BIT(0)) {
3017 			/*RCU*/
3018 			coex_stat->bt_ble_hid_exist = false;
3019 			coex_stat->bt_ble_exist = true;
3020 		} else {
3021 			coex_stat->bt_ble_hid_exist = false;
3022 			coex_stat->bt_ble_exist = false;
3023 		}
3024 	} else {
3025 		if (coex_stat->bt_info_hb1 & BIT(0)) {
3026 			if (coex_stat->bt_hid_slot == 1 &&
3027 			    coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx &&
3028 			    coex_stat->hi_pri_rx < 100) {
3029 				coex_stat->bt_ble_hid_exist = true;
3030 				coex_stat->bt_ble_exist = false;
3031 			} else {
3032 				coex_stat->bt_ble_hid_exist = false;
3033 				coex_stat->bt_ble_exist = true;
3034 			}
3035 		} else {
3036 			coex_stat->bt_ble_hid_exist = false;
3037 			coex_stat->bt_ble_exist = false;
3038 		}
3039 	}
3040 
3041 	coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
3042 	if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
3043 		coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
3044 
3045 	coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
3046 	coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
3047 	if (coex_stat->bt_inq)
3048 		coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
3049 
3050 	coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
3051 	if (coex_stat->bt_page)
3052 		coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
3053 
3054 	/* unit: % (value-100 to translate to unit: dBm in coex info) */
3055 	if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
3056 		coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
3057 	} else {
3058 		if (coex_stat->bt_info_hb0 <= 127)
3059 			coex_stat->bt_rssi = 100;
3060 		else if (256 - coex_stat->bt_info_hb0 <= 100)
3061 			coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
3062 		else
3063 			coex_stat->bt_rssi = 0;
3064 	}
3065 
3066 	if (coex_stat->bt_info_hb1 & BIT(1))
3067 		coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
3068 
3069 	if (coex_stat->bt_info_hb1 & BIT(2)) {
3070 		coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
3071 		coex_stat->bt_setup_link = true;
3072 		if (coex_stat->bt_reenable)
3073 			bt_relink_time = 6 * HZ;
3074 		else
3075 			bt_relink_time = 1 * HZ;
3076 
3077 		ieee80211_queue_delayed_work(rtwdev->hw,
3078 					     &coex->bt_relink_work,
3079 					     bt_relink_time);
3080 
3081 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3082 			"[BTCoex], Re-Link start in BT info!!\n");
3083 	}
3084 
3085 	if (coex_stat->bt_info_hb1 & BIT(3))
3086 		coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
3087 
3088 	coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
3089 	coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
3090 	if (coex_stat->bt_info_hb1 & BIT(6))
3091 		coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
3092 
3093 	coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
3094 	/* for multi_link = 0 but bt pkt remain exist */
3095 	/* Use PS-TDMA to protect WL RX */
3096 	if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) {
3097 		coex_stat->bt_multi_link_remain = true;
3098 		ieee80211_queue_delayed_work(rtwdev->hw,
3099 					     &coex->bt_multi_link_remain_work,
3100 					     3 * HZ);
3101 	}
3102 	coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link;
3103 
3104 	/* resend wifi info to bt, it is reset and lost the info */
3105 	if (coex_stat->bt_info_hb1 & BIT(1)) {
3106 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3107 			"[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n");
3108 
3109 		if (coex_stat->wl_connected)
3110 			type = COEX_MEDIA_CONNECT;
3111 		else
3112 			type = COEX_MEDIA_DISCONNECT;
3113 		rtw_coex_update_wl_ch_info(rtwdev, type);
3114 	}
3115 
3116 	/* if ignore_wlan_act && not set_up_link */
3117 	if ((coex_stat->bt_info_hb1 & BIT(3)) &&
3118 	    (!(coex_stat->bt_info_hb1 & BIT(2)))) {
3119 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3120 			"[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
3121 		rtw_coex_ignore_wlan_act(rtwdev, false);
3122 	}
3123 
3124 	coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
3125 	if (coex_stat->bt_info_hb2 & BIT(1))
3126 		coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
3127 
3128 	coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
3129 	coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
3130 	coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
3131 	coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
3132 	if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
3133 		coex_stat->bt_418_hid_exist = true;
3134 	else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1)
3135 		coex_stat->bt_418_hid_exist = false;
3136 
3137 	if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
3138 		coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
3139 	else
3140 		coex_stat->bt_a2dp_bitpool = 0;
3141 
3142 	coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
3143 
3144 	rtw_coex_update_bt_link_info(rtwdev);
3145 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
3146 }
3147 
rtw_coex_wl_fwdbginfo_notify(struct rtw_dev * rtwdev,u8 * buf,u8 length)3148 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3149 {
3150 	struct rtw_coex *coex = &rtwdev->coex;
3151 	struct rtw_coex_stat *coex_stat = &coex->stat;
3152 	u8 val;
3153 	int i;
3154 
3155 	rtw_dbg(rtwdev, RTW_DBG_COEX,
3156 		"[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n",
3157 		buf, length);
3158 	if (WARN(length < 8, "invalid wl info c2h length\n"))
3159 		return;
3160 
3161 	if (buf[0] != 0x08)
3162 		return;
3163 
3164 	for (i = 1; i < 8; i++) {
3165 		val = coex_stat->wl_fw_dbg_info_pre[i];
3166 		if (buf[i] >= val)
3167 			coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
3168 		else
3169 			coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i];
3170 
3171 		coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
3172 	}
3173 
3174 	coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
3175 	rtw_coex_wl_ccklock_action(rtwdev);
3176 	rtw_coex_wl_ccklock_detect(rtwdev);
3177 }
3178 
rtw_coex_wl_status_change_notify(struct rtw_dev * rtwdev,u32 type)3179 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type)
3180 {
3181 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3182 }
3183 
rtw_coex_bt_relink_work(struct work_struct * work)3184 void rtw_coex_bt_relink_work(struct work_struct *work)
3185 {
3186 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3187 					      coex.bt_relink_work.work);
3188 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3189 
3190 	mutex_lock(&rtwdev->mutex);
3191 	coex_stat->bt_setup_link = false;
3192 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3193 	mutex_unlock(&rtwdev->mutex);
3194 }
3195 
rtw_coex_bt_reenable_work(struct work_struct * work)3196 void rtw_coex_bt_reenable_work(struct work_struct *work)
3197 {
3198 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3199 					      coex.bt_reenable_work.work);
3200 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3201 
3202 	mutex_lock(&rtwdev->mutex);
3203 	coex_stat->bt_reenable = false;
3204 	mutex_unlock(&rtwdev->mutex);
3205 }
3206 
rtw_coex_defreeze_work(struct work_struct * work)3207 void rtw_coex_defreeze_work(struct work_struct *work)
3208 {
3209 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3210 					      coex.defreeze_work.work);
3211 	struct rtw_coex *coex = &rtwdev->coex;
3212 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3213 
3214 	mutex_lock(&rtwdev->mutex);
3215 	coex->freeze = false;
3216 	coex_stat->wl_hi_pri_task1 = false;
3217 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3218 	mutex_unlock(&rtwdev->mutex);
3219 }
3220 
rtw_coex_wl_remain_work(struct work_struct * work)3221 void rtw_coex_wl_remain_work(struct work_struct *work)
3222 {
3223 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3224 					      coex.wl_remain_work.work);
3225 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3226 
3227 	mutex_lock(&rtwdev->mutex);
3228 	coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
3229 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3230 	mutex_unlock(&rtwdev->mutex);
3231 }
3232 
rtw_coex_bt_remain_work(struct work_struct * work)3233 void rtw_coex_bt_remain_work(struct work_struct *work)
3234 {
3235 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3236 					      coex.bt_remain_work.work);
3237 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3238 
3239 	mutex_lock(&rtwdev->mutex);
3240 	coex_stat->bt_inq_remain = coex_stat->bt_inq_page;
3241 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
3242 	mutex_unlock(&rtwdev->mutex);
3243 }
3244 
rtw_coex_wl_connecting_work(struct work_struct * work)3245 void rtw_coex_wl_connecting_work(struct work_struct *work)
3246 {
3247 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3248 					      coex.wl_connecting_work.work);
3249 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3250 
3251 	mutex_lock(&rtwdev->mutex);
3252 	coex_stat->wl_connecting = false;
3253 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n");
3254 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3255 	mutex_unlock(&rtwdev->mutex);
3256 }
3257 
rtw_coex_bt_multi_link_remain_work(struct work_struct * work)3258 void rtw_coex_bt_multi_link_remain_work(struct work_struct *work)
3259 {
3260 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3261 		coex.bt_multi_link_remain_work.work);
3262 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3263 
3264 	mutex_lock(&rtwdev->mutex);
3265 	coex_stat->bt_multi_link_remain = false;
3266 	mutex_unlock(&rtwdev->mutex);
3267 }
3268 
rtw_coex_wl_ccklock_work(struct work_struct * work)3269 void rtw_coex_wl_ccklock_work(struct work_struct *work)
3270 {
3271 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3272 					      coex.wl_ccklock_work.work);
3273 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3274 
3275 	mutex_lock(&rtwdev->mutex);
3276 	coex_stat->wl_cck_lock = false;
3277 	mutex_unlock(&rtwdev->mutex);
3278 }
3279 
3280 #ifdef CONFIG_RTW88_DEBUGFS
3281 #define INFO_SIZE	80
3282 
3283 #define case_BTINFO(src) \
3284 	case COEX_BTINFO_SRC_##src: return #src
3285 
rtw_coex_get_bt_info_src_string(u8 bt_info_src)3286 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
3287 {
3288 	switch (bt_info_src) {
3289 	case_BTINFO(WL_FW);
3290 	case_BTINFO(BT_RSP);
3291 	case_BTINFO(BT_ACT);
3292 	default:
3293 		return "Unknown";
3294 	}
3295 }
3296 
3297 #define case_RSN(src) \
3298 	case COEX_RSN_##src: return #src
3299 
rtw_coex_get_reason_string(u8 reason)3300 static const char *rtw_coex_get_reason_string(u8 reason)
3301 {
3302 	switch (reason) {
3303 	case_RSN(2GSCANSTART);
3304 	case_RSN(5GSCANSTART);
3305 	case_RSN(SCANFINISH);
3306 	case_RSN(2GSWITCHBAND);
3307 	case_RSN(5GSWITCHBAND);
3308 	case_RSN(2GCONSTART);
3309 	case_RSN(5GCONSTART);
3310 	case_RSN(2GCONFINISH);
3311 	case_RSN(5GCONFINISH);
3312 	case_RSN(2GMEDIA);
3313 	case_RSN(5GMEDIA);
3314 	case_RSN(MEDIADISCON);
3315 	case_RSN(BTINFO);
3316 	case_RSN(LPS);
3317 	case_RSN(WLSTATUS);
3318 	default:
3319 		return "Unknown";
3320 	}
3321 }
3322 
rtw_coex_get_table_index(struct rtw_dev * rtwdev,u32 wl_reg_6c0,u32 wl_reg_6c4)3323 static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
3324 				   u32 wl_reg_6c4)
3325 {
3326 	struct rtw_chip_info *chip = rtwdev->chip;
3327 	struct rtw_efuse *efuse = &rtwdev->efuse;
3328 	u8 ans = 0xFF;
3329 	u8 n, i;
3330 	u32 load_bt_val;
3331 	u32 load_wl_val;
3332 	bool share_ant = efuse->share_ant;
3333 
3334 	if (share_ant)
3335 		n = chip->table_sant_num;
3336 	else
3337 		n = chip->table_nsant_num;
3338 
3339 	for (i = 0; i < n; i++) {
3340 		if (share_ant) {
3341 			load_bt_val = chip->table_sant[i].bt;
3342 			load_wl_val = chip->table_sant[i].wl;
3343 		} else {
3344 			load_bt_val = chip->table_nsant[i].bt;
3345 			load_wl_val = chip->table_nsant[i].wl;
3346 		}
3347 
3348 		if (wl_reg_6c0 == load_bt_val &&
3349 		    wl_reg_6c4 == load_wl_val) {
3350 			ans = i;
3351 			if (!share_ant)
3352 				ans += 100;
3353 			break;
3354 		}
3355 	}
3356 
3357 	return ans;
3358 }
3359 
rtw_coex_get_tdma_index(struct rtw_dev * rtwdev,u8 * tdma_para)3360 static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)
3361 {
3362 	struct rtw_efuse *efuse = &rtwdev->efuse;
3363 	struct rtw_chip_info *chip = rtwdev->chip;
3364 	u8 ans = 0xFF;
3365 	u8 n, i, j;
3366 	u8 load_cur_tab_val;
3367 	bool valid = false;
3368 	bool share_ant = efuse->share_ant;
3369 
3370 	if (share_ant)
3371 		n = chip->tdma_sant_num;
3372 	else
3373 		n = chip->tdma_nsant_num;
3374 
3375 	for (i = 0; i < n; i++) {
3376 		valid = false;
3377 		for (j = 0; j < 5; j++) {
3378 			if (share_ant)
3379 				load_cur_tab_val = chip->tdma_sant[i].para[j];
3380 			else
3381 				load_cur_tab_val = chip->tdma_nsant[i].para[j];
3382 
3383 			if (*(tdma_para + j) != load_cur_tab_val)
3384 				break;
3385 
3386 			if (j == 4)
3387 				valid = true;
3388 		}
3389 		if (valid) {
3390 			ans = i;
3391 			break;
3392 		}
3393 	}
3394 
3395 	return ans;
3396 }
3397 
rtw_coex_addr_info(struct rtw_dev * rtwdev,const struct rtw_reg_domain * reg,char addr_info[],int n)3398 static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
3399 			      const struct rtw_reg_domain *reg,
3400 			      char addr_info[], int n)
3401 {
3402 	const char *rf_prefix = "";
3403 	const char *sep = n == 0 ? "" : "/ ";
3404 	int ffs, fls;
3405 	int max_fls;
3406 
3407 	if (INFO_SIZE - n <= 0)
3408 		return 0;
3409 
3410 	switch (reg->domain) {
3411 	case RTW_REG_DOMAIN_MAC32:
3412 		max_fls = 31;
3413 		break;
3414 	case RTW_REG_DOMAIN_MAC16:
3415 		max_fls = 15;
3416 		break;
3417 	case RTW_REG_DOMAIN_MAC8:
3418 		max_fls = 7;
3419 		break;
3420 	case RTW_REG_DOMAIN_RF_A:
3421 	case RTW_REG_DOMAIN_RF_B:
3422 		rf_prefix = "RF_";
3423 		max_fls = 19;
3424 		break;
3425 	default:
3426 		return 0;
3427 	}
3428 
3429 	ffs = __ffs(reg->mask);
3430 	fls = __fls(reg->mask);
3431 
3432 	if (ffs == 0 && fls == max_fls)
3433 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
3434 				 sep, rf_prefix, reg->addr);
3435 	else if (ffs == fls)
3436 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
3437 				 sep, rf_prefix, reg->addr, ffs);
3438 	else
3439 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
3440 				 sep, rf_prefix, reg->addr, fls, ffs);
3441 }
3442 
rtw_coex_val_info(struct rtw_dev * rtwdev,const struct rtw_reg_domain * reg,char val_info[],int n)3443 static int rtw_coex_val_info(struct rtw_dev *rtwdev,
3444 			     const struct rtw_reg_domain *reg,
3445 			     char val_info[], int n)
3446 {
3447 	const char *sep = n == 0 ? "" : "/ ";
3448 	u8 rf_path;
3449 
3450 	if (INFO_SIZE - n <= 0)
3451 		return 0;
3452 
3453 	switch (reg->domain) {
3454 	case RTW_REG_DOMAIN_MAC32:
3455 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3456 				 rtw_read32_mask(rtwdev, reg->addr, reg->mask));
3457 	case RTW_REG_DOMAIN_MAC16:
3458 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3459 				 rtw_read16_mask(rtwdev, reg->addr, reg->mask));
3460 	case RTW_REG_DOMAIN_MAC8:
3461 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3462 				 rtw_read8_mask(rtwdev, reg->addr, reg->mask));
3463 	case RTW_REG_DOMAIN_RF_A:
3464 		rf_path = RF_PATH_A;
3465 		break;
3466 	case RTW_REG_DOMAIN_RF_B:
3467 		rf_path = RF_PATH_B;
3468 		break;
3469 	default:
3470 		return 0;
3471 	}
3472 
3473 	/* only RF go through here */
3474 	return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3475 			 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
3476 }
3477 
rtw_coex_set_coexinfo_hw(struct rtw_dev * rtwdev,struct seq_file * m)3478 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
3479 {
3480 	struct rtw_chip_info *chip = rtwdev->chip;
3481 	const struct rtw_reg_domain *reg;
3482 	char addr_info[INFO_SIZE];
3483 	int n_addr = 0;
3484 	char val_info[INFO_SIZE];
3485 	int n_val = 0;
3486 	int i;
3487 
3488 	for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
3489 		reg = &chip->coex_info_hw_regs[i];
3490 
3491 		n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
3492 		n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
3493 
3494 		if (reg->domain == RTW_REG_DOMAIN_NL) {
3495 			seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3496 			n_addr = 0;
3497 			n_val = 0;
3498 		}
3499 	}
3500 
3501 	if (n_addr != 0 && n_val != 0)
3502 		seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3503 }
3504 
rtw_coex_get_bt_reg(struct rtw_dev * rtwdev,u8 type,u16 addr,u16 * val)3505 static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
3506 				u8 type, u16 addr, u16 *val)
3507 {
3508 	struct rtw_coex_info_req req = {0};
3509 	struct sk_buff *skb;
3510 	__le16 le_addr;
3511 	u8 *payload;
3512 
3513 	le_addr = cpu_to_le16(addr);
3514 	req.op_code = BT_MP_INFO_OP_READ_REG;
3515 	req.para1 = type;
3516 	req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
3517 	req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
3518 	skb = rtw_coex_info_request(rtwdev, &req);
3519 	if (!skb) {
3520 		*val = 0xeaea;
3521 		return false;
3522 	}
3523 
3524 	payload = get_payload_from_coex_resp(skb);
3525 	*val = GET_COEX_RESP_BT_REG_VAL(payload);
3526 
3527 	return true;
3528 }
3529 
rtw_coex_get_bt_patch_version(struct rtw_dev * rtwdev,u32 * patch_version)3530 static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
3531 					  u32 *patch_version)
3532 {
3533 	struct rtw_coex_info_req req = {0};
3534 	struct sk_buff *skb;
3535 	u8 *payload;
3536 	bool ret = false;
3537 
3538 	req.op_code = BT_MP_INFO_OP_PATCH_VER;
3539 	skb = rtw_coex_info_request(rtwdev, &req);
3540 	if (!skb)
3541 		goto out;
3542 
3543 	payload = get_payload_from_coex_resp(skb);
3544 	*patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
3545 	ret = true;
3546 
3547 out:
3548 	return ret;
3549 }
3550 
rtw_coex_get_bt_supported_version(struct rtw_dev * rtwdev,u32 * supported_version)3551 static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
3552 					      u32 *supported_version)
3553 {
3554 	struct rtw_coex_info_req req = {0};
3555 	struct sk_buff *skb;
3556 	u8 *payload;
3557 	bool ret = false;
3558 
3559 	req.op_code = BT_MP_INFO_OP_SUPP_VER;
3560 	skb = rtw_coex_info_request(rtwdev, &req);
3561 	if (!skb)
3562 		goto out;
3563 
3564 	payload = get_payload_from_coex_resp(skb);
3565 	*supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
3566 	ret = true;
3567 
3568 out:
3569 	return ret;
3570 }
3571 
rtw_coex_get_bt_supported_feature(struct rtw_dev * rtwdev,u32 * supported_feature)3572 static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
3573 					      u32 *supported_feature)
3574 {
3575 	struct rtw_coex_info_req req = {0};
3576 	struct sk_buff *skb;
3577 	u8 *payload;
3578 	bool ret = false;
3579 
3580 	req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
3581 	skb = rtw_coex_info_request(rtwdev, &req);
3582 	if (!skb)
3583 		goto out;
3584 
3585 	payload = get_payload_from_coex_resp(skb);
3586 	*supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
3587 	ret = true;
3588 
3589 out:
3590 	return ret;
3591 }
3592 
3593 struct rtw_coex_sta_stat_iter_data {
3594 	struct rtw_vif *rtwvif;
3595 	struct seq_file *file;
3596 };
3597 
rtw_coex_sta_stat_iter(void * data,struct ieee80211_sta * sta)3598 static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
3599 {
3600 	struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
3601 	struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
3602 	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
3603 	struct seq_file *m = sta_iter_data->file;
3604 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
3605 	u8 rssi;
3606 
3607 	if (si->vif != vif)
3608 		return;
3609 
3610 	rssi = ewma_rssi_read(&si->avg_rssi);
3611 	seq_printf(m, "\tPeer %3d\n", si->mac_id);
3612 	seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
3613 	seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
3614 }
3615 
3616 struct rtw_coex_vif_stat_iter_data {
3617 	struct rtw_dev *rtwdev;
3618 	struct seq_file *file;
3619 };
3620 
rtw_coex_vif_stat_iter(void * data,u8 * mac,struct ieee80211_vif * vif)3621 static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
3622 				   struct ieee80211_vif *vif)
3623 {
3624 	struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
3625 	struct rtw_coex_sta_stat_iter_data sta_iter_data;
3626 	struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
3627 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
3628 	struct seq_file *m = vif_iter_data->file;
3629 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
3630 
3631 	seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
3632 	seq_printf(m, "\t%-32s = %d\n",
3633 		   "Beacon interval", bss_conf->beacon_int);
3634 	seq_printf(m, "\t%-32s = %d\n",
3635 		   "Network Type", rtwvif->net_type);
3636 
3637 	sta_iter_data.rtwvif = rtwvif;
3638 	sta_iter_data.file = m;
3639 	rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
3640 				&sta_iter_data);
3641 }
3642 
3643 #define case_WLINK(src) \
3644 	case COEX_WLINK_##src: return #src
3645 
rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)3646 static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
3647 {
3648 	switch (coex_wl_link_mode) {
3649 	case_WLINK(2G1PORT);
3650 	case_WLINK(5G);
3651 	default:
3652 		return "Unknown";
3653 	}
3654 }
3655 
rtw_coex_display_coex_info(struct rtw_dev * rtwdev,struct seq_file * m)3656 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
3657 {
3658 	struct rtw_chip_info *chip = rtwdev->chip;
3659 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
3660 	struct rtw_coex *coex = &rtwdev->coex;
3661 	struct rtw_coex_stat *coex_stat = &coex->stat;
3662 	struct rtw_coex_dm *coex_dm = &coex->dm;
3663 	struct rtw_hal *hal = &rtwdev->hal;
3664 	struct rtw_efuse *efuse = &rtwdev->efuse;
3665 	struct rtw_fw_state *fw = &rtwdev->fw;
3666 	struct rtw_coex_vif_stat_iter_data vif_iter_data;
3667 	u8 reason = coex_dm->reason;
3668 	u8 sys_lte;
3669 	u16 score_board_WB, score_board_BW;
3670 	u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
3671 	u32 lte_coex, bt_coex;
3672 	u32 bt_hi_pri, bt_lo_pri;
3673 	int i;
3674 
3675 	score_board_BW = rtw_coex_read_scbd(rtwdev);
3676 	score_board_WB = coex_stat->score_board;
3677 	wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0);
3678 	wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1);
3679 	wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE);
3680 	wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H);
3681 	wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
3682 
3683 	bt_hi_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);
3684 	bt_lo_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);
3685 	rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,
3686 		   BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);
3687 
3688 	coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, bt_hi_pri);
3689 	coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, bt_hi_pri);
3690 
3691 	coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, bt_lo_pri);
3692 	coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, bt_lo_pri);
3693 
3694 	sys_lte = rtw_read8(rtwdev, 0x73);
3695 	lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
3696 	bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
3697 
3698 	if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
3699 		rtw_coex_get_bt_supported_version(rtwdev,
3700 				&coex_stat->bt_supported_version);
3701 		rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
3702 		rtw_coex_get_bt_supported_feature(rtwdev,
3703 				&coex_stat->bt_supported_feature);
3704 		rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
3705 		rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
3706 
3707 		if (coex_stat->patch_ver != 0)
3708 			coex_stat->bt_mailbox_reply = true;
3709 	}
3710 
3711 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
3712 	seq_printf(m, "**********************************************\n");
3713 	seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
3714 	seq_printf(m, "**********************************************\n");
3715 
3716 	if (coex->manual_control) {
3717 		seq_puts(m, "============[Under Manual Control]============\n");
3718 		seq_puts(m, "==========================================\n");
3719 
3720 	} else if (coex->stop_dm) {
3721 		seq_puts(m, "============[Coex is STOPPED]============\n");
3722 		seq_puts(m, "==========================================\n");
3723 
3724 	} else if (coex->freeze) {
3725 		seq_puts(m, "============[coex_freeze]============\n");
3726 		seq_puts(m, "==========================================\n");
3727 	}
3728 
3729 	seq_printf(m, "%-40s = %s/ %d\n",
3730 		   "Mech/ RFE",
3731 		   efuse->share_ant ? "Shared" : "Non-Shared",
3732 		   efuse->rfe_option);
3733 	seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
3734 		   "Coex Ver/ BT Dez/ BT Rpt",
3735 		   chip->coex_para_ver, chip->bt_desired_ver,
3736 		   coex_stat->bt_supported_version,
3737 		   coex_stat->bt_disabled ? "(BT disabled)" :
3738 		   coex_stat->bt_supported_version >= chip->bt_desired_ver ?
3739 		   "(Match)" : "(Mismatch)");
3740 	seq_printf(m, "%-40s = %s/ %u/ %d\n",
3741 		   "Role/ RoleSwCnt/ IgnWL/ Feature",
3742 		   coex_stat->bt_slave ? "Slave" : "Master",
3743 		   coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
3744 		   coex_dm->ignore_wl_act);
3745 	seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n",
3746 		   "WL FW/ BT FW/ BT FW Desired/ KT",
3747 		   fw->version, fw->sub_version,
3748 		   coex_stat->patch_ver,
3749 		   chip->wl_fw_desired_ver, coex_stat->kt_ver + 65);
3750 	seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
3751 		   "AFH Map",
3752 		   coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
3753 		   coex_dm->wl_ch_info[2], hal->current_channel);
3754 
3755 	rtw_debugfs_get_simple_phy_info(m);
3756 	seq_printf(m, "**********************************************\n");
3757 	seq_printf(m, "\t\tBT Status\n");
3758 	seq_printf(m, "**********************************************\n");
3759 	seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
3760 		   "BT status/ rssi/ retry/ pop",
3761 		   coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
3762 		   coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
3763 		   coex_stat->bt_rssi - 100,
3764 		   coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
3765 		   coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
3766 	seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
3767 		   "Profiles",
3768 		   coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
3769 					       "A2DP sink," : "A2DP,") : "",
3770 		   coex_stat->bt_hfp_exist ? "HFP," : "",
3771 		   coex_stat->bt_hid_exist ?
3772 		   (coex_stat->bt_ble_exist ? "HID(RCU)," :
3773 		    coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
3774 		    coex_stat->bt_ble_hid_exist ? "HID(BLE)" :
3775 		    "HID(2/18),") : "",
3776 		   coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
3777 		   "OPP," : "PAN," : "",
3778 		   coex_stat->bt_ble_voice ? "Voice," : "",
3779 		   coex_stat->bt_multi_link);
3780 	seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
3781 		   "Reinit/ Relink/ IgnWl/ Feature",
3782 		   coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
3783 		   coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
3784 		   coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
3785 		   coex_stat->bt_supported_feature);
3786 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3787 		   "Page/ Inq/ iqk/ iqk fail",
3788 		   coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
3789 		   coex_stat->cnt_bt[COEX_CNT_BT_INQ],
3790 		   coex_stat->cnt_bt[COEX_CNT_BT_IQK],
3791 		   coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
3792 	seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
3793 		   "0xae/ 0xac/ score board (W->B)/ (B->W)",
3794 		   coex_stat->bt_reg_vendor_ae,
3795 		   coex_stat->bt_reg_vendor_ac,
3796 		   score_board_WB, score_board_BW);
3797 	seq_printf(m, "%-40s = %u/%u, %u/%u\n",
3798 		   "Hi-Pri TX/RX, Lo-Pri TX/RX",
3799 		   coex_stat->hi_pri_tx, coex_stat->hi_pri_rx,
3800 		   coex_stat->lo_pri_tx, coex_stat->lo_pri_rx);
3801 	for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
3802 		seq_printf(m, "%-40s = %7ph\n",
3803 			   rtw_coex_get_bt_info_src_string(i),
3804 			   coex_stat->bt_info_c2h[i]);
3805 
3806 	seq_printf(m, "**********************************************\n");
3807 	seq_printf(m, "\t\tWiFi Status\n");
3808 	seq_printf(m, "**********************************************\n");
3809 	seq_printf(m, "%-40s = %d\n",
3810 		   "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
3811 	seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
3812 		   "G_busy/ TX/ RX",
3813 		   coex_stat->wl_gl_busy,
3814 		   rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
3815 	seq_printf(m, "%-40s = %u/ %u/ %u\n",
3816 		   "IPS/ Low Power/ PS mode",
3817 		   test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
3818 		   test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
3819 		   rtwdev->lps_conf.mode);
3820 
3821 	vif_iter_data.rtwdev = rtwdev;
3822 	vif_iter_data.file = m;
3823 	rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
3824 
3825 	if (coex->manual_control) {
3826 		seq_printf(m, "**********************************************\n");
3827 		seq_printf(m, "\t\tMechanism (Under Manual)\n");
3828 		seq_printf(m, "**********************************************\n");
3829 		seq_printf(m, "%-40s = %5ph (%d)\n",
3830 			   "TDMA Now",
3831 			   coex_dm->fw_tdma_para,
3832 			   rtw_coex_get_tdma_index(rtwdev,
3833 						   &coex_dm->fw_tdma_para[0]));
3834 	} else {
3835 		seq_printf(m, "**********************************************\n");
3836 		seq_printf(m, "\t\tMechanism\n");
3837 		seq_printf(m, "**********************************************\n");
3838 		seq_printf(m, "%-40s = %5ph (case-%d)\n",
3839 			   "TDMA",
3840 			   coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
3841 	}
3842 	seq_printf(m, "%-40s = %s/ %s/ %d\n",
3843 		   "Coex Mode/Free Run/Timer base",
3844 		   rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode),
3845 		   coex->freerun ? "Yes" : "No",
3846 		   coex_stat->tdma_timer_base);
3847 	seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n",
3848 		   "Table/ 0x6c0/ 0x6c4/ 0x6c8",
3849 		   coex_dm->cur_table,
3850 		   rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4),
3851 		   wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
3852 	seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n",
3853 		   "0x778/ 0x6cc/ Run Count/ Reason",
3854 		   wl_reg_778, wl_reg_6cc,
3855 		   coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN],
3856 		   rtw_coex_get_reason_string(reason));
3857 	seq_printf(m, "%-40s = %3ph\n",
3858 		   "AFH Map to BT",
3859 		   coex_dm->wl_ch_info);
3860 	seq_printf(m, "%-40s = %s/ %d\n",
3861 		   "AntDiv/ BtCtrlLPS/ g_busy",
3862 		   coex_stat->wl_force_lps_ctrl ? "On" : "Off",
3863 		   coex_stat->wl_gl_busy);
3864 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
3865 		   "Null All/ Retry/ Ack/ BT Empty/ BT Late",
3866 		   coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
3867 		   coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
3868 		   coex_stat->wl_fw_dbg_info[5]);
3869 	seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
3870 		   "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
3871 		   coex_stat->wl_fw_dbg_info[6],
3872 		   coex_stat->wl_fw_dbg_info[7],
3873 		   coex_stat->wl_slot_extend ? "Yes" : "No",
3874 		   coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
3875 	seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n",
3876 		   "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl",
3877 		   coex_dm->cur_wl_pwr_lvl,
3878 		   coex_dm->cur_bt_pwr_lvl,
3879 		   coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off",
3880 		   coex_dm->cur_bt_lna_lvl);
3881 
3882 	seq_printf(m, "**********************************************\n");
3883 	seq_printf(m, "\t\tHW setting\n");
3884 	seq_printf(m, "**********************************************\n");
3885 	seq_printf(m, "%-40s = %s/ %s\n",
3886 		   "LTE Coex/ Path Owner",
3887 		   lte_coex & BIT(7) ? "ON" : "OFF",
3888 		   sys_lte & BIT(2) ? "WL" : "BT");
3889 	seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
3890 		   "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
3891 		   lte_coex & BIT(12) ? "SW" : "HW",
3892 		   lte_coex & BIT(8) ? "SW" : "HW",
3893 		   lte_coex & BIT(14) ? "SW" : "HW",
3894 		   lte_coex & BIT(10) ? "SW" : "HW",
3895 		   sys_lte & BIT(3) ? "On" : "Off");
3896 	seq_printf(m, "%-40s = %lu/ %lu\n",
3897 		   "GNT_WL/ GNT_BT",
3898 		   (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
3899 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3900 		   "CRC OK CCK/ OFDM/ HT/ VHT",
3901 		   dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
3902 		   dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
3903 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3904 		   "CRC ERR CCK/ OFDM/ HT/ VHT",
3905 		   dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
3906 		   dm_info->ht_err_cnt, dm_info->vht_err_cnt);
3907 	seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
3908 		   "HiPr/ Locking/ Locked/ Noisy",
3909 		   coex_stat->wl_hi_pri_task1 ? "Y" : "N",
3910 		   coex_stat->wl_cck_lock ? "Y" : "N",
3911 		   coex_stat->wl_cck_lock_ever ? "Y" : "N",
3912 		   coex_stat->wl_noisy_level);
3913 
3914 	rtw_coex_set_coexinfo_hw(rtwdev, m);
3915 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
3916 		   "EVM A/ EVM B/ SNR A/ SNR B",
3917 		   -dm_info->rx_evm_dbm[RF_PATH_A],
3918 		   -dm_info->rx_evm_dbm[RF_PATH_B],
3919 		   -dm_info->rx_snr[RF_PATH_A],
3920 		   -dm_info->rx_snr[RF_PATH_B]);
3921 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
3922 		   "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA",
3923 		   dm_info->cck_cca_cnt, dm_info->cck_fa_cnt,
3924 		   dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt);
3925 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac",
3926 		   dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
3927 		   dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
3928 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac",
3929 		   dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
3930 		   dm_info->ht_err_cnt, dm_info->vht_err_cnt);
3931 
3932 }
3933 #endif /* CONFIG_RTW88_DEBUGFS */
3934