1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019 Realtek Corporation
13 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
14 u8 rssi, u8 rssi_thresh)
16 struct rtw_chip_info *chip = rtwdev->chip;
17 u8 tol = chip->rssi_tolerance;
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;
25 next_state = COEX_RSSI_STATE_STAY_LOW;
27 if (rssi < rssi_thresh)
28 next_state = COEX_RSSI_STATE_LOW;
30 next_state = COEX_RSSI_STATE_STAY_HIGH;
36 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
37 bool tx_limit_en, bool ampdu_limit_en)
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;
44 if (!chip->scbd_support)
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)
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);
58 if (!coex_stat->wl_ampdu_limit_en)
59 coex_stat->ampdu_max_time =
60 rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
62 coex_stat->wl_tx_limit_en = tx_limit_en;
63 coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
66 /* set BT polluted packet on for tx rate adaptive,
67 * not including tx retry broken by PTA
69 rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
71 /* set queue life time to avoid can't reach tx retry limit
72 * if tx is always broken by GNT_BT
74 if (num_of_active_port <= 1)
75 rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
76 rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
78 /* auto rate fallback step within 8 retries */
79 rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
80 rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
82 rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
83 rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
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);
91 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
93 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
94 coex_stat->ampdu_max_time);
97 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
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;
104 if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) {
109 rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
112 static bool rtw_coex_freerun_check(struct rtw_dev *rtwdev)
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;
119 u8 ant_distance = 10;
121 if (coex_stat->bt_disabled)
124 if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy)
127 if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2)
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]))
135 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
136 bt_rssi = coex_dm->bt_rssi_state[0];
138 bt_rssi = coex_dm->bt_rssi_state[1];
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)
148 static void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable)
150 struct rtw_coex *coex = &rtwdev->coex;
151 struct rtw_coex_stat *coex_stat = &coex->stat;
154 para[0] = COEX_H2C69_WL_LEAKAP;
155 para[1] = PARA1_H2C69_DIS_5MS;
158 para[1] = PARA1_H2C69_EN_5MS;
160 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
162 coex_stat->wl_slot_extend = enable;
163 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
166 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
168 struct rtw_coex *coex = &rtwdev->coex;
169 struct rtw_coex_stat *coex_stat = &coex->stat;
171 if (coex->manual_control || coex->stop_dm)
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);
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]++;
187 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
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]);
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);
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");
202 rtw_coex_wl_slot_extend(rtwdev, true);
206 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
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;
212 bool is_cck_lock_rate = false;
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;
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;
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;
233 rtw_dbg(rtwdev, RTW_DBG_COEX,
234 "[BTCoex], cck locking...\n");
237 coex_stat->wl_cck_lock = false;
239 rtw_dbg(rtwdev, RTW_DBG_COEX,
240 "[BTCoex], cck unlock...\n");
243 coex_stat->wl_cck_lock = false;
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,
251 coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock;
254 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
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;
260 bool wl_cck_lock = false;
262 /* wifi noisy environment identification */
263 cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
265 if (!coex_stat->wl_gl_busy && !wl_cck_lock) {
267 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
268 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
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;
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]++;
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;
283 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
284 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
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;
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;
297 coex_stat->wl_noisy_level = 0;
299 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n",
300 coex_stat->wl_noisy_level);
304 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
306 struct rtw_coex *coex = &rtwdev->coex;
307 struct rtw_coex_stat *coex_stat = &coex->stat;
310 u16 tbtt_interval = coex_stat->wl_beacon_interval;
312 if (coex_stat->tdma_timer_base == type)
315 coex_stat->tdma_timer_base = type;
317 para[0] = COEX_H2C69_TDMA_SLOT;
319 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n",
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)
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)
335 para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) |
336 FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1);
338 para[1] = PARA1_H2C69_TDMA_2SLOT;
341 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
343 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n",
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);
351 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
356 addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
359 rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
362 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
364 struct rtw_chip_info *chip = rtwdev->chip;
365 struct rtw_coex *coex = &rtwdev->coex;
366 struct rtw_coex_stat *coex_stat = &coex->stat;
369 if (!chip->scbd_support)
372 val |= coex_stat->score_board;
374 /* for 8822b, scbd[10] is CQDDR on
375 * for 8822c, scbd[10] is no fix 2M
377 if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
379 val &= ~COEX_SCBD_FIX2M;
381 val |= COEX_SCBD_FIX2M;
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);
395 EXPORT_SYMBOL(rtw_coex_write_scbd);
397 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
399 struct rtw_chip_info *chip = rtwdev->chip;
401 if (!chip->scbd_support)
404 return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
407 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
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;
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");
422 wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
425 btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
428 wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
433 rtw_dbg(rtwdev, RTW_DBG_COEX,
434 "[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n",
437 mdelay(COEX_MIN_DELAY);
438 } while (++cnt < wait_cnt);
441 coex_stat->bt_iqk_state = 0xff;
445 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
447 struct rtw_coex *coex = &rtwdev->coex;
448 struct rtw_coex_stat *coex_stat = &coex->stat;
450 if (coex_stat->bt_disabled)
453 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
455 rtw_fw_query_bt_info(rtwdev);
458 static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode)
460 rtw_coex_set_gnt_fix(rtwdev);
463 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
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;
472 if (chip->scbd_support) {
473 score_board = rtw_coex_read_scbd(rtwdev);
474 bt_disabled = !(score_board & COEX_SCBD_ONOFF);
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);
482 coex_stat->bt_disabled = bt_disabled;
483 coex_stat->bt_ble_scan_type = 0;
484 coex_dm->cur_bt_lna_lvl = 0;
486 if (!coex_stat->bt_disabled) {
487 coex_stat->bt_reenable = true;
488 ieee80211_queue_delayed_work(rtwdev->hw,
489 &coex->bt_reenable_work,
492 coex_stat->bt_mailbox_reply = false;
493 coex_stat->bt_reenable = false;
498 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
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;
506 bool wl_busy = false;
507 bool scan = false, link = false;
513 scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
514 coex_stat->wl_connected = !!rtwdev->sta_cnt;
516 wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
517 if (wl_busy != coex_stat->wl_gl_busy) {
519 coex_stat->wl_gl_busy = true;
521 ieee80211_queue_delayed_work(rtwdev->hw,
522 &coex->wl_remain_work,
526 if (stats->tx_throughput > stats->rx_throughput)
527 coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
529 coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
531 if (scan || link || reason == COEX_RSN_2GCONSTART ||
532 reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
533 coex_stat->wl_linkscan_proc = true;
535 coex_stat->wl_linkscan_proc = false;
537 rtw_coex_wl_noisy_detect(rtwdev);
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,
545 coex_dm->wl_rssi_state[i] = rssi_state;
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);
552 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
555 case COEX_RSN_5GSCANSTART:
556 case COEX_RSN_5GSWITCHBAND:
557 case COEX_RSN_5GCONSTART:
561 case COEX_RSN_2GSCANSTART:
562 case COEX_RSN_2GSWITCHBAND:
563 case COEX_RSN_2GCONSTART:
568 if (rtwdev->hal.current_band_type == RTW_BAND_5G)
575 coex->under_5g = is_5G;
578 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
580 struct rtw_c2h_cmd *c2h;
583 pkt_offset = *((u32 *)resp->cb);
584 c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
589 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
591 struct rtw_coex *coex = &rtwdev->coex;
592 u8 *payload = get_payload_from_coex_resp(skb);
594 if (payload[0] != COEX_RESP_ACK_BY_WL_FW) {
595 dev_kfree_skb_any(skb);
599 skb_queue_tail(&coex->queue, skb);
600 wake_up(&coex->wait);
603 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
604 struct rtw_coex_info_req *req)
606 struct rtw_coex *coex = &rtwdev->coex;
607 struct sk_buff *skb_resp = NULL;
609 mutex_lock(&coex->mutex);
611 rtw_fw_query_bt_mp_info(rtwdev, req);
613 if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
614 COEX_REQUEST_TIMEOUT)) {
615 rtw_err(rtwdev, "coex request time out\n");
619 skb_resp = skb_dequeue(&coex->queue);
621 rtw_err(rtwdev, "failed to get coex info response\n");
626 mutex_unlock(&coex->mutex);
630 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
632 struct rtw_coex_info_req req = {0};
636 req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
637 skb = rtw_coex_info_request(rtwdev, &req);
641 payload = get_payload_from_coex_resp(skb);
642 *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
643 dev_kfree_skb_any(skb);
647 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
648 u8 lna_constrain_level)
650 struct rtw_coex_info_req req = {0};
653 req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
654 req.para1 = lna_constrain_level;
655 skb = rtw_coex_info_request(rtwdev, &req);
659 dev_kfree_skb_any(skb);
663 #define case_BTSTATUS(src) \
664 case COEX_BTSTATUS_##src: return #src
666 static const char *rtw_coex_get_bt_status_string(u8 bt_status)
669 case_BTSTATUS(NCON_IDLE);
670 case_BTSTATUS(CON_IDLE);
671 case_BTSTATUS(INQ_PAGE);
672 case_BTSTATUS(ACL_BUSY);
673 case_BTSTATUS(SCO_BUSY);
674 case_BTSTATUS(ACL_SCO_BUSY);
680 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
682 struct rtw_coex *coex = &rtwdev->coex;
683 struct rtw_coex_stat *coex_stat = &coex->stat;
684 struct rtw_coex_dm *coex_dm = &coex->dm;
685 struct rtw_chip_info *chip = rtwdev->chip;
691 /* update wl/bt rssi by btinfo */
692 for (i = 0; i < COEX_RSSI_STEP; i++) {
693 rssi_state = coex_dm->bt_rssi_state[i];
694 rssi_step = chip->bt_rssi_step[i];
695 rssi = coex_stat->bt_rssi;
696 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi,
698 coex_dm->bt_rssi_state[i] = rssi_state;
701 if (coex_stat->bt_ble_scan_en &&
702 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
705 if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
706 coex_stat->bt_ble_scan_type = scan_type;
707 if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
708 coex_stat->bt_init_scan = true;
710 coex_stat->bt_init_scan = false;
714 coex_stat->bt_profile_num = 0;
716 /* set link exist status */
717 if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
718 coex_stat->bt_link_exist = false;
719 coex_stat->bt_pan_exist = false;
720 coex_stat->bt_a2dp_exist = false;
721 coex_stat->bt_hid_exist = false;
722 coex_stat->bt_hfp_exist = false;
724 /* connection exists */
725 coex_stat->bt_link_exist = true;
726 if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
727 coex_stat->bt_pan_exist = true;
728 coex_stat->bt_profile_num++;
730 coex_stat->bt_pan_exist = false;
733 if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
734 coex_stat->bt_a2dp_exist = true;
735 coex_stat->bt_profile_num++;
737 coex_stat->bt_a2dp_exist = false;
740 if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
741 coex_stat->bt_hid_exist = true;
742 coex_stat->bt_profile_num++;
744 coex_stat->bt_hid_exist = false;
747 if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
748 coex_stat->bt_hfp_exist = true;
749 coex_stat->bt_profile_num++;
751 coex_stat->bt_hfp_exist = false;
755 if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
756 coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
757 } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
758 coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
759 coex_stat->bt_multi_link_remain = false;
760 } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
761 coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
762 } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
763 (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
764 if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
765 coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
767 coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
768 } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
769 coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
771 coex_dm->bt_status = COEX_BTSTATUS_MAX;
774 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
776 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__,
777 rtw_coex_get_bt_status_string(coex_dm->bt_status));
780 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
782 struct rtw_chip_info *chip = rtwdev->chip;
783 struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
789 bw = rtwdev->hal.current_band_width;
791 if (type != COEX_MEDIA_DISCONNECT)
792 center_chan = rtwdev->hal.current_channel;
794 if (center_chan == 0) {
798 } else if (center_chan <= 14) {
801 if (bw == RTW_CHANNEL_WIDTH_40)
802 bw = chip->bt_afh_span_bw40;
804 bw = chip->bt_afh_span_bw20;
805 } else if (chip->afh_5g_num > 1) {
806 for (i = 0; i < chip->afh_5g_num; i++) {
807 if (center_chan == chip->afh_5g[i].wl_5g_ch) {
809 center_chan = chip->afh_5g[i].bt_skip_ch;
810 bw = chip->afh_5g[i].bt_skip_span;
816 coex_dm->wl_ch_info[0] = link;
817 coex_dm->wl_ch_info[1] = center_chan;
818 coex_dm->wl_ch_info[2] = bw;
820 rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
821 rtw_dbg(rtwdev, RTW_DBG_COEX,
822 "[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link,
826 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
828 struct rtw_coex *coex = &rtwdev->coex;
829 struct rtw_coex_dm *coex_dm = &coex->dm;
831 if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
834 coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
836 rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
839 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
841 struct rtw_coex *coex = &rtwdev->coex;
842 struct rtw_coex_dm *coex_dm = &coex->dm;
844 if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
847 coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
849 /* notify BT rx gain table changed */
850 if (bt_lna_lvl < 7) {
851 rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
852 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
854 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
856 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n",
857 __func__, bt_lna_lvl);
860 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
861 struct coex_rf_para para)
863 struct rtw_coex *coex = &rtwdev->coex;
864 struct rtw_coex_stat *coex_stat = &coex->stat;
867 if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
870 rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
871 rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
872 rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
873 rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
876 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
880 if (!ltecoex_read_reg(rtwdev, addr, &val)) {
881 rtw_err(rtwdev, "failed to read indirect register\n");
887 EXPORT_SYMBOL(rtw_coex_read_indirect_reg);
889 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
892 u32 shift = __ffs(mask);
895 tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
896 tmp = (tmp & (~mask)) | ((val << shift) & mask);
898 if (!ltecoex_reg_write(rtwdev, addr, tmp))
899 rtw_err(rtwdev, "failed to write indirect register\n");
901 EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
903 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
905 struct rtw_chip_info *chip = rtwdev->chip;
906 const struct rtw_hw_reg *btg_reg = chip->btg_reg;
909 rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3,
910 BIT_LTE_MUX_CTRL_PATH >> 24);
912 rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
914 rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3,
915 BIT_LTE_MUX_CTRL_PATH >> 24);
917 rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
921 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
923 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);
924 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);
927 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
929 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);
930 rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
933 static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,
936 struct rtw_chip_info *chip = rtwdev->chip;
937 struct rtw_efuse *efuse = &rtwdev->efuse;
938 u8 h2c_para[6] = {0};
939 u32 table_wl = 0x5a5a5a5a;
941 h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A;
945 if (efuse->share_ant) {
946 if (table_case < chip->table_sant_num)
947 table_wl = chip->table_sant[table_case].wl;
949 if (table_case < chip->table_nsant_num)
950 table_wl = chip->table_nsant[table_case].wl;
953 /* tell WL FW WL slot toggle table-A*/
954 h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0));
955 h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8));
956 h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16));
957 h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24));
959 rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]);
961 rtw_dbg(rtwdev, RTW_DBG_COEX,
962 "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
963 __func__, h2c_para[0], h2c_para[1], h2c_para[2],
964 h2c_para[3], h2c_para[4], h2c_para[5]);
967 #define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa
968 static void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force,
969 u8 interval, u32 table)
971 struct rtw_coex *coex = &rtwdev->coex;
972 struct rtw_coex_stat *coex_stat = &coex->stat;
973 u8 cur_h2c_para[6] = {0};
976 cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B;
977 cur_h2c_para[1] = interval;
978 cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0));
979 cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8));
980 cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16));
981 cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24));
983 coex_stat->wl_toggle_interval = interval;
985 for (i = 0; i <= 5; i++)
986 coex_stat->wl_toggle_para[i] = cur_h2c_para[i];
988 rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]);
990 rtw_dbg(rtwdev, RTW_DBG_COEX,
991 "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
992 __func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2],
993 cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]);
996 static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,
999 #define DEF_BRK_TABLE_VAL 0xf0ffffff
1000 struct rtw_coex *coex = &rtwdev->coex;
1001 struct rtw_coex_dm *coex_dm = &coex->dm;
1003 /* If last tdma is wl slot toggle, force write table*/
1004 if (!force && coex_dm->reason != COEX_RSN_LPS) {
1005 if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) &&
1006 table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1))
1009 rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
1010 rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
1011 rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
1013 rtw_dbg(rtwdev, RTW_DBG_COEX,
1014 "[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0,
1018 static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)
1020 struct rtw_coex *coex = &rtwdev->coex;
1021 struct rtw_coex_dm *coex_dm = &coex->dm;
1022 struct rtw_chip_info *chip = rtwdev->chip;
1023 struct rtw_efuse *efuse = &rtwdev->efuse;
1024 struct rtw_coex_stat *coex_stat = &coex->stat;
1026 coex_dm->cur_table = type;
1028 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type);
1030 if (efuse->share_ant) {
1031 if (type < chip->table_sant_num)
1032 rtw_coex_set_table(rtwdev, force,
1033 chip->table_sant[type].bt,
1034 chip->table_sant[type].wl);
1037 if (type < chip->table_nsant_num)
1038 rtw_coex_set_table(rtwdev, force,
1039 chip->table_nsant[type].bt,
1040 chip->table_nsant[type].wl);
1042 if (coex_stat->wl_slot_toggle_change)
1043 rtw_btc_wltoggle_table_a(rtwdev, true, type);
1046 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
1048 struct rtw_coex *coex = &rtwdev->coex;
1050 if (coex->manual_control || coex->stop_dm)
1053 rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
1056 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
1057 u8 lps_val, u8 rpwm_val)
1059 struct rtw_coex *coex = &rtwdev->coex;
1060 struct rtw_coex_stat *coex_stat = &coex->stat;
1063 lps_mode = rtwdev->lps_conf.mode;
1066 case COEX_PS_WIFI_NATIVE:
1067 /* recover to original 32k low power setting */
1068 coex_stat->wl_force_lps_ctrl = false;
1069 rtw_dbg(rtwdev, RTW_DBG_COEX,
1070 "[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__);
1071 rtw_leave_lps(rtwdev);
1073 case COEX_PS_LPS_OFF:
1074 coex_stat->wl_force_lps_ctrl = true;
1076 rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0);
1078 rtw_leave_lps(rtwdev);
1079 rtw_dbg(rtwdev, RTW_DBG_COEX,
1080 "[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__);
1087 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
1088 u8 byte3, u8 byte4, u8 byte5)
1090 struct rtw_coex *coex = &rtwdev->coex;
1091 struct rtw_coex_dm *coex_dm = &coex->dm;
1092 struct rtw_chip_info *chip = rtwdev->chip;
1093 struct rtw_coex_stat *coex_stat = &coex->stat;
1094 u8 ps_type = COEX_PS_WIFI_NATIVE;
1095 bool ap_enable = false;
1097 if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
1098 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n",
1107 ps_type = COEX_PS_WIFI_NATIVE;
1108 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1109 } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
1110 rtw_dbg(rtwdev, RTW_DBG_COEX,
1111 "[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__,
1114 if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
1115 ps_type = COEX_PS_LPS_OFF;
1117 ps_type = COEX_PS_LPS_ON;
1118 rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
1120 rtw_dbg(rtwdev, RTW_DBG_COEX,
1121 "[BTCoex], %s(): native power save (byte1 = 0x%x)\n",
1124 ps_type = COEX_PS_WIFI_NATIVE;
1125 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1128 coex_dm->ps_tdma_para[0] = byte1;
1129 coex_dm->ps_tdma_para[1] = byte2;
1130 coex_dm->ps_tdma_para[2] = byte3;
1131 coex_dm->ps_tdma_para[3] = byte4;
1132 coex_dm->ps_tdma_para[4] = byte5;
1134 rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
1136 if (byte1 & BIT(2)) {
1137 coex_stat->wl_slot_toggle = true;
1138 coex_stat->wl_slot_toggle_change = false;
1140 coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle;
1141 coex_stat->wl_slot_toggle = false;
1145 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
1147 struct rtw_coex *coex = &rtwdev->coex;
1148 struct rtw_coex_dm *coex_dm = &coex->dm;
1149 struct rtw_coex_stat *coex_stat = &coex->stat;
1150 struct rtw_chip_info *chip = rtwdev->chip;
1151 struct rtw_efuse *efuse = &rtwdev->efuse;
1154 bool wl_busy = false;
1156 if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */
1157 rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT);
1159 rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT);
1161 type = (u8)(tcase & 0xff);
1163 turn_on = (type == 0 || type == 100) ? false : true;
1165 if (!force && turn_on == coex_dm->cur_ps_tdma_on &&
1166 type == coex_dm->cur_ps_tdma) {
1167 rtw_dbg(rtwdev, RTW_DBG_COEX,
1168 "[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n",
1169 (coex_dm->cur_ps_tdma_on ? "on" : "off"),
1170 coex_dm->cur_ps_tdma);
1174 wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
1176 if ((coex_stat->bt_a2dp_exist &&
1177 (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||
1179 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
1181 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
1183 /* update pre state */
1184 coex_dm->cur_ps_tdma_on = turn_on;
1185 coex_dm->cur_ps_tdma = type;
1187 if (efuse->share_ant) {
1188 if (type < chip->tdma_sant_num)
1189 rtw_coex_set_tdma(rtwdev,
1190 chip->tdma_sant[type].para[0],
1191 chip->tdma_sant[type].para[1],
1192 chip->tdma_sant[type].para[2],
1193 chip->tdma_sant[type].para[3],
1194 chip->tdma_sant[type].para[4]);
1197 if (n < chip->tdma_nsant_num)
1198 rtw_coex_set_tdma(rtwdev,
1199 chip->tdma_nsant[n].para[0],
1200 chip->tdma_nsant[n].para[1],
1201 chip->tdma_nsant[n].para[2],
1202 chip->tdma_nsant[n].para[3],
1203 chip->tdma_nsant[n].para[4]);
1207 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n",
1208 turn_on ? "on" : "off", type);
1211 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
1213 struct rtw_coex *coex = &rtwdev->coex;
1214 struct rtw_coex_stat *coex_stat = &coex->stat;
1215 struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1216 struct rtw_coex_dm *coex_dm = &coex->dm;
1217 u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
1218 u8 pos_type = COEX_SWITCH_TO_MAX;
1220 if (!force && coex_dm->cur_ant_pos_type == phase)
1223 coex_dm->cur_ant_pos_type = phase;
1225 /* avoid switch coex_ctrl_owner during BT IQK */
1226 rtw_coex_check_rfk(rtwdev);
1228 rtw_dbg(rtwdev, RTW_DBG_COEX,
1229 "[BTCoex], coex_stat->bt_disabled = 0x%x\n",
1230 coex_stat->bt_disabled);
1233 case COEX_SET_ANT_POWERON:
1234 rtw_dbg(rtwdev, RTW_DBG_COEX,
1235 "[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__);
1236 /* set path control owner to BT at power-on */
1237 if (coex_stat->bt_disabled)
1238 rtw_coex_coex_ctrl_owner(rtwdev, true);
1240 rtw_coex_coex_ctrl_owner(rtwdev, false);
1242 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1243 pos_type = COEX_SWITCH_TO_BT;
1245 case COEX_SET_ANT_INIT:
1246 rtw_dbg(rtwdev, RTW_DBG_COEX,
1247 "[BTCoex], %s() - PHASE_COEX_INIT\n", __func__);
1248 if (coex_stat->bt_disabled) {
1249 /* set GNT_BT to SW low */
1250 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1252 /* set GNT_WL to SW high */
1253 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1255 /* set GNT_BT to SW high */
1256 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1258 /* set GNT_WL to SW low */
1259 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
1262 /* set path control owner to wl at initial step */
1263 rtw_coex_coex_ctrl_owner(rtwdev, true);
1265 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1266 pos_type = COEX_SWITCH_TO_BT;
1268 case COEX_SET_ANT_WONLY:
1269 rtw_dbg(rtwdev, RTW_DBG_COEX,
1270 "[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__);
1271 /* set GNT_BT to SW Low */
1272 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1274 /* set GNT_WL to SW high */
1275 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1277 /* set path control owner to wl at initial step */
1278 rtw_coex_coex_ctrl_owner(rtwdev, true);
1280 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1281 pos_type = COEX_SWITCH_TO_WLG;
1283 case COEX_SET_ANT_WOFF:
1284 rtw_dbg(rtwdev, RTW_DBG_COEX,
1285 "[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__);
1286 /* set path control owner to BT */
1287 rtw_coex_coex_ctrl_owner(rtwdev, false);
1289 ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1290 pos_type = COEX_SWITCH_TO_NOCARE;
1292 case COEX_SET_ANT_2G:
1293 rtw_dbg(rtwdev, RTW_DBG_COEX,
1294 "[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__);
1295 /* set GNT_BT to PTA */
1296 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1298 /* set GNT_WL to PTA */
1299 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1301 /* set path control owner to wl at runtime step */
1302 rtw_coex_coex_ctrl_owner(rtwdev, true);
1304 ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1305 pos_type = COEX_SWITCH_TO_NOCARE;
1307 case COEX_SET_ANT_5G:
1308 rtw_dbg(rtwdev, RTW_DBG_COEX,
1309 "[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__);
1311 /* set GNT_BT to HW PTA */
1312 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1314 /* set GNT_WL to SW high */
1315 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1317 /* set path control owner to wl at runtime step */
1318 rtw_coex_coex_ctrl_owner(rtwdev, true);
1320 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1321 pos_type = COEX_SWITCH_TO_WLA;
1323 case COEX_SET_ANT_2G_FREERUN:
1324 rtw_dbg(rtwdev, RTW_DBG_COEX,
1325 "[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__);
1327 /* set GNT_BT to HW PTA */
1328 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1330 /* Set GNT_WL to SW high */
1331 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1333 /* set path control owner to wl at runtime step */
1334 rtw_coex_coex_ctrl_owner(rtwdev, true);
1336 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1337 pos_type = COEX_SWITCH_TO_WLG_BT;
1339 case COEX_SET_ANT_2G_WLBT:
1340 rtw_dbg(rtwdev, RTW_DBG_COEX,
1341 "[BTCoex], %s() - PHASE_2G_WLBT\n", __func__);
1342 /* set GNT_BT to HW PTA */
1343 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1345 /* Set GNT_WL to HW PTA */
1346 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1348 /* set path control owner to wl at runtime step */
1349 rtw_coex_coex_ctrl_owner(rtwdev, true);
1351 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1352 pos_type = COEX_SWITCH_TO_WLG_BT;
1355 WARN(1, "unknown phase when setting antenna path\n");
1359 if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX &&
1360 coex_rfe->ant_switch_exist)
1361 rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1364 #define case_ALGO(src) \
1365 case COEX_ALGO_##src: return #src
1367 static const char *rtw_coex_get_algo_string(u8 algo)
1370 case_ALGO(NOPROFILE);
1375 case_ALGO(A2DP_HID);
1376 case_ALGO(A2DP_PAN);
1378 case_ALGO(A2DP_PAN_HID);
1384 #define case_BT_PROFILE(src) \
1385 case BPM_##src: return #src
1387 static const char *rtw_coex_get_bt_profile_string(u8 bt_profile)
1389 switch (bt_profile) {
1390 case_BT_PROFILE(NOPROFILE);
1391 case_BT_PROFILE(HFP);
1392 case_BT_PROFILE(HID);
1393 case_BT_PROFILE(A2DP);
1394 case_BT_PROFILE(PAN);
1395 case_BT_PROFILE(HID_HFP);
1396 case_BT_PROFILE(A2DP_HFP);
1397 case_BT_PROFILE(A2DP_HID);
1398 case_BT_PROFILE(A2DP_HID_HFP);
1399 case_BT_PROFILE(PAN_HFP);
1400 case_BT_PROFILE(PAN_HID);
1401 case_BT_PROFILE(PAN_HID_HFP);
1402 case_BT_PROFILE(PAN_A2DP);
1403 case_BT_PROFILE(PAN_A2DP_HFP);
1404 case_BT_PROFILE(PAN_A2DP_HID);
1405 case_BT_PROFILE(PAN_A2DP_HID_HFP);
1411 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1413 struct rtw_coex *coex = &rtwdev->coex;
1414 struct rtw_coex_stat *coex_stat = &coex->stat;
1415 u8 algorithm = COEX_ALGO_NOPROFILE;
1418 if (coex_stat->bt_hfp_exist)
1419 profile_map |= BPM_HFP;
1420 if (coex_stat->bt_hid_exist)
1421 profile_map |= BPM_HID;
1422 if (coex_stat->bt_a2dp_exist)
1423 profile_map |= BPM_A2DP;
1424 if (coex_stat->bt_pan_exist)
1425 profile_map |= BPM_PAN;
1427 switch (profile_map) {
1429 algorithm = COEX_ALGO_HFP;
1432 case BPM_HFP + BPM_HID:
1433 algorithm = COEX_ALGO_HID;
1435 case BPM_HFP + BPM_A2DP:
1436 case BPM_HID + BPM_A2DP:
1437 case BPM_HFP + BPM_HID + BPM_A2DP:
1438 algorithm = COEX_ALGO_A2DP_HID;
1440 case BPM_HFP + BPM_PAN:
1441 case BPM_HID + BPM_PAN:
1442 case BPM_HFP + BPM_HID + BPM_PAN:
1443 algorithm = COEX_ALGO_PAN_HID;
1445 case BPM_HFP + BPM_A2DP + BPM_PAN:
1446 case BPM_HID + BPM_A2DP + BPM_PAN:
1447 case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
1448 algorithm = COEX_ALGO_A2DP_PAN_HID;
1451 algorithm = COEX_ALGO_PAN;
1453 case BPM_A2DP + BPM_PAN:
1454 algorithm = COEX_ALGO_A2DP_PAN;
1457 if (coex_stat->bt_multi_link) {
1458 if (coex_stat->bt_hid_pair_num > 0)
1459 algorithm = COEX_ALGO_A2DP_HID;
1461 algorithm = COEX_ALGO_A2DP_PAN;
1463 algorithm = COEX_ALGO_A2DP;
1467 algorithm = COEX_ALGO_NOPROFILE;
1471 rtw_dbg(rtwdev, RTW_DBG_COEX,
1472 "[BTCoex], BT Profile = %s => Algorithm = %s\n",
1473 rtw_coex_get_bt_profile_string(profile_map),
1474 rtw_coex_get_algo_string(algorithm));
1478 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1480 struct rtw_efuse *efuse = &rtwdev->efuse;
1481 struct rtw_chip_info *chip = rtwdev->chip;
1482 u8 table_case, tdma_case;
1484 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1485 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1487 if (efuse->share_ant) {
1492 /* Non-Shared-Ant */
1497 rtw_coex_table(rtwdev, false, table_case);
1498 rtw_coex_tdma(rtwdev, false, tdma_case);
1501 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1503 struct rtw_coex *coex = &rtwdev->coex;
1504 struct rtw_coex_stat *coex_stat = &coex->stat;
1505 struct rtw_coex_dm *coex_dm = &coex->dm;
1506 struct rtw_efuse *efuse = &rtwdev->efuse;
1507 struct rtw_chip_info *chip = rtwdev->chip;
1509 bool bt_afh_loss = true;
1511 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1513 if (efuse->share_ant)
1516 coex->freerun = true;
1519 rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1521 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1523 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1525 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1527 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1529 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1534 if (level > chip->wl_rf_para_num - 1)
1535 level = chip->wl_rf_para_num - 1;
1537 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1538 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1540 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1542 rtw_coex_table(rtwdev, false, 100);
1543 rtw_coex_tdma(rtwdev, false, 100);
1546 static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
1548 struct rtw_efuse *efuse = &rtwdev->efuse;
1549 struct rtw_chip_info *chip = rtwdev->chip;
1550 u8 table_case, tdma_case;
1552 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1554 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1555 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1557 if (efuse->share_ant) {
1562 /* Non-Shared-Ant */
1567 rtw_coex_table(rtwdev, false, table_case);
1568 rtw_coex_tdma(rtwdev, false, tdma_case);
1571 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1573 struct rtw_efuse *efuse = &rtwdev->efuse;
1574 struct rtw_chip_info *chip = rtwdev->chip;
1575 u8 table_case, tdma_case;
1577 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1579 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1580 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1582 if (efuse->share_ant) {
1587 /* Non-Shared-Ant */
1592 rtw_coex_table(rtwdev, false, table_case);
1593 rtw_coex_tdma(rtwdev, false, tdma_case);
1596 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1598 struct rtw_coex *coex = &rtwdev->coex;
1599 struct rtw_coex_stat *coex_stat = &coex->stat;
1600 struct rtw_efuse *efuse = &rtwdev->efuse;
1601 struct rtw_chip_info *chip = rtwdev->chip;
1602 u8 table_case, tdma_case;
1605 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1607 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1608 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1610 if (efuse->share_ant) { /* Shared-Ant */
1611 if (coex_stat->wl_gl_busy) {
1613 if (coex_stat->bt_hid_exist &&
1614 coex_stat->bt_profile_num == 1) {
1615 slot_type = TDMA_4SLOT;
1624 } else { /* Non-Shared-Ant */
1625 if (coex_stat->wl_gl_busy)
1632 rtw_coex_table(rtwdev, false, table_case);
1633 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1636 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1638 struct rtw_coex *coex = &rtwdev->coex;
1639 struct rtw_coex_stat *coex_stat = &coex->stat;
1640 struct rtw_coex_dm *coex_dm = &coex->dm;
1641 struct rtw_efuse *efuse = &rtwdev->efuse;
1642 struct rtw_chip_info *chip = rtwdev->chip;
1643 struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1644 u8 table_case = 0xff, tdma_case = 0xff;
1646 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1647 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1649 if (coex_rfe->ant_switch_with_bt &&
1650 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1651 if (efuse->share_ant &&
1652 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1653 coex_stat->wl_gl_busy) {
1656 } else if (!efuse->share_ant) {
1662 if (table_case != 0xff && tdma_case != 0xff) {
1663 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1667 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1669 if (efuse->share_ant) {
1671 if (!coex_stat->wl_gl_busy) {
1674 } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1677 if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250)
1686 /* Non-Shared-Ant */
1687 if (!coex_stat->wl_gl_busy) {
1690 } else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1691 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1701 rtw_coex_table(rtwdev, false, table_case);
1702 rtw_coex_tdma(rtwdev, false, tdma_case);
1705 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1707 struct rtw_coex *coex = &rtwdev->coex;
1708 struct rtw_coex_stat *coex_stat = &coex->stat;
1709 struct rtw_efuse *efuse = &rtwdev->efuse;
1710 struct rtw_chip_info *chip = rtwdev->chip;
1711 bool wl_hi_pri = false;
1712 u8 table_case, tdma_case;
1715 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1716 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1717 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1719 if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1720 coex_stat->wl_hi_pri_task2)
1723 if (efuse->share_ant) {
1726 rtw_dbg(rtwdev, RTW_DBG_COEX,
1727 "[BTCoex], bt inq/page + wifi hi-pri task\n");
1730 if (coex_stat->bt_profile_num > 0)
1732 else if (coex_stat->wl_hi_pri_task1)
1734 else if (!coex_stat->bt_page)
1738 } else if (coex_stat->wl_gl_busy) {
1739 rtw_dbg(rtwdev, RTW_DBG_COEX,
1740 "[BTCoex], bt inq/page + wifi busy\n");
1741 if (coex_stat->bt_profile_num == 0) {
1744 } else if (coex_stat->bt_profile_num == 1 &&
1745 !coex_stat->bt_a2dp_exist) {
1746 slot_type = TDMA_4SLOT;
1750 slot_type = TDMA_4SLOT;
1754 } else if (coex_stat->wl_connected) {
1755 rtw_dbg(rtwdev, RTW_DBG_COEX,
1756 "[BTCoex], bt inq/page + wifi connected\n");
1760 rtw_dbg(rtwdev, RTW_DBG_COEX,
1761 "[BTCoex], bt inq/page + wifi not-connected\n");
1766 /* Non_Shared-Ant */
1768 rtw_dbg(rtwdev, RTW_DBG_COEX,
1769 "[BTCoex], bt inq/page + wifi hi-pri task\n");
1772 if (coex_stat->bt_profile_num > 0)
1774 else if (coex_stat->wl_hi_pri_task1)
1776 else if (!coex_stat->bt_page)
1780 } else if (coex_stat->wl_gl_busy) {
1781 rtw_dbg(rtwdev, RTW_DBG_COEX,
1782 "[BTCoex], bt inq/page + wifi busy\n");
1785 } else if (coex_stat->wl_connected) {
1786 rtw_dbg(rtwdev, RTW_DBG_COEX,
1787 "[BTCoex], bt inq/page + wifi connected\n");
1791 rtw_dbg(rtwdev, RTW_DBG_COEX,
1792 "[BTCoex], bt inq/page + wifi not-connected\n");
1798 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n",
1799 wl_hi_pri, coex_stat->bt_page);
1801 rtw_coex_table(rtwdev, false, table_case);
1802 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1805 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1807 struct rtw_coex *coex = &rtwdev->coex;
1808 struct rtw_coex_stat *coex_stat = &coex->stat;
1809 struct rtw_efuse *efuse = &rtwdev->efuse;
1810 struct rtw_chip_info *chip = rtwdev->chip;
1811 u8 table_case, tdma_case;
1813 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1814 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1815 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1817 if (efuse->share_ant) {
1819 if (coex_stat->bt_multi_link) {
1827 /* Non-Shared-Ant */
1828 if (coex_stat->bt_multi_link) {
1837 rtw_coex_table(rtwdev, false, table_case);
1838 rtw_coex_tdma(rtwdev, false, tdma_case);
1841 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1843 struct rtw_coex *coex = &rtwdev->coex;
1844 struct rtw_coex_stat *coex_stat = &coex->stat;
1845 struct rtw_efuse *efuse = &rtwdev->efuse;
1846 struct rtw_chip_info *chip = rtwdev->chip;
1847 u8 table_case, tdma_case;
1849 bool bt_multi_link_remain = false, is_toggle_table = false;
1851 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1852 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1853 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1855 if (efuse->share_ant) {
1857 if (coex_stat->bt_ble_exist) {
1859 if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
1868 if (coex_stat->bt_profile_num == 1 &&
1869 (coex_stat->bt_multi_link ||
1870 (coex_stat->lo_pri_rx +
1871 coex_stat->lo_pri_tx > 360) ||
1872 coex_stat->bt_slave ||
1873 bt_multi_link_remain)) {
1874 slot_type = TDMA_4SLOT;
1877 } else if (coex_stat->bt_a2dp_active) {
1880 } else if (coex_stat->bt_418_hid_exist &&
1881 coex_stat->wl_gl_busy) {
1882 is_toggle_table = true;
1883 slot_type = TDMA_4SLOT;
1886 } else if (coex_stat->bt_ble_hid_exist &&
1887 coex_stat->wl_gl_busy) {
1896 /* Non-Shared-Ant */
1897 if (coex_stat->bt_ble_exist) {
1899 if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
1906 } else if (coex_stat->bt_a2dp_active) {
1915 rtw_coex_table(rtwdev, false, table_case);
1916 if (is_toggle_table) {
1917 rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
1918 rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE);
1921 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1924 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
1926 struct rtw_coex *coex = &rtwdev->coex;
1927 struct rtw_coex_stat *coex_stat = &coex->stat;
1928 struct rtw_coex_dm *coex_dm = &coex->dm;
1929 struct rtw_efuse *efuse = &rtwdev->efuse;
1930 struct rtw_chip_info *chip = rtwdev->chip;
1931 u8 table_case, tdma_case;
1934 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1936 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1937 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1939 slot_type = TDMA_4SLOT;
1941 if (efuse->share_ant) {
1943 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1948 if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy)
1953 /* Non-Shared-Ant */
1956 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1962 rtw_coex_table(rtwdev, false, table_case);
1963 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1966 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
1968 struct rtw_coex *coex = &rtwdev->coex;
1969 struct rtw_coex_stat *coex_stat = &coex->stat;
1970 struct rtw_efuse *efuse = &rtwdev->efuse;
1971 struct rtw_chip_info *chip = rtwdev->chip;
1972 u8 table_case, tdma_case;
1973 bool ap_enable = false;
1975 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1977 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1978 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1980 if (efuse->share_ant) { /* Shared-Ant */
1984 } else if (coex_stat->wl_gl_busy) {
1991 } else { /* Non-Shared-Ant */
2001 rtw_coex_table(rtwdev, false, table_case);
2002 rtw_coex_tdma(rtwdev, false, tdma_case);
2005 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
2007 struct rtw_coex *coex = &rtwdev->coex;
2008 struct rtw_coex_stat *coex_stat = &coex->stat;
2009 struct rtw_efuse *efuse = &rtwdev->efuse;
2010 struct rtw_chip_info *chip = rtwdev->chip;
2011 u8 table_case, tdma_case;
2013 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2014 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2015 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2017 if (efuse->share_ant) {
2019 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
2024 if (coex_stat->wl_gl_busy)
2029 /* Non-Shared-Ant */
2032 if (coex_stat->wl_gl_busy)
2038 rtw_coex_table(rtwdev, false, table_case);
2039 rtw_coex_tdma(rtwdev, false, tdma_case);
2042 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
2044 struct rtw_coex *coex = &rtwdev->coex;
2045 struct rtw_coex_stat *coex_stat = &coex->stat;
2046 struct rtw_coex_dm *coex_dm = &coex->dm;
2047 struct rtw_efuse *efuse = &rtwdev->efuse;
2048 struct rtw_chip_info *chip = rtwdev->chip;
2049 u8 table_case, tdma_case, interval = 0;
2051 bool is_toggle_table = false;
2053 slot_type = TDMA_4SLOT;
2055 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2056 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2057 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2059 if (efuse->share_ant) {
2061 if (coex_stat->bt_ble_exist) {
2062 table_case = 26; /* for RCU */
2063 } else if (coex_stat->bt_418_hid_exist) {
2070 if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) {
2072 } else if (coex_stat->bt_418_hid_exist) {
2073 is_toggle_table = true;
2079 /* Non-Shared-Ant */
2080 if (coex_stat->bt_ble_exist)
2085 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
2091 rtw_coex_table(rtwdev, false, table_case);
2092 if (is_toggle_table) {
2093 rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
2094 rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE);
2096 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2099 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
2101 struct rtw_coex *coex = &rtwdev->coex;
2102 struct rtw_coex_stat *coex_stat = &coex->stat;
2103 struct rtw_efuse *efuse = &rtwdev->efuse;
2104 struct rtw_chip_info *chip = rtwdev->chip;
2105 u8 table_case, tdma_case;
2106 bool wl_cpt_test = false, bt_cpt_test = false;
2108 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2110 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2111 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2112 if (efuse->share_ant) {
2115 if (coex_stat->wl_gl_busy) {
2122 } else if (bt_cpt_test) {
2126 if (coex_stat->wl_gl_busy &&
2127 coex_stat->wl_noisy_level == 0)
2132 if (coex_stat->wl_gl_busy)
2138 /* Non-Shared-Ant */
2141 if (coex_stat->wl_gl_busy)
2148 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[1]);
2150 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2152 rtw_coex_table(rtwdev, false, table_case);
2153 rtw_coex_tdma(rtwdev, false, tdma_case);
2156 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
2158 struct rtw_coex *coex = &rtwdev->coex;
2159 struct rtw_coex_stat *coex_stat = &coex->stat;
2160 struct rtw_efuse *efuse = &rtwdev->efuse;
2161 struct rtw_chip_info *chip = rtwdev->chip;
2162 u8 table_case, tdma_case;
2164 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2166 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2167 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2169 if (efuse->share_ant) {
2173 if (coex_stat->wl_gl_busy)
2178 /* Non-Shared-Ant */
2181 if (coex_stat->wl_gl_busy)
2187 rtw_coex_table(rtwdev, false, table_case);
2188 rtw_coex_tdma(rtwdev, false, tdma_case);
2191 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
2193 struct rtw_coex *coex = &rtwdev->coex;
2194 struct rtw_coex_stat *coex_stat = &coex->stat;
2195 struct rtw_efuse *efuse = &rtwdev->efuse;
2196 struct rtw_chip_info *chip = rtwdev->chip;
2197 u8 table_case, tdma_case;
2199 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2200 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2201 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2203 if (efuse->share_ant) {
2207 if (coex_stat->wl_gl_busy)
2212 /* Non-Shared-Ant */
2215 if (coex_stat->wl_gl_busy)
2221 rtw_coex_table(rtwdev, false, table_case);
2222 rtw_coex_tdma(rtwdev, false, tdma_case);
2225 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
2227 struct rtw_efuse *efuse = &rtwdev->efuse;
2228 struct rtw_chip_info *chip = rtwdev->chip;
2229 u8 table_case, tdma_case;
2231 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2233 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2234 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2236 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
2238 if (efuse->share_ant) {
2243 /* Non-Shared-Ant */
2248 rtw_coex_table(rtwdev, false, table_case);
2249 rtw_coex_tdma(rtwdev, false, tdma_case);
2252 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
2254 struct rtw_efuse *efuse = &rtwdev->efuse;
2255 struct rtw_chip_info *chip = rtwdev->chip;
2256 u8 table_case, tdma_case;
2258 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2259 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2260 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2262 if (efuse->share_ant) {
2267 /* Non-Shared-Ant */
2272 rtw_coex_table(rtwdev, false, table_case);
2273 rtw_coex_tdma(rtwdev, false, tdma_case);
2276 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
2278 struct rtw_coex *coex = &rtwdev->coex;
2279 struct rtw_efuse *efuse = &rtwdev->efuse;
2280 struct rtw_chip_info *chip = rtwdev->chip;
2281 u8 table_case, tdma_case;
2286 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2288 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2289 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2291 if (efuse->share_ant) {
2296 /* Non-Shared-Ant */
2301 rtw_coex_table(rtwdev, false, table_case);
2302 rtw_coex_tdma(rtwdev, false, tdma_case);
2305 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
2307 struct rtw_coex *coex = &rtwdev->coex;
2308 struct rtw_coex_stat *coex_stat = &coex->stat;
2309 struct rtw_efuse *efuse = &rtwdev->efuse;
2310 struct rtw_chip_info *chip = rtwdev->chip;
2311 u8 table_case, tdma_case;
2314 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2315 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2316 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2318 if (efuse->share_ant) { /* Shared-Ant */
2319 if (coex_stat->bt_a2dp_exist) {
2320 slot_type = TDMA_4SLOT;
2322 if (coex_stat->wl_gl_busy)
2330 } else { /* Non-Shared-Ant */
2331 if (coex_stat->bt_a2dp_exist) {
2332 slot_type = TDMA_4SLOT;
2341 rtw_coex_table(rtwdev, false, table_case);
2342 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2345 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
2347 struct rtw_efuse *efuse = &rtwdev->efuse;
2348 struct rtw_chip_info *chip = rtwdev->chip;
2349 u8 table_case, tdma_case;
2351 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2352 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2353 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2355 if (efuse->share_ant) {
2360 /* Non-Shared-Ant */
2365 rtw_coex_table(rtwdev, false, table_case);
2366 rtw_coex_tdma(rtwdev, false, tdma_case);
2369 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
2371 struct rtw_coex *coex = &rtwdev->coex;
2372 struct rtw_coex_stat *coex_stat = &coex->stat;
2375 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2377 algorithm = rtw_coex_algorithm(rtwdev);
2379 switch (algorithm) {
2381 rtw_coex_action_bt_hfp(rtwdev);
2384 if (rtw_coex_freerun_check(rtwdev))
2385 rtw_coex_action_freerun(rtwdev);
2387 rtw_coex_action_bt_hid(rtwdev);
2389 case COEX_ALGO_A2DP:
2390 if (rtw_coex_freerun_check(rtwdev))
2391 rtw_coex_action_freerun(rtwdev);
2392 else if (coex_stat->bt_a2dp_sink)
2393 rtw_coex_action_bt_a2dpsink(rtwdev);
2395 rtw_coex_action_bt_a2dp(rtwdev);
2398 rtw_coex_action_bt_pan(rtwdev);
2400 case COEX_ALGO_A2DP_HID:
2401 if (rtw_coex_freerun_check(rtwdev))
2402 rtw_coex_action_freerun(rtwdev);
2404 rtw_coex_action_bt_a2dp_hid(rtwdev);
2406 case COEX_ALGO_A2DP_PAN:
2407 rtw_coex_action_bt_a2dp_pan(rtwdev);
2409 case COEX_ALGO_PAN_HID:
2410 rtw_coex_action_bt_pan_hid(rtwdev);
2412 case COEX_ALGO_A2DP_PAN_HID:
2413 rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
2416 case COEX_ALGO_NOPROFILE:
2417 rtw_coex_action_bt_idle(rtwdev);
2422 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
2424 struct rtw_coex *coex = &rtwdev->coex;
2425 struct rtw_coex_dm *coex_dm = &coex->dm;
2426 struct rtw_coex_stat *coex_stat = &coex->stat;
2427 bool rf4ce_en = false;
2429 lockdep_assert_held(&rtwdev->mutex);
2431 if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
2434 coex_dm->reason = reason;
2436 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__,
2439 /* update wifi_link_info_ext variable */
2440 rtw_coex_update_wl_link_info(rtwdev, reason);
2442 rtw_coex_monitor_bt_enable(rtwdev);
2444 if (coex->manual_control) {
2445 rtw_dbg(rtwdev, RTW_DBG_COEX,
2446 "[BTCoex], return for Manual CTRL!!\n");
2450 if (coex->stop_dm) {
2451 rtw_dbg(rtwdev, RTW_DBG_COEX,
2452 "[BTCoex], return for Stop Coex DM!!\n");
2456 if (coex_stat->wl_under_ips) {
2457 rtw_dbg(rtwdev, RTW_DBG_COEX,
2458 "[BTCoex], return for wifi is under IPS!!\n");
2462 if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
2463 !coex_stat->bt_setup_link) {
2464 rtw_dbg(rtwdev, RTW_DBG_COEX,
2465 "[BTCoex], return for coex_freeze!!\n");
2469 coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
2470 coex->freerun = false;
2472 /* Pure-5G Coex Process */
2473 if (coex->under_5g) {
2474 coex_stat->wl_coex_mode = COEX_WLINK_5G;
2475 rtw_coex_action_wl_under5g(rtwdev);
2479 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n");
2480 coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
2482 if (coex_stat->bt_disabled) {
2483 if (coex_stat->wl_connected && rf4ce_en)
2484 rtw_coex_action_rf4ce(rtwdev);
2485 else if (!coex_stat->wl_connected)
2486 rtw_coex_action_wl_not_connected(rtwdev);
2488 rtw_coex_action_wl_only(rtwdev);
2492 if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
2493 rtw_coex_action_wl_native_lps(rtwdev);
2497 if (coex_stat->bt_whck_test) {
2498 rtw_coex_action_bt_whql_test(rtwdev);
2502 if (coex_stat->bt_setup_link) {
2503 rtw_coex_action_bt_relink(rtwdev);
2507 if (coex_stat->bt_inq_page) {
2508 rtw_coex_action_bt_inquiry(rtwdev);
2512 if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
2513 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
2514 coex_stat->wl_connected) {
2515 rtw_coex_action_bt_idle(rtwdev);
2519 if (coex_stat->wl_linkscan_proc && !coex->freerun) {
2520 rtw_coex_action_wl_linkscan(rtwdev);
2524 if (coex_stat->wl_connected) {
2525 rtw_coex_action_wl_connected(rtwdev);
2528 rtw_coex_action_wl_not_connected(rtwdev);
2533 rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode);
2534 rtw_coex_limited_wl(rtwdev);
2537 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
2539 struct rtw_coex *coex = &rtwdev->coex;
2540 struct rtw_coex_stat *coex_stat = &coex->stat;
2541 struct rtw_coex_dm *coex_dm = &coex->dm;
2544 memset(coex_dm, 0, sizeof(*coex_dm));
2545 memset(coex_stat, 0, sizeof(*coex_stat));
2547 for (i = 0; i < COEX_CNT_WL_MAX; i++)
2548 coex_stat->cnt_wl[i] = 0;
2550 for (i = 0; i < COEX_CNT_BT_MAX; i++)
2551 coex_stat->cnt_bt[i] = 0;
2553 for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2554 coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2556 for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2557 coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2559 coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2560 coex_stat->wl_rx_rate = DESC_RATE5_5M;
2561 coex_stat->wl_rts_rx_rate = DESC_RATE5_5M;
2564 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2566 struct rtw_coex *coex = &rtwdev->coex;
2567 struct rtw_coex_stat *coex_stat = &coex->stat;
2569 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2571 rtw_coex_init_coex_var(rtwdev);
2573 coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4));
2575 rtw_coex_monitor_bt_enable(rtwdev);
2576 rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend);
2578 rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
2580 rtw_coex_set_rfe_type(rtwdev);
2581 rtw_coex_set_init(rtwdev);
2583 /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2584 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2586 /* set Tx beacon = Hi-Pri */
2587 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2589 /* set Tx beacon queue = Hi-Pri */
2590 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2592 /* antenna config */
2593 if (coex->wl_rf_off) {
2594 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2595 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2596 coex->stop_dm = true;
2598 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n",
2600 } else if (wifi_only) {
2601 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2602 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2604 coex->stop_dm = true;
2606 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2607 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2609 coex->stop_dm = false;
2610 coex->freeze = true;
2614 rtw_coex_table(rtwdev, true, 1);
2615 rtw_coex_tdma(rtwdev, true, 0);
2616 rtw_coex_query_bt_info(rtwdev);
2619 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2621 struct rtw_coex *coex = &rtwdev->coex;
2624 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2626 coex->stop_dm = true;
2627 coex->wl_rf_off = false;
2629 /* enable BB, we can write 0x948 */
2630 rtw_write8_set(rtwdev, REG_SYS_FUNC_EN,
2631 BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB);
2633 rtw_coex_monitor_bt_enable(rtwdev);
2634 rtw_coex_set_rfe_type(rtwdev);
2636 /* set antenna path to BT */
2637 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2639 rtw_coex_table(rtwdev, true, table_case);
2641 rtw_write8(rtwdev, 0xff1a, 0x0);
2642 rtw_coex_set_gnt_debug(rtwdev);
2645 void rtw_coex_power_off_setting(struct rtw_dev *rtwdev)
2647 rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN);
2650 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2652 __rtw_coex_init_hw_config(rtwdev, wifi_only);
2655 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2657 struct rtw_coex *coex = &rtwdev->coex;
2658 struct rtw_coex_stat *coex_stat = &coex->stat;
2660 if (coex->manual_control || coex->stop_dm)
2663 if (type == COEX_IPS_ENTER) {
2664 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n");
2666 coex_stat->wl_under_ips = true;
2669 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2671 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2672 rtw_coex_action_coex_all_off(rtwdev);
2673 } else if (type == COEX_IPS_LEAVE) {
2674 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n");
2676 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2677 /* run init hw config (exclude wifi only) */
2678 __rtw_coex_init_hw_config(rtwdev, false);
2680 coex_stat->wl_under_ips = false;
2684 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2686 struct rtw_coex *coex = &rtwdev->coex;
2687 struct rtw_coex_stat *coex_stat = &coex->stat;
2689 if (coex->manual_control || coex->stop_dm)
2692 if (type == COEX_LPS_ENABLE) {
2693 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n");
2695 coex_stat->wl_under_lps = true;
2697 if (coex_stat->wl_force_lps_ctrl) {
2699 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2702 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2703 rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false);
2705 rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2707 } else if (type == COEX_LPS_DISABLE) {
2708 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n");
2710 coex_stat->wl_under_lps = false;
2713 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2715 if (!coex_stat->wl_force_lps_ctrl)
2716 rtw_coex_query_bt_info(rtwdev);
2718 rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2722 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2724 struct rtw_coex *coex = &rtwdev->coex;
2725 struct rtw_coex_stat *coex_stat = &coex->stat;
2727 if (coex->manual_control || coex->stop_dm)
2730 coex->freeze = false;
2731 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2733 if (type == COEX_SCAN_START_5G) {
2734 rtw_dbg(rtwdev, RTW_DBG_COEX,
2735 "[BTCoex], SCAN START notify (5G)\n");
2737 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2738 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2739 } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2740 rtw_dbg(rtwdev, RTW_DBG_COEX,
2741 "[BTCoex], SCAN START notify (2G)\n");
2743 coex_stat->wl_hi_pri_task2 = true;
2745 /* Force antenna setup for no scan result issue */
2746 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2747 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2749 coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */
2751 rtw_dbg(rtwdev, RTW_DBG_COEX,
2752 "[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n",
2753 coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]);
2755 coex_stat->wl_hi_pri_task2 = false;
2756 rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2760 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2762 struct rtw_coex *coex = &rtwdev->coex;
2764 if (coex->manual_control || coex->stop_dm)
2767 if (type == COEX_SWITCH_TO_5G) {
2768 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n",
2770 } else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) {
2771 rtw_dbg(rtwdev, RTW_DBG_COEX,
2772 "[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__);
2774 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n",
2778 if (type == COEX_SWITCH_TO_5G)
2779 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2780 else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2781 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2783 rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2786 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2788 struct rtw_coex *coex = &rtwdev->coex;
2789 struct rtw_coex_stat *coex_stat = &coex->stat;
2791 if (coex->manual_control || coex->stop_dm)
2794 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2796 if (type == COEX_ASSOCIATE_5G_START) {
2797 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n",
2800 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2801 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2802 } else if (type == COEX_ASSOCIATE_5G_FINISH) {
2803 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n",
2806 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2807 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2808 } else if (type == COEX_ASSOCIATE_START) {
2809 coex_stat->wl_hi_pri_task1 = true;
2810 coex_stat->wl_connecting = true;
2811 coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2812 coex_stat->wl_connecting = true;
2813 ieee80211_queue_delayed_work(rtwdev->hw,
2814 &coex->wl_connecting_work, 2 * HZ);
2816 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n",
2818 /* Force antenna setup for no scan result issue */
2819 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2821 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2823 /* To keep TDMA case during connect process,
2824 * to avoid changed by Btinfo and runcoexmechanism
2826 coex->freeze = true;
2827 ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2830 coex_stat->wl_hi_pri_task1 = false;
2831 coex->freeze = false;
2832 coex_stat->wl_connecting = false;
2834 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n",
2836 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2840 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2842 struct rtw_coex *coex = &rtwdev->coex;
2843 struct rtw_coex_stat *coex_stat = &coex->stat;
2845 if (coex->manual_control || coex->stop_dm)
2848 if (type == COEX_MEDIA_CONNECT_5G) {
2849 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__);
2851 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2853 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2854 rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2855 } else if (type == COEX_MEDIA_CONNECT) {
2856 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__);
2858 coex_stat->wl_connecting = false;
2860 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2862 /* Force antenna setup for no scan result issue */
2863 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2865 /* Set CCK Rx high Pri */
2866 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2867 rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2869 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n",
2871 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2872 rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2875 rtw_coex_update_wl_ch_info(rtwdev, type);
2878 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2880 struct rtw_coex *coex = &rtwdev->coex;
2881 struct rtw_coex_stat *coex_stat = &coex->stat;
2882 struct rtw_chip_info *chip = rtwdev->chip;
2883 struct rtw_coex_dm *coex_dm = &coex->dm;
2885 u8 i, rsp_source = 0, type;
2886 bool inq_page = false;
2888 rsp_source = buf[0] & 0xf;
2889 if (rsp_source >= COEX_BTINFO_SRC_MAX)
2891 coex_stat->cnt_bt_info_c2h[rsp_source]++;
2893 if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
2894 coex_stat->bt_iqk_state = buf[1];
2895 if (coex_stat->bt_iqk_state == 0)
2896 coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
2897 else if (coex_stat->bt_iqk_state == 2)
2898 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
2900 rtw_dbg(rtwdev, RTW_DBG_COEX,
2901 "[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n",
2907 if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
2908 rtw_dbg(rtwdev, RTW_DBG_COEX,
2909 "[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n",
2912 rtw_coex_monitor_bt_enable(rtwdev);
2913 if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
2914 coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
2915 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2920 if (rsp_source == COEX_BTINFO_SRC_H2C60) {
2921 rtw_dbg(rtwdev, RTW_DBG_COEX,
2922 "[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n",
2923 buf[1], buf[2], buf[3], buf[4], buf[5]);
2925 for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++)
2926 coex_dm->fw_tdma_para[i - 1] = buf[i];
2930 if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
2931 rtw_dbg(rtwdev, RTW_DBG_COEX,
2932 "[BTCoex], bt_info reply by WL FW\n");
2934 rtw_coex_update_bt_link_info(rtwdev);
2938 if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
2939 rsp_source == COEX_BTINFO_SRC_BT_ACT) {
2940 if (coex_stat->bt_disabled) {
2941 coex_stat->bt_disabled = false;
2942 coex_stat->bt_reenable = true;
2943 ieee80211_queue_delayed_work(rtwdev->hw,
2944 &coex->bt_reenable_work,
2946 rtw_dbg(rtwdev, RTW_DBG_COEX,
2947 "[BTCoex], BT enable detected by bt_info\n");
2951 if (length != COEX_BTINFO_LENGTH) {
2952 rtw_dbg(rtwdev, RTW_DBG_COEX,
2953 "[BTCoex], Bt_info length = %d invalid!!\n", length);
2958 rtw_dbg(rtwdev, RTW_DBG_COEX,
2959 "[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n",
2960 buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
2962 for (i = 0; i < COEX_BTINFO_LENGTH; i++)
2963 coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
2965 /* get the same info from bt, skip it */
2966 if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
2967 coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
2968 coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
2969 coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
2970 coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
2971 coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) {
2972 rtw_dbg(rtwdev, RTW_DBG_COEX,
2973 "[BTCoex], Return because Btinfo duplicate!!\n");
2977 coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
2978 coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
2979 coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
2980 coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
2981 coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
2982 coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
2984 /* 0xff means BT is under WHCK test */
2985 coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
2987 inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
2989 if (inq_page != coex_stat->bt_inq_page) {
2990 cancel_delayed_work_sync(&coex->bt_remain_work);
2991 coex_stat->bt_inq_page = inq_page;
2994 coex_stat->bt_inq_remain = true;
2996 ieee80211_queue_delayed_work(rtwdev->hw,
2997 &coex->bt_remain_work,
3000 coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
3001 if (chip->ble_hid_profile_support) {
3002 if (coex_stat->bt_info_lb2 & BIT(5)) {
3003 if (coex_stat->bt_info_hb1 & BIT(0)) {
3005 coex_stat->bt_ble_hid_exist = true;
3007 coex_stat->bt_ble_hid_exist = false;
3009 coex_stat->bt_ble_exist = false;
3010 } else if (coex_stat->bt_info_hb1 & BIT(0)) {
3012 coex_stat->bt_ble_hid_exist = false;
3013 coex_stat->bt_ble_exist = true;
3015 coex_stat->bt_ble_hid_exist = false;
3016 coex_stat->bt_ble_exist = false;
3019 if (coex_stat->bt_info_hb1 & BIT(0)) {
3020 if (coex_stat->bt_hid_slot == 1 &&
3021 coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx &&
3022 coex_stat->hi_pri_rx < 100) {
3023 coex_stat->bt_ble_hid_exist = true;
3024 coex_stat->bt_ble_exist = false;
3026 coex_stat->bt_ble_hid_exist = false;
3027 coex_stat->bt_ble_exist = true;
3030 coex_stat->bt_ble_hid_exist = false;
3031 coex_stat->bt_ble_exist = false;
3035 coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
3036 if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
3037 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
3039 coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
3040 coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
3041 if (coex_stat->bt_inq)
3042 coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
3044 coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
3045 if (coex_stat->bt_page)
3046 coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
3048 /* unit: % (value-100 to translate to unit: dBm in coex info) */
3049 if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
3050 coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
3052 if (coex_stat->bt_info_hb0 <= 127)
3053 coex_stat->bt_rssi = 100;
3054 else if (256 - coex_stat->bt_info_hb0 <= 100)
3055 coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
3057 coex_stat->bt_rssi = 0;
3060 if (coex_stat->bt_info_hb1 & BIT(1))
3061 coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
3063 if (coex_stat->bt_info_hb1 & BIT(2)) {
3064 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
3065 coex_stat->bt_setup_link = true;
3066 if (coex_stat->bt_reenable)
3067 bt_relink_time = 6 * HZ;
3069 bt_relink_time = 1 * HZ;
3071 ieee80211_queue_delayed_work(rtwdev->hw,
3072 &coex->bt_relink_work,
3075 rtw_dbg(rtwdev, RTW_DBG_COEX,
3076 "[BTCoex], Re-Link start in BT info!!\n");
3079 if (coex_stat->bt_info_hb1 & BIT(3))
3080 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
3082 coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
3083 coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
3084 if (coex_stat->bt_info_hb1 & BIT(6))
3085 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
3087 coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
3088 /* for multi_link = 0 but bt pkt remain exist */
3089 /* Use PS-TDMA to protect WL RX */
3090 if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) {
3091 coex_stat->bt_multi_link_remain = true;
3092 ieee80211_queue_delayed_work(rtwdev->hw,
3093 &coex->bt_multi_link_remain_work,
3096 coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link;
3098 /* resend wifi info to bt, it is reset and lost the info */
3099 if (coex_stat->bt_info_hb1 & BIT(1)) {
3100 rtw_dbg(rtwdev, RTW_DBG_COEX,
3101 "[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n");
3103 if (coex_stat->wl_connected)
3104 type = COEX_MEDIA_CONNECT;
3106 type = COEX_MEDIA_DISCONNECT;
3107 rtw_coex_update_wl_ch_info(rtwdev, type);
3110 /* if ignore_wlan_act && not set_up_link */
3111 if ((coex_stat->bt_info_hb1 & BIT(3)) &&
3112 (!(coex_stat->bt_info_hb1 & BIT(2)))) {
3113 rtw_dbg(rtwdev, RTW_DBG_COEX,
3114 "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
3115 rtw_coex_ignore_wlan_act(rtwdev, false);
3118 coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
3119 if (coex_stat->bt_info_hb2 & BIT(1))
3120 coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
3122 coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
3123 coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
3124 coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
3125 coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
3126 if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
3127 coex_stat->bt_418_hid_exist = true;
3128 else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1)
3129 coex_stat->bt_418_hid_exist = false;
3131 if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
3132 coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
3134 coex_stat->bt_a2dp_bitpool = 0;
3136 coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
3138 rtw_coex_update_bt_link_info(rtwdev);
3139 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
3142 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3144 struct rtw_coex *coex = &rtwdev->coex;
3145 struct rtw_coex_stat *coex_stat = &coex->stat;
3149 rtw_dbg(rtwdev, RTW_DBG_COEX,
3150 "[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n",
3152 if (WARN(length < 8, "invalid wl info c2h length\n"))
3158 for (i = 1; i < 8; i++) {
3159 val = coex_stat->wl_fw_dbg_info_pre[i];
3161 coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
3163 coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i];
3165 coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
3168 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
3169 rtw_coex_wl_ccklock_action(rtwdev);
3170 rtw_coex_wl_ccklock_detect(rtwdev);
3173 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type)
3175 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3178 void rtw_coex_bt_relink_work(struct work_struct *work)
3180 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3181 coex.bt_relink_work.work);
3182 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3184 mutex_lock(&rtwdev->mutex);
3185 coex_stat->bt_setup_link = false;
3186 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3187 mutex_unlock(&rtwdev->mutex);
3190 void rtw_coex_bt_reenable_work(struct work_struct *work)
3192 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3193 coex.bt_reenable_work.work);
3194 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3196 mutex_lock(&rtwdev->mutex);
3197 coex_stat->bt_reenable = false;
3198 mutex_unlock(&rtwdev->mutex);
3201 void rtw_coex_defreeze_work(struct work_struct *work)
3203 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3204 coex.defreeze_work.work);
3205 struct rtw_coex *coex = &rtwdev->coex;
3206 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3208 mutex_lock(&rtwdev->mutex);
3209 coex->freeze = false;
3210 coex_stat->wl_hi_pri_task1 = false;
3211 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3212 mutex_unlock(&rtwdev->mutex);
3215 void rtw_coex_wl_remain_work(struct work_struct *work)
3217 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3218 coex.wl_remain_work.work);
3219 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3221 mutex_lock(&rtwdev->mutex);
3222 coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
3223 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3224 mutex_unlock(&rtwdev->mutex);
3227 void rtw_coex_bt_remain_work(struct work_struct *work)
3229 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3230 coex.bt_remain_work.work);
3231 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3233 mutex_lock(&rtwdev->mutex);
3234 coex_stat->bt_inq_remain = coex_stat->bt_inq_page;
3235 rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
3236 mutex_unlock(&rtwdev->mutex);
3239 void rtw_coex_wl_connecting_work(struct work_struct *work)
3241 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3242 coex.wl_connecting_work.work);
3243 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3245 mutex_lock(&rtwdev->mutex);
3246 coex_stat->wl_connecting = false;
3247 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n");
3248 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3249 mutex_unlock(&rtwdev->mutex);
3252 void rtw_coex_bt_multi_link_remain_work(struct work_struct *work)
3254 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3255 coex.bt_multi_link_remain_work.work);
3256 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3258 mutex_lock(&rtwdev->mutex);
3259 coex_stat->bt_multi_link_remain = false;
3260 mutex_unlock(&rtwdev->mutex);
3263 void rtw_coex_wl_ccklock_work(struct work_struct *work)
3265 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3266 coex.wl_ccklock_work.work);
3267 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3269 mutex_lock(&rtwdev->mutex);
3270 coex_stat->wl_cck_lock = false;
3271 mutex_unlock(&rtwdev->mutex);
3274 #ifdef CONFIG_RTW88_DEBUGFS
3275 #define INFO_SIZE 80
3277 #define case_BTINFO(src) \
3278 case COEX_BTINFO_SRC_##src: return #src
3280 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
3282 switch (bt_info_src) {
3284 case_BTINFO(BT_RSP);
3285 case_BTINFO(BT_ACT);
3291 #define case_RSN(src) \
3292 case COEX_RSN_##src: return #src
3294 static const char *rtw_coex_get_reason_string(u8 reason)
3297 case_RSN(2GSCANSTART);
3298 case_RSN(5GSCANSTART);
3299 case_RSN(SCANFINISH);
3300 case_RSN(2GSWITCHBAND);
3301 case_RSN(5GSWITCHBAND);
3302 case_RSN(2GCONSTART);
3303 case_RSN(5GCONSTART);
3304 case_RSN(2GCONFINISH);
3305 case_RSN(5GCONFINISH);
3308 case_RSN(MEDIADISCON);
3317 static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
3320 struct rtw_chip_info *chip = rtwdev->chip;
3321 struct rtw_efuse *efuse = &rtwdev->efuse;
3326 bool share_ant = efuse->share_ant;
3329 n = chip->table_sant_num;
3331 n = chip->table_nsant_num;
3333 for (i = 0; i < n; i++) {
3335 load_bt_val = chip->table_sant[i].bt;
3336 load_wl_val = chip->table_sant[i].wl;
3338 load_bt_val = chip->table_nsant[i].bt;
3339 load_wl_val = chip->table_nsant[i].wl;
3342 if (wl_reg_6c0 == load_bt_val &&
3343 wl_reg_6c4 == load_wl_val) {
3354 static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)
3356 struct rtw_efuse *efuse = &rtwdev->efuse;
3357 struct rtw_chip_info *chip = rtwdev->chip;
3360 u8 load_cur_tab_val;
3362 bool share_ant = efuse->share_ant;
3365 n = chip->tdma_sant_num;
3367 n = chip->tdma_nsant_num;
3369 for (i = 0; i < n; i++) {
3371 for (j = 0; j < 5; j++) {
3373 load_cur_tab_val = chip->tdma_sant[i].para[j];
3375 load_cur_tab_val = chip->tdma_nsant[i].para[j];
3377 if (*(tdma_para + j) != load_cur_tab_val)
3392 static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
3393 const struct rtw_reg_domain *reg,
3394 char addr_info[], int n)
3396 const char *rf_prefix = "";
3397 const char *sep = n == 0 ? "" : "/ ";
3401 if (INFO_SIZE - n <= 0)
3404 switch (reg->domain) {
3405 case RTW_REG_DOMAIN_MAC32:
3408 case RTW_REG_DOMAIN_MAC16:
3411 case RTW_REG_DOMAIN_MAC8:
3414 case RTW_REG_DOMAIN_RF_A:
3415 case RTW_REG_DOMAIN_RF_B:
3423 ffs = __ffs(reg->mask);
3424 fls = __fls(reg->mask);
3426 if (ffs == 0 && fls == max_fls)
3427 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
3428 sep, rf_prefix, reg->addr);
3429 else if (ffs == fls)
3430 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
3431 sep, rf_prefix, reg->addr, ffs);
3433 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
3434 sep, rf_prefix, reg->addr, fls, ffs);
3437 static int rtw_coex_val_info(struct rtw_dev *rtwdev,
3438 const struct rtw_reg_domain *reg,
3439 char val_info[], int n)
3441 const char *sep = n == 0 ? "" : "/ ";
3444 if (INFO_SIZE - n <= 0)
3447 switch (reg->domain) {
3448 case RTW_REG_DOMAIN_MAC32:
3449 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3450 rtw_read32_mask(rtwdev, reg->addr, reg->mask));
3451 case RTW_REG_DOMAIN_MAC16:
3452 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3453 rtw_read16_mask(rtwdev, reg->addr, reg->mask));
3454 case RTW_REG_DOMAIN_MAC8:
3455 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3456 rtw_read8_mask(rtwdev, reg->addr, reg->mask));
3457 case RTW_REG_DOMAIN_RF_A:
3458 rf_path = RF_PATH_A;
3460 case RTW_REG_DOMAIN_RF_B:
3461 rf_path = RF_PATH_B;
3467 /* only RF go through here */
3468 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3469 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
3472 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
3474 struct rtw_chip_info *chip = rtwdev->chip;
3475 const struct rtw_reg_domain *reg;
3476 char addr_info[INFO_SIZE];
3478 char val_info[INFO_SIZE];
3482 for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
3483 reg = &chip->coex_info_hw_regs[i];
3485 n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
3486 n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
3488 if (reg->domain == RTW_REG_DOMAIN_NL) {
3489 seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3495 if (n_addr != 0 && n_val != 0)
3496 seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3499 static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
3500 u8 type, u16 addr, u16 *val)
3502 struct rtw_coex_info_req req = {0};
3503 struct sk_buff *skb;
3507 le_addr = cpu_to_le16(addr);
3508 req.op_code = BT_MP_INFO_OP_READ_REG;
3510 req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
3511 req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
3512 skb = rtw_coex_info_request(rtwdev, &req);
3518 payload = get_payload_from_coex_resp(skb);
3519 *val = GET_COEX_RESP_BT_REG_VAL(payload);
3520 dev_kfree_skb_any(skb);
3525 static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
3528 struct rtw_coex_info_req req = {0};
3529 struct sk_buff *skb;
3532 req.op_code = BT_MP_INFO_OP_PATCH_VER;
3533 skb = rtw_coex_info_request(rtwdev, &req);
3537 payload = get_payload_from_coex_resp(skb);
3538 *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
3539 dev_kfree_skb_any(skb);
3544 static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
3545 u32 *supported_version)
3547 struct rtw_coex_info_req req = {0};
3548 struct sk_buff *skb;
3551 req.op_code = BT_MP_INFO_OP_SUPP_VER;
3552 skb = rtw_coex_info_request(rtwdev, &req);
3556 payload = get_payload_from_coex_resp(skb);
3557 *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
3558 dev_kfree_skb_any(skb);
3563 static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
3564 u32 *supported_feature)
3566 struct rtw_coex_info_req req = {0};
3567 struct sk_buff *skb;
3570 req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
3571 skb = rtw_coex_info_request(rtwdev, &req);
3575 payload = get_payload_from_coex_resp(skb);
3576 *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
3577 dev_kfree_skb_any(skb);
3582 struct rtw_coex_sta_stat_iter_data {
3583 struct rtw_vif *rtwvif;
3584 struct seq_file *file;
3587 static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
3589 struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
3590 struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
3591 struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
3592 struct seq_file *m = sta_iter_data->file;
3593 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
3599 rssi = ewma_rssi_read(&si->avg_rssi);
3600 seq_printf(m, "\tPeer %3d\n", si->mac_id);
3601 seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
3602 seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
3605 struct rtw_coex_vif_stat_iter_data {
3606 struct rtw_dev *rtwdev;
3607 struct seq_file *file;
3610 static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
3611 struct ieee80211_vif *vif)
3613 struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
3614 struct rtw_coex_sta_stat_iter_data sta_iter_data;
3615 struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
3616 struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
3617 struct seq_file *m = vif_iter_data->file;
3618 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
3620 seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
3621 seq_printf(m, "\t%-32s = %d\n",
3622 "Beacon interval", bss_conf->beacon_int);
3623 seq_printf(m, "\t%-32s = %d\n",
3624 "Network Type", rtwvif->net_type);
3626 sta_iter_data.rtwvif = rtwvif;
3627 sta_iter_data.file = m;
3628 rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
3632 #define case_WLINK(src) \
3633 case COEX_WLINK_##src: return #src
3635 static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
3637 switch (coex_wl_link_mode) {
3638 case_WLINK(2G1PORT);
3645 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
3647 struct rtw_chip_info *chip = rtwdev->chip;
3648 struct rtw_dm_info *dm_info = &rtwdev->dm_info;
3649 struct rtw_coex *coex = &rtwdev->coex;
3650 struct rtw_coex_stat *coex_stat = &coex->stat;
3651 struct rtw_coex_dm *coex_dm = &coex->dm;
3652 struct rtw_hal *hal = &rtwdev->hal;
3653 struct rtw_efuse *efuse = &rtwdev->efuse;
3654 struct rtw_fw_state *fw = &rtwdev->fw;
3655 struct rtw_coex_vif_stat_iter_data vif_iter_data;
3656 u8 reason = coex_dm->reason;
3658 u16 score_board_WB, score_board_BW;
3659 u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
3660 u32 lte_coex, bt_coex;
3661 u32 bt_hi_pri, bt_lo_pri;
3664 score_board_BW = rtw_coex_read_scbd(rtwdev);
3665 score_board_WB = coex_stat->score_board;
3666 wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0);
3667 wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1);
3668 wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE);
3669 wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H);
3670 wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
3672 bt_hi_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);
3673 bt_lo_pri = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);
3674 rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,
3675 BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);
3677 coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, bt_hi_pri);
3678 coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, bt_hi_pri);
3680 coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, bt_lo_pri);
3681 coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, bt_lo_pri);
3683 sys_lte = rtw_read8(rtwdev, 0x73);
3684 lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
3685 bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
3687 if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
3688 rtw_coex_get_bt_supported_version(rtwdev,
3689 &coex_stat->bt_supported_version);
3690 rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
3691 rtw_coex_get_bt_supported_feature(rtwdev,
3692 &coex_stat->bt_supported_feature);
3693 rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
3694 rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
3696 if (coex_stat->patch_ver != 0)
3697 coex_stat->bt_mailbox_reply = true;
3700 rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
3701 seq_printf(m, "**********************************************\n");
3702 seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
3703 seq_printf(m, "**********************************************\n");
3705 if (coex->manual_control) {
3706 seq_puts(m, "============[Under Manual Control]============\n");
3707 seq_puts(m, "==========================================\n");
3709 } else if (coex->stop_dm) {
3710 seq_puts(m, "============[Coex is STOPPED]============\n");
3711 seq_puts(m, "==========================================\n");
3713 } else if (coex->freeze) {
3714 seq_puts(m, "============[coex_freeze]============\n");
3715 seq_puts(m, "==========================================\n");
3718 seq_printf(m, "%-40s = %s/ %d\n",
3720 efuse->share_ant ? "Shared" : "Non-Shared",
3722 seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
3723 "Coex Ver/ BT Dez/ BT Rpt",
3724 chip->coex_para_ver, chip->bt_desired_ver,
3725 coex_stat->bt_supported_version,
3726 coex_stat->bt_disabled ? "(BT disabled)" :
3727 coex_stat->bt_supported_version >= chip->bt_desired_ver ?
3728 "(Match)" : "(Mismatch)");
3729 seq_printf(m, "%-40s = %s/ %u/ %d\n",
3730 "Role/ RoleSwCnt/ IgnWL/ Feature",
3731 coex_stat->bt_slave ? "Slave" : "Master",
3732 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
3733 coex_dm->ignore_wl_act);
3734 seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n",
3735 "WL FW/ BT FW/ BT FW Desired/ KT",
3736 fw->version, fw->sub_version,
3737 coex_stat->patch_ver,
3738 chip->wl_fw_desired_ver, coex_stat->kt_ver + 65);
3739 seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
3741 coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
3742 coex_dm->wl_ch_info[2], hal->current_channel);
3744 rtw_debugfs_get_simple_phy_info(m);
3745 seq_printf(m, "**********************************************\n");
3746 seq_printf(m, "\t\tBT Status\n");
3747 seq_printf(m, "**********************************************\n");
3748 seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
3749 "BT status/ rssi/ retry/ pop",
3750 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
3751 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
3752 coex_stat->bt_rssi - 100,
3753 coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
3754 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
3755 seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
3757 coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
3758 "A2DP sink," : "A2DP,") : "",
3759 coex_stat->bt_hfp_exist ? "HFP," : "",
3760 coex_stat->bt_hid_exist ?
3761 (coex_stat->bt_ble_exist ? "HID(RCU)," :
3762 coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
3763 coex_stat->bt_ble_hid_exist ? "HID(BLE)" :
3765 coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
3766 "OPP," : "PAN," : "",
3767 coex_stat->bt_ble_voice ? "Voice," : "",
3768 coex_stat->bt_multi_link);
3769 seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
3770 "Reinit/ Relink/ IgnWl/ Feature",
3771 coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
3772 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
3773 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
3774 coex_stat->bt_supported_feature);
3775 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3776 "Page/ Inq/ iqk/ iqk fail",
3777 coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
3778 coex_stat->cnt_bt[COEX_CNT_BT_INQ],
3779 coex_stat->cnt_bt[COEX_CNT_BT_IQK],
3780 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
3781 seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
3782 "0xae/ 0xac/ score board (W->B)/ (B->W)",
3783 coex_stat->bt_reg_vendor_ae,
3784 coex_stat->bt_reg_vendor_ac,
3785 score_board_WB, score_board_BW);
3786 seq_printf(m, "%-40s = %u/%u, %u/%u\n",
3787 "Hi-Pri TX/RX, Lo-Pri TX/RX",
3788 coex_stat->hi_pri_tx, coex_stat->hi_pri_rx,
3789 coex_stat->lo_pri_tx, coex_stat->lo_pri_rx);
3790 for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
3791 seq_printf(m, "%-40s = %7ph\n",
3792 rtw_coex_get_bt_info_src_string(i),
3793 coex_stat->bt_info_c2h[i]);
3795 seq_printf(m, "**********************************************\n");
3796 seq_printf(m, "\t\tWiFi Status\n");
3797 seq_printf(m, "**********************************************\n");
3798 seq_printf(m, "%-40s = %d\n",
3799 "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
3800 seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
3802 coex_stat->wl_gl_busy,
3803 rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
3804 seq_printf(m, "%-40s = %u/ %u/ %u\n",
3805 "IPS/ Low Power/ PS mode",
3806 test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
3807 test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
3808 rtwdev->lps_conf.mode);
3810 vif_iter_data.rtwdev = rtwdev;
3811 vif_iter_data.file = m;
3812 rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
3814 if (coex->manual_control) {
3815 seq_printf(m, "**********************************************\n");
3816 seq_printf(m, "\t\tMechanism (Under Manual)\n");
3817 seq_printf(m, "**********************************************\n");
3818 seq_printf(m, "%-40s = %5ph (%d)\n",
3820 coex_dm->fw_tdma_para,
3821 rtw_coex_get_tdma_index(rtwdev,
3822 &coex_dm->fw_tdma_para[0]));
3824 seq_printf(m, "**********************************************\n");
3825 seq_printf(m, "\t\tMechanism\n");
3826 seq_printf(m, "**********************************************\n");
3827 seq_printf(m, "%-40s = %5ph (case-%d)\n",
3829 coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
3831 seq_printf(m, "%-40s = %s/ %s/ %d\n",
3832 "Coex Mode/Free Run/Timer base",
3833 rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode),
3834 coex->freerun ? "Yes" : "No",
3835 coex_stat->tdma_timer_base);
3836 seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n",
3837 "Table/ 0x6c0/ 0x6c4/ 0x6c8",
3839 rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4),
3840 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
3841 seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n",
3842 "0x778/ 0x6cc/ Run Count/ Reason",
3843 wl_reg_778, wl_reg_6cc,
3844 coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN],
3845 rtw_coex_get_reason_string(reason));
3846 seq_printf(m, "%-40s = %3ph\n",
3848 coex_dm->wl_ch_info);
3849 seq_printf(m, "%-40s = %s/ %d\n",
3850 "AntDiv/ BtCtrlLPS/ g_busy",
3851 coex_stat->wl_force_lps_ctrl ? "On" : "Off",
3852 coex_stat->wl_gl_busy);
3853 seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
3854 "Null All/ Retry/ Ack/ BT Empty/ BT Late",
3855 coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
3856 coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
3857 coex_stat->wl_fw_dbg_info[5]);
3858 seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
3859 "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
3860 coex_stat->wl_fw_dbg_info[6],
3861 coex_stat->wl_fw_dbg_info[7],
3862 coex_stat->wl_slot_extend ? "Yes" : "No",
3863 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
3864 seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n",
3865 "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl",
3866 coex_dm->cur_wl_pwr_lvl,
3867 coex_dm->cur_bt_pwr_lvl,
3868 coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off",
3869 coex_dm->cur_bt_lna_lvl);
3871 seq_printf(m, "**********************************************\n");
3872 seq_printf(m, "\t\tHW setting\n");
3873 seq_printf(m, "**********************************************\n");
3874 seq_printf(m, "%-40s = %s/ %s\n",
3875 "LTE Coex/ Path Owner",
3876 lte_coex & BIT(7) ? "ON" : "OFF",
3877 sys_lte & BIT(2) ? "WL" : "BT");
3878 seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
3879 "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
3880 lte_coex & BIT(12) ? "SW" : "HW",
3881 lte_coex & BIT(8) ? "SW" : "HW",
3882 lte_coex & BIT(14) ? "SW" : "HW",
3883 lte_coex & BIT(10) ? "SW" : "HW",
3884 sys_lte & BIT(3) ? "On" : "Off");
3885 seq_printf(m, "%-40s = %lu/ %lu\n",
3887 (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
3888 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3889 "CRC OK CCK/ OFDM/ HT/ VHT",
3890 dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
3891 dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
3892 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3893 "CRC ERR CCK/ OFDM/ HT/ VHT",
3894 dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
3895 dm_info->ht_err_cnt, dm_info->vht_err_cnt);
3896 seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
3897 "HiPr/ Locking/ Locked/ Noisy",
3898 coex_stat->wl_hi_pri_task1 ? "Y" : "N",
3899 coex_stat->wl_cck_lock ? "Y" : "N",
3900 coex_stat->wl_cck_lock_ever ? "Y" : "N",
3901 coex_stat->wl_noisy_level);
3903 rtw_coex_set_coexinfo_hw(rtwdev, m);
3904 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
3905 "EVM A/ EVM B/ SNR A/ SNR B",
3906 -dm_info->rx_evm_dbm[RF_PATH_A],
3907 -dm_info->rx_evm_dbm[RF_PATH_B],
3908 -dm_info->rx_snr[RF_PATH_A],
3909 -dm_info->rx_snr[RF_PATH_B]);
3910 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
3911 "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA",
3912 dm_info->cck_cca_cnt, dm_info->cck_fa_cnt,
3913 dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt);
3914 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac",
3915 dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
3916 dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
3917 seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac",
3918 dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
3919 dm_info->ht_err_cnt, dm_info->vht_err_cnt);
3922 #endif /* CONFIG_RTW88_DEBUGFS */