cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

coex.c (115865B)


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