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], ¶[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], ¶[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