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
)
597 skb_queue_tail(&coex
->queue
, skb
);
598 wake_up(&coex
->wait
);
601 static struct sk_buff
*rtw_coex_info_request(struct rtw_dev
*rtwdev
,
602 struct rtw_coex_info_req
*req
)
604 struct rtw_coex
*coex
= &rtwdev
->coex
;
605 struct sk_buff
*skb_resp
= NULL
;
607 mutex_lock(&coex
->mutex
);
609 rtw_fw_query_bt_mp_info(rtwdev
, req
);
611 if (!wait_event_timeout(coex
->wait
, !skb_queue_empty(&coex
->queue
),
612 COEX_REQUEST_TIMEOUT
)) {
613 rtw_err(rtwdev
, "coex request time out\n");
617 skb_resp
= skb_dequeue(&coex
->queue
);
619 rtw_err(rtwdev
, "failed to get coex info response\n");
624 mutex_unlock(&coex
->mutex
);
628 static bool rtw_coex_get_bt_scan_type(struct rtw_dev
*rtwdev
, u8
*scan_type
)
630 struct rtw_coex_info_req req
= {0};
635 req
.op_code
= BT_MP_INFO_OP_SCAN_TYPE
;
636 skb
= rtw_coex_info_request(rtwdev
, &req
);
640 payload
= get_payload_from_coex_resp(skb
);
641 *scan_type
= GET_COEX_RESP_BT_SCAN_TYPE(payload
);
642 dev_kfree_skb_any(skb
);
649 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev
*rtwdev
,
650 u8 lna_constrain_level
)
652 struct rtw_coex_info_req req
= {0};
656 req
.op_code
= BT_MP_INFO_OP_LNA_CONSTRAINT
;
657 req
.para1
= lna_constrain_level
;
658 skb
= rtw_coex_info_request(rtwdev
, &req
);
662 dev_kfree_skb_any(skb
);
669 #define case_BTSTATUS(src) \
670 case COEX_BTSTATUS_##src: return #src
672 static const char *rtw_coex_get_bt_status_string(u8 bt_status
)
675 case_BTSTATUS(NCON_IDLE
);
676 case_BTSTATUS(CON_IDLE
);
677 case_BTSTATUS(INQ_PAGE
);
678 case_BTSTATUS(ACL_BUSY
);
679 case_BTSTATUS(SCO_BUSY
);
680 case_BTSTATUS(ACL_SCO_BUSY
);
686 static void rtw_coex_update_bt_link_info(struct rtw_dev
*rtwdev
)
688 struct rtw_coex
*coex
= &rtwdev
->coex
;
689 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
690 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
691 struct rtw_chip_info
*chip
= rtwdev
->chip
;
697 /* update wl/bt rssi by btinfo */
698 for (i
= 0; i
< COEX_RSSI_STEP
; i
++) {
699 rssi_state
= coex_dm
->bt_rssi_state
[i
];
700 rssi_step
= chip
->bt_rssi_step
[i
];
701 rssi
= coex_stat
->bt_rssi
;
702 rssi_state
= rtw_coex_next_rssi_state(rtwdev
, rssi_state
, rssi
,
704 coex_dm
->bt_rssi_state
[i
] = rssi_state
;
707 if (coex_stat
->bt_ble_scan_en
&&
708 coex_stat
->cnt_bt
[COEX_CNT_BT_INFOUPDATE
] % 3 == 0) {
711 if (rtw_coex_get_bt_scan_type(rtwdev
, &scan_type
)) {
712 coex_stat
->bt_ble_scan_type
= scan_type
;
713 if ((coex_stat
->bt_ble_scan_type
& 0x1) == 0x1)
714 coex_stat
->bt_init_scan
= true;
716 coex_stat
->bt_init_scan
= false;
720 coex_stat
->bt_profile_num
= 0;
722 /* set link exist status */
723 if (!(coex_stat
->bt_info_lb2
& COEX_INFO_CONNECTION
)) {
724 coex_stat
->bt_link_exist
= false;
725 coex_stat
->bt_pan_exist
= false;
726 coex_stat
->bt_a2dp_exist
= false;
727 coex_stat
->bt_hid_exist
= false;
728 coex_stat
->bt_hfp_exist
= false;
730 /* connection exists */
731 coex_stat
->bt_link_exist
= true;
732 if (coex_stat
->bt_info_lb2
& COEX_INFO_FTP
) {
733 coex_stat
->bt_pan_exist
= true;
734 coex_stat
->bt_profile_num
++;
736 coex_stat
->bt_pan_exist
= false;
739 if (coex_stat
->bt_info_lb2
& COEX_INFO_A2DP
) {
740 coex_stat
->bt_a2dp_exist
= true;
741 coex_stat
->bt_profile_num
++;
743 coex_stat
->bt_a2dp_exist
= false;
746 if (coex_stat
->bt_info_lb2
& COEX_INFO_HID
) {
747 coex_stat
->bt_hid_exist
= true;
748 coex_stat
->bt_profile_num
++;
750 coex_stat
->bt_hid_exist
= false;
753 if (coex_stat
->bt_info_lb2
& COEX_INFO_SCO_ESCO
) {
754 coex_stat
->bt_hfp_exist
= true;
755 coex_stat
->bt_profile_num
++;
757 coex_stat
->bt_hfp_exist
= false;
761 if (coex_stat
->bt_info_lb2
& COEX_INFO_INQ_PAGE
) {
762 coex_dm
->bt_status
= COEX_BTSTATUS_INQ_PAGE
;
763 } else if (!(coex_stat
->bt_info_lb2
& COEX_INFO_CONNECTION
)) {
764 coex_dm
->bt_status
= COEX_BTSTATUS_NCON_IDLE
;
765 coex_stat
->bt_multi_link_remain
= false;
766 } else if (coex_stat
->bt_info_lb2
== COEX_INFO_CONNECTION
) {
767 coex_dm
->bt_status
= COEX_BTSTATUS_CON_IDLE
;
768 } else if ((coex_stat
->bt_info_lb2
& COEX_INFO_SCO_ESCO
) ||
769 (coex_stat
->bt_info_lb2
& COEX_INFO_SCO_BUSY
)) {
770 if (coex_stat
->bt_info_lb2
& COEX_INFO_ACL_BUSY
)
771 coex_dm
->bt_status
= COEX_BTSTATUS_ACL_SCO_BUSY
;
773 coex_dm
->bt_status
= COEX_BTSTATUS_SCO_BUSY
;
774 } else if (coex_stat
->bt_info_lb2
& COEX_INFO_ACL_BUSY
) {
775 coex_dm
->bt_status
= COEX_BTSTATUS_ACL_BUSY
;
777 coex_dm
->bt_status
= COEX_BTSTATUS_MAX
;
780 coex_stat
->cnt_bt
[COEX_CNT_BT_INFOUPDATE
]++;
782 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(), %s!!!\n", __func__
,
783 rtw_coex_get_bt_status_string(coex_dm
->bt_status
));
786 static void rtw_coex_update_wl_ch_info(struct rtw_dev
*rtwdev
, u8 type
)
788 struct rtw_chip_info
*chip
= rtwdev
->chip
;
789 struct rtw_coex_dm
*coex_dm
= &rtwdev
->coex
.dm
;
790 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
796 bw
= rtwdev
->hal
.current_band_width
;
798 if (type
!= COEX_MEDIA_DISCONNECT
)
799 center_chan
= rtwdev
->hal
.current_channel
;
801 if (center_chan
== 0 || (efuse
->share_ant
&& center_chan
<= 14)) {
805 } else if (center_chan
<= 14) {
808 if (bw
== RTW_CHANNEL_WIDTH_40
)
809 bw
= chip
->bt_afh_span_bw40
;
811 bw
= chip
->bt_afh_span_bw20
;
812 } else if (chip
->afh_5g_num
> 1) {
813 for (i
= 0; i
< chip
->afh_5g_num
; i
++) {
814 if (center_chan
== chip
->afh_5g
[i
].wl_5g_ch
) {
816 center_chan
= chip
->afh_5g
[i
].bt_skip_ch
;
817 bw
= chip
->afh_5g
[i
].bt_skip_span
;
823 coex_dm
->wl_ch_info
[0] = link
;
824 coex_dm
->wl_ch_info
[1] = center_chan
;
825 coex_dm
->wl_ch_info
[2] = bw
;
827 rtw_fw_wl_ch_info(rtwdev
, link
, center_chan
, bw
);
828 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
829 "[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__
, link
,
833 static void rtw_coex_set_bt_tx_power(struct rtw_dev
*rtwdev
, u8 bt_pwr_dec_lvl
)
835 struct rtw_coex
*coex
= &rtwdev
->coex
;
836 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
838 if (bt_pwr_dec_lvl
== coex_dm
->cur_bt_pwr_lvl
)
841 coex_dm
->cur_bt_pwr_lvl
= bt_pwr_dec_lvl
;
843 rtw_fw_force_bt_tx_power(rtwdev
, bt_pwr_dec_lvl
);
846 static void rtw_coex_set_bt_rx_gain(struct rtw_dev
*rtwdev
, u8 bt_lna_lvl
)
848 struct rtw_coex
*coex
= &rtwdev
->coex
;
849 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
851 if (bt_lna_lvl
== coex_dm
->cur_bt_lna_lvl
)
854 coex_dm
->cur_bt_lna_lvl
= bt_lna_lvl
;
856 /* notify BT rx gain table changed */
857 if (bt_lna_lvl
< 7) {
858 rtw_coex_set_lna_constrain_level(rtwdev
, bt_lna_lvl
);
859 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_RXGAIN
, true);
861 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_RXGAIN
, false);
863 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): bt_rx_LNA_level = %d\n",
864 __func__
, bt_lna_lvl
);
867 static void rtw_coex_set_rf_para(struct rtw_dev
*rtwdev
,
868 struct coex_rf_para para
)
870 struct rtw_coex
*coex
= &rtwdev
->coex
;
871 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
874 if (coex
->freerun
&& coex_stat
->cnt_wl
[COEX_CNT_WL_SCANAP
] <= 5)
877 rtw_coex_set_wl_tx_power(rtwdev
, para
.wl_pwr_dec_lvl
);
878 rtw_coex_set_bt_tx_power(rtwdev
, para
.bt_pwr_dec_lvl
+ offset
);
879 rtw_coex_set_wl_rx_gain(rtwdev
, para
.wl_low_gain_en
);
880 rtw_coex_set_bt_rx_gain(rtwdev
, para
.bt_lna_lvl
);
883 u32
rtw_coex_read_indirect_reg(struct rtw_dev
*rtwdev
, u16 addr
)
887 if (!ltecoex_read_reg(rtwdev
, addr
, &val
)) {
888 rtw_err(rtwdev
, "failed to read indirect register\n");
894 EXPORT_SYMBOL(rtw_coex_read_indirect_reg
);
896 void rtw_coex_write_indirect_reg(struct rtw_dev
*rtwdev
, u16 addr
,
899 u32 shift
= __ffs(mask
);
902 tmp
= rtw_coex_read_indirect_reg(rtwdev
, addr
);
903 tmp
= (tmp
& (~mask
)) | ((val
<< shift
) & mask
);
905 if (!ltecoex_reg_write(rtwdev
, addr
, tmp
))
906 rtw_err(rtwdev
, "failed to write indirect register\n");
908 EXPORT_SYMBOL(rtw_coex_write_indirect_reg
);
910 static void rtw_coex_coex_ctrl_owner(struct rtw_dev
*rtwdev
, bool wifi_control
)
912 struct rtw_chip_info
*chip
= rtwdev
->chip
;
913 const struct rtw_hw_reg
*btg_reg
= chip
->btg_reg
;
916 rtw_write8_set(rtwdev
, REG_SYS_SDIO_CTRL
+ 3,
917 BIT_LTE_MUX_CTRL_PATH
>> 24);
919 rtw_write8_set(rtwdev
, btg_reg
->addr
, btg_reg
->mask
);
921 rtw_write8_clr(rtwdev
, REG_SYS_SDIO_CTRL
+ 3,
922 BIT_LTE_MUX_CTRL_PATH
>> 24);
924 rtw_write8_clr(rtwdev
, btg_reg
->addr
, btg_reg
->mask
);
928 static void rtw_coex_set_gnt_bt(struct rtw_dev
*rtwdev
, u8 state
)
930 rtw_coex_write_indirect_reg(rtwdev
, LTE_COEX_CTRL
, 0xc000, state
);
931 rtw_coex_write_indirect_reg(rtwdev
, LTE_COEX_CTRL
, 0x0c00, state
);
934 static void rtw_coex_set_gnt_wl(struct rtw_dev
*rtwdev
, u8 state
)
936 rtw_coex_write_indirect_reg(rtwdev
, LTE_COEX_CTRL
, 0x3000, state
);
937 rtw_coex_write_indirect_reg(rtwdev
, LTE_COEX_CTRL
, 0x0300, state
);
940 static void rtw_btc_wltoggle_table_a(struct rtw_dev
*rtwdev
, bool force
,
943 struct rtw_chip_info
*chip
= rtwdev
->chip
;
944 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
945 u8 h2c_para
[6] = {0};
946 u32 table_wl
= 0x5a5a5a5a;
948 h2c_para
[0] = COEX_H2C69_TOGGLE_TABLE_A
;
952 if (efuse
->share_ant
) {
953 if (table_case
< chip
->table_sant_num
)
954 table_wl
= chip
->table_sant
[table_case
].wl
;
956 if (table_case
< chip
->table_nsant_num
)
957 table_wl
= chip
->table_nsant
[table_case
].wl
;
960 /* tell WL FW WL slot toggle table-A*/
961 h2c_para
[2] = (u8
)u32_get_bits(table_wl
, GENMASK(7, 0));
962 h2c_para
[3] = (u8
)u32_get_bits(table_wl
, GENMASK(15, 8));
963 h2c_para
[4] = (u8
)u32_get_bits(table_wl
, GENMASK(23, 16));
964 h2c_para
[5] = (u8
)u32_get_bits(table_wl
, GENMASK(31, 24));
966 rtw_fw_bt_wifi_control(rtwdev
, h2c_para
[0], &h2c_para
[1]);
968 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
969 "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
970 __func__
, h2c_para
[0], h2c_para
[1], h2c_para
[2],
971 h2c_para
[3], h2c_para
[4], h2c_para
[5]);
974 #define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa
975 static void rtw_btc_wltoggle_table_b(struct rtw_dev
*rtwdev
, bool force
,
976 u8 interval
, u32 table
)
978 struct rtw_coex
*coex
= &rtwdev
->coex
;
979 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
980 u8 cur_h2c_para
[6] = {0};
983 cur_h2c_para
[0] = COEX_H2C69_TOGGLE_TABLE_B
;
984 cur_h2c_para
[1] = interval
;
985 cur_h2c_para
[2] = (u8
)u32_get_bits(table
, GENMASK(7, 0));
986 cur_h2c_para
[3] = (u8
)u32_get_bits(table
, GENMASK(15, 8));
987 cur_h2c_para
[4] = (u8
)u32_get_bits(table
, GENMASK(23, 16));
988 cur_h2c_para
[5] = (u8
)u32_get_bits(table
, GENMASK(31, 24));
990 coex_stat
->wl_toggle_interval
= interval
;
992 for (i
= 0; i
<= 5; i
++)
993 coex_stat
->wl_toggle_para
[i
] = cur_h2c_para
[i
];
995 rtw_fw_bt_wifi_control(rtwdev
, cur_h2c_para
[0], &cur_h2c_para
[1]);
997 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
998 "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
999 __func__
, cur_h2c_para
[0], cur_h2c_para
[1], cur_h2c_para
[2],
1000 cur_h2c_para
[3], cur_h2c_para
[4], cur_h2c_para
[5]);
1003 static void rtw_coex_set_table(struct rtw_dev
*rtwdev
, bool force
, u32 table0
,
1006 #define DEF_BRK_TABLE_VAL 0xf0ffffff
1007 struct rtw_coex
*coex
= &rtwdev
->coex
;
1008 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1010 /* If last tdma is wl slot toggle, force write table*/
1011 if (!force
&& coex_dm
->reason
!= COEX_RSN_LPS
) {
1012 if (table0
== rtw_read32(rtwdev
, REG_BT_COEX_TABLE0
) &&
1013 table1
== rtw_read32(rtwdev
, REG_BT_COEX_TABLE1
))
1016 rtw_write32(rtwdev
, REG_BT_COEX_TABLE0
, table0
);
1017 rtw_write32(rtwdev
, REG_BT_COEX_TABLE1
, table1
);
1018 rtw_write32(rtwdev
, REG_BT_COEX_BRK_TABLE
, DEF_BRK_TABLE_VAL
);
1020 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1021 "[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__
, table0
,
1025 static void rtw_coex_table(struct rtw_dev
*rtwdev
, bool force
, u8 type
)
1027 struct rtw_coex
*coex
= &rtwdev
->coex
;
1028 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1029 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1030 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1031 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1033 coex_dm
->cur_table
= type
;
1035 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], Coex_Table - %d\n", type
);
1037 if (efuse
->share_ant
) {
1038 if (type
< chip
->table_sant_num
)
1039 rtw_coex_set_table(rtwdev
, force
,
1040 chip
->table_sant
[type
].bt
,
1041 chip
->table_sant
[type
].wl
);
1044 if (type
< chip
->table_nsant_num
)
1045 rtw_coex_set_table(rtwdev
, force
,
1046 chip
->table_nsant
[type
].bt
,
1047 chip
->table_nsant
[type
].wl
);
1049 if (coex_stat
->wl_slot_toggle_change
)
1050 rtw_btc_wltoggle_table_a(rtwdev
, true, type
);
1053 static void rtw_coex_ignore_wlan_act(struct rtw_dev
*rtwdev
, bool enable
)
1055 struct rtw_coex
*coex
= &rtwdev
->coex
;
1057 if (coex
->manual_control
|| coex
->stop_dm
)
1060 rtw_fw_bt_ignore_wlan_action(rtwdev
, enable
);
1063 static void rtw_coex_power_save_state(struct rtw_dev
*rtwdev
, u8 ps_type
,
1064 u8 lps_val
, u8 rpwm_val
)
1066 struct rtw_coex
*coex
= &rtwdev
->coex
;
1067 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1070 lps_mode
= rtwdev
->lps_conf
.mode
;
1073 case COEX_PS_WIFI_NATIVE
:
1074 /* recover to original 32k low power setting */
1075 coex_stat
->wl_force_lps_ctrl
= false;
1076 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1077 "[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__
);
1078 rtw_leave_lps(rtwdev
);
1080 case COEX_PS_LPS_OFF
:
1081 coex_stat
->wl_force_lps_ctrl
= true;
1083 rtw_fw_coex_tdma_type(rtwdev
, 0, 0, 0, 0, 0);
1085 rtw_leave_lps(rtwdev
);
1086 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1087 "[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__
);
1094 static void rtw_coex_set_tdma(struct rtw_dev
*rtwdev
, u8 byte1
, u8 byte2
,
1095 u8 byte3
, u8 byte4
, u8 byte5
)
1097 struct rtw_coex
*coex
= &rtwdev
->coex
;
1098 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1099 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1100 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1101 u8 ps_type
= COEX_PS_WIFI_NATIVE
;
1102 bool ap_enable
= false;
1104 if (ap_enable
&& (byte1
& BIT(4) && !(byte1
& BIT(5)))) {
1105 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): AP mode\n",
1114 ps_type
= COEX_PS_WIFI_NATIVE
;
1115 rtw_coex_power_save_state(rtwdev
, ps_type
, 0x0, 0x0);
1116 } else if (byte1
& BIT(4) && !(byte1
& BIT(5))) {
1117 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1118 "[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__
,
1121 if (chip
->pstdma_type
== COEX_PSTDMA_FORCE_LPSOFF
)
1122 ps_type
= COEX_PS_LPS_OFF
;
1124 ps_type
= COEX_PS_LPS_ON
;
1125 rtw_coex_power_save_state(rtwdev
, ps_type
, 0x50, 0x4);
1127 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1128 "[BTCoex], %s(): native power save (byte1 = 0x%x)\n",
1131 ps_type
= COEX_PS_WIFI_NATIVE
;
1132 rtw_coex_power_save_state(rtwdev
, ps_type
, 0x0, 0x0);
1135 coex_dm
->ps_tdma_para
[0] = byte1
;
1136 coex_dm
->ps_tdma_para
[1] = byte2
;
1137 coex_dm
->ps_tdma_para
[2] = byte3
;
1138 coex_dm
->ps_tdma_para
[3] = byte4
;
1139 coex_dm
->ps_tdma_para
[4] = byte5
;
1141 rtw_fw_coex_tdma_type(rtwdev
, byte1
, byte2
, byte3
, byte4
, byte5
);
1143 if (byte1
& BIT(2)) {
1144 coex_stat
->wl_slot_toggle
= true;
1145 coex_stat
->wl_slot_toggle_change
= false;
1147 coex_stat
->wl_slot_toggle_change
= coex_stat
->wl_slot_toggle
;
1148 coex_stat
->wl_slot_toggle
= false;
1152 static void rtw_coex_tdma(struct rtw_dev
*rtwdev
, bool force
, u32 tcase
)
1154 struct rtw_coex
*coex
= &rtwdev
->coex
;
1155 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1156 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1157 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1158 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1161 bool wl_busy
= false;
1163 if (tcase
& TDMA_4SLOT
) /* 4-slot (50ms) mode */
1164 rtw_coex_tdma_timer_base(rtwdev
, TDMA_TIMER_TYPE_4SLOT
);
1166 rtw_coex_tdma_timer_base(rtwdev
, TDMA_TIMER_TYPE_2SLOT
);
1168 type
= (u8
)(tcase
& 0xff);
1170 turn_on
= (type
== 0 || type
== 100) ? false : true;
1172 if (!force
&& turn_on
== coex_dm
->cur_ps_tdma_on
&&
1173 type
== coex_dm
->cur_ps_tdma
) {
1174 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1175 "[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n",
1176 (coex_dm
->cur_ps_tdma_on
? "on" : "off"),
1177 coex_dm
->cur_ps_tdma
);
1181 wl_busy
= test_bit(RTW_FLAG_BUSY_TRAFFIC
, rtwdev
->flags
);
1183 if ((coex_stat
->bt_a2dp_exist
&&
1184 (coex_stat
->bt_inq_remain
|| coex_stat
->bt_multi_link
)) ||
1186 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_TDMA
, false);
1188 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_TDMA
, true);
1190 /* update pre state */
1191 coex_dm
->cur_ps_tdma_on
= turn_on
;
1192 coex_dm
->cur_ps_tdma
= type
;
1194 if (efuse
->share_ant
) {
1195 if (type
< chip
->tdma_sant_num
)
1196 rtw_coex_set_tdma(rtwdev
,
1197 chip
->tdma_sant
[type
].para
[0],
1198 chip
->tdma_sant
[type
].para
[1],
1199 chip
->tdma_sant
[type
].para
[2],
1200 chip
->tdma_sant
[type
].para
[3],
1201 chip
->tdma_sant
[type
].para
[4]);
1204 if (n
< chip
->tdma_nsant_num
)
1205 rtw_coex_set_tdma(rtwdev
,
1206 chip
->tdma_nsant
[n
].para
[0],
1207 chip
->tdma_nsant
[n
].para
[1],
1208 chip
->tdma_nsant
[n
].para
[2],
1209 chip
->tdma_nsant
[n
].para
[3],
1210 chip
->tdma_nsant
[n
].para
[4]);
1214 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], coex tdma type(%s, %d)\n",
1215 turn_on
? "on" : "off", type
);
1218 static void rtw_coex_set_ant_path(struct rtw_dev
*rtwdev
, bool force
, u8 phase
)
1220 struct rtw_coex
*coex
= &rtwdev
->coex
;
1221 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1222 struct rtw_coex_rfe
*coex_rfe
= &coex
->rfe
;
1223 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1224 u8 ctrl_type
= COEX_SWITCH_CTRL_MAX
;
1225 u8 pos_type
= COEX_SWITCH_TO_MAX
;
1227 if (!force
&& coex_dm
->cur_ant_pos_type
== phase
)
1230 coex_dm
->cur_ant_pos_type
= phase
;
1232 /* avoid switch coex_ctrl_owner during BT IQK */
1233 rtw_coex_check_rfk(rtwdev
);
1235 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1236 "[BTCoex], coex_stat->bt_disabled = 0x%x\n",
1237 coex_stat
->bt_disabled
);
1240 case COEX_SET_ANT_POWERON
:
1241 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1242 "[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__
);
1243 /* set path control owner to BT at power-on */
1244 if (coex_stat
->bt_disabled
)
1245 rtw_coex_coex_ctrl_owner(rtwdev
, true);
1247 rtw_coex_coex_ctrl_owner(rtwdev
, false);
1249 ctrl_type
= COEX_SWITCH_CTRL_BY_BBSW
;
1250 pos_type
= COEX_SWITCH_TO_BT
;
1252 case COEX_SET_ANT_INIT
:
1253 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1254 "[BTCoex], %s() - PHASE_COEX_INIT\n", __func__
);
1255 if (coex_stat
->bt_disabled
) {
1256 /* set GNT_BT to SW low */
1257 rtw_coex_set_gnt_bt(rtwdev
, COEX_GNT_SET_SW_LOW
);
1259 /* set GNT_WL to SW high */
1260 rtw_coex_set_gnt_wl(rtwdev
, COEX_GNT_SET_SW_HIGH
);
1262 /* set GNT_BT to SW high */
1263 rtw_coex_set_gnt_bt(rtwdev
, COEX_GNT_SET_SW_HIGH
);
1265 /* set GNT_WL to SW low */
1266 rtw_coex_set_gnt_wl(rtwdev
, COEX_GNT_SET_SW_LOW
);
1269 /* set path control owner to wl at initial step */
1270 rtw_coex_coex_ctrl_owner(rtwdev
, true);
1272 ctrl_type
= COEX_SWITCH_CTRL_BY_BBSW
;
1273 pos_type
= COEX_SWITCH_TO_BT
;
1275 case COEX_SET_ANT_WONLY
:
1276 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1277 "[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__
);
1278 /* set GNT_BT to SW Low */
1279 rtw_coex_set_gnt_bt(rtwdev
, COEX_GNT_SET_SW_LOW
);
1281 /* set GNT_WL to SW high */
1282 rtw_coex_set_gnt_wl(rtwdev
, COEX_GNT_SET_SW_HIGH
);
1284 /* set path control owner to wl at initial step */
1285 rtw_coex_coex_ctrl_owner(rtwdev
, true);
1287 ctrl_type
= COEX_SWITCH_CTRL_BY_BBSW
;
1288 pos_type
= COEX_SWITCH_TO_WLG
;
1290 case COEX_SET_ANT_WOFF
:
1291 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1292 "[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__
);
1293 /* set path control owner to BT */
1294 rtw_coex_coex_ctrl_owner(rtwdev
, false);
1296 ctrl_type
= COEX_SWITCH_CTRL_BY_BT
;
1297 pos_type
= COEX_SWITCH_TO_NOCARE
;
1299 case COEX_SET_ANT_2G
:
1300 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1301 "[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__
);
1302 /* set GNT_BT to PTA */
1303 rtw_coex_set_gnt_bt(rtwdev
, COEX_GNT_SET_HW_PTA
);
1305 /* set GNT_WL to PTA */
1306 rtw_coex_set_gnt_wl(rtwdev
, COEX_GNT_SET_HW_PTA
);
1308 /* set path control owner to wl at runtime step */
1309 rtw_coex_coex_ctrl_owner(rtwdev
, true);
1311 ctrl_type
= COEX_SWITCH_CTRL_BY_PTA
;
1312 pos_type
= COEX_SWITCH_TO_NOCARE
;
1314 case COEX_SET_ANT_5G
:
1315 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1316 "[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__
);
1318 /* set GNT_BT to HW PTA */
1319 rtw_coex_set_gnt_bt(rtwdev
, COEX_GNT_SET_HW_PTA
);
1321 /* set GNT_WL to SW high */
1322 rtw_coex_set_gnt_wl(rtwdev
, COEX_GNT_SET_SW_HIGH
);
1324 /* set path control owner to wl at runtime step */
1325 rtw_coex_coex_ctrl_owner(rtwdev
, true);
1327 ctrl_type
= COEX_SWITCH_CTRL_BY_BBSW
;
1328 pos_type
= COEX_SWITCH_TO_WLA
;
1330 case COEX_SET_ANT_2G_FREERUN
:
1331 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1332 "[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__
);
1334 /* set GNT_BT to HW PTA */
1335 rtw_coex_set_gnt_bt(rtwdev
, COEX_GNT_SET_HW_PTA
);
1337 /* Set GNT_WL to SW high */
1338 rtw_coex_set_gnt_wl(rtwdev
, COEX_GNT_SET_SW_HIGH
);
1340 /* set path control owner to wl at runtime step */
1341 rtw_coex_coex_ctrl_owner(rtwdev
, true);
1343 ctrl_type
= COEX_SWITCH_CTRL_BY_BBSW
;
1344 pos_type
= COEX_SWITCH_TO_WLG_BT
;
1346 case COEX_SET_ANT_2G_WLBT
:
1347 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1348 "[BTCoex], %s() - PHASE_2G_WLBT\n", __func__
);
1349 /* set GNT_BT to HW PTA */
1350 rtw_coex_set_gnt_bt(rtwdev
, COEX_GNT_SET_HW_PTA
);
1352 /* Set GNT_WL to HW PTA */
1353 rtw_coex_set_gnt_wl(rtwdev
, COEX_GNT_SET_HW_PTA
);
1355 /* set path control owner to wl at runtime step */
1356 rtw_coex_coex_ctrl_owner(rtwdev
, true);
1358 ctrl_type
= COEX_SWITCH_CTRL_BY_BBSW
;
1359 pos_type
= COEX_SWITCH_TO_WLG_BT
;
1362 WARN(1, "unknown phase when setting antenna path\n");
1366 if (ctrl_type
< COEX_SWITCH_CTRL_MAX
&& pos_type
< COEX_SWITCH_TO_MAX
&&
1367 coex_rfe
->ant_switch_exist
)
1368 rtw_coex_set_ant_switch(rtwdev
, ctrl_type
, pos_type
);
1371 #define case_ALGO(src) \
1372 case COEX_ALGO_##src: return #src
1374 static const char *rtw_coex_get_algo_string(u8 algo
)
1377 case_ALGO(NOPROFILE
);
1382 case_ALGO(A2DP_HID
);
1383 case_ALGO(A2DP_PAN
);
1385 case_ALGO(A2DP_PAN_HID
);
1391 #define case_BT_PROFILE(src) \
1392 case BPM_##src: return #src
1394 static const char *rtw_coex_get_bt_profile_string(u8 bt_profile
)
1396 switch (bt_profile
) {
1397 case_BT_PROFILE(NOPROFILE
);
1398 case_BT_PROFILE(HFP
);
1399 case_BT_PROFILE(HID
);
1400 case_BT_PROFILE(A2DP
);
1401 case_BT_PROFILE(PAN
);
1402 case_BT_PROFILE(HID_HFP
);
1403 case_BT_PROFILE(A2DP_HFP
);
1404 case_BT_PROFILE(A2DP_HID
);
1405 case_BT_PROFILE(A2DP_HID_HFP
);
1406 case_BT_PROFILE(PAN_HFP
);
1407 case_BT_PROFILE(PAN_HID
);
1408 case_BT_PROFILE(PAN_HID_HFP
);
1409 case_BT_PROFILE(PAN_A2DP
);
1410 case_BT_PROFILE(PAN_A2DP_HFP
);
1411 case_BT_PROFILE(PAN_A2DP_HID
);
1412 case_BT_PROFILE(PAN_A2DP_HID_HFP
);
1418 static u8
rtw_coex_algorithm(struct rtw_dev
*rtwdev
)
1420 struct rtw_coex
*coex
= &rtwdev
->coex
;
1421 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1422 u8 algorithm
= COEX_ALGO_NOPROFILE
;
1425 if (coex_stat
->bt_hfp_exist
)
1426 profile_map
|= BPM_HFP
;
1427 if (coex_stat
->bt_hid_exist
)
1428 profile_map
|= BPM_HID
;
1429 if (coex_stat
->bt_a2dp_exist
)
1430 profile_map
|= BPM_A2DP
;
1431 if (coex_stat
->bt_pan_exist
)
1432 profile_map
|= BPM_PAN
;
1434 switch (profile_map
) {
1436 algorithm
= COEX_ALGO_HFP
;
1439 case BPM_HFP
+ BPM_HID
:
1440 algorithm
= COEX_ALGO_HID
;
1442 case BPM_HFP
+ BPM_A2DP
:
1443 case BPM_HID
+ BPM_A2DP
:
1444 case BPM_HFP
+ BPM_HID
+ BPM_A2DP
:
1445 algorithm
= COEX_ALGO_A2DP_HID
;
1447 case BPM_HFP
+ BPM_PAN
:
1448 case BPM_HID
+ BPM_PAN
:
1449 case BPM_HFP
+ BPM_HID
+ BPM_PAN
:
1450 algorithm
= COEX_ALGO_PAN_HID
;
1452 case BPM_HFP
+ BPM_A2DP
+ BPM_PAN
:
1453 case BPM_HID
+ BPM_A2DP
+ BPM_PAN
:
1454 case BPM_HFP
+ BPM_HID
+ BPM_A2DP
+ BPM_PAN
:
1455 algorithm
= COEX_ALGO_A2DP_PAN_HID
;
1458 algorithm
= COEX_ALGO_PAN
;
1460 case BPM_A2DP
+ BPM_PAN
:
1461 algorithm
= COEX_ALGO_A2DP_PAN
;
1464 if (coex_stat
->bt_multi_link
) {
1465 if (coex_stat
->bt_hid_pair_num
> 0)
1466 algorithm
= COEX_ALGO_A2DP_HID
;
1468 algorithm
= COEX_ALGO_A2DP_PAN
;
1470 algorithm
= COEX_ALGO_A2DP
;
1474 algorithm
= COEX_ALGO_NOPROFILE
;
1478 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1479 "[BTCoex], BT Profile = %s => Algorithm = %s\n",
1480 rtw_coex_get_bt_profile_string(profile_map
),
1481 rtw_coex_get_algo_string(algorithm
));
1485 static void rtw_coex_action_coex_all_off(struct rtw_dev
*rtwdev
)
1487 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1488 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1489 u8 table_case
, tdma_case
;
1491 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1492 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1494 if (efuse
->share_ant
) {
1499 /* Non-Shared-Ant */
1504 rtw_coex_table(rtwdev
, false, table_case
);
1505 rtw_coex_tdma(rtwdev
, false, tdma_case
);
1508 static void rtw_coex_action_freerun(struct rtw_dev
*rtwdev
)
1510 struct rtw_coex
*coex
= &rtwdev
->coex
;
1511 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1512 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1513 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1514 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1516 bool bt_afh_loss
= true;
1518 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1520 if (efuse
->share_ant
)
1523 coex
->freerun
= true;
1526 rtw_coex_update_wl_ch_info(rtwdev
, COEX_MEDIA_CONNECT
);
1528 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G_FREERUN
);
1530 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_FIX2M
, false);
1532 if (COEX_RSSI_HIGH(coex_dm
->wl_rssi_state
[0]))
1534 else if (COEX_RSSI_HIGH(coex_dm
->wl_rssi_state
[1]))
1536 else if (COEX_RSSI_HIGH(coex_dm
->wl_rssi_state
[2]))
1541 if (level
> chip
->wl_rf_para_num
- 1)
1542 level
= chip
->wl_rf_para_num
- 1;
1544 if (coex_stat
->wl_tput_dir
== COEX_WL_TPUT_TX
)
1545 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_tx
[level
]);
1547 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[level
]);
1549 rtw_coex_table(rtwdev
, false, 100);
1550 rtw_coex_tdma(rtwdev
, false, 100);
1553 static void rtw_coex_action_rf4ce(struct rtw_dev
*rtwdev
)
1555 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1556 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1557 u8 table_case
, tdma_case
;
1559 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1561 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1562 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1564 if (efuse
->share_ant
) {
1569 /* Non-Shared-Ant */
1574 rtw_coex_table(rtwdev
, false, table_case
);
1575 rtw_coex_tdma(rtwdev
, false, tdma_case
);
1578 static void rtw_coex_action_bt_whql_test(struct rtw_dev
*rtwdev
)
1580 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1581 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1582 u8 table_case
, tdma_case
;
1584 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1586 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1587 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1589 if (efuse
->share_ant
) {
1594 /* Non-Shared-Ant */
1599 rtw_coex_table(rtwdev
, false, table_case
);
1600 rtw_coex_tdma(rtwdev
, false, tdma_case
);
1603 static void rtw_coex_action_bt_relink(struct rtw_dev
*rtwdev
)
1605 struct rtw_coex
*coex
= &rtwdev
->coex
;
1606 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1607 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1608 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1609 u8 table_case
, tdma_case
;
1611 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1613 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1614 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1616 if (efuse
->share_ant
) { /* Shared-Ant */
1617 if (coex_stat
->wl_gl_busy
) {
1619 if (coex_stat
->bt_hid_exist
&&
1620 coex_stat
->bt_profile_num
== 1) {
1629 } else { /* Non-Shared-Ant */
1630 if (coex_stat
->wl_gl_busy
)
1637 rtw_coex_table(rtwdev
, false, table_case
);
1638 rtw_coex_tdma(rtwdev
, false, tdma_case
);
1641 static void rtw_coex_action_bt_idle(struct rtw_dev
*rtwdev
)
1643 struct rtw_coex
*coex
= &rtwdev
->coex
;
1644 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1645 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1646 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1647 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1648 struct rtw_coex_rfe
*coex_rfe
= &coex
->rfe
;
1649 u8 table_case
= 0xff, tdma_case
= 0xff;
1651 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1652 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1654 if (coex_rfe
->ant_switch_with_bt
&&
1655 coex_dm
->bt_status
== COEX_BTSTATUS_NCON_IDLE
) {
1656 if (efuse
->share_ant
&&
1657 COEX_RSSI_HIGH(coex_dm
->wl_rssi_state
[3]) &&
1658 coex_stat
->wl_gl_busy
) {
1661 } else if (!efuse
->share_ant
) {
1667 if (table_case
!= 0xff && tdma_case
!= 0xff) {
1668 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G_FREERUN
);
1672 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1674 if (efuse
->share_ant
) {
1676 if (!coex_stat
->wl_gl_busy
) {
1679 } else if (coex_dm
->bt_status
== COEX_BTSTATUS_NCON_IDLE
) {
1682 if (coex_stat
->lo_pri_rx
+ coex_stat
->lo_pri_tx
> 250)
1691 /* Non-Shared-Ant */
1692 if (!coex_stat
->wl_gl_busy
) {
1695 } else if ((coex_stat
->bt_ble_scan_type
& 0x2) &&
1696 coex_dm
->bt_status
== COEX_BTSTATUS_NCON_IDLE
) {
1706 rtw_coex_table(rtwdev
, false, table_case
);
1707 rtw_coex_tdma(rtwdev
, false, tdma_case
);
1710 static void rtw_coex_action_bt_inquiry(struct rtw_dev
*rtwdev
)
1712 struct rtw_coex
*coex
= &rtwdev
->coex
;
1713 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1714 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1715 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1716 bool wl_hi_pri
= false;
1717 u8 table_case
, tdma_case
;
1720 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1721 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1722 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1724 if (coex_stat
->wl_linkscan_proc
|| coex_stat
->wl_hi_pri_task1
||
1725 coex_stat
->wl_hi_pri_task2
)
1728 if (efuse
->share_ant
) {
1731 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1732 "[BTCoex], bt inq/page + wifi hi-pri task\n");
1735 if (coex_stat
->bt_profile_num
> 0)
1737 else if (coex_stat
->wl_hi_pri_task1
)
1739 else if (!coex_stat
->bt_page
)
1743 } else if (coex_stat
->wl_gl_busy
) {
1744 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1745 "[BTCoex], bt inq/page + wifi busy\n");
1746 if (coex_stat
->bt_profile_num
== 0) {
1749 } else if (coex_stat
->bt_profile_num
== 1 &&
1750 !coex_stat
->bt_a2dp_exist
) {
1751 slot_type
= TDMA_4SLOT
;
1755 slot_type
= TDMA_4SLOT
;
1759 } else if (coex_stat
->wl_connected
) {
1760 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1761 "[BTCoex], bt inq/page + wifi connected\n");
1765 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1766 "[BTCoex], bt inq/page + wifi not-connected\n");
1771 /* Non_Shared-Ant */
1773 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1774 "[BTCoex], bt inq/page + wifi hi-pri task\n");
1777 if (coex_stat
->bt_profile_num
> 0)
1779 else if (coex_stat
->wl_hi_pri_task1
)
1781 else if (!coex_stat
->bt_page
)
1785 } else if (coex_stat
->wl_gl_busy
) {
1786 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1787 "[BTCoex], bt inq/page + wifi busy\n");
1790 } else if (coex_stat
->wl_connected
) {
1791 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1792 "[BTCoex], bt inq/page + wifi connected\n");
1796 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
1797 "[BTCoex], bt inq/page + wifi not-connected\n");
1803 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], wifi hi(%d), bt page(%d)\n",
1804 wl_hi_pri
, coex_stat
->bt_page
);
1806 rtw_coex_table(rtwdev
, false, table_case
);
1807 rtw_coex_tdma(rtwdev
, false, tdma_case
| slot_type
);
1810 static void rtw_coex_action_bt_hfp(struct rtw_dev
*rtwdev
)
1812 struct rtw_coex
*coex
= &rtwdev
->coex
;
1813 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1814 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1815 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1816 u8 table_case
, tdma_case
;
1818 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1819 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1820 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1822 if (efuse
->share_ant
) {
1824 if (coex_stat
->bt_multi_link
) {
1832 /* Non-Shared-Ant */
1833 if (coex_stat
->bt_multi_link
) {
1842 rtw_coex_table(rtwdev
, false, table_case
);
1843 rtw_coex_tdma(rtwdev
, false, tdma_case
);
1846 static void rtw_coex_action_bt_hid(struct rtw_dev
*rtwdev
)
1848 struct rtw_coex
*coex
= &rtwdev
->coex
;
1849 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1850 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1851 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1852 u8 table_case
, tdma_case
;
1854 bool bt_multi_link_remain
= false, is_toggle_table
= false;
1856 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1857 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1858 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1860 if (efuse
->share_ant
) {
1862 if (coex_stat
->bt_ble_exist
) {
1864 if (coex_stat
->cnt_wl
[COEX_CNT_WL_SCANAP
] > 5) {
1873 if (coex_stat
->bt_profile_num
== 1 &&
1874 (coex_stat
->bt_multi_link
||
1875 (coex_stat
->lo_pri_rx
+
1876 coex_stat
->lo_pri_tx
> 360) ||
1877 coex_stat
->bt_slave
||
1878 bt_multi_link_remain
)) {
1879 slot_type
= TDMA_4SLOT
;
1882 } else if (coex_stat
->bt_a2dp_active
) {
1885 } else if (coex_stat
->bt_418_hid_exist
&&
1886 coex_stat
->wl_gl_busy
) {
1887 is_toggle_table
= true;
1888 slot_type
= TDMA_4SLOT
;
1891 } else if (coex_stat
->bt_ble_hid_exist
&&
1892 coex_stat
->wl_gl_busy
) {
1901 /* Non-Shared-Ant */
1902 if (coex_stat
->bt_ble_exist
) {
1904 if (coex_stat
->cnt_wl
[COEX_CNT_WL_SCANAP
] > 5) {
1911 } else if (coex_stat
->bt_a2dp_active
) {
1920 rtw_coex_table(rtwdev
, false, table_case
);
1921 if (is_toggle_table
) {
1922 rtw_btc_wltoggle_table_a(rtwdev
, true, table_case
);
1923 rtw_btc_wltoggle_table_b(rtwdev
, false, 1, COEX_WL_SLOT_TOGLLE
);
1926 rtw_coex_tdma(rtwdev
, false, tdma_case
| slot_type
);
1929 static void rtw_coex_action_bt_a2dp(struct rtw_dev
*rtwdev
)
1931 struct rtw_coex
*coex
= &rtwdev
->coex
;
1932 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1933 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
1934 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1935 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1936 u8 table_case
, tdma_case
;
1939 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1941 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1942 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1944 slot_type
= TDMA_4SLOT
;
1946 if (efuse
->share_ant
) {
1948 if (coex_stat
->wl_gl_busy
&& coex_stat
->wl_noisy_level
== 0)
1953 if (coex_stat
->wl_connecting
|| !coex_stat
->wl_gl_busy
)
1958 /* Non-Shared-Ant */
1961 if (COEX_RSSI_HIGH(coex_dm
->wl_rssi_state
[1]))
1967 rtw_coex_table(rtwdev
, false, table_case
);
1968 rtw_coex_tdma(rtwdev
, false, tdma_case
| slot_type
);
1971 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev
*rtwdev
)
1973 struct rtw_coex
*coex
= &rtwdev
->coex
;
1974 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
1975 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
1976 struct rtw_chip_info
*chip
= rtwdev
->chip
;
1977 u8 table_case
, tdma_case
;
1978 bool ap_enable
= false;
1980 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
1982 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
1983 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
1985 if (efuse
->share_ant
) { /* Shared-Ant */
1989 } else if (coex_stat
->wl_gl_busy
) {
1996 } else { /* Non-Shared-Ant */
2006 rtw_coex_table(rtwdev
, false, table_case
);
2007 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2010 static void rtw_coex_action_bt_pan(struct rtw_dev
*rtwdev
)
2012 struct rtw_coex
*coex
= &rtwdev
->coex
;
2013 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2014 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2015 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2016 u8 table_case
, tdma_case
;
2018 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2019 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2020 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2022 if (efuse
->share_ant
) {
2024 if (coex_stat
->wl_gl_busy
&& coex_stat
->wl_noisy_level
== 0)
2029 if (coex_stat
->wl_gl_busy
)
2034 /* Non-Shared-Ant */
2037 if (coex_stat
->wl_gl_busy
)
2043 rtw_coex_table(rtwdev
, false, table_case
);
2044 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2047 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev
*rtwdev
)
2049 struct rtw_coex
*coex
= &rtwdev
->coex
;
2050 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2051 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
2052 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2053 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2054 u8 table_case
, tdma_case
, interval
= 0;
2056 bool is_toggle_table
= false;
2058 slot_type
= TDMA_4SLOT
;
2060 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2061 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2062 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2064 if (efuse
->share_ant
) {
2066 if (coex_stat
->bt_ble_exist
) {
2067 table_case
= 26; /* for RCU */
2068 } else if (coex_stat
->bt_418_hid_exist
) {
2075 if (coex_stat
->wl_connecting
|| !coex_stat
->wl_gl_busy
) {
2077 } else if (coex_stat
->bt_418_hid_exist
) {
2078 is_toggle_table
= true;
2084 /* Non-Shared-Ant */
2085 if (coex_stat
->bt_ble_exist
)
2090 if (COEX_RSSI_HIGH(coex_dm
->wl_rssi_state
[1]))
2096 rtw_coex_table(rtwdev
, false, table_case
);
2097 if (is_toggle_table
) {
2098 rtw_btc_wltoggle_table_a(rtwdev
, true, table_case
);
2099 rtw_btc_wltoggle_table_b(rtwdev
, false, interval
, COEX_WL_SLOT_TOGLLE
);
2101 rtw_coex_tdma(rtwdev
, false, tdma_case
| slot_type
);
2104 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev
*rtwdev
)
2106 struct rtw_coex
*coex
= &rtwdev
->coex
;
2107 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2108 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2109 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2110 u8 table_case
, tdma_case
;
2111 bool wl_cpt_test
= false, bt_cpt_test
= false;
2113 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2115 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2116 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2117 if (efuse
->share_ant
) {
2120 if (coex_stat
->wl_gl_busy
) {
2127 } else if (bt_cpt_test
) {
2131 if (coex_stat
->wl_gl_busy
&&
2132 coex_stat
->wl_noisy_level
== 0)
2137 if (coex_stat
->wl_gl_busy
)
2143 /* Non-Shared-Ant */
2146 if (coex_stat
->wl_gl_busy
)
2153 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[1]);
2155 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2157 rtw_coex_table(rtwdev
, false, table_case
);
2158 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2161 static void rtw_coex_action_bt_pan_hid(struct rtw_dev
*rtwdev
)
2163 struct rtw_coex
*coex
= &rtwdev
->coex
;
2164 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2165 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2166 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2167 u8 table_case
, tdma_case
;
2169 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2171 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2172 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2174 if (efuse
->share_ant
) {
2178 if (coex_stat
->wl_gl_busy
)
2183 /* Non-Shared-Ant */
2186 if (coex_stat
->wl_gl_busy
)
2192 rtw_coex_table(rtwdev
, false, table_case
);
2193 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2196 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev
*rtwdev
)
2198 struct rtw_coex
*coex
= &rtwdev
->coex
;
2199 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2200 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2201 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2202 u8 table_case
, tdma_case
;
2204 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2205 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2206 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2208 if (efuse
->share_ant
) {
2212 if (coex_stat
->wl_gl_busy
)
2217 /* Non-Shared-Ant */
2220 if (coex_stat
->wl_gl_busy
)
2226 rtw_coex_table(rtwdev
, false, table_case
);
2227 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2230 static void rtw_coex_action_wl_under5g(struct rtw_dev
*rtwdev
)
2232 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2233 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2234 u8 table_case
, tdma_case
;
2236 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2238 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_5G
);
2239 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2241 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_FIX2M
, false);
2243 if (efuse
->share_ant
) {
2248 /* Non-Shared-Ant */
2253 rtw_coex_table(rtwdev
, false, table_case
);
2254 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2257 static void rtw_coex_action_wl_only(struct rtw_dev
*rtwdev
)
2259 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2260 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2261 u8 table_case
, tdma_case
;
2263 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2264 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2265 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2267 if (efuse
->share_ant
) {
2272 /* Non-Shared-Ant */
2277 rtw_coex_table(rtwdev
, false, table_case
);
2278 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2281 static void rtw_coex_action_wl_native_lps(struct rtw_dev
*rtwdev
)
2283 struct rtw_coex
*coex
= &rtwdev
->coex
;
2284 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2285 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2286 u8 table_case
, tdma_case
;
2291 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2293 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2294 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2296 if (efuse
->share_ant
) {
2301 /* Non-Shared-Ant */
2306 rtw_coex_table(rtwdev
, false, table_case
);
2307 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2310 static void rtw_coex_action_wl_linkscan(struct rtw_dev
*rtwdev
)
2312 struct rtw_coex
*coex
= &rtwdev
->coex
;
2313 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2314 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2315 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2316 u8 table_case
, tdma_case
;
2319 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2320 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2321 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2323 if (efuse
->share_ant
) { /* Shared-Ant */
2324 if (coex_stat
->bt_a2dp_exist
) {
2325 slot_type
= TDMA_4SLOT
;
2332 } else { /* Non-Shared-Ant */
2333 if (coex_stat
->bt_a2dp_exist
) {
2334 slot_type
= TDMA_4SLOT
;
2343 rtw_coex_table(rtwdev
, false, table_case
);
2344 rtw_coex_tdma(rtwdev
, false, tdma_case
| slot_type
);
2347 static void rtw_coex_action_wl_not_connected(struct rtw_dev
*rtwdev
)
2349 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
2350 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2351 u8 table_case
, tdma_case
;
2353 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2354 rtw_coex_set_ant_path(rtwdev
, false, COEX_SET_ANT_2G
);
2355 rtw_coex_set_rf_para(rtwdev
, chip
->wl_rf_para_rx
[0]);
2357 if (efuse
->share_ant
) {
2362 /* Non-Shared-Ant */
2367 rtw_coex_table(rtwdev
, false, table_case
);
2368 rtw_coex_tdma(rtwdev
, false, tdma_case
);
2371 static void rtw_coex_action_wl_connected(struct rtw_dev
*rtwdev
)
2373 struct rtw_coex
*coex
= &rtwdev
->coex
;
2374 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2377 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2379 algorithm
= rtw_coex_algorithm(rtwdev
);
2381 switch (algorithm
) {
2383 rtw_coex_action_bt_hfp(rtwdev
);
2386 if (rtw_coex_freerun_check(rtwdev
))
2387 rtw_coex_action_freerun(rtwdev
);
2389 rtw_coex_action_bt_hid(rtwdev
);
2391 case COEX_ALGO_A2DP
:
2392 if (rtw_coex_freerun_check(rtwdev
))
2393 rtw_coex_action_freerun(rtwdev
);
2394 else if (coex_stat
->bt_a2dp_sink
)
2395 rtw_coex_action_bt_a2dpsink(rtwdev
);
2397 rtw_coex_action_bt_a2dp(rtwdev
);
2400 rtw_coex_action_bt_pan(rtwdev
);
2402 case COEX_ALGO_A2DP_HID
:
2403 if (rtw_coex_freerun_check(rtwdev
))
2404 rtw_coex_action_freerun(rtwdev
);
2406 rtw_coex_action_bt_a2dp_hid(rtwdev
);
2408 case COEX_ALGO_A2DP_PAN
:
2409 rtw_coex_action_bt_a2dp_pan(rtwdev
);
2411 case COEX_ALGO_PAN_HID
:
2412 rtw_coex_action_bt_pan_hid(rtwdev
);
2414 case COEX_ALGO_A2DP_PAN_HID
:
2415 rtw_coex_action_bt_a2dp_pan_hid(rtwdev
);
2418 case COEX_ALGO_NOPROFILE
:
2419 rtw_coex_action_bt_idle(rtwdev
);
2424 static void rtw_coex_run_coex(struct rtw_dev
*rtwdev
, u8 reason
)
2426 struct rtw_coex
*coex
= &rtwdev
->coex
;
2427 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
2428 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2429 bool rf4ce_en
= false;
2431 lockdep_assert_held(&rtwdev
->mutex
);
2433 if (!test_bit(RTW_FLAG_RUNNING
, rtwdev
->flags
))
2436 coex_dm
->reason
= reason
;
2438 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): reason = %d\n", __func__
,
2441 /* update wifi_link_info_ext variable */
2442 rtw_coex_update_wl_link_info(rtwdev
, reason
);
2444 rtw_coex_monitor_bt_enable(rtwdev
);
2446 if (coex
->manual_control
) {
2447 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2448 "[BTCoex], return for Manual CTRL!!\n");
2452 if (coex
->stop_dm
) {
2453 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2454 "[BTCoex], return for Stop Coex DM!!\n");
2458 if (coex_stat
->wl_under_ips
) {
2459 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2460 "[BTCoex], return for wifi is under IPS!!\n");
2464 if (coex
->freeze
&& coex_dm
->reason
== COEX_RSN_BTINFO
&&
2465 !coex_stat
->bt_setup_link
) {
2466 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2467 "[BTCoex], return for coex_freeze!!\n");
2471 coex_stat
->cnt_wl
[COEX_CNT_WL_COEXRUN
]++;
2472 coex
->freerun
= false;
2474 /* Pure-5G Coex Process */
2475 if (coex
->under_5g
) {
2476 coex_stat
->wl_coex_mode
= COEX_WLINK_5G
;
2477 rtw_coex_action_wl_under5g(rtwdev
);
2481 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], WiFi is single-port 2G!!\n");
2482 coex_stat
->wl_coex_mode
= COEX_WLINK_2G1PORT
;
2484 if (coex_stat
->bt_disabled
) {
2485 if (coex_stat
->wl_connected
&& rf4ce_en
)
2486 rtw_coex_action_rf4ce(rtwdev
);
2487 else if (!coex_stat
->wl_connected
)
2488 rtw_coex_action_wl_not_connected(rtwdev
);
2490 rtw_coex_action_wl_only(rtwdev
);
2494 if (coex_stat
->wl_under_lps
&& !coex_stat
->wl_force_lps_ctrl
) {
2495 rtw_coex_action_wl_native_lps(rtwdev
);
2499 if (coex_stat
->bt_whck_test
) {
2500 rtw_coex_action_bt_whql_test(rtwdev
);
2504 if (coex_stat
->bt_setup_link
) {
2505 rtw_coex_action_bt_relink(rtwdev
);
2509 if (coex_stat
->bt_inq_page
) {
2510 rtw_coex_action_bt_inquiry(rtwdev
);
2514 if ((coex_dm
->bt_status
== COEX_BTSTATUS_NCON_IDLE
||
2515 coex_dm
->bt_status
== COEX_BTSTATUS_CON_IDLE
) &&
2516 coex_stat
->wl_connected
) {
2517 rtw_coex_action_bt_idle(rtwdev
);
2521 if (coex_stat
->wl_linkscan_proc
&& !coex
->freerun
) {
2522 rtw_coex_action_wl_linkscan(rtwdev
);
2526 if (coex_stat
->wl_connected
) {
2527 rtw_coex_action_wl_connected(rtwdev
);
2530 rtw_coex_action_wl_not_connected(rtwdev
);
2535 rtw_coex_gnt_workaround(rtwdev
, false, coex_stat
->wl_coex_mode
);
2536 rtw_coex_limited_wl(rtwdev
);
2539 static void rtw_coex_init_coex_var(struct rtw_dev
*rtwdev
)
2541 struct rtw_coex
*coex
= &rtwdev
->coex
;
2542 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2543 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
2546 memset(coex_dm
, 0, sizeof(*coex_dm
));
2547 memset(coex_stat
, 0, sizeof(*coex_stat
));
2549 for (i
= 0; i
< COEX_CNT_WL_MAX
; i
++)
2550 coex_stat
->cnt_wl
[i
] = 0;
2552 for (i
= 0; i
< COEX_CNT_BT_MAX
; i
++)
2553 coex_stat
->cnt_bt
[i
] = 0;
2555 for (i
= 0; i
< ARRAY_SIZE(coex_dm
->bt_rssi_state
); i
++)
2556 coex_dm
->bt_rssi_state
[i
] = COEX_RSSI_STATE_LOW
;
2558 for (i
= 0; i
< ARRAY_SIZE(coex_dm
->wl_rssi_state
); i
++)
2559 coex_dm
->wl_rssi_state
[i
] = COEX_RSSI_STATE_LOW
;
2561 coex_stat
->wl_coex_mode
= COEX_WLINK_MAX
;
2562 coex_stat
->wl_rx_rate
= DESC_RATE5_5M
;
2563 coex_stat
->wl_rts_rx_rate
= DESC_RATE5_5M
;
2566 static void __rtw_coex_init_hw_config(struct rtw_dev
*rtwdev
, bool wifi_only
)
2568 struct rtw_coex
*coex
= &rtwdev
->coex
;
2569 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2571 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2573 rtw_coex_init_coex_var(rtwdev
);
2575 coex_stat
->kt_ver
= u8_get_bits(rtw_read8(rtwdev
, 0xf1), GENMASK(7, 4));
2577 rtw_coex_monitor_bt_enable(rtwdev
);
2578 rtw_coex_wl_slot_extend(rtwdev
, coex_stat
->wl_slot_extend
);
2580 rtw_write8_set(rtwdev
, REG_BCN_CTRL
, BIT_EN_BCN_FUNCTION
);
2582 rtw_coex_set_rfe_type(rtwdev
);
2583 rtw_coex_set_init(rtwdev
);
2585 /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2586 rtw_coex_set_wl_pri_mask(rtwdev
, COEX_WLPRI_TX_RSP
, 1);
2588 /* set Tx beacon = Hi-Pri */
2589 rtw_coex_set_wl_pri_mask(rtwdev
, COEX_WLPRI_TX_BEACON
, 1);
2591 /* set Tx beacon queue = Hi-Pri */
2592 rtw_coex_set_wl_pri_mask(rtwdev
, COEX_WLPRI_TX_BEACONQ
, 1);
2594 /* antenna config */
2595 if (coex
->wl_rf_off
) {
2596 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_WOFF
);
2597 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ALL
, false);
2598 coex
->stop_dm
= true;
2600 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): RF Off\n",
2602 } else if (wifi_only
) {
2603 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_WONLY
);
2604 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
| COEX_SCBD_ONOFF
,
2606 coex
->stop_dm
= true;
2608 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_INIT
);
2609 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
| COEX_SCBD_ONOFF
,
2611 coex
->stop_dm
= false;
2612 coex
->freeze
= true;
2616 rtw_coex_table(rtwdev
, true, 1);
2617 rtw_coex_tdma(rtwdev
, true, 0);
2618 rtw_coex_query_bt_info(rtwdev
);
2621 void rtw_coex_power_on_setting(struct rtw_dev
*rtwdev
)
2623 struct rtw_coex
*coex
= &rtwdev
->coex
;
2626 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
2628 coex
->stop_dm
= true;
2629 coex
->wl_rf_off
= false;
2631 /* enable BB, we can write 0x948 */
2632 rtw_write8_set(rtwdev
, REG_SYS_FUNC_EN
,
2633 BIT_FEN_BB_GLB_RST
| BIT_FEN_BB_RSTB
);
2635 rtw_coex_monitor_bt_enable(rtwdev
);
2636 rtw_coex_set_rfe_type(rtwdev
);
2638 /* set antenna path to BT */
2639 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_POWERON
);
2641 rtw_coex_table(rtwdev
, true, table_case
);
2643 rtw_write8(rtwdev
, 0xff1a, 0x0);
2644 rtw_coex_set_gnt_debug(rtwdev
);
2647 void rtw_coex_init_hw_config(struct rtw_dev
*rtwdev
, bool wifi_only
)
2649 __rtw_coex_init_hw_config(rtwdev
, wifi_only
);
2652 void rtw_coex_ips_notify(struct rtw_dev
*rtwdev
, u8 type
)
2654 struct rtw_coex
*coex
= &rtwdev
->coex
;
2655 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2657 if (coex
->manual_control
|| coex
->stop_dm
)
2660 if (type
== COEX_IPS_ENTER
) {
2661 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], IPS ENTER notify\n");
2663 coex_stat
->wl_under_ips
= true;
2666 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ALL
, false);
2668 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_WOFF
);
2669 rtw_coex_action_coex_all_off(rtwdev
);
2670 } else if (type
== COEX_IPS_LEAVE
) {
2671 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], IPS LEAVE notify\n");
2673 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
| COEX_SCBD_ONOFF
, true);
2674 /* run init hw config (exclude wifi only) */
2675 __rtw_coex_init_hw_config(rtwdev
, false);
2677 coex_stat
->wl_under_ips
= false;
2681 void rtw_coex_lps_notify(struct rtw_dev
*rtwdev
, u8 type
)
2683 struct rtw_coex
*coex
= &rtwdev
->coex
;
2684 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2686 if (coex
->manual_control
|| coex
->stop_dm
)
2689 if (type
== COEX_LPS_ENABLE
) {
2690 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], LPS ENABLE notify\n");
2692 coex_stat
->wl_under_lps
= true;
2694 if (coex_stat
->wl_force_lps_ctrl
) {
2696 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
, true);
2699 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
, false);
2700 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_WLBUSY
, false);
2702 rtw_coex_run_coex(rtwdev
, COEX_RSN_LPS
);
2704 } else if (type
== COEX_LPS_DISABLE
) {
2705 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], LPS DISABLE notify\n");
2707 coex_stat
->wl_under_lps
= false;
2710 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
, true);
2712 if (!coex_stat
->wl_force_lps_ctrl
)
2713 rtw_coex_query_bt_info(rtwdev
);
2715 rtw_coex_run_coex(rtwdev
, COEX_RSN_LPS
);
2719 void rtw_coex_scan_notify(struct rtw_dev
*rtwdev
, u8 type
)
2721 struct rtw_coex
*coex
= &rtwdev
->coex
;
2722 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2724 if (coex
->manual_control
|| coex
->stop_dm
)
2727 coex
->freeze
= false;
2728 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
| COEX_SCBD_ONOFF
, true);
2730 if (type
== COEX_SCAN_START_5G
) {
2731 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2732 "[BTCoex], SCAN START notify (5G)\n");
2734 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_5G
);
2735 rtw_coex_run_coex(rtwdev
, COEX_RSN_5GSCANSTART
);
2736 } else if ((type
== COEX_SCAN_START_2G
) || (type
== COEX_SCAN_START
)) {
2737 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2738 "[BTCoex], SCAN START notify (2G)\n");
2740 coex_stat
->wl_hi_pri_task2
= true;
2742 /* Force antenna setup for no scan result issue */
2743 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_2G
);
2744 rtw_coex_run_coex(rtwdev
, COEX_RSN_2GSCANSTART
);
2746 coex_stat
->cnt_wl
[COEX_CNT_WL_SCANAP
] = 30; /* To do */
2748 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2749 "[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n",
2750 coex_stat
->cnt_wl
[COEX_CNT_WL_SCANAP
]);
2752 coex_stat
->wl_hi_pri_task2
= false;
2753 rtw_coex_run_coex(rtwdev
, COEX_RSN_SCANFINISH
);
2757 void rtw_coex_switchband_notify(struct rtw_dev
*rtwdev
, u8 type
)
2759 struct rtw_coex
*coex
= &rtwdev
->coex
;
2761 if (coex
->manual_control
|| coex
->stop_dm
)
2764 if (type
== COEX_SWITCH_TO_5G
) {
2765 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): TO_5G\n",
2767 } else if (type
== COEX_SWITCH_TO_24G_NOFORSCAN
) {
2768 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2769 "[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__
);
2771 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): TO_2G\n",
2775 if (type
== COEX_SWITCH_TO_5G
)
2776 rtw_coex_run_coex(rtwdev
, COEX_RSN_5GSWITCHBAND
);
2777 else if (type
== COEX_SWITCH_TO_24G_NOFORSCAN
)
2778 rtw_coex_run_coex(rtwdev
, COEX_RSN_2GSWITCHBAND
);
2780 rtw_coex_scan_notify(rtwdev
, COEX_SCAN_START_2G
);
2783 void rtw_coex_connect_notify(struct rtw_dev
*rtwdev
, u8 type
)
2785 struct rtw_coex
*coex
= &rtwdev
->coex
;
2786 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2788 if (coex
->manual_control
|| coex
->stop_dm
)
2791 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
| COEX_SCBD_ONOFF
, true);
2793 if (type
== COEX_ASSOCIATE_5G_START
) {
2794 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): 5G start\n",
2797 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_5G
);
2798 rtw_coex_run_coex(rtwdev
, COEX_RSN_5GCONSTART
);
2799 } else if (type
== COEX_ASSOCIATE_5G_FINISH
) {
2800 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): 5G finish\n",
2803 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_5G
);
2804 rtw_coex_run_coex(rtwdev
, COEX_RSN_5GCONFINISH
);
2805 } else if (type
== COEX_ASSOCIATE_START
) {
2806 coex_stat
->wl_hi_pri_task1
= true;
2807 coex_stat
->wl_connecting
= true;
2808 coex_stat
->cnt_wl
[COEX_CNT_WL_CONNPKT
] = 2;
2809 coex_stat
->wl_connecting
= true;
2810 ieee80211_queue_delayed_work(rtwdev
->hw
,
2811 &coex
->wl_connecting_work
, 2 * HZ
);
2813 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): 2G start\n",
2815 /* Force antenna setup for no scan result issue */
2816 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_2G
);
2818 rtw_coex_run_coex(rtwdev
, COEX_RSN_2GCONSTART
);
2820 /* To keep TDMA case during connect process,
2821 * to avoid changed by Btinfo and runcoexmechanism
2823 coex
->freeze
= true;
2824 ieee80211_queue_delayed_work(rtwdev
->hw
, &coex
->defreeze_work
,
2827 coex_stat
->wl_hi_pri_task1
= false;
2828 coex
->freeze
= false;
2829 coex_stat
->wl_connecting
= false;
2831 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): 2G finish\n",
2833 rtw_coex_run_coex(rtwdev
, COEX_RSN_2GCONFINISH
);
2837 void rtw_coex_media_status_notify(struct rtw_dev
*rtwdev
, u8 type
)
2839 struct rtw_coex
*coex
= &rtwdev
->coex
;
2840 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2842 if (coex
->manual_control
|| coex
->stop_dm
)
2845 if (type
== COEX_MEDIA_CONNECT_5G
) {
2846 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): 5G\n", __func__
);
2848 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
, true);
2850 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_5G
);
2851 rtw_coex_run_coex(rtwdev
, COEX_RSN_5GMEDIA
);
2852 } else if (type
== COEX_MEDIA_CONNECT
) {
2853 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): 2G\n", __func__
);
2855 coex_stat
->wl_connecting
= false;
2857 rtw_coex_write_scbd(rtwdev
, COEX_SCBD_ACTIVE
, true);
2859 /* Force antenna setup for no scan result issue */
2860 rtw_coex_set_ant_path(rtwdev
, true, COEX_SET_ANT_2G
);
2862 /* Set CCK Rx high Pri */
2863 rtw_coex_set_wl_pri_mask(rtwdev
, COEX_WLPRI_RX_CCK
, 1);
2864 rtw_coex_run_coex(rtwdev
, COEX_RSN_2GMEDIA
);
2866 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s(): disconnect!!\n",
2868 rtw_coex_set_wl_pri_mask(rtwdev
, COEX_WLPRI_RX_CCK
, 0);
2869 rtw_coex_run_coex(rtwdev
, COEX_RSN_MEDIADISCON
);
2872 rtw_coex_update_wl_ch_info(rtwdev
, type
);
2875 void rtw_coex_bt_info_notify(struct rtw_dev
*rtwdev
, u8
*buf
, u8 length
)
2877 struct rtw_coex
*coex
= &rtwdev
->coex
;
2878 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
2879 struct rtw_chip_info
*chip
= rtwdev
->chip
;
2880 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
2882 u8 i
, rsp_source
= 0, type
;
2883 bool inq_page
= false;
2885 rsp_source
= buf
[0] & 0xf;
2886 if (rsp_source
>= COEX_BTINFO_SRC_MAX
)
2888 coex_stat
->cnt_bt_info_c2h
[rsp_source
]++;
2890 if (rsp_source
== COEX_BTINFO_SRC_BT_IQK
) {
2891 coex_stat
->bt_iqk_state
= buf
[1];
2892 if (coex_stat
->bt_iqk_state
== 0)
2893 coex_stat
->cnt_bt
[COEX_CNT_BT_IQK
]++;
2894 else if (coex_stat
->bt_iqk_state
== 2)
2895 coex_stat
->cnt_bt
[COEX_CNT_BT_IQKFAIL
]++;
2897 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2898 "[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n",
2904 if (rsp_source
== COEX_BTINFO_SRC_BT_SCBD
) {
2905 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2906 "[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n",
2909 rtw_coex_monitor_bt_enable(rtwdev
);
2910 if (coex_stat
->bt_disabled
!= coex_stat
->bt_disabled_pre
) {
2911 coex_stat
->bt_disabled_pre
= coex_stat
->bt_disabled
;
2912 rtw_coex_run_coex(rtwdev
, COEX_RSN_BTINFO
);
2917 if (rsp_source
== COEX_BTINFO_SRC_H2C60
) {
2918 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2919 "[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n",
2920 buf
[1], buf
[2], buf
[3], buf
[4], buf
[5]);
2922 for (i
= 1; i
<= COEX_WL_TDMA_PARA_LENGTH
; i
++)
2923 coex_dm
->fw_tdma_para
[i
- 1] = buf
[i
];
2927 if (rsp_source
== COEX_BTINFO_SRC_WL_FW
) {
2928 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2929 "[BTCoex], bt_info reply by WL FW\n");
2931 rtw_coex_update_bt_link_info(rtwdev
);
2935 if (rsp_source
== COEX_BTINFO_SRC_BT_RSP
||
2936 rsp_source
== COEX_BTINFO_SRC_BT_ACT
) {
2937 if (coex_stat
->bt_disabled
) {
2938 coex_stat
->bt_disabled
= false;
2939 coex_stat
->bt_reenable
= true;
2940 ieee80211_queue_delayed_work(rtwdev
->hw
,
2941 &coex
->bt_reenable_work
,
2943 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2944 "[BTCoex], BT enable detected by bt_info\n");
2948 if (length
!= COEX_BTINFO_LENGTH
) {
2949 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2950 "[BTCoex], Bt_info length = %d invalid!!\n", length
);
2955 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2956 "[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n",
2957 buf
[0], length
, buf
[1], buf
[2], buf
[3], buf
[4], buf
[5], buf
[6]);
2959 for (i
= 0; i
< COEX_BTINFO_LENGTH
; i
++)
2960 coex_stat
->bt_info_c2h
[rsp_source
][i
] = buf
[i
];
2962 /* get the same info from bt, skip it */
2963 if (coex_stat
->bt_info_c2h
[rsp_source
][1] == coex_stat
->bt_info_lb2
&&
2964 coex_stat
->bt_info_c2h
[rsp_source
][2] == coex_stat
->bt_info_lb3
&&
2965 coex_stat
->bt_info_c2h
[rsp_source
][3] == coex_stat
->bt_info_hb0
&&
2966 coex_stat
->bt_info_c2h
[rsp_source
][4] == coex_stat
->bt_info_hb1
&&
2967 coex_stat
->bt_info_c2h
[rsp_source
][5] == coex_stat
->bt_info_hb2
&&
2968 coex_stat
->bt_info_c2h
[rsp_source
][6] == coex_stat
->bt_info_hb3
) {
2969 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
2970 "[BTCoex], Return because Btinfo duplicate!!\n");
2974 coex_stat
->bt_info_lb2
= coex_stat
->bt_info_c2h
[rsp_source
][1];
2975 coex_stat
->bt_info_lb3
= coex_stat
->bt_info_c2h
[rsp_source
][2];
2976 coex_stat
->bt_info_hb0
= coex_stat
->bt_info_c2h
[rsp_source
][3];
2977 coex_stat
->bt_info_hb1
= coex_stat
->bt_info_c2h
[rsp_source
][4];
2978 coex_stat
->bt_info_hb2
= coex_stat
->bt_info_c2h
[rsp_source
][5];
2979 coex_stat
->bt_info_hb3
= coex_stat
->bt_info_c2h
[rsp_source
][6];
2981 /* 0xff means BT is under WHCK test */
2982 coex_stat
->bt_whck_test
= (coex_stat
->bt_info_lb2
== 0xff);
2984 inq_page
= ((coex_stat
->bt_info_lb2
& BIT(2)) == BIT(2));
2986 if (inq_page
!= coex_stat
->bt_inq_page
) {
2987 cancel_delayed_work_sync(&coex
->bt_remain_work
);
2988 coex_stat
->bt_inq_page
= inq_page
;
2991 coex_stat
->bt_inq_remain
= true;
2993 ieee80211_queue_delayed_work(rtwdev
->hw
,
2994 &coex
->bt_remain_work
,
2997 coex_stat
->bt_acl_busy
= ((coex_stat
->bt_info_lb2
& BIT(3)) == BIT(3));
2998 if (chip
->ble_hid_profile_support
) {
2999 if (coex_stat
->bt_info_lb2
& BIT(5)) {
3000 if (coex_stat
->bt_info_hb1
& BIT(0)) {
3002 coex_stat
->bt_ble_hid_exist
= true;
3004 coex_stat
->bt_ble_hid_exist
= false;
3006 coex_stat
->bt_ble_exist
= false;
3007 } else if (coex_stat
->bt_info_hb1
& BIT(0)) {
3009 coex_stat
->bt_ble_hid_exist
= false;
3010 coex_stat
->bt_ble_exist
= true;
3012 coex_stat
->bt_ble_hid_exist
= false;
3013 coex_stat
->bt_ble_exist
= false;
3016 if (coex_stat
->bt_info_hb1
& BIT(0)) {
3017 if (coex_stat
->bt_hid_slot
== 1 &&
3018 coex_stat
->hi_pri_rx
+ 100 < coex_stat
->hi_pri_tx
&&
3019 coex_stat
->hi_pri_rx
< 100) {
3020 coex_stat
->bt_ble_hid_exist
= true;
3021 coex_stat
->bt_ble_exist
= false;
3023 coex_stat
->bt_ble_hid_exist
= false;
3024 coex_stat
->bt_ble_exist
= true;
3027 coex_stat
->bt_ble_hid_exist
= false;
3028 coex_stat
->bt_ble_exist
= false;
3032 coex_stat
->cnt_bt
[COEX_CNT_BT_RETRY
] = coex_stat
->bt_info_lb3
& 0xf;
3033 if (coex_stat
->cnt_bt
[COEX_CNT_BT_RETRY
] >= 1)
3034 coex_stat
->cnt_bt
[COEX_CNT_BT_POPEVENT
]++;
3036 coex_stat
->bt_fix_2M
= ((coex_stat
->bt_info_lb3
& BIT(4)) == BIT(4));
3037 coex_stat
->bt_inq
= ((coex_stat
->bt_info_lb3
& BIT(5)) == BIT(5));
3038 if (coex_stat
->bt_inq
)
3039 coex_stat
->cnt_bt
[COEX_CNT_BT_INQ
]++;
3041 coex_stat
->bt_page
= ((coex_stat
->bt_info_lb3
& BIT(7)) == BIT(7));
3042 if (coex_stat
->bt_page
)
3043 coex_stat
->cnt_bt
[COEX_CNT_BT_PAGE
]++;
3045 /* unit: % (value-100 to translate to unit: dBm in coex info) */
3046 if (chip
->bt_rssi_type
== COEX_BTRSSI_RATIO
) {
3047 coex_stat
->bt_rssi
= coex_stat
->bt_info_hb0
* 2 + 10;
3049 if (coex_stat
->bt_info_hb0
<= 127)
3050 coex_stat
->bt_rssi
= 100;
3051 else if (256 - coex_stat
->bt_info_hb0
<= 100)
3052 coex_stat
->bt_rssi
= 100 - (256 - coex_stat
->bt_info_hb0
);
3054 coex_stat
->bt_rssi
= 0;
3057 if (coex_stat
->bt_info_hb1
& BIT(1))
3058 coex_stat
->cnt_bt
[COEX_CNT_BT_REINIT
]++;
3060 if (coex_stat
->bt_info_hb1
& BIT(2)) {
3061 coex_stat
->cnt_bt
[COEX_CNT_BT_SETUPLINK
]++;
3062 coex_stat
->bt_setup_link
= true;
3063 if (coex_stat
->bt_reenable
)
3064 bt_relink_time
= 6 * HZ
;
3066 bt_relink_time
= 1 * HZ
;
3068 ieee80211_queue_delayed_work(rtwdev
->hw
,
3069 &coex
->bt_relink_work
,
3072 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
3073 "[BTCoex], Re-Link start in BT info!!\n");
3076 if (coex_stat
->bt_info_hb1
& BIT(3))
3077 coex_stat
->cnt_bt
[COEX_CNT_BT_IGNWLANACT
]++;
3079 coex_stat
->bt_ble_voice
= ((coex_stat
->bt_info_hb1
& BIT(4)) == BIT(4));
3080 coex_stat
->bt_ble_scan_en
= ((coex_stat
->bt_info_hb1
& BIT(5)) == BIT(5));
3081 if (coex_stat
->bt_info_hb1
& BIT(6))
3082 coex_stat
->cnt_bt
[COEX_CNT_BT_ROLESWITCH
]++;
3084 coex_stat
->bt_multi_link
= ((coex_stat
->bt_info_hb1
& BIT(7)) == BIT(7));
3085 /* for multi_link = 0 but bt pkt remain exist */
3086 /* Use PS-TDMA to protect WL RX */
3087 if (!coex_stat
->bt_multi_link
&& coex_stat
->bt_multi_link_pre
) {
3088 coex_stat
->bt_multi_link_remain
= true;
3089 ieee80211_queue_delayed_work(rtwdev
->hw
,
3090 &coex
->bt_multi_link_remain_work
,
3093 coex_stat
->bt_multi_link_pre
= coex_stat
->bt_multi_link
;
3095 /* resend wifi info to bt, it is reset and lost the info */
3096 if (coex_stat
->bt_info_hb1
& BIT(1)) {
3097 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
3098 "[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n");
3100 if (coex_stat
->wl_connected
)
3101 type
= COEX_MEDIA_CONNECT
;
3103 type
= COEX_MEDIA_DISCONNECT
;
3104 rtw_coex_update_wl_ch_info(rtwdev
, type
);
3107 /* if ignore_wlan_act && not set_up_link */
3108 if ((coex_stat
->bt_info_hb1
& BIT(3)) &&
3109 (!(coex_stat
->bt_info_hb1
& BIT(2)))) {
3110 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
3111 "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
3112 rtw_coex_ignore_wlan_act(rtwdev
, false);
3115 coex_stat
->bt_opp_exist
= ((coex_stat
->bt_info_hb2
& BIT(0)) == BIT(0));
3116 if (coex_stat
->bt_info_hb2
& BIT(1))
3117 coex_stat
->cnt_bt
[COEX_CNT_BT_AFHUPDATE
]++;
3119 coex_stat
->bt_a2dp_active
= (coex_stat
->bt_info_hb2
& BIT(2)) == BIT(2);
3120 coex_stat
->bt_slave
= ((coex_stat
->bt_info_hb2
& BIT(3)) == BIT(3));
3121 coex_stat
->bt_hid_slot
= (coex_stat
->bt_info_hb2
& 0x30) >> 4;
3122 coex_stat
->bt_hid_pair_num
= (coex_stat
->bt_info_hb2
& 0xc0) >> 6;
3123 if (coex_stat
->bt_hid_pair_num
> 0 && coex_stat
->bt_hid_slot
>= 2)
3124 coex_stat
->bt_418_hid_exist
= true;
3125 else if (coex_stat
->bt_hid_pair_num
== 0 || coex_stat
->bt_hid_slot
== 1)
3126 coex_stat
->bt_418_hid_exist
= false;
3128 if ((coex_stat
->bt_info_lb2
& 0x49) == 0x49)
3129 coex_stat
->bt_a2dp_bitpool
= (coex_stat
->bt_info_hb3
& 0x7f);
3131 coex_stat
->bt_a2dp_bitpool
= 0;
3133 coex_stat
->bt_a2dp_sink
= ((coex_stat
->bt_info_hb3
& BIT(7)) == BIT(7));
3135 rtw_coex_update_bt_link_info(rtwdev
);
3136 rtw_coex_run_coex(rtwdev
, COEX_RSN_BTINFO
);
3139 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev
*rtwdev
, u8
*buf
, u8 length
)
3141 struct rtw_coex
*coex
= &rtwdev
->coex
;
3142 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
3146 rtw_dbg(rtwdev
, RTW_DBG_COEX
,
3147 "[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n",
3149 if (WARN(length
< 8, "invalid wl info c2h length\n"))
3155 for (i
= 1; i
< 8; i
++) {
3156 val
= coex_stat
->wl_fw_dbg_info_pre
[i
];
3158 coex_stat
->wl_fw_dbg_info
[i
] = buf
[i
] - val
;
3160 coex_stat
->wl_fw_dbg_info
[i
] = 255 - val
+ buf
[i
];
3162 coex_stat
->wl_fw_dbg_info_pre
[i
] = buf
[i
];
3165 coex_stat
->cnt_wl
[COEX_CNT_WL_FW_NOTIFY
]++;
3166 rtw_coex_wl_ccklock_action(rtwdev
);
3167 rtw_coex_wl_ccklock_detect(rtwdev
);
3170 void rtw_coex_wl_status_change_notify(struct rtw_dev
*rtwdev
, u32 type
)
3172 rtw_coex_run_coex(rtwdev
, COEX_RSN_WLSTATUS
);
3175 void rtw_coex_bt_relink_work(struct work_struct
*work
)
3177 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3178 coex
.bt_relink_work
.work
);
3179 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3181 mutex_lock(&rtwdev
->mutex
);
3182 coex_stat
->bt_setup_link
= false;
3183 rtw_coex_run_coex(rtwdev
, COEX_RSN_WLSTATUS
);
3184 mutex_unlock(&rtwdev
->mutex
);
3187 void rtw_coex_bt_reenable_work(struct work_struct
*work
)
3189 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3190 coex
.bt_reenable_work
.work
);
3191 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3193 mutex_lock(&rtwdev
->mutex
);
3194 coex_stat
->bt_reenable
= false;
3195 mutex_unlock(&rtwdev
->mutex
);
3198 void rtw_coex_defreeze_work(struct work_struct
*work
)
3200 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3201 coex
.defreeze_work
.work
);
3202 struct rtw_coex
*coex
= &rtwdev
->coex
;
3203 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3205 mutex_lock(&rtwdev
->mutex
);
3206 coex
->freeze
= false;
3207 coex_stat
->wl_hi_pri_task1
= false;
3208 rtw_coex_run_coex(rtwdev
, COEX_RSN_WLSTATUS
);
3209 mutex_unlock(&rtwdev
->mutex
);
3212 void rtw_coex_wl_remain_work(struct work_struct
*work
)
3214 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3215 coex
.wl_remain_work
.work
);
3216 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3218 mutex_lock(&rtwdev
->mutex
);
3219 coex_stat
->wl_gl_busy
= test_bit(RTW_FLAG_BUSY_TRAFFIC
, rtwdev
->flags
);
3220 rtw_coex_run_coex(rtwdev
, COEX_RSN_WLSTATUS
);
3221 mutex_unlock(&rtwdev
->mutex
);
3224 void rtw_coex_bt_remain_work(struct work_struct
*work
)
3226 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3227 coex
.bt_remain_work
.work
);
3228 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3230 mutex_lock(&rtwdev
->mutex
);
3231 coex_stat
->bt_inq_remain
= coex_stat
->bt_inq_page
;
3232 rtw_coex_run_coex(rtwdev
, COEX_RSN_BTSTATUS
);
3233 mutex_unlock(&rtwdev
->mutex
);
3236 void rtw_coex_wl_connecting_work(struct work_struct
*work
)
3238 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3239 coex
.wl_connecting_work
.work
);
3240 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3242 mutex_lock(&rtwdev
->mutex
);
3243 coex_stat
->wl_connecting
= false;
3244 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], WL connecting stop!!\n");
3245 rtw_coex_run_coex(rtwdev
, COEX_RSN_WLSTATUS
);
3246 mutex_unlock(&rtwdev
->mutex
);
3249 void rtw_coex_bt_multi_link_remain_work(struct work_struct
*work
)
3251 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3252 coex
.bt_multi_link_remain_work
.work
);
3253 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3255 mutex_lock(&rtwdev
->mutex
);
3256 coex_stat
->bt_multi_link_remain
= false;
3257 mutex_unlock(&rtwdev
->mutex
);
3260 void rtw_coex_wl_ccklock_work(struct work_struct
*work
)
3262 struct rtw_dev
*rtwdev
= container_of(work
, struct rtw_dev
,
3263 coex
.wl_ccklock_work
.work
);
3264 struct rtw_coex_stat
*coex_stat
= &rtwdev
->coex
.stat
;
3266 mutex_lock(&rtwdev
->mutex
);
3267 coex_stat
->wl_cck_lock
= false;
3268 mutex_unlock(&rtwdev
->mutex
);
3271 #ifdef CONFIG_RTW88_DEBUGFS
3272 #define INFO_SIZE 80
3274 #define case_BTINFO(src) \
3275 case COEX_BTINFO_SRC_##src: return #src
3277 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src
)
3279 switch (bt_info_src
) {
3281 case_BTINFO(BT_RSP
);
3282 case_BTINFO(BT_ACT
);
3288 #define case_RSN(src) \
3289 case COEX_RSN_##src: return #src
3291 static const char *rtw_coex_get_reason_string(u8 reason
)
3294 case_RSN(2GSCANSTART
);
3295 case_RSN(5GSCANSTART
);
3296 case_RSN(SCANFINISH
);
3297 case_RSN(2GSWITCHBAND
);
3298 case_RSN(5GSWITCHBAND
);
3299 case_RSN(2GCONSTART
);
3300 case_RSN(5GCONSTART
);
3301 case_RSN(2GCONFINISH
);
3302 case_RSN(5GCONFINISH
);
3305 case_RSN(MEDIADISCON
);
3314 static u8
rtw_coex_get_table_index(struct rtw_dev
*rtwdev
, u32 wl_reg_6c0
,
3317 struct rtw_chip_info
*chip
= rtwdev
->chip
;
3318 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
3323 bool share_ant
= efuse
->share_ant
;
3326 n
= chip
->table_sant_num
;
3328 n
= chip
->table_nsant_num
;
3330 for (i
= 0; i
< n
; i
++) {
3332 load_bt_val
= chip
->table_sant
[i
].bt
;
3333 load_wl_val
= chip
->table_sant
[i
].wl
;
3335 load_bt_val
= chip
->table_nsant
[i
].bt
;
3336 load_wl_val
= chip
->table_nsant
[i
].wl
;
3339 if (wl_reg_6c0
== load_bt_val
&&
3340 wl_reg_6c4
== load_wl_val
) {
3351 static u8
rtw_coex_get_tdma_index(struct rtw_dev
*rtwdev
, u8
*tdma_para
)
3353 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
3354 struct rtw_chip_info
*chip
= rtwdev
->chip
;
3357 u8 load_cur_tab_val
;
3359 bool share_ant
= efuse
->share_ant
;
3362 n
= chip
->tdma_sant_num
;
3364 n
= chip
->tdma_nsant_num
;
3366 for (i
= 0; i
< n
; i
++) {
3368 for (j
= 0; j
< 5; j
++) {
3370 load_cur_tab_val
= chip
->tdma_sant
[i
].para
[j
];
3372 load_cur_tab_val
= chip
->tdma_nsant
[i
].para
[j
];
3374 if (*(tdma_para
+ j
) != load_cur_tab_val
)
3389 static int rtw_coex_addr_info(struct rtw_dev
*rtwdev
,
3390 const struct rtw_reg_domain
*reg
,
3391 char addr_info
[], int n
)
3393 const char *rf_prefix
= "";
3394 const char *sep
= n
== 0 ? "" : "/ ";
3398 if (INFO_SIZE
- n
<= 0)
3401 switch (reg
->domain
) {
3402 case RTW_REG_DOMAIN_MAC32
:
3405 case RTW_REG_DOMAIN_MAC16
:
3408 case RTW_REG_DOMAIN_MAC8
:
3411 case RTW_REG_DOMAIN_RF_A
:
3412 case RTW_REG_DOMAIN_RF_B
:
3420 ffs
= __ffs(reg
->mask
);
3421 fls
= __fls(reg
->mask
);
3423 if (ffs
== 0 && fls
== max_fls
)
3424 return scnprintf(addr_info
+ n
, INFO_SIZE
- n
, "%s%s%x",
3425 sep
, rf_prefix
, reg
->addr
);
3426 else if (ffs
== fls
)
3427 return scnprintf(addr_info
+ n
, INFO_SIZE
- n
, "%s%s%x[%d]",
3428 sep
, rf_prefix
, reg
->addr
, ffs
);
3430 return scnprintf(addr_info
+ n
, INFO_SIZE
- n
, "%s%s%x[%d:%d]",
3431 sep
, rf_prefix
, reg
->addr
, fls
, ffs
);
3434 static int rtw_coex_val_info(struct rtw_dev
*rtwdev
,
3435 const struct rtw_reg_domain
*reg
,
3436 char val_info
[], int n
)
3438 const char *sep
= n
== 0 ? "" : "/ ";
3441 if (INFO_SIZE
- n
<= 0)
3444 switch (reg
->domain
) {
3445 case RTW_REG_DOMAIN_MAC32
:
3446 return scnprintf(val_info
+ n
, INFO_SIZE
- n
, "%s0x%x", sep
,
3447 rtw_read32_mask(rtwdev
, reg
->addr
, reg
->mask
));
3448 case RTW_REG_DOMAIN_MAC16
:
3449 return scnprintf(val_info
+ n
, INFO_SIZE
- n
, "%s0x%x", sep
,
3450 rtw_read16_mask(rtwdev
, reg
->addr
, reg
->mask
));
3451 case RTW_REG_DOMAIN_MAC8
:
3452 return scnprintf(val_info
+ n
, INFO_SIZE
- n
, "%s0x%x", sep
,
3453 rtw_read8_mask(rtwdev
, reg
->addr
, reg
->mask
));
3454 case RTW_REG_DOMAIN_RF_A
:
3455 rf_path
= RF_PATH_A
;
3457 case RTW_REG_DOMAIN_RF_B
:
3458 rf_path
= RF_PATH_B
;
3464 /* only RF go through here */
3465 return scnprintf(val_info
+ n
, INFO_SIZE
- n
, "%s0x%x", sep
,
3466 rtw_read_rf(rtwdev
, rf_path
, reg
->addr
, reg
->mask
));
3469 static void rtw_coex_set_coexinfo_hw(struct rtw_dev
*rtwdev
, struct seq_file
*m
)
3471 struct rtw_chip_info
*chip
= rtwdev
->chip
;
3472 const struct rtw_reg_domain
*reg
;
3473 char addr_info
[INFO_SIZE
];
3475 char val_info
[INFO_SIZE
];
3479 for (i
= 0; i
< chip
->coex_info_hw_regs_num
; i
++) {
3480 reg
= &chip
->coex_info_hw_regs
[i
];
3482 n_addr
+= rtw_coex_addr_info(rtwdev
, reg
, addr_info
, n_addr
);
3483 n_val
+= rtw_coex_val_info(rtwdev
, reg
, val_info
, n_val
);
3485 if (reg
->domain
== RTW_REG_DOMAIN_NL
) {
3486 seq_printf(m
, "%-40s = %s\n", addr_info
, val_info
);
3492 if (n_addr
!= 0 && n_val
!= 0)
3493 seq_printf(m
, "%-40s = %s\n", addr_info
, val_info
);
3496 static bool rtw_coex_get_bt_reg(struct rtw_dev
*rtwdev
,
3497 u8 type
, u16 addr
, u16
*val
)
3499 struct rtw_coex_info_req req
= {0};
3500 struct sk_buff
*skb
;
3504 le_addr
= cpu_to_le16(addr
);
3505 req
.op_code
= BT_MP_INFO_OP_READ_REG
;
3507 req
.para2
= le16_get_bits(le_addr
, GENMASK(7, 0));
3508 req
.para3
= le16_get_bits(le_addr
, GENMASK(15, 8));
3509 skb
= rtw_coex_info_request(rtwdev
, &req
);
3515 payload
= get_payload_from_coex_resp(skb
);
3516 *val
= GET_COEX_RESP_BT_REG_VAL(payload
);
3521 static bool rtw_coex_get_bt_patch_version(struct rtw_dev
*rtwdev
,
3524 struct rtw_coex_info_req req
= {0};
3525 struct sk_buff
*skb
;
3529 req
.op_code
= BT_MP_INFO_OP_PATCH_VER
;
3530 skb
= rtw_coex_info_request(rtwdev
, &req
);
3534 payload
= get_payload_from_coex_resp(skb
);
3535 *patch_version
= GET_COEX_RESP_BT_PATCH_VER(payload
);
3542 static bool rtw_coex_get_bt_supported_version(struct rtw_dev
*rtwdev
,
3543 u32
*supported_version
)
3545 struct rtw_coex_info_req req
= {0};
3546 struct sk_buff
*skb
;
3550 req
.op_code
= BT_MP_INFO_OP_SUPP_VER
;
3551 skb
= rtw_coex_info_request(rtwdev
, &req
);
3555 payload
= get_payload_from_coex_resp(skb
);
3556 *supported_version
= GET_COEX_RESP_BT_SUPP_VER(payload
);
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
;
3571 req
.op_code
= BT_MP_INFO_OP_SUPP_FEAT
;
3572 skb
= rtw_coex_info_request(rtwdev
, &req
);
3576 payload
= get_payload_from_coex_resp(skb
);
3577 *supported_feature
= GET_COEX_RESP_BT_SUPP_FEAT(payload
);
3584 struct rtw_coex_sta_stat_iter_data
{
3585 struct rtw_vif
*rtwvif
;
3586 struct seq_file
*file
;
3589 static void rtw_coex_sta_stat_iter(void *data
, struct ieee80211_sta
*sta
)
3591 struct rtw_coex_sta_stat_iter_data
*sta_iter_data
= data
;
3592 struct rtw_vif
*rtwvif
= sta_iter_data
->rtwvif
;
3593 struct rtw_sta_info
*si
= (struct rtw_sta_info
*)sta
->drv_priv
;
3594 struct seq_file
*m
= sta_iter_data
->file
;
3595 struct ieee80211_vif
*vif
= rtwvif_to_vif(rtwvif
);
3601 rssi
= ewma_rssi_read(&si
->avg_rssi
);
3602 seq_printf(m
, "\tPeer %3d\n", si
->mac_id
);
3603 seq_printf(m
, "\t\t%-24s = %d\n", "RSSI", rssi
);
3604 seq_printf(m
, "\t\t%-24s = %d\n", "BW mode", si
->bw_mode
);
3607 struct rtw_coex_vif_stat_iter_data
{
3608 struct rtw_dev
*rtwdev
;
3609 struct seq_file
*file
;
3612 static void rtw_coex_vif_stat_iter(void *data
, u8
*mac
,
3613 struct ieee80211_vif
*vif
)
3615 struct rtw_coex_vif_stat_iter_data
*vif_iter_data
= data
;
3616 struct rtw_coex_sta_stat_iter_data sta_iter_data
;
3617 struct rtw_dev
*rtwdev
= vif_iter_data
->rtwdev
;
3618 struct rtw_vif
*rtwvif
= (struct rtw_vif
*)vif
->drv_priv
;
3619 struct seq_file
*m
= vif_iter_data
->file
;
3620 struct ieee80211_bss_conf
*bss_conf
= &vif
->bss_conf
;
3622 seq_printf(m
, "Iface on Port (%d)\n", rtwvif
->port
);
3623 seq_printf(m
, "\t%-32s = %d\n",
3624 "Beacon interval", bss_conf
->beacon_int
);
3625 seq_printf(m
, "\t%-32s = %d\n",
3626 "Network Type", rtwvif
->net_type
);
3628 sta_iter_data
.rtwvif
= rtwvif
;
3629 sta_iter_data
.file
= m
;
3630 rtw_iterate_stas_atomic(rtwdev
, rtw_coex_sta_stat_iter
,
3634 #define case_WLINK(src) \
3635 case COEX_WLINK_##src: return #src
3637 static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode
)
3639 switch (coex_wl_link_mode
) {
3640 case_WLINK(2G1PORT
);
3647 void rtw_coex_display_coex_info(struct rtw_dev
*rtwdev
, struct seq_file
*m
)
3649 struct rtw_chip_info
*chip
= rtwdev
->chip
;
3650 struct rtw_dm_info
*dm_info
= &rtwdev
->dm_info
;
3651 struct rtw_coex
*coex
= &rtwdev
->coex
;
3652 struct rtw_coex_stat
*coex_stat
= &coex
->stat
;
3653 struct rtw_coex_dm
*coex_dm
= &coex
->dm
;
3654 struct rtw_hal
*hal
= &rtwdev
->hal
;
3655 struct rtw_efuse
*efuse
= &rtwdev
->efuse
;
3656 struct rtw_fw_state
*fw
= &rtwdev
->fw
;
3657 struct rtw_coex_vif_stat_iter_data vif_iter_data
;
3658 u8 reason
= coex_dm
->reason
;
3660 u16 score_board_WB
, score_board_BW
;
3661 u32 wl_reg_6c0
, wl_reg_6c4
, wl_reg_6c8
, wl_reg_778
, wl_reg_6cc
;
3662 u32 lte_coex
, bt_coex
;
3663 u32 bt_hi_pri
, bt_lo_pri
;
3666 score_board_BW
= rtw_coex_read_scbd(rtwdev
);
3667 score_board_WB
= coex_stat
->score_board
;
3668 wl_reg_6c0
= rtw_read32(rtwdev
, REG_BT_COEX_TABLE0
);
3669 wl_reg_6c4
= rtw_read32(rtwdev
, REG_BT_COEX_TABLE1
);
3670 wl_reg_6c8
= rtw_read32(rtwdev
, REG_BT_COEX_BRK_TABLE
);
3671 wl_reg_6cc
= rtw_read32(rtwdev
, REG_BT_COEX_TABLE_H
);
3672 wl_reg_778
= rtw_read8(rtwdev
, REG_BT_STAT_CTRL
);
3674 bt_hi_pri
= rtw_read32(rtwdev
, REG_BT_ACT_STATISTICS
);
3675 bt_lo_pri
= rtw_read32(rtwdev
, REG_BT_ACT_STATISTICS_1
);
3676 rtw_write8(rtwdev
, REG_BT_COEX_ENH_INTR_CTRL
,
3677 BIT_R_GRANTALL_WLMASK
| BIT_STATIS_BT_EN
);
3679 coex_stat
->hi_pri_tx
= FIELD_GET(MASKLWORD
, bt_hi_pri
);
3680 coex_stat
->hi_pri_rx
= FIELD_GET(MASKHWORD
, bt_hi_pri
);
3682 coex_stat
->lo_pri_tx
= FIELD_GET(MASKLWORD
, bt_lo_pri
);
3683 coex_stat
->lo_pri_rx
= FIELD_GET(MASKHWORD
, bt_lo_pri
);
3685 sys_lte
= rtw_read8(rtwdev
, 0x73);
3686 lte_coex
= rtw_coex_read_indirect_reg(rtwdev
, 0x38);
3687 bt_coex
= rtw_coex_read_indirect_reg(rtwdev
, 0x54);
3689 if (!coex_stat
->bt_disabled
&& !coex_stat
->bt_mailbox_reply
) {
3690 rtw_coex_get_bt_supported_version(rtwdev
,
3691 &coex_stat
->bt_supported_version
);
3692 rtw_coex_get_bt_patch_version(rtwdev
, &coex_stat
->patch_ver
);
3693 rtw_coex_get_bt_supported_feature(rtwdev
,
3694 &coex_stat
->bt_supported_feature
);
3695 rtw_coex_get_bt_reg(rtwdev
, 3, 0xae, &coex_stat
->bt_reg_vendor_ae
);
3696 rtw_coex_get_bt_reg(rtwdev
, 3, 0xac, &coex_stat
->bt_reg_vendor_ac
);
3698 if (coex_stat
->patch_ver
!= 0)
3699 coex_stat
->bt_mailbox_reply
= true;
3702 rtw_dbg(rtwdev
, RTW_DBG_COEX
, "[BTCoex], %s()\n", __func__
);
3703 seq_printf(m
, "**********************************************\n");
3704 seq_printf(m
, "\t\tBT Coexist info %x\n", chip
->id
);
3705 seq_printf(m
, "**********************************************\n");
3707 if (coex
->manual_control
) {
3708 seq_puts(m
, "============[Under Manual Control]============\n");
3709 seq_puts(m
, "==========================================\n");
3711 } else if (coex
->stop_dm
) {
3712 seq_puts(m
, "============[Coex is STOPPED]============\n");
3713 seq_puts(m
, "==========================================\n");
3715 } else if (coex
->freeze
) {
3716 seq_puts(m
, "============[coex_freeze]============\n");
3717 seq_puts(m
, "==========================================\n");
3720 seq_printf(m
, "%-40s = %s/ %d\n",
3722 efuse
->share_ant
? "Shared" : "Non-Shared",
3724 seq_printf(m
, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
3725 "Coex Ver/ BT Dez/ BT Rpt",
3726 chip
->coex_para_ver
, chip
->bt_desired_ver
,
3727 coex_stat
->bt_supported_version
,
3728 coex_stat
->bt_disabled
? "(BT disabled)" :
3729 coex_stat
->bt_supported_version
>= chip
->bt_desired_ver
?
3730 "(Match)" : "(Mismatch)");
3731 seq_printf(m
, "%-40s = %s/ %u/ %d\n",
3732 "Role/ RoleSwCnt/ IgnWL/ Feature",
3733 coex_stat
->bt_slave
? "Slave" : "Master",
3734 coex_stat
->cnt_bt
[COEX_CNT_BT_ROLESWITCH
],
3735 coex_dm
->ignore_wl_act
);
3736 seq_printf(m
, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n",
3737 "WL FW/ BT FW/ BT FW Desired/ KT",
3738 fw
->version
, fw
->sub_version
,
3739 coex_stat
->patch_ver
,
3740 chip
->wl_fw_desired_ver
, coex_stat
->kt_ver
+ 65);
3741 seq_printf(m
, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
3743 coex_dm
->wl_ch_info
[0], coex_dm
->wl_ch_info
[1],
3744 coex_dm
->wl_ch_info
[2], hal
->current_channel
);
3746 rtw_debugfs_get_simple_phy_info(m
);
3747 seq_printf(m
, "**********************************************\n");
3748 seq_printf(m
, "\t\tBT Status\n");
3749 seq_printf(m
, "**********************************************\n");
3750 seq_printf(m
, "%-40s = %s/ %ddBm/ %u/ %u\n",
3751 "BT status/ rssi/ retry/ pop",
3752 coex_dm
->bt_status
== COEX_BTSTATUS_NCON_IDLE
? "non-conn" :
3753 coex_dm
->bt_status
== COEX_BTSTATUS_CON_IDLE
? "conn-idle" : "busy",
3754 coex_stat
->bt_rssi
- 100,
3755 coex_stat
->cnt_bt
[COEX_CNT_BT_RETRY
],
3756 coex_stat
->cnt_bt
[COEX_CNT_BT_POPEVENT
]);
3757 seq_printf(m
, "%-40s = %s%s%s%s%s (multi-link %d)\n",
3759 coex_stat
->bt_a2dp_exist
? (coex_stat
->bt_a2dp_sink
?
3760 "A2DP sink," : "A2DP,") : "",
3761 coex_stat
->bt_hfp_exist
? "HFP," : "",
3762 coex_stat
->bt_hid_exist
?
3763 (coex_stat
->bt_ble_exist
? "HID(RCU)," :
3764 coex_stat
->bt_hid_slot
>= 2 ? "HID(4/18)" :
3765 coex_stat
->bt_ble_hid_exist
? "HID(BLE)" :
3767 coex_stat
->bt_pan_exist
? coex_stat
->bt_opp_exist
?
3768 "OPP," : "PAN," : "",
3769 coex_stat
->bt_ble_voice
? "Voice," : "",
3770 coex_stat
->bt_multi_link
);
3771 seq_printf(m
, "%-40s = %u/ %u/ %u/ 0x%08x\n",
3772 "Reinit/ Relink/ IgnWl/ Feature",
3773 coex_stat
->cnt_bt
[COEX_CNT_BT_REINIT
],
3774 coex_stat
->cnt_bt
[COEX_CNT_BT_SETUPLINK
],
3775 coex_stat
->cnt_bt
[COEX_CNT_BT_IGNWLANACT
],
3776 coex_stat
->bt_supported_feature
);
3777 seq_printf(m
, "%-40s = %u/ %u/ %u/ %u\n",
3778 "Page/ Inq/ iqk/ iqk fail",
3779 coex_stat
->cnt_bt
[COEX_CNT_BT_PAGE
],
3780 coex_stat
->cnt_bt
[COEX_CNT_BT_INQ
],
3781 coex_stat
->cnt_bt
[COEX_CNT_BT_IQK
],
3782 coex_stat
->cnt_bt
[COEX_CNT_BT_IQKFAIL
]);
3783 seq_printf(m
, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
3784 "0xae/ 0xac/ score board (W->B)/ (B->W)",
3785 coex_stat
->bt_reg_vendor_ae
,
3786 coex_stat
->bt_reg_vendor_ac
,
3787 score_board_WB
, score_board_BW
);
3788 seq_printf(m
, "%-40s = %u/%u, %u/%u\n",
3789 "Hi-Pri TX/RX, Lo-Pri TX/RX",
3790 coex_stat
->hi_pri_tx
, coex_stat
->hi_pri_rx
,
3791 coex_stat
->lo_pri_tx
, coex_stat
->lo_pri_rx
);
3792 for (i
= 0; i
< COEX_BTINFO_SRC_BT_IQK
; i
++)
3793 seq_printf(m
, "%-40s = %7ph\n",
3794 rtw_coex_get_bt_info_src_string(i
),
3795 coex_stat
->bt_info_c2h
[i
]);
3797 seq_printf(m
, "**********************************************\n");
3798 seq_printf(m
, "\t\tWiFi Status\n");
3799 seq_printf(m
, "**********************************************\n");
3800 seq_printf(m
, "%-40s = %d\n",
3801 "Scanning", test_bit(RTW_FLAG_SCANNING
, rtwdev
->flags
));
3802 seq_printf(m
, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
3804 coex_stat
->wl_gl_busy
,
3805 rtwdev
->stats
.tx_throughput
, rtwdev
->stats
.rx_throughput
);
3806 seq_printf(m
, "%-40s = %u/ %u/ %u\n",
3807 "IPS/ Low Power/ PS mode",
3808 test_bit(RTW_FLAG_INACTIVE_PS
, rtwdev
->flags
),
3809 test_bit(RTW_FLAG_LEISURE_PS_DEEP
, rtwdev
->flags
),
3810 rtwdev
->lps_conf
.mode
);
3812 vif_iter_data
.rtwdev
= rtwdev
;
3813 vif_iter_data
.file
= m
;
3814 rtw_iterate_vifs_atomic(rtwdev
, rtw_coex_vif_stat_iter
, &vif_iter_data
);
3816 if (coex
->manual_control
) {
3817 seq_printf(m
, "**********************************************\n");
3818 seq_printf(m
, "\t\tMechanism (Under Manual)\n");
3819 seq_printf(m
, "**********************************************\n");
3820 seq_printf(m
, "%-40s = %5ph (%d)\n",
3822 coex_dm
->fw_tdma_para
,
3823 rtw_coex_get_tdma_index(rtwdev
,
3824 &coex_dm
->fw_tdma_para
[0]));
3826 seq_printf(m
, "**********************************************\n");
3827 seq_printf(m
, "\t\tMechanism\n");
3828 seq_printf(m
, "**********************************************\n");
3829 seq_printf(m
, "%-40s = %5ph (case-%d)\n",
3831 coex_dm
->ps_tdma_para
, coex_dm
->cur_ps_tdma
);
3833 seq_printf(m
, "%-40s = %s/ %s/ %d\n",
3834 "Coex Mode/Free Run/Timer base",
3835 rtw_coex_get_wl_coex_mode(coex_stat
->wl_coex_mode
),
3836 coex
->freerun
? "Yes" : "No",
3837 coex_stat
->tdma_timer_base
);
3838 seq_printf(m
, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n",
3839 "Table/ 0x6c0/ 0x6c4/ 0x6c8",
3841 rtw_coex_get_table_index(rtwdev
, wl_reg_6c0
, wl_reg_6c4
),
3842 wl_reg_6c0
, wl_reg_6c4
, wl_reg_6c8
);
3843 seq_printf(m
, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n",
3844 "0x778/ 0x6cc/ Run Count/ Reason",
3845 wl_reg_778
, wl_reg_6cc
,
3846 coex_stat
->cnt_wl
[COEX_CNT_WL_COEXRUN
],
3847 rtw_coex_get_reason_string(reason
));
3848 seq_printf(m
, "%-40s = %3ph\n",
3850 coex_dm
->wl_ch_info
);
3851 seq_printf(m
, "%-40s = %s/ %d\n",
3852 "AntDiv/ BtCtrlLPS/ g_busy",
3853 coex_stat
->wl_force_lps_ctrl
? "On" : "Off",
3854 coex_stat
->wl_gl_busy
);
3855 seq_printf(m
, "%-40s = %u/ %u/ %u/ %u/ %u\n",
3856 "Null All/ Retry/ Ack/ BT Empty/ BT Late",
3857 coex_stat
->wl_fw_dbg_info
[1], coex_stat
->wl_fw_dbg_info
[2],
3858 coex_stat
->wl_fw_dbg_info
[3], coex_stat
->wl_fw_dbg_info
[4],
3859 coex_stat
->wl_fw_dbg_info
[5]);
3860 seq_printf(m
, "%-40s = %u/ %u/ %s/ %u\n",
3861 "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
3862 coex_stat
->wl_fw_dbg_info
[6],
3863 coex_stat
->wl_fw_dbg_info
[7],
3864 coex_stat
->wl_slot_extend
? "Yes" : "No",
3865 coex_stat
->cnt_wl
[COEX_CNT_WL_FW_NOTIFY
]);
3866 seq_printf(m
, "%-40s = %d/ %d/ %s/ %d\n",
3867 "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl",
3868 coex_dm
->cur_wl_pwr_lvl
,
3869 coex_dm
->cur_bt_pwr_lvl
,
3870 coex_dm
->cur_wl_rx_low_gain_en
? "On" : "Off",
3871 coex_dm
->cur_bt_lna_lvl
);
3873 seq_printf(m
, "**********************************************\n");
3874 seq_printf(m
, "\t\tHW setting\n");
3875 seq_printf(m
, "**********************************************\n");
3876 seq_printf(m
, "%-40s = %s/ %s\n",
3877 "LTE Coex/ Path Owner",
3878 lte_coex
& BIT(7) ? "ON" : "OFF",
3879 sys_lte
& BIT(2) ? "WL" : "BT");
3880 seq_printf(m
, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
3881 "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
3882 lte_coex
& BIT(12) ? "SW" : "HW",
3883 lte_coex
& BIT(8) ? "SW" : "HW",
3884 lte_coex
& BIT(14) ? "SW" : "HW",
3885 lte_coex
& BIT(10) ? "SW" : "HW",
3886 sys_lte
& BIT(3) ? "On" : "Off");
3887 seq_printf(m
, "%-40s = %lu/ %lu\n",
3889 (bt_coex
& BIT(2)) >> 2, (bt_coex
& BIT(3)) >> 3);
3890 seq_printf(m
, "%-40s = %u/ %u/ %u/ %u\n",
3891 "CRC OK CCK/ OFDM/ HT/ VHT",
3892 dm_info
->cck_ok_cnt
, dm_info
->ofdm_ok_cnt
,
3893 dm_info
->ht_ok_cnt
, dm_info
->vht_ok_cnt
);
3894 seq_printf(m
, "%-40s = %u/ %u/ %u/ %u\n",
3895 "CRC ERR CCK/ OFDM/ HT/ VHT",
3896 dm_info
->cck_err_cnt
, dm_info
->ofdm_err_cnt
,
3897 dm_info
->ht_err_cnt
, dm_info
->vht_err_cnt
);
3898 seq_printf(m
, "%-40s = %s/ %s/ %s/ %u\n",
3899 "HiPr/ Locking/ Locked/ Noisy",
3900 coex_stat
->wl_hi_pri_task1
? "Y" : "N",
3901 coex_stat
->wl_cck_lock
? "Y" : "N",
3902 coex_stat
->wl_cck_lock_ever
? "Y" : "N",
3903 coex_stat
->wl_noisy_level
);
3905 rtw_coex_set_coexinfo_hw(rtwdev
, m
);
3906 seq_printf(m
, "%-40s = %d/ %d/ %d/ %d\n",
3907 "EVM A/ EVM B/ SNR A/ SNR B",
3908 -dm_info
->rx_evm_dbm
[RF_PATH_A
],
3909 -dm_info
->rx_evm_dbm
[RF_PATH_B
],
3910 -dm_info
->rx_snr
[RF_PATH_A
],
3911 -dm_info
->rx_snr
[RF_PATH_B
]);
3912 seq_printf(m
, "%-40s = %d/ %d/ %d/ %d\n",
3913 "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA",
3914 dm_info
->cck_cca_cnt
, dm_info
->cck_fa_cnt
,
3915 dm_info
->ofdm_cca_cnt
, dm_info
->ofdm_fa_cnt
);
3916 seq_printf(m
, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac",
3917 dm_info
->cck_ok_cnt
, dm_info
->ofdm_ok_cnt
,
3918 dm_info
->ht_ok_cnt
, dm_info
->vht_ok_cnt
);
3919 seq_printf(m
, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac",
3920 dm_info
->cck_err_cnt
, dm_info
->ofdm_err_cnt
,
3921 dm_info
->ht_err_cnt
, dm_info
->vht_err_cnt
);
3924 #endif /* CONFIG_RTW88_DEBUGFS */