xref: /freebsd/sys/contrib/dev/rtw89/coex.c (revision 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75)
18e93258fSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
28e93258fSBjoern A. Zeeb /* Copyright(c) 2019-2020  Realtek Corporation
38e93258fSBjoern A. Zeeb  */
48e93258fSBjoern A. Zeeb 
58e93258fSBjoern A. Zeeb #include "coex.h"
68e93258fSBjoern A. Zeeb #include "debug.h"
78e93258fSBjoern A. Zeeb #include "fw.h"
88e93258fSBjoern A. Zeeb #include "mac.h"
9*6d67aabdSBjoern A. Zeeb #include "phy.h"
108e93258fSBjoern A. Zeeb #include "ps.h"
118e93258fSBjoern A. Zeeb #include "reg.h"
128e93258fSBjoern A. Zeeb 
13e2340276SBjoern A. Zeeb #define RTW89_COEX_VERSION 0x07000113
148e93258fSBjoern A. Zeeb #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
15*6d67aabdSBjoern A. Zeeb #define BTC_E2G_LIMIT_DEF 80
168e93258fSBjoern A. Zeeb 
178e93258fSBjoern A. Zeeb enum btc_fbtc_tdma_template {
188e93258fSBjoern A. Zeeb 	CXTD_OFF = 0x0,
198e93258fSBjoern A. Zeeb 	CXTD_OFF_B2,
208e93258fSBjoern A. Zeeb 	CXTD_OFF_EXT,
218e93258fSBjoern A. Zeeb 	CXTD_FIX,
228e93258fSBjoern A. Zeeb 	CXTD_PFIX,
238e93258fSBjoern A. Zeeb 	CXTD_AUTO,
248e93258fSBjoern A. Zeeb 	CXTD_PAUTO,
258e93258fSBjoern A. Zeeb 	CXTD_AUTO2,
268e93258fSBjoern A. Zeeb 	CXTD_PAUTO2,
278e93258fSBjoern A. Zeeb 	CXTD_MAX,
288e93258fSBjoern A. Zeeb };
298e93258fSBjoern A. Zeeb 
308e93258fSBjoern A. Zeeb enum btc_fbtc_tdma_type {
318e93258fSBjoern A. Zeeb 	CXTDMA_OFF = 0x0,
328e93258fSBjoern A. Zeeb 	CXTDMA_FIX = 0x1,
338e93258fSBjoern A. Zeeb 	CXTDMA_AUTO = 0x2,
348e93258fSBjoern A. Zeeb 	CXTDMA_AUTO2 = 0x3,
358e93258fSBjoern A. Zeeb 	CXTDMA_MAX
368e93258fSBjoern A. Zeeb };
378e93258fSBjoern A. Zeeb 
388e93258fSBjoern A. Zeeb enum btc_fbtc_tdma_rx_flow_ctrl {
398e93258fSBjoern A. Zeeb 	CXFLC_OFF = 0x0,
408e93258fSBjoern A. Zeeb 	CXFLC_NULLP = 0x1,
418e93258fSBjoern A. Zeeb 	CXFLC_QOSNULL = 0x2,
428e93258fSBjoern A. Zeeb 	CXFLC_CTS = 0x3,
438e93258fSBjoern A. Zeeb 	CXFLC_MAX
448e93258fSBjoern A. Zeeb };
458e93258fSBjoern A. Zeeb 
468e93258fSBjoern A. Zeeb enum btc_fbtc_tdma_wlan_tx_pause {
478e93258fSBjoern A. Zeeb 	CXTPS_OFF = 0x0,  /* no wl tx pause*/
488e93258fSBjoern A. Zeeb 	CXTPS_ON = 0x1,
498e93258fSBjoern A. Zeeb 	CXTPS_MAX
508e93258fSBjoern A. Zeeb };
518e93258fSBjoern A. Zeeb 
528e93258fSBjoern A. Zeeb enum btc_mlme_state {
538e93258fSBjoern A. Zeeb 	MLME_NO_LINK,
548e93258fSBjoern A. Zeeb 	MLME_LINKING,
558e93258fSBjoern A. Zeeb 	MLME_LINKED,
568e93258fSBjoern A. Zeeb };
578e93258fSBjoern A. Zeeb 
588e93258fSBjoern A. Zeeb struct btc_fbtc_1slot {
598e93258fSBjoern A. Zeeb 	u8 fver;
608e93258fSBjoern A. Zeeb 	u8 sid; /* slot id */
618e93258fSBjoern A. Zeeb 	struct rtw89_btc_fbtc_slot slot;
628e93258fSBjoern A. Zeeb } __packed;
638e93258fSBjoern A. Zeeb 
648e93258fSBjoern A. Zeeb static const struct rtw89_btc_fbtc_tdma t_def[] = {
658e93258fSBjoern A. Zeeb 	[CXTD_OFF]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
668e93258fSBjoern A. Zeeb 	[CXTD_OFF_B2]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
67e2340276SBjoern A. Zeeb 	[CXTD_OFF_EXT]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
688e93258fSBjoern A. Zeeb 	[CXTD_FIX]	= { CXTDMA_FIX,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
698e93258fSBjoern A. Zeeb 	[CXTD_PFIX]	= { CXTDMA_FIX,  CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
708e93258fSBjoern A. Zeeb 	[CXTD_AUTO]	= { CXTDMA_AUTO,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
718e93258fSBjoern A. Zeeb 	[CXTD_PAUTO]	= { CXTDMA_AUTO, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
728e93258fSBjoern A. Zeeb 	[CXTD_AUTO2]	= {CXTDMA_AUTO2,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
738e93258fSBjoern A. Zeeb 	[CXTD_PAUTO2]	= {CXTDMA_AUTO2, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0}
748e93258fSBjoern A. Zeeb };
758e93258fSBjoern A. Zeeb 
768e93258fSBjoern A. Zeeb #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
778e93258fSBjoern A. Zeeb 	{ .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
788e93258fSBjoern A. Zeeb 	  .cxtype = cpu_to_le16(__cxtype),}
798e93258fSBjoern A. Zeeb 
808e93258fSBjoern A. Zeeb static const struct rtw89_btc_fbtc_slot s_def[] = {
818e93258fSBjoern A. Zeeb 	[CXST_OFF]	= __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
82e2340276SBjoern A. Zeeb 	[CXST_B2W]	= __DEF_FBTC_SLOT(5,   0xea5a5a5a, SLOT_ISO),
83e2340276SBjoern A. Zeeb 	[CXST_W1]	= __DEF_FBTC_SLOT(70,  0xea5a5a5a, SLOT_ISO),
84e2340276SBjoern A. Zeeb 	[CXST_W2]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
85e2340276SBjoern A. Zeeb 	[CXST_W2B]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
86e2340276SBjoern A. Zeeb 	[CXST_B1]	= __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
87e2340276SBjoern A. Zeeb 	[CXST_B2]	= __DEF_FBTC_SLOT(7,   0xea5a5a5a, SLOT_MIX),
88e2340276SBjoern A. Zeeb 	[CXST_B3]	= __DEF_FBTC_SLOT(5,   0xe5555555, SLOT_MIX),
89e2340276SBjoern A. Zeeb 	[CXST_B4]	= __DEF_FBTC_SLOT(50,  0xe5555555, SLOT_MIX),
90e2340276SBjoern A. Zeeb 	[CXST_LK]	= __DEF_FBTC_SLOT(20,  0xea5a5a5a, SLOT_ISO),
91e2340276SBjoern A. Zeeb 	[CXST_BLK]	= __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
92e2340276SBjoern A. Zeeb 	[CXST_E2G]	= __DEF_FBTC_SLOT(0,   0xea5a5a5a, SLOT_MIX),
93e2340276SBjoern A. Zeeb 	[CXST_E5G]	= __DEF_FBTC_SLOT(0,   0xffffffff, SLOT_ISO),
94*6d67aabdSBjoern A. Zeeb 	[CXST_EBT]	= __DEF_FBTC_SLOT(5,   0xe5555555, SLOT_MIX),
95e2340276SBjoern A. Zeeb 	[CXST_ENULL]	= __DEF_FBTC_SLOT(0,   0xaaaaaaaa, SLOT_ISO),
96e2340276SBjoern A. Zeeb 	[CXST_WLK]	= __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
97e2340276SBjoern A. Zeeb 	[CXST_W1FDD]	= __DEF_FBTC_SLOT(50,  0xffffffff, SLOT_ISO),
98e2340276SBjoern A. Zeeb 	[CXST_B1FDD]	= __DEF_FBTC_SLOT(50,  0xffffdfff, SLOT_ISO),
998e93258fSBjoern A. Zeeb };
1008e93258fSBjoern A. Zeeb 
1018e93258fSBjoern A. Zeeb static const u32 cxtbl[] = {
1028e93258fSBjoern A. Zeeb 	0xffffffff, /* 0 */
1038e93258fSBjoern A. Zeeb 	0xaaaaaaaa, /* 1 */
104e2340276SBjoern A. Zeeb 	0xe5555555, /* 2 */
105e2340276SBjoern A. Zeeb 	0xee555555, /* 3 */
106e2340276SBjoern A. Zeeb 	0xd5555555, /* 4 */
1078e93258fSBjoern A. Zeeb 	0x5a5a5a5a, /* 5 */
108e2340276SBjoern A. Zeeb 	0xfa5a5a5a, /* 6 */
109e2340276SBjoern A. Zeeb 	0xda5a5a5a, /* 7 */
110e2340276SBjoern A. Zeeb 	0xea5a5a5a, /* 8 */
1118e93258fSBjoern A. Zeeb 	0x6a5a5aaa, /* 9 */
1128e93258fSBjoern A. Zeeb 	0x6a5a6a5a, /* 10 */
1138e93258fSBjoern A. Zeeb 	0x6a5a6aaa, /* 11 */
1148e93258fSBjoern A. Zeeb 	0x6afa5afa, /* 12 */
1158e93258fSBjoern A. Zeeb 	0xaaaa5aaa, /* 13 */
1168e93258fSBjoern A. Zeeb 	0xaaffffaa, /* 14 */
1178e93258fSBjoern A. Zeeb 	0xaa5555aa, /* 15 */
1188e93258fSBjoern A. Zeeb 	0xfafafafa, /* 16 */
1198e93258fSBjoern A. Zeeb 	0xffffddff, /* 17 */
1208e93258fSBjoern A. Zeeb 	0xdaffdaff, /* 18 */
121e2340276SBjoern A. Zeeb 	0xfafadafa, /* 19 */
122e2340276SBjoern A. Zeeb 	0xea6a6a6a, /* 20 */
123e2340276SBjoern A. Zeeb 	0xea55556a, /* 21 */
124e2340276SBjoern A. Zeeb 	0xaafafafa, /* 22 */
125e2340276SBjoern A. Zeeb 	0xfafaaafa, /* 23 */
126*6d67aabdSBjoern A. Zeeb 	0xfafffaff, /* 24 */
127*6d67aabdSBjoern A. Zeeb 	0xea6a5a5a, /* 25 */
1288e93258fSBjoern A. Zeeb };
1298e93258fSBjoern A. Zeeb 
130e2340276SBjoern A. Zeeb static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
131e2340276SBjoern A. Zeeb 	/* firmware version must be in decreasing order for each chip */
132*6d67aabdSBjoern A. Zeeb 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
133*6d67aabdSBjoern A. Zeeb 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
134*6d67aabdSBjoern A. Zeeb 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
135*6d67aabdSBjoern A. Zeeb 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
136*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 8,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
137*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6,
138*6d67aabdSBjoern A. Zeeb 	},
139e2340276SBjoern A. Zeeb 	{RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
140e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 105, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 5,
141e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
142e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
143*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
144*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
145e2340276SBjoern A. Zeeb 	},
146e2340276SBjoern A. Zeeb 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
147e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
148e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
149e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
150*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
151*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
152e2340276SBjoern A. Zeeb 	},
153e2340276SBjoern A. Zeeb 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
154e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
155e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
156e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
157*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
158*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
159e2340276SBjoern A. Zeeb 	},
160e2340276SBjoern A. Zeeb 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
161e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
162e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
163e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
164*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
165*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
166e2340276SBjoern A. Zeeb 	},
167e2340276SBjoern A. Zeeb 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
168e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 105, .fcxtdma = 3,  .fcxslots = 1, .fcxcysta = 5,
169e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
170e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
171*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
172*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
173e2340276SBjoern A. Zeeb 	},
174e2340276SBjoern A. Zeeb 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
175e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 5, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 4,
176e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
177e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
178*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
179*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
180e2340276SBjoern A. Zeeb 	},
181e2340276SBjoern A. Zeeb 	{RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
182e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
183e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
184e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
185*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 1,   .frptmap = 1,    .fcxctrl = 1,  .fcxinit = 0,
186*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
187e2340276SBjoern A. Zeeb 	},
188e2340276SBjoern A. Zeeb 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
189e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
190e2340276SBjoern A. Zeeb 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
191e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
192*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
193*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
194e2340276SBjoern A. Zeeb 	},
195e2340276SBjoern A. Zeeb 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
196e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
197e2340276SBjoern A. Zeeb 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
198e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
199*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
200*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5,
201e2340276SBjoern A. Zeeb 	},
202e2340276SBjoern A. Zeeb 
203e2340276SBjoern A. Zeeb 	/* keep it to be the last as default entry */
204e2340276SBjoern A. Zeeb 	{0, RTW89_FW_VER_CODE(0, 0, 0, 0),
205e2340276SBjoern A. Zeeb 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
206e2340276SBjoern A. Zeeb 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
207e2340276SBjoern A. Zeeb 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
208*6d67aabdSBjoern A. Zeeb 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
209*6d67aabdSBjoern A. Zeeb 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5,
210e2340276SBjoern A. Zeeb 	},
211e2340276SBjoern A. Zeeb };
212e2340276SBjoern A. Zeeb 
213e2340276SBjoern A. Zeeb #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
214e2340276SBjoern A. Zeeb 
215*6d67aabdSBjoern A. Zeeb static const union rtw89_btc_wl_state_map btc_scanning_map = {
216*6d67aabdSBjoern A. Zeeb 	.map = {
217*6d67aabdSBjoern A. Zeeb 		.scan = 1,
218*6d67aabdSBjoern A. Zeeb 		.connecting = 1,
219*6d67aabdSBjoern A. Zeeb 		.roaming = 1,
220*6d67aabdSBjoern A. Zeeb 		.transacting = 1,
221*6d67aabdSBjoern A. Zeeb 		._4way = 1,
222*6d67aabdSBjoern A. Zeeb 	},
223*6d67aabdSBjoern A. Zeeb };
224*6d67aabdSBjoern A. Zeeb 
225*6d67aabdSBjoern A. Zeeb static u32 chip_id_to_bt_rom_code_id(u32 id)
226*6d67aabdSBjoern A. Zeeb {
227*6d67aabdSBjoern A. Zeeb 	switch (id) {
228*6d67aabdSBjoern A. Zeeb 	case RTL8852A:
229*6d67aabdSBjoern A. Zeeb 	case RTL8852B:
230*6d67aabdSBjoern A. Zeeb 	case RTL8852C:
231*6d67aabdSBjoern A. Zeeb 	case RTL8852BT:
232*6d67aabdSBjoern A. Zeeb 		return 0x8852;
233*6d67aabdSBjoern A. Zeeb 	case RTL8851B:
234*6d67aabdSBjoern A. Zeeb 		return 0x8851;
235*6d67aabdSBjoern A. Zeeb 	case RTL8922A:
236*6d67aabdSBjoern A. Zeeb 		return 0x8922;
237*6d67aabdSBjoern A. Zeeb 	default:
238*6d67aabdSBjoern A. Zeeb 		return 0;
239*6d67aabdSBjoern A. Zeeb 	}
240*6d67aabdSBjoern A. Zeeb }
241*6d67aabdSBjoern A. Zeeb 
2428e93258fSBjoern A. Zeeb struct rtw89_btc_btf_tlv {
2438e93258fSBjoern A. Zeeb 	u8 type;
2448e93258fSBjoern A. Zeeb 	u8 len;
245e2340276SBjoern A. Zeeb 	u8 val[];
2468e93258fSBjoern A. Zeeb } __packed;
2478e93258fSBjoern A. Zeeb 
248*6d67aabdSBjoern A. Zeeb struct rtw89_btc_btf_tlv_v7 {
249*6d67aabdSBjoern A. Zeeb 	u8 type;
250*6d67aabdSBjoern A. Zeeb 	u8 ver;
251*6d67aabdSBjoern A. Zeeb 	u8 len;
252*6d67aabdSBjoern A. Zeeb 	u8 val[];
253*6d67aabdSBjoern A. Zeeb } __packed;
254*6d67aabdSBjoern A. Zeeb 
2558e93258fSBjoern A. Zeeb enum btc_btf_set_report_en {
256e2340276SBjoern A. Zeeb 	RPT_EN_TDMA,
257e2340276SBjoern A. Zeeb 	RPT_EN_CYCLE,
258e2340276SBjoern A. Zeeb 	RPT_EN_MREG,
259e2340276SBjoern A. Zeeb 	RPT_EN_BT_VER_INFO,
260e2340276SBjoern A. Zeeb 	RPT_EN_BT_SCAN_INFO,
261e2340276SBjoern A. Zeeb 	RPT_EN_BT_DEVICE_INFO,
262e2340276SBjoern A. Zeeb 	RPT_EN_BT_AFH_MAP,
263e2340276SBjoern A. Zeeb 	RPT_EN_BT_AFH_MAP_LE,
264e2340276SBjoern A. Zeeb 	RPT_EN_FW_STEP_INFO,
265e2340276SBjoern A. Zeeb 	RPT_EN_TEST,
266e2340276SBjoern A. Zeeb 	RPT_EN_WL_ALL,
267e2340276SBjoern A. Zeeb 	RPT_EN_BT_ALL,
268e2340276SBjoern A. Zeeb 	RPT_EN_ALL,
269e2340276SBjoern A. Zeeb 	RPT_EN_MONITER,
2708e93258fSBjoern A. Zeeb };
2718e93258fSBjoern A. Zeeb 
272*6d67aabdSBjoern A. Zeeb struct rtw89_btc_btf_set_report_v1 {
2738e93258fSBjoern A. Zeeb 	u8 fver;
2748e93258fSBjoern A. Zeeb 	__le32 enable;
2758e93258fSBjoern A. Zeeb 	__le32 para;
2768e93258fSBjoern A. Zeeb } __packed;
2778e93258fSBjoern A. Zeeb 
278*6d67aabdSBjoern A. Zeeb struct rtw89_btc_btf_set_report_v8 {
279*6d67aabdSBjoern A. Zeeb 	u8 type;
280*6d67aabdSBjoern A. Zeeb 	u8 fver;
281*6d67aabdSBjoern A. Zeeb 	u8 len;
282*6d67aabdSBjoern A. Zeeb 	__le32 map;
283*6d67aabdSBjoern A. Zeeb } __packed;
284*6d67aabdSBjoern A. Zeeb 
285*6d67aabdSBjoern A. Zeeb union rtw89_fbtc_rtp_ctrl {
286*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_set_report_v1 v1;
287*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_set_report_v8 v8;
288*6d67aabdSBjoern A. Zeeb };
289*6d67aabdSBjoern A. Zeeb 
2908e93258fSBjoern A. Zeeb #define BTF_SET_SLOT_TABLE_VER 1
2918e93258fSBjoern A. Zeeb struct rtw89_btc_btf_set_slot_table {
2928e93258fSBjoern A. Zeeb 	u8 fver;
2938e93258fSBjoern A. Zeeb 	u8 tbl_num;
294*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
2958e93258fSBjoern A. Zeeb } __packed;
2968e93258fSBjoern A. Zeeb 
297*6d67aabdSBjoern A. Zeeb struct rtw89_btc_btf_set_slot_table_v7 {
298*6d67aabdSBjoern A. Zeeb 	u8 type;
299*6d67aabdSBjoern A. Zeeb 	u8 ver;
300*6d67aabdSBjoern A. Zeeb 	u8 len;
301*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
302*6d67aabdSBjoern A. Zeeb } __packed;
303*6d67aabdSBjoern A. Zeeb 
304*6d67aabdSBjoern A. Zeeb struct rtw89_btc_btf_set_mon_reg_v1 {
3058e93258fSBjoern A. Zeeb 	u8 fver;
3068e93258fSBjoern A. Zeeb 	u8 reg_num;
307*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
3088e93258fSBjoern A. Zeeb } __packed;
3098e93258fSBjoern A. Zeeb 
310*6d67aabdSBjoern A. Zeeb struct rtw89_btc_btf_set_mon_reg_v7 {
311*6d67aabdSBjoern A. Zeeb 	u8 type;
312*6d67aabdSBjoern A. Zeeb 	u8 fver;
313*6d67aabdSBjoern A. Zeeb 	u8 len;
314*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
315*6d67aabdSBjoern A. Zeeb } __packed;
316*6d67aabdSBjoern A. Zeeb 
317*6d67aabdSBjoern A. Zeeb union rtw89_fbtc_set_mon_reg {
318*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_set_mon_reg_v1 v1;
319*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_set_mon_reg_v7 v7;
320*6d67aabdSBjoern A. Zeeb } __packed;
321*6d67aabdSBjoern A. Zeeb 
322*6d67aabdSBjoern A. Zeeb struct _wl_rinfo_now {
323*6d67aabdSBjoern A. Zeeb 	u8 link_mode;
324*6d67aabdSBjoern A. Zeeb 	u32 dbcc_2g_phy: 2;
325*6d67aabdSBjoern A. Zeeb };
326*6d67aabdSBjoern A. Zeeb 
3278e93258fSBjoern A. Zeeb enum btc_btf_set_cx_policy {
3288e93258fSBjoern A. Zeeb 	CXPOLICY_TDMA = 0x0,
3298e93258fSBjoern A. Zeeb 	CXPOLICY_SLOT = 0x1,
3308e93258fSBjoern A. Zeeb 	CXPOLICY_TYPE = 0x2,
3318e93258fSBjoern A. Zeeb 	CXPOLICY_MAX,
3328e93258fSBjoern A. Zeeb };
3338e93258fSBjoern A. Zeeb 
3348e93258fSBjoern A. Zeeb enum btc_b2w_scoreboard {
3358e93258fSBjoern A. Zeeb 	BTC_BSCB_ACT = BIT(0),
3368e93258fSBjoern A. Zeeb 	BTC_BSCB_ON = BIT(1),
3378e93258fSBjoern A. Zeeb 	BTC_BSCB_WHQL = BIT(2),
3388e93258fSBjoern A. Zeeb 	BTC_BSCB_BT_S1 = BIT(3),
3398e93258fSBjoern A. Zeeb 	BTC_BSCB_A2DP_ACT = BIT(4),
3408e93258fSBjoern A. Zeeb 	BTC_BSCB_RFK_RUN = BIT(5),
3418e93258fSBjoern A. Zeeb 	BTC_BSCB_RFK_REQ = BIT(6),
3428e93258fSBjoern A. Zeeb 	BTC_BSCB_LPS = BIT(7),
343*6d67aabdSBjoern A. Zeeb 	BTC_BSCB_BT_LNAB0 = BIT(8),
344*6d67aabdSBjoern A. Zeeb 	BTC_BSCB_BT_LNAB1 = BIT(10),
3458e93258fSBjoern A. Zeeb 	BTC_BSCB_WLRFK = BIT(11),
3468e93258fSBjoern A. Zeeb 	BTC_BSCB_BT_HILNA = BIT(13),
3478e93258fSBjoern A. Zeeb 	BTC_BSCB_BT_CONNECT = BIT(16),
3488e93258fSBjoern A. Zeeb 	BTC_BSCB_PATCH_CODE = BIT(30),
3498e93258fSBjoern A. Zeeb 	BTC_BSCB_ALL = GENMASK(30, 0),
3508e93258fSBjoern A. Zeeb };
3518e93258fSBjoern A. Zeeb 
3528e93258fSBjoern A. Zeeb enum btc_phymap {
3538e93258fSBjoern A. Zeeb 	BTC_PHY_0 = BIT(0),
3548e93258fSBjoern A. Zeeb 	BTC_PHY_1 = BIT(1),
3558e93258fSBjoern A. Zeeb 	BTC_PHY_ALL = BIT(0) | BIT(1),
3568e93258fSBjoern A. Zeeb };
3578e93258fSBjoern A. Zeeb 
3588e93258fSBjoern A. Zeeb enum btc_cx_state_map {
3598e93258fSBjoern A. Zeeb 	BTC_WIDLE = 0,
3608e93258fSBjoern A. Zeeb 	BTC_WBUSY_BNOSCAN,
3618e93258fSBjoern A. Zeeb 	BTC_WBUSY_BSCAN,
3628e93258fSBjoern A. Zeeb 	BTC_WSCAN_BNOSCAN,
3638e93258fSBjoern A. Zeeb 	BTC_WSCAN_BSCAN,
3648e93258fSBjoern A. Zeeb 	BTC_WLINKING
3658e93258fSBjoern A. Zeeb };
3668e93258fSBjoern A. Zeeb 
3678e93258fSBjoern A. Zeeb enum btc_ant_phase {
3688e93258fSBjoern A. Zeeb 	BTC_ANT_WPOWERON = 0,
3698e93258fSBjoern A. Zeeb 	BTC_ANT_WINIT,
3708e93258fSBjoern A. Zeeb 	BTC_ANT_WONLY,
3718e93258fSBjoern A. Zeeb 	BTC_ANT_WOFF,
3728e93258fSBjoern A. Zeeb 	BTC_ANT_W2G,
3738e93258fSBjoern A. Zeeb 	BTC_ANT_W5G,
3748e93258fSBjoern A. Zeeb 	BTC_ANT_W25G,
3758e93258fSBjoern A. Zeeb 	BTC_ANT_FREERUN,
3768e93258fSBjoern A. Zeeb 	BTC_ANT_WRFK,
377*6d67aabdSBjoern A. Zeeb 	BTC_ANT_WRFK2,
3788e93258fSBjoern A. Zeeb 	BTC_ANT_BRFK,
3798e93258fSBjoern A. Zeeb 	BTC_ANT_MAX
3808e93258fSBjoern A. Zeeb };
3818e93258fSBjoern A. Zeeb 
3828e93258fSBjoern A. Zeeb enum btc_plt {
3838e93258fSBjoern A. Zeeb 	BTC_PLT_NONE = 0,
3848e93258fSBjoern A. Zeeb 	BTC_PLT_LTE_RX = BIT(0),
3858e93258fSBjoern A. Zeeb 	BTC_PLT_GNT_BT_TX = BIT(1),
3868e93258fSBjoern A. Zeeb 	BTC_PLT_GNT_BT_RX = BIT(2),
3878e93258fSBjoern A. Zeeb 	BTC_PLT_GNT_WL = BIT(3),
3888e93258fSBjoern A. Zeeb 	BTC_PLT_BT = BIT(1) | BIT(2),
3898e93258fSBjoern A. Zeeb 	BTC_PLT_ALL = 0xf
3908e93258fSBjoern A. Zeeb };
3918e93258fSBjoern A. Zeeb 
3928e93258fSBjoern A. Zeeb enum btc_cx_poicy_main_type {
3938e93258fSBjoern A. Zeeb 	BTC_CXP_OFF = 0,
3948e93258fSBjoern A. Zeeb 	BTC_CXP_OFFB,
3958e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE,
3968e93258fSBjoern A. Zeeb 	BTC_CXP_FIX,
3978e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX,
3988e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO,
3998e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO,
4008e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO2,
4018e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO2,
4028e93258fSBjoern A. Zeeb 	BTC_CXP_MANUAL,
4038e93258fSBjoern A. Zeeb 	BTC_CXP_USERDEF0,
4048e93258fSBjoern A. Zeeb 	BTC_CXP_MAIN_MAX
4058e93258fSBjoern A. Zeeb };
4068e93258fSBjoern A. Zeeb 
4078e93258fSBjoern A. Zeeb enum btc_cx_poicy_type {
4088e93258fSBjoern A. Zeeb 	/* TDMA off + pri: BT > WL */
4098e93258fSBjoern A. Zeeb 	BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
4108e93258fSBjoern A. Zeeb 
4118e93258fSBjoern A. Zeeb 	/* TDMA off + pri: WL > BT */
4128e93258fSBjoern A. Zeeb 	BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
4138e93258fSBjoern A. Zeeb 
4148e93258fSBjoern A. Zeeb 	/* TDMA off + pri: BT = WL */
4158e93258fSBjoern A. Zeeb 	BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
4168e93258fSBjoern A. Zeeb 
4178e93258fSBjoern A. Zeeb 	/* TDMA off + pri: BT = WL > BT_Lo */
4188e93258fSBjoern A. Zeeb 	BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
4198e93258fSBjoern A. Zeeb 
4208e93258fSBjoern A. Zeeb 	/* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
4218e93258fSBjoern A. Zeeb 	BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
4228e93258fSBjoern A. Zeeb 
4238e93258fSBjoern A. Zeeb 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
4248e93258fSBjoern A. Zeeb 	BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
4258e93258fSBjoern A. Zeeb 
426*6d67aabdSBjoern A. Zeeb 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
427*6d67aabdSBjoern A. Zeeb 	BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
428*6d67aabdSBjoern A. Zeeb 
429*6d67aabdSBjoern A. Zeeb 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
430*6d67aabdSBjoern A. Zeeb 	BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
431*6d67aabdSBjoern A. Zeeb 
4328e93258fSBjoern A. Zeeb 	/* TDMA off + pri: BT_Hi > WL > BT_Lo */
433*6d67aabdSBjoern A. Zeeb 	BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
4348e93258fSBjoern A. Zeeb 
4358e93258fSBjoern A. Zeeb 	/* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
436*6d67aabdSBjoern A. Zeeb 	BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
4378e93258fSBjoern A. Zeeb 
4388e93258fSBjoern A. Zeeb 	/* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
439*6d67aabdSBjoern A. Zeeb 	BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
4408e93258fSBjoern A. Zeeb 
441e2340276SBjoern A. Zeeb 	/* TDMA off + pri: WL_Hi-Tx = BT */
442*6d67aabdSBjoern A. Zeeb 	BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
443*6d67aabdSBjoern A. Zeeb 
444*6d67aabdSBjoern A. Zeeb 	/* TDMA off + pri: WL > BT, Block-BT*/
445*6d67aabdSBjoern A. Zeeb 	BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
446e2340276SBjoern A. Zeeb 
4478e93258fSBjoern A. Zeeb 	/* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
4488e93258fSBjoern A. Zeeb 	BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
4498e93258fSBjoern A. Zeeb 
4508e93258fSBjoern A. Zeeb 	/* TDMA off + Ext-Ctrl + pri: default */
4518e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
4528e93258fSBjoern A. Zeeb 
4538e93258fSBjoern A. Zeeb 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
4548e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
4558e93258fSBjoern A. Zeeb 
4568e93258fSBjoern A. Zeeb 	/* TDMA off + Ext-Ctrl + pri: default */
4578e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
4588e93258fSBjoern A. Zeeb 
4598e93258fSBjoern A. Zeeb 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
4608e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
4618e93258fSBjoern A. Zeeb 
4628e93258fSBjoern A. Zeeb 	/* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
4638e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
4648e93258fSBjoern A. Zeeb 
4658e93258fSBjoern A. Zeeb 	/* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
4668e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
4678e93258fSBjoern A. Zeeb 
4688e93258fSBjoern A. Zeeb 	/* TDMA off + Ext-Ctrl + pri: default */
4698e93258fSBjoern A. Zeeb 	BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
4708e93258fSBjoern A. Zeeb 
4718e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-0: W1:B1 = 30:30 */
4728e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
4738e93258fSBjoern A. Zeeb 
4748e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-1: W1:B1 = 50:50 */
4758e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
4768e93258fSBjoern A. Zeeb 
4778e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-2: W1:B1 = 20:30 */
4788e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
4798e93258fSBjoern A. Zeeb 
4808e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-3: W1:B1 = 40:10 */
4818e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
4828e93258fSBjoern A. Zeeb 
4838e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-4: W1:B1 = 70:10 */
4848e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
4858e93258fSBjoern A. Zeeb 
4868e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-5: W1:B1 = 20:60 */
4878e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
4888e93258fSBjoern A. Zeeb 
4898e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-6: W1:B1 = 30:60 */
4908e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
4918e93258fSBjoern A. Zeeb 
4928e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-7: W1:B1 = 20:80 */
4938e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
4948e93258fSBjoern A. Zeeb 
4958e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-8: W1:B1 = user-define */
4968e93258fSBjoern A. Zeeb 	BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
4978e93258fSBjoern A. Zeeb 
4988e93258fSBjoern A. Zeeb 	/* TDMA Fix slot-9: W1:B1 = 40:10 */
499*6d67aabdSBjoern A. Zeeb 	BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
500*6d67aabdSBjoern A. Zeeb 
501*6d67aabdSBjoern A. Zeeb 	/* TDMA Fix slot-10: W1:B1 = 40:10 */
502*6d67aabdSBjoern A. Zeeb 	BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
503*6d67aabdSBjoern A. Zeeb 
504*6d67aabdSBjoern A. Zeeb 	/* TDMA Fix slot-11: W1:B1 = 40:10 */
505*6d67aabdSBjoern A. Zeeb 	BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
5068e93258fSBjoern A. Zeeb 
5078e93258fSBjoern A. Zeeb 	/* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
5088e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
5098e93258fSBjoern A. Zeeb 
5108e93258fSBjoern A. Zeeb 	/* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
5118e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
5128e93258fSBjoern A. Zeeb 
5138e93258fSBjoern A. Zeeb 	/* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
5148e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
5158e93258fSBjoern A. Zeeb 
5168e93258fSBjoern A. Zeeb 	/* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
5178e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
5188e93258fSBjoern A. Zeeb 
5198e93258fSBjoern A. Zeeb 	/* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
5208e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
5218e93258fSBjoern A. Zeeb 
5228e93258fSBjoern A. Zeeb 	/* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
5238e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
5248e93258fSBjoern A. Zeeb 
5258e93258fSBjoern A. Zeeb 	/* PS-TDMA Fix slot-6: W1:B1 = user-define */
5268e93258fSBjoern A. Zeeb 	BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
5278e93258fSBjoern A. Zeeb 
5288e93258fSBjoern A. Zeeb 	/* TDMA Auto slot-0: W1:B1 = 50:200 */
5298e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
5308e93258fSBjoern A. Zeeb 
5318e93258fSBjoern A. Zeeb 	/* TDMA Auto slot-1: W1:B1 = 60:200 */
5328e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
5338e93258fSBjoern A. Zeeb 
5348e93258fSBjoern A. Zeeb 	/* TDMA Auto slot-2: W1:B1 = 20:200 */
5358e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
5368e93258fSBjoern A. Zeeb 
5378e93258fSBjoern A. Zeeb 	/* TDMA Auto slot-3: W1:B1 = user-define */
5388e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
5398e93258fSBjoern A. Zeeb 
5408e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
5418e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
5428e93258fSBjoern A. Zeeb 
5438e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
5448e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
5458e93258fSBjoern A. Zeeb 
5468e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
5478e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
5488e93258fSBjoern A. Zeeb 
5498e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot-3: W1:B1 = user-define */
5508e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
5518e93258fSBjoern A. Zeeb 
5528e93258fSBjoern A. Zeeb 	/* TDMA Auto slot2-0: W1:B4 = 30:50 */
5538e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
5548e93258fSBjoern A. Zeeb 
5558e93258fSBjoern A. Zeeb 	/* TDMA Auto slot2-1: W1:B4 = 30:70 */
5568e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
5578e93258fSBjoern A. Zeeb 
5588e93258fSBjoern A. Zeeb 	/* TDMA Auto slot2-2: W1:B4 = 50:50 */
5598e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
5608e93258fSBjoern A. Zeeb 
5618e93258fSBjoern A. Zeeb 	/* TDMA Auto slot2-3: W1:B4 = 60:60 */
5628e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
5638e93258fSBjoern A. Zeeb 
5648e93258fSBjoern A. Zeeb 	/* TDMA Auto slot2-4: W1:B4 = 20:80 */
5658e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
5668e93258fSBjoern A. Zeeb 
5678e93258fSBjoern A. Zeeb 	/* TDMA Auto slot2-5: W1:B4 = user-define */
5688e93258fSBjoern A. Zeeb 	BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
5698e93258fSBjoern A. Zeeb 
5708e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
5718e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
5728e93258fSBjoern A. Zeeb 
5738e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
5748e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
5758e93258fSBjoern A. Zeeb 
5768e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
5778e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
5788e93258fSBjoern A. Zeeb 
5798e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
5808e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
5818e93258fSBjoern A. Zeeb 
5828e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
5838e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
5848e93258fSBjoern A. Zeeb 
5858e93258fSBjoern A. Zeeb 	/* PS-TDMA Auto slot2-5: W1:B4 = user-define */
5868e93258fSBjoern A. Zeeb 	BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
5878e93258fSBjoern A. Zeeb 
5888e93258fSBjoern A. Zeeb 	BTC_CXP_MAX = 0xffff
5898e93258fSBjoern A. Zeeb };
5908e93258fSBjoern A. Zeeb 
5918e93258fSBjoern A. Zeeb enum btc_wl_rfk_result {
5928e93258fSBjoern A. Zeeb 	BTC_WRFK_REJECT = 0,
5938e93258fSBjoern A. Zeeb 	BTC_WRFK_ALLOW = 1,
5948e93258fSBjoern A. Zeeb };
5958e93258fSBjoern A. Zeeb 
5968e93258fSBjoern A. Zeeb enum btc_coex_info_map_en {
5978e93258fSBjoern A. Zeeb 	BTC_COEX_INFO_CX = BIT(0),
5988e93258fSBjoern A. Zeeb 	BTC_COEX_INFO_WL = BIT(1),
5998e93258fSBjoern A. Zeeb 	BTC_COEX_INFO_BT = BIT(2),
6008e93258fSBjoern A. Zeeb 	BTC_COEX_INFO_DM = BIT(3),
6018e93258fSBjoern A. Zeeb 	BTC_COEX_INFO_MREG = BIT(4),
6028e93258fSBjoern A. Zeeb 	BTC_COEX_INFO_SUMMARY = BIT(5),
6038e93258fSBjoern A. Zeeb 	BTC_COEX_INFO_ALL = GENMASK(7, 0),
6048e93258fSBjoern A. Zeeb };
6058e93258fSBjoern A. Zeeb 
6068e93258fSBjoern A. Zeeb #define BTC_CXP_MASK GENMASK(15, 8)
6078e93258fSBjoern A. Zeeb 
6088e93258fSBjoern A. Zeeb enum btc_w2b_scoreboard {
6098e93258fSBjoern A. Zeeb 	BTC_WSCB_ACTIVE = BIT(0),
6108e93258fSBjoern A. Zeeb 	BTC_WSCB_ON = BIT(1),
6118e93258fSBjoern A. Zeeb 	BTC_WSCB_SCAN = BIT(2),
6128e93258fSBjoern A. Zeeb 	BTC_WSCB_UNDERTEST = BIT(3),
6138e93258fSBjoern A. Zeeb 	BTC_WSCB_RXGAIN = BIT(4),
6148e93258fSBjoern A. Zeeb 	BTC_WSCB_WLBUSY = BIT(7),
6158e93258fSBjoern A. Zeeb 	BTC_WSCB_EXTFEM = BIT(8),
6168e93258fSBjoern A. Zeeb 	BTC_WSCB_TDMA = BIT(9),
6178e93258fSBjoern A. Zeeb 	BTC_WSCB_FIX2M = BIT(10),
6188e93258fSBjoern A. Zeeb 	BTC_WSCB_WLRFK = BIT(11),
619e2340276SBjoern A. Zeeb 	BTC_WSCB_RXSCAN_PRI = BIT(12),
6208e93258fSBjoern A. Zeeb 	BTC_WSCB_BT_HILNA = BIT(13),
6218e93258fSBjoern A. Zeeb 	BTC_WSCB_BTLOG = BIT(14),
6228e93258fSBjoern A. Zeeb 	BTC_WSCB_ALL = GENMASK(23, 0),
6238e93258fSBjoern A. Zeeb };
6248e93258fSBjoern A. Zeeb 
6258e93258fSBjoern A. Zeeb enum btc_wl_link_mode {
6268e93258fSBjoern A. Zeeb 	BTC_WLINK_NOLINK = 0x0,
6278e93258fSBjoern A. Zeeb 	BTC_WLINK_2G_STA,
6288e93258fSBjoern A. Zeeb 	BTC_WLINK_2G_AP,
6298e93258fSBjoern A. Zeeb 	BTC_WLINK_2G_GO,
6308e93258fSBjoern A. Zeeb 	BTC_WLINK_2G_GC,
6318e93258fSBjoern A. Zeeb 	BTC_WLINK_2G_SCC,
6328e93258fSBjoern A. Zeeb 	BTC_WLINK_2G_MCC,
6338e93258fSBjoern A. Zeeb 	BTC_WLINK_25G_MCC,
6348e93258fSBjoern A. Zeeb 	BTC_WLINK_25G_DBCC,
6358e93258fSBjoern A. Zeeb 	BTC_WLINK_5G,
6368e93258fSBjoern A. Zeeb 	BTC_WLINK_2G_NAN,
6378e93258fSBjoern A. Zeeb 	BTC_WLINK_OTHER,
6388e93258fSBjoern A. Zeeb 	BTC_WLINK_MAX
6398e93258fSBjoern A. Zeeb };
6408e93258fSBjoern A. Zeeb 
6418e93258fSBjoern A. Zeeb enum btc_wl_mrole_type {
6428e93258fSBjoern A. Zeeb 	BTC_WLMROLE_NONE = 0x0,
6438e93258fSBjoern A. Zeeb 	BTC_WLMROLE_STA_GC,
6448e93258fSBjoern A. Zeeb 	BTC_WLMROLE_STA_GC_NOA,
6458e93258fSBjoern A. Zeeb 	BTC_WLMROLE_STA_GO,
6468e93258fSBjoern A. Zeeb 	BTC_WLMROLE_STA_GO_NOA,
6478e93258fSBjoern A. Zeeb 	BTC_WLMROLE_STA_STA,
6488e93258fSBjoern A. Zeeb 	BTC_WLMROLE_MAX
6498e93258fSBjoern A. Zeeb };
6508e93258fSBjoern A. Zeeb 
6518e93258fSBjoern A. Zeeb enum btc_bt_hid_type {
6528e93258fSBjoern A. Zeeb 	BTC_HID_218 = BIT(0),
6538e93258fSBjoern A. Zeeb 	BTC_HID_418 = BIT(1),
6548e93258fSBjoern A. Zeeb 	BTC_HID_BLE = BIT(2),
6558e93258fSBjoern A. Zeeb 	BTC_HID_RCU = BIT(3),
6568e93258fSBjoern A. Zeeb 	BTC_HID_RCU_VOICE = BIT(4),
6578e93258fSBjoern A. Zeeb 	BTC_HID_OTHER_LEGACY = BIT(5)
6588e93258fSBjoern A. Zeeb };
6598e93258fSBjoern A. Zeeb 
6608e93258fSBjoern A. Zeeb enum btc_reset_module {
6618e93258fSBjoern A. Zeeb 	BTC_RESET_CX = BIT(0),
6628e93258fSBjoern A. Zeeb 	BTC_RESET_DM = BIT(1),
6638e93258fSBjoern A. Zeeb 	BTC_RESET_CTRL = BIT(2),
6648e93258fSBjoern A. Zeeb 	BTC_RESET_CXDM = BIT(0) | BIT(1),
6658e93258fSBjoern A. Zeeb 	BTC_RESET_BTINFO = BIT(3),
6668e93258fSBjoern A. Zeeb 	BTC_RESET_MDINFO = BIT(4),
6678e93258fSBjoern A. Zeeb 	BTC_RESET_ALL =  GENMASK(7, 0),
6688e93258fSBjoern A. Zeeb };
6698e93258fSBjoern A. Zeeb 
6708e93258fSBjoern A. Zeeb enum btc_gnt_state {
6718e93258fSBjoern A. Zeeb 	BTC_GNT_HW	= 0,
6728e93258fSBjoern A. Zeeb 	BTC_GNT_SW_LO,
6738e93258fSBjoern A. Zeeb 	BTC_GNT_SW_HI,
6748e93258fSBjoern A. Zeeb 	BTC_GNT_MAX
6758e93258fSBjoern A. Zeeb };
6768e93258fSBjoern A. Zeeb 
677e2340276SBjoern A. Zeeb enum btc_ctr_path {
678e2340276SBjoern A. Zeeb 	BTC_CTRL_BY_BT = 0,
679e2340276SBjoern A. Zeeb 	BTC_CTRL_BY_WL
680e2340276SBjoern A. Zeeb };
681e2340276SBjoern A. Zeeb 
682*6d67aabdSBjoern A. Zeeb enum btc_wlact_state {
683*6d67aabdSBjoern A. Zeeb 	BTC_WLACT_HW = 0,
684*6d67aabdSBjoern A. Zeeb 	BTC_WLACT_SW_LO,
685*6d67aabdSBjoern A. Zeeb 	BTC_WLACT_SW_HI,
686*6d67aabdSBjoern A. Zeeb 	BTC_WLACT_MAX,
687*6d67aabdSBjoern A. Zeeb };
688*6d67aabdSBjoern A. Zeeb 
6898e93258fSBjoern A. Zeeb enum btc_wl_max_tx_time {
6908e93258fSBjoern A. Zeeb 	BTC_MAX_TX_TIME_L1 = 500,
6918e93258fSBjoern A. Zeeb 	BTC_MAX_TX_TIME_L2 = 1000,
6928e93258fSBjoern A. Zeeb 	BTC_MAX_TX_TIME_L3 = 2000,
6938e93258fSBjoern A. Zeeb 	BTC_MAX_TX_TIME_DEF = 5280
6948e93258fSBjoern A. Zeeb };
6958e93258fSBjoern A. Zeeb 
6968e93258fSBjoern A. Zeeb enum btc_wl_max_tx_retry {
6978e93258fSBjoern A. Zeeb 	BTC_MAX_TX_RETRY_L1 = 7,
6988e93258fSBjoern A. Zeeb 	BTC_MAX_TX_RETRY_L2 = 15,
6998e93258fSBjoern A. Zeeb 	BTC_MAX_TX_RETRY_DEF = 31,
7008e93258fSBjoern A. Zeeb };
7018e93258fSBjoern A. Zeeb 
7028e93258fSBjoern A. Zeeb enum btc_reason_and_action {
7038e93258fSBjoern A. Zeeb 	BTC_RSN_NONE,
7048e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_INIT,
7058e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_SWBAND,
7068e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_WL_STA,
7078e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_RADIO_STATE,
7088e93258fSBjoern A. Zeeb 	BTC_RSN_UPDATE_BT_SCBD,
7098e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_WL_RFK,
7108e93258fSBjoern A. Zeeb 	BTC_RSN_UPDATE_BT_INFO,
7118e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_SCAN_START,
7128e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_SCAN_FINISH,
7138e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_SPECIFIC_PACKET,
7148e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_POWEROFF,
7158e93258fSBjoern A. Zeeb 	BTC_RSN_NTFY_ROLE_INFO,
7168e93258fSBjoern A. Zeeb 	BTC_RSN_CMD_SET_COEX,
7178e93258fSBjoern A. Zeeb 	BTC_RSN_ACT1_WORK,
7188e93258fSBjoern A. Zeeb 	BTC_RSN_BT_DEVINFO_WORK,
7198e93258fSBjoern A. Zeeb 	BTC_RSN_RFK_CHK_WORK,
7208e93258fSBjoern A. Zeeb 	BTC_RSN_NUM,
7218e93258fSBjoern A. Zeeb 	BTC_ACT_NONE = 100,
7228e93258fSBjoern A. Zeeb 	BTC_ACT_WL_ONLY,
7238e93258fSBjoern A. Zeeb 	BTC_ACT_WL_5G,
7248e93258fSBjoern A. Zeeb 	BTC_ACT_WL_OTHER,
7258e93258fSBjoern A. Zeeb 	BTC_ACT_WL_IDLE,
7268e93258fSBjoern A. Zeeb 	BTC_ACT_WL_NC,
7278e93258fSBjoern A. Zeeb 	BTC_ACT_WL_RFK,
7288e93258fSBjoern A. Zeeb 	BTC_ACT_WL_INIT,
7298e93258fSBjoern A. Zeeb 	BTC_ACT_WL_OFF,
7308e93258fSBjoern A. Zeeb 	BTC_ACT_FREERUN,
7318e93258fSBjoern A. Zeeb 	BTC_ACT_BT_WHQL,
7328e93258fSBjoern A. Zeeb 	BTC_ACT_BT_RFK,
7338e93258fSBjoern A. Zeeb 	BTC_ACT_BT_OFF,
7348e93258fSBjoern A. Zeeb 	BTC_ACT_BT_IDLE,
7358e93258fSBjoern A. Zeeb 	BTC_ACT_BT_HFP,
7368e93258fSBjoern A. Zeeb 	BTC_ACT_BT_HID,
7378e93258fSBjoern A. Zeeb 	BTC_ACT_BT_A2DP,
7388e93258fSBjoern A. Zeeb 	BTC_ACT_BT_A2DPSINK,
7398e93258fSBjoern A. Zeeb 	BTC_ACT_BT_PAN,
7408e93258fSBjoern A. Zeeb 	BTC_ACT_BT_A2DP_HID,
7418e93258fSBjoern A. Zeeb 	BTC_ACT_BT_A2DP_PAN,
7428e93258fSBjoern A. Zeeb 	BTC_ACT_BT_PAN_HID,
7438e93258fSBjoern A. Zeeb 	BTC_ACT_BT_A2DP_PAN_HID,
7448e93258fSBjoern A. Zeeb 	BTC_ACT_WL_25G_MCC,
7458e93258fSBjoern A. Zeeb 	BTC_ACT_WL_2G_MCC,
7468e93258fSBjoern A. Zeeb 	BTC_ACT_WL_2G_SCC,
7478e93258fSBjoern A. Zeeb 	BTC_ACT_WL_2G_AP,
7488e93258fSBjoern A. Zeeb 	BTC_ACT_WL_2G_GO,
7498e93258fSBjoern A. Zeeb 	BTC_ACT_WL_2G_GC,
7508e93258fSBjoern A. Zeeb 	BTC_ACT_WL_2G_NAN,
7518e93258fSBjoern A. Zeeb 	BTC_ACT_LAST,
7528e93258fSBjoern A. Zeeb 	BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
7538e93258fSBjoern A. Zeeb 	BTC_ACT_EXT_BIT = BIT(14),
7548e93258fSBjoern A. Zeeb 	BTC_POLICY_EXT_BIT = BIT(15),
7558e93258fSBjoern A. Zeeb };
7568e93258fSBjoern A. Zeeb 
7578e93258fSBjoern A. Zeeb #define BTC_FREERUN_ANTISO_MIN 30
7588e93258fSBjoern A. Zeeb #define BTC_TDMA_BTHID_MAX 2
7598e93258fSBjoern A. Zeeb #define BTC_BLINK_NOCONNECT 0
7608e93258fSBjoern A. Zeeb #define BTC_B1_MAX 250 /* unit ms */
7618e93258fSBjoern A. Zeeb 
7628e93258fSBjoern A. Zeeb static void _run_coex(struct rtw89_dev *rtwdev,
7638e93258fSBjoern A. Zeeb 		      enum btc_reason_and_action reason);
7648e93258fSBjoern A. Zeeb static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
7658e93258fSBjoern A. Zeeb static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
7668e93258fSBjoern A. Zeeb 
767*6d67aabdSBjoern A. Zeeb static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
7688e93258fSBjoern A. Zeeb 			void *param, u16 len)
7698e93258fSBjoern A. Zeeb {
7708e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
7718e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
7728e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
7738e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
774*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
7758e93258fSBjoern A. Zeeb 	int ret;
7768e93258fSBjoern A. Zeeb 
777*6d67aabdSBjoern A. Zeeb 	if (len > BTC_H2C_MAXLEN || len == 0) {
778*6d67aabdSBjoern A. Zeeb 		btc->fwinfo.cnt_h2c_fail++;
779*6d67aabdSBjoern A. Zeeb 		dm->error.map.h2c_buffer_over = true;
780*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
781*6d67aabdSBjoern A. Zeeb 	} else if (!wl->status.map.init_ok) {
7828e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7838e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return by btc not init!!\n", __func__);
7848e93258fSBjoern A. Zeeb 		pfwinfo->cnt_h2c_fail++;
785*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
7868e93258fSBjoern A. Zeeb 	} else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
7878e93258fSBjoern A. Zeeb 		    wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
7888e93258fSBjoern A. Zeeb 		   (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
7898e93258fSBjoern A. Zeeb 		    wl->status.map.lps == BTC_LPS_RF_OFF)) {
7908e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7918e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return by wl off!!\n", __func__);
7928e93258fSBjoern A. Zeeb 		pfwinfo->cnt_h2c_fail++;
793*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
7948e93258fSBjoern A. Zeeb 	}
7958e93258fSBjoern A. Zeeb 
7968e93258fSBjoern A. Zeeb 	ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
7978e93258fSBjoern A. Zeeb 					false, true);
798*6d67aabdSBjoern A. Zeeb 	if (ret)
7998e93258fSBjoern A. Zeeb 		pfwinfo->cnt_h2c_fail++;
800*6d67aabdSBjoern A. Zeeb 	else
801*6d67aabdSBjoern A. Zeeb 		pfwinfo->cnt_h2c++;
802*6d67aabdSBjoern A. Zeeb 
803*6d67aabdSBjoern A. Zeeb 	return ret;
8048e93258fSBjoern A. Zeeb }
8058e93258fSBjoern A. Zeeb 
8068e93258fSBjoern A. Zeeb static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
8078e93258fSBjoern A. Zeeb {
8088e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
809*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
8108e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
8118e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8128e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8138e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
814*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *wl_linfo;
8158e93258fSBjoern A. Zeeb 	u8 i;
8168e93258fSBjoern A. Zeeb 
8178e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
8188e93258fSBjoern A. Zeeb 
8198e93258fSBjoern A. Zeeb 	if (type & BTC_RESET_CX)
8208e93258fSBjoern A. Zeeb 		memset(cx, 0, sizeof(*cx));
821*6d67aabdSBjoern A. Zeeb 
822*6d67aabdSBjoern A. Zeeb 	if (type & BTC_RESET_BTINFO) /* only for BT enable */
8238e93258fSBjoern A. Zeeb 		memset(bt, 0, sizeof(*bt));
8248e93258fSBjoern A. Zeeb 
8258e93258fSBjoern A. Zeeb 	if (type & BTC_RESET_CTRL) {
8268e93258fSBjoern A. Zeeb 		memset(&btc->ctrl, 0, sizeof(btc->ctrl));
827*6d67aabdSBjoern A. Zeeb 		btc->manual_ctrl = false;
828*6d67aabdSBjoern A. Zeeb 		if (ver->fcxctrl != 7)
829*6d67aabdSBjoern A. Zeeb 			btc->ctrl.ctrl.trace_step = FCXDEF_STEP;
8308e93258fSBjoern A. Zeeb 	}
8318e93258fSBjoern A. Zeeb 
8328e93258fSBjoern A. Zeeb 	/* Init Coex variables that are not zero */
8338e93258fSBjoern A. Zeeb 	if (type & BTC_RESET_DM) {
8348e93258fSBjoern A. Zeeb 		memset(&btc->dm, 0, sizeof(btc->dm));
8358e93258fSBjoern A. Zeeb 		memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
836*6d67aabdSBjoern A. Zeeb 		for (i = 0; i < RTW89_PORT_NUM; i++) {
837*6d67aabdSBjoern A. Zeeb 			if (btc->ver->fwlrole == 8)
838*6d67aabdSBjoern A. Zeeb 				wl_linfo = &wl->rlink_info[i][0];
839*6d67aabdSBjoern A. Zeeb 			else
840*6d67aabdSBjoern A. Zeeb 				wl_linfo = &wl->link_info[i];
841*6d67aabdSBjoern A. Zeeb 			memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state));
842*6d67aabdSBjoern A. Zeeb 		}
8438e93258fSBjoern A. Zeeb 
8448e93258fSBjoern A. Zeeb 		/* set the slot_now table to original */
8458e93258fSBjoern A. Zeeb 		btc->dm.tdma_now = t_def[CXTD_OFF];
8468e93258fSBjoern A. Zeeb 		btc->dm.tdma = t_def[CXTD_OFF];
847*6d67aabdSBjoern A. Zeeb 		if (ver->fcxslots >= 7) {
848*6d67aabdSBjoern A. Zeeb 			for (i = 0; i < ARRAY_SIZE(s_def); i++) {
849*6d67aabdSBjoern A. Zeeb 				btc->dm.slot.v7[i].dur = s_def[i].dur;
850*6d67aabdSBjoern A. Zeeb 				btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
851*6d67aabdSBjoern A. Zeeb 				btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
852*6d67aabdSBjoern A. Zeeb 			}
853*6d67aabdSBjoern A. Zeeb 			memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
854*6d67aabdSBjoern A. Zeeb 			       sizeof(btc->dm.slot_now.v7));
855*6d67aabdSBjoern A. Zeeb 		} else {
856*6d67aabdSBjoern A. Zeeb 			memcpy(&btc->dm.slot_now.v1, s_def,
857*6d67aabdSBjoern A. Zeeb 			       sizeof(btc->dm.slot_now.v1));
858*6d67aabdSBjoern A. Zeeb 			memcpy(&btc->dm.slot.v1, s_def,
859*6d67aabdSBjoern A. Zeeb 			       sizeof(btc->dm.slot.v1));
860*6d67aabdSBjoern A. Zeeb 		}
8618e93258fSBjoern A. Zeeb 
8628e93258fSBjoern A. Zeeb 		btc->policy_len = 0;
8638e93258fSBjoern A. Zeeb 		btc->bt_req_len = 0;
8648e93258fSBjoern A. Zeeb 
8658e93258fSBjoern A. Zeeb 		btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
8668e93258fSBjoern A. Zeeb 		btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
8678e93258fSBjoern A. Zeeb 		btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
868*6d67aabdSBjoern A. Zeeb 		btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
869*6d67aabdSBjoern A. Zeeb 		btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
8708e93258fSBjoern A. Zeeb 	}
8718e93258fSBjoern A. Zeeb 
8728e93258fSBjoern A. Zeeb 	if (type & BTC_RESET_MDINFO)
8738e93258fSBjoern A. Zeeb 		memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
8748e93258fSBjoern A. Zeeb }
8758e93258fSBjoern A. Zeeb 
876*6d67aabdSBjoern A. Zeeb static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
877*6d67aabdSBjoern A. Zeeb {
878*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
879*6d67aabdSBjoern A. Zeeb 	u8 i;
880*6d67aabdSBjoern A. Zeeb 
881*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < mreg_num; i++)
882*6d67aabdSBjoern A. Zeeb 		if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
883*6d67aabdSBjoern A. Zeeb 		    le32_to_cpu(chip->mon_reg[i].offset) == target) {
884*6d67aabdSBjoern A. Zeeb 			return i;
885*6d67aabdSBjoern A. Zeeb 	}
886*6d67aabdSBjoern A. Zeeb 	return BTC_REG_NOTFOUND;
887*6d67aabdSBjoern A. Zeeb }
888*6d67aabdSBjoern A. Zeeb 
889*6d67aabdSBjoern A. Zeeb static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
890*6d67aabdSBjoern A. Zeeb {
891*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
892*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
893*6d67aabdSBjoern A. Zeeb 	union rtw89_btc_module_info *md = &btc->mdinfo;
894*6d67aabdSBjoern A. Zeeb 	union rtw89_btc_fbtc_mreg_val *pmreg;
895*6d67aabdSBjoern A. Zeeb 	u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
896*6d67aabdSBjoern A. Zeeb 	u32 reg_val;
897*6d67aabdSBjoern A. Zeeb 	u8 idx, switch_type;
898*6d67aabdSBjoern A. Zeeb 
899*6d67aabdSBjoern A. Zeeb 	if (ver->fcxinit == 7)
900*6d67aabdSBjoern A. Zeeb 		switch_type = md->md_v7.switch_type;
901*6d67aabdSBjoern A. Zeeb 	else
902*6d67aabdSBjoern A. Zeeb 		switch_type = md->md.switch_type;
903*6d67aabdSBjoern A. Zeeb 
904*6d67aabdSBjoern A. Zeeb 	if (btc->btg_pos == RF_PATH_A)
905*6d67aabdSBjoern A. Zeeb 		pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
906*6d67aabdSBjoern A. Zeeb 
907*6d67aabdSBjoern A. Zeeb 	switch (type) {
908*6d67aabdSBjoern A. Zeeb 	case BTC_CSTATUS_TXDIV_POS:
909*6d67aabdSBjoern A. Zeeb 		if (switch_type == BTC_SWITCH_INTERNAL)
910*6d67aabdSBjoern A. Zeeb 			*val = BTC_ANT_DIV_MAIN;
911*6d67aabdSBjoern A. Zeeb 		break;
912*6d67aabdSBjoern A. Zeeb 	case BTC_CSTATUS_RXDIV_POS:
913*6d67aabdSBjoern A. Zeeb 		if (switch_type == BTC_SWITCH_INTERNAL)
914*6d67aabdSBjoern A. Zeeb 			*val = BTC_ANT_DIV_MAIN;
915*6d67aabdSBjoern A. Zeeb 		break;
916*6d67aabdSBjoern A. Zeeb 	case BTC_CSTATUS_BB_GNT_MUX:
917*6d67aabdSBjoern A. Zeeb 		reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
918*6d67aabdSBjoern A. Zeeb 		*val = !(reg_val & B_BTC_BB_GNT_MUX);
919*6d67aabdSBjoern A. Zeeb 		break;
920*6d67aabdSBjoern A. Zeeb 	case BTC_CSTATUS_BB_GNT_MUX_MON:
921*6d67aabdSBjoern A. Zeeb 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
922*6d67aabdSBjoern A. Zeeb 			return;
923*6d67aabdSBjoern A. Zeeb 
924*6d67aabdSBjoern A. Zeeb 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
925*6d67aabdSBjoern A. Zeeb 		if (ver->fcxmreg == 1) {
926*6d67aabdSBjoern A. Zeeb 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
927*6d67aabdSBjoern A. Zeeb 						REG_BB, R_BTC_BB_BTG_RX);
928*6d67aabdSBjoern A. Zeeb 			if (idx == BTC_REG_NOTFOUND) {
929*6d67aabdSBjoern A. Zeeb 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
930*6d67aabdSBjoern A. Zeeb 			} else {
931*6d67aabdSBjoern A. Zeeb 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
932*6d67aabdSBjoern A. Zeeb 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
933*6d67aabdSBjoern A. Zeeb 			}
934*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxmreg == 2) {
935*6d67aabdSBjoern A. Zeeb 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
936*6d67aabdSBjoern A. Zeeb 						REG_BB, R_BTC_BB_BTG_RX);
937*6d67aabdSBjoern A. Zeeb 			if (idx == BTC_REG_NOTFOUND) {
938*6d67aabdSBjoern A. Zeeb 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
939*6d67aabdSBjoern A. Zeeb 			} else {
940*6d67aabdSBjoern A. Zeeb 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
941*6d67aabdSBjoern A. Zeeb 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
942*6d67aabdSBjoern A. Zeeb 			}
943*6d67aabdSBjoern A. Zeeb 		}
944*6d67aabdSBjoern A. Zeeb 		break;
945*6d67aabdSBjoern A. Zeeb 	case BTC_CSTATUS_BB_PRE_AGC:
946*6d67aabdSBjoern A. Zeeb 		reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
947*6d67aabdSBjoern A. Zeeb 		reg_val &= B_BTC_BB_PRE_AGC_MASK;
948*6d67aabdSBjoern A. Zeeb 		*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
949*6d67aabdSBjoern A. Zeeb 		break;
950*6d67aabdSBjoern A. Zeeb 	case BTC_CSTATUS_BB_PRE_AGC_MON:
951*6d67aabdSBjoern A. Zeeb 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
952*6d67aabdSBjoern A. Zeeb 			return;
953*6d67aabdSBjoern A. Zeeb 
954*6d67aabdSBjoern A. Zeeb 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
955*6d67aabdSBjoern A. Zeeb 		if (ver->fcxmreg == 1) {
956*6d67aabdSBjoern A. Zeeb 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
957*6d67aabdSBjoern A. Zeeb 						REG_BB, pre_agc_addr);
958*6d67aabdSBjoern A. Zeeb 			if (idx == BTC_REG_NOTFOUND) {
959*6d67aabdSBjoern A. Zeeb 				*val = BTC_PREAGC_NOTFOUND;
960*6d67aabdSBjoern A. Zeeb 			} else {
961*6d67aabdSBjoern A. Zeeb 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
962*6d67aabdSBjoern A. Zeeb 					  B_BTC_BB_PRE_AGC_MASK;
963*6d67aabdSBjoern A. Zeeb 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
964*6d67aabdSBjoern A. Zeeb 			}
965*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxmreg == 2) {
966*6d67aabdSBjoern A. Zeeb 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
967*6d67aabdSBjoern A. Zeeb 						REG_BB, pre_agc_addr);
968*6d67aabdSBjoern A. Zeeb 			if (idx == BTC_REG_NOTFOUND) {
969*6d67aabdSBjoern A. Zeeb 				*val = BTC_PREAGC_NOTFOUND;
970*6d67aabdSBjoern A. Zeeb 			} else {
971*6d67aabdSBjoern A. Zeeb 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
972*6d67aabdSBjoern A. Zeeb 					  B_BTC_BB_PRE_AGC_MASK;
973*6d67aabdSBjoern A. Zeeb 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
974*6d67aabdSBjoern A. Zeeb 			}
975*6d67aabdSBjoern A. Zeeb 		}
976*6d67aabdSBjoern A. Zeeb 		break;
977*6d67aabdSBjoern A. Zeeb 	default:
978*6d67aabdSBjoern A. Zeeb 		break;
979*6d67aabdSBjoern A. Zeeb 	}
980*6d67aabdSBjoern A. Zeeb }
981*6d67aabdSBjoern A. Zeeb 
9828e93258fSBjoern A. Zeeb #define BTC_RPT_HDR_SIZE 3
9838e93258fSBjoern A. Zeeb #define BTC_CHK_WLSLOT_DRIFT_MAX 15
984e2340276SBjoern A. Zeeb #define BTC_CHK_BTSLOT_DRIFT_MAX 15
9858e93258fSBjoern A. Zeeb #define BTC_CHK_HANG_MAX 3
9868e93258fSBjoern A. Zeeb 
9878e93258fSBjoern A. Zeeb static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
9888e93258fSBjoern A. Zeeb {
9898e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9908e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
9918e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
992*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
993*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
9948e93258fSBjoern A. Zeeb 
9958e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9968e93258fSBjoern A. Zeeb 		    "[BTC], %s(): type:%d cnt:%d\n",
9978e93258fSBjoern A. Zeeb 		    __func__, type, cnt);
9988e93258fSBjoern A. Zeeb 
9998e93258fSBjoern A. Zeeb 	switch (type) {
1000*6d67aabdSBjoern A. Zeeb 	case BTC_DCNT_WL_FW_VER_MATCH:
1001*6d67aabdSBjoern A. Zeeb 		if ((wl->ver_info.fw_coex & 0xffff0000) !=
1002*6d67aabdSBjoern A. Zeeb 		     rtwdev->chip->wlcx_desired) {
1003*6d67aabdSBjoern A. Zeeb 			wl->fw_ver_mismatch = true;
1004*6d67aabdSBjoern A. Zeeb 			dm->error.map.wl_ver_mismatch = true;
1005*6d67aabdSBjoern A. Zeeb 		} else {
1006*6d67aabdSBjoern A. Zeeb 			wl->fw_ver_mismatch = false;
1007*6d67aabdSBjoern A. Zeeb 			dm->error.map.wl_ver_mismatch = false;
1008*6d67aabdSBjoern A. Zeeb 		}
1009*6d67aabdSBjoern A. Zeeb 		break;
1010e2340276SBjoern A. Zeeb 	case BTC_DCNT_RPT_HANG:
10118e93258fSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1012e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
10138e93258fSBjoern A. Zeeb 		else
1014e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
10158e93258fSBjoern A. Zeeb 
1016e2340276SBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
10178e93258fSBjoern A. Zeeb 			dm->error.map.wl_fw_hang = true;
10188e93258fSBjoern A. Zeeb 		else
10198e93258fSBjoern A. Zeeb 			dm->error.map.wl_fw_hang = false;
10208e93258fSBjoern A. Zeeb 
10218e93258fSBjoern A. Zeeb 		dm->cnt_dm[BTC_DCNT_RPT] = cnt;
10228e93258fSBjoern A. Zeeb 		break;
1023e2340276SBjoern A. Zeeb 	case BTC_DCNT_CYCLE_HANG:
10248e93258fSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
10258e93258fSBjoern A. Zeeb 		    (dm->tdma_now.type != CXTDMA_OFF ||
10268e93258fSBjoern A. Zeeb 		     dm->tdma_now.ext_ctrl == CXECTL_EXT))
1027e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
10288e93258fSBjoern A. Zeeb 		else
1029e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
10308e93258fSBjoern A. Zeeb 
1031e2340276SBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
10328e93258fSBjoern A. Zeeb 			dm->error.map.cycle_hang = true;
10338e93258fSBjoern A. Zeeb 		else
10348e93258fSBjoern A. Zeeb 			dm->error.map.cycle_hang = false;
10358e93258fSBjoern A. Zeeb 
10368e93258fSBjoern A. Zeeb 		dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
10378e93258fSBjoern A. Zeeb 		break;
1038e2340276SBjoern A. Zeeb 	case BTC_DCNT_W1_HANG:
10398e93258fSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
10408e93258fSBjoern A. Zeeb 		    dm->tdma_now.type != CXTDMA_OFF)
1041e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_W1_HANG]++;
10428e93258fSBjoern A. Zeeb 		else
1043e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
10448e93258fSBjoern A. Zeeb 
1045e2340276SBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
10468e93258fSBjoern A. Zeeb 			dm->error.map.w1_hang = true;
10478e93258fSBjoern A. Zeeb 		else
10488e93258fSBjoern A. Zeeb 			dm->error.map.w1_hang = false;
10498e93258fSBjoern A. Zeeb 
10508e93258fSBjoern A. Zeeb 		dm->cnt_dm[BTC_DCNT_W1] = cnt;
10518e93258fSBjoern A. Zeeb 		break;
1052e2340276SBjoern A. Zeeb 	case BTC_DCNT_B1_HANG:
10538e93258fSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
10548e93258fSBjoern A. Zeeb 		    dm->tdma_now.type != CXTDMA_OFF)
1055e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_B1_HANG]++;
10568e93258fSBjoern A. Zeeb 		else
1057e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
10588e93258fSBjoern A. Zeeb 
1059e2340276SBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
10608e93258fSBjoern A. Zeeb 			dm->error.map.b1_hang = true;
10618e93258fSBjoern A. Zeeb 		else
10628e93258fSBjoern A. Zeeb 			dm->error.map.b1_hang = false;
10638e93258fSBjoern A. Zeeb 
10648e93258fSBjoern A. Zeeb 		dm->cnt_dm[BTC_DCNT_B1] = cnt;
10658e93258fSBjoern A. Zeeb 		break;
1066e2340276SBjoern A. Zeeb 	case BTC_DCNT_E2G_HANG:
1067e2340276SBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1068e2340276SBjoern A. Zeeb 		    dm->tdma_now.ext_ctrl == CXECTL_EXT)
1069e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1070e2340276SBjoern A. Zeeb 		else
1071e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1072e2340276SBjoern A. Zeeb 
1073e2340276SBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1074e2340276SBjoern A. Zeeb 			dm->error.map.wl_e2g_hang = true;
1075e2340276SBjoern A. Zeeb 		else
1076e2340276SBjoern A. Zeeb 			dm->error.map.wl_e2g_hang = false;
1077e2340276SBjoern A. Zeeb 
1078e2340276SBjoern A. Zeeb 		dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1079e2340276SBjoern A. Zeeb 		break;
10808e93258fSBjoern A. Zeeb 	case BTC_DCNT_TDMA_NONSYNC:
10818e93258fSBjoern A. Zeeb 		if (cnt != 0) /* if tdma not sync between drv/fw  */
10828e93258fSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
10838e93258fSBjoern A. Zeeb 		else
10848e93258fSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
10858e93258fSBjoern A. Zeeb 
10868e93258fSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
10878e93258fSBjoern A. Zeeb 			dm->error.map.tdma_no_sync = true;
10888e93258fSBjoern A. Zeeb 		else
10898e93258fSBjoern A. Zeeb 			dm->error.map.tdma_no_sync = false;
10908e93258fSBjoern A. Zeeb 		break;
10918e93258fSBjoern A. Zeeb 	case BTC_DCNT_SLOT_NONSYNC:
10928e93258fSBjoern A. Zeeb 		if (cnt != 0) /* if slot not sync between drv/fw  */
10938e93258fSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
10948e93258fSBjoern A. Zeeb 		else
10958e93258fSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
10968e93258fSBjoern A. Zeeb 
10978e93258fSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1098e2340276SBjoern A. Zeeb 			dm->error.map.slot_no_sync = true;
10998e93258fSBjoern A. Zeeb 		else
1100e2340276SBjoern A. Zeeb 			dm->error.map.slot_no_sync = false;
11018e93258fSBjoern A. Zeeb 		break;
1102*6d67aabdSBjoern A. Zeeb 	case BTC_DCNT_BTTX_HANG:
1103*6d67aabdSBjoern A. Zeeb 		cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1104*6d67aabdSBjoern A. Zeeb 
1105*6d67aabdSBjoern A. Zeeb 		if (cnt == 0 && bt->link_info.slave_role)
1106*6d67aabdSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1107*6d67aabdSBjoern A. Zeeb 		else
1108*6d67aabdSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1109*6d67aabdSBjoern A. Zeeb 
1110*6d67aabdSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1111*6d67aabdSBjoern A. Zeeb 			dm->error.map.bt_tx_hang = true;
1112*6d67aabdSBjoern A. Zeeb 		else
1113*6d67aabdSBjoern A. Zeeb 			dm->error.map.bt_tx_hang = false;
1114*6d67aabdSBjoern A. Zeeb 		break;
1115e2340276SBjoern A. Zeeb 	case BTC_DCNT_BTCNT_HANG:
11168e93258fSBjoern A. Zeeb 		cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
11178e93258fSBjoern A. Zeeb 		      cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
11188e93258fSBjoern A. Zeeb 		      cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
11198e93258fSBjoern A. Zeeb 		      cx->cnt_bt[BTC_BCNT_LOPRI_TX];
11208e93258fSBjoern A. Zeeb 
11218e93258fSBjoern A. Zeeb 		if (cnt == 0)
1122e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
11238e93258fSBjoern A. Zeeb 		else
1124e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
11258e93258fSBjoern A. Zeeb 
1126e2340276SBjoern A. Zeeb 		if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX &&
1127e2340276SBjoern A. Zeeb 		     bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] &&
11288e93258fSBjoern A. Zeeb 		     !bt->enable.now))
11298e93258fSBjoern A. Zeeb 			_update_bt_scbd(rtwdev, false);
11308e93258fSBjoern A. Zeeb 		break;
11318e93258fSBjoern A. Zeeb 	case BTC_DCNT_WL_SLOT_DRIFT:
11328e93258fSBjoern A. Zeeb 		if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
11338e93258fSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
11348e93258fSBjoern A. Zeeb 		else
11358e93258fSBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
11368e93258fSBjoern A. Zeeb 
11378e93258fSBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
11388e93258fSBjoern A. Zeeb 			dm->error.map.wl_slot_drift = true;
11398e93258fSBjoern A. Zeeb 		else
11408e93258fSBjoern A. Zeeb 			dm->error.map.wl_slot_drift = false;
11418e93258fSBjoern A. Zeeb 		break;
1142e2340276SBjoern A. Zeeb 	case BTC_DCNT_BT_SLOT_DRIFT:
1143e2340276SBjoern A. Zeeb 		if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1144e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1145e2340276SBjoern A. Zeeb 		else
1146e2340276SBjoern A. Zeeb 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1147e2340276SBjoern A. Zeeb 
1148e2340276SBjoern A. Zeeb 		if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1149e2340276SBjoern A. Zeeb 			dm->error.map.bt_slot_drift = true;
1150e2340276SBjoern A. Zeeb 		else
1151e2340276SBjoern A. Zeeb 			dm->error.map.bt_slot_drift = false;
1152e2340276SBjoern A. Zeeb 
1153e2340276SBjoern A. Zeeb 		break;
11548e93258fSBjoern A. Zeeb 	}
11558e93258fSBjoern A. Zeeb }
11568e93258fSBjoern A. Zeeb 
11578e93258fSBjoern A. Zeeb static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
11588e93258fSBjoern A. Zeeb {
11598e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
1160e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
11618e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
11628e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
11638e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1164*6d67aabdSBjoern A. Zeeb 	union  rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1165*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1166*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1167*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1168*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1169e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1170e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1171*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1172e2340276SBjoern A. Zeeb 	bool scan_update = true;
1173e2340276SBjoern A. Zeeb 	int i;
11748e93258fSBjoern A. Zeeb 
11758e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
11768e93258fSBjoern A. Zeeb 		    "[BTC], %s(): rpt_type:%d\n",
11778e93258fSBjoern A. Zeeb 		    __func__, rpt_type);
11788e93258fSBjoern A. Zeeb 
11798e93258fSBjoern A. Zeeb 	switch (rpt_type) {
11808e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_VER:
1181*6d67aabdSBjoern A. Zeeb 		if (ver->fcxbtver == 7) {
1182*6d67aabdSBjoern A. Zeeb 			pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1183*6d67aabdSBjoern A. Zeeb 			bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1184*6d67aabdSBjoern A. Zeeb 			bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1185*6d67aabdSBjoern A. Zeeb 							     GENMASK(7, 0));
1186*6d67aabdSBjoern A. Zeeb 			bt->feature = le32_to_cpu(pver->v7.feature);
1187*6d67aabdSBjoern A. Zeeb 		} else {
1188*6d67aabdSBjoern A. Zeeb 			pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1189*6d67aabdSBjoern A. Zeeb 			bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1190*6d67aabdSBjoern A. Zeeb 			bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1191*6d67aabdSBjoern A. Zeeb 							     GENMASK(7, 0));
1192*6d67aabdSBjoern A. Zeeb 			bt->feature = le32_to_cpu(pver->v1.feature);
1193*6d67aabdSBjoern A. Zeeb 		}
11948e93258fSBjoern A. Zeeb 		break;
11958e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_SCAN:
1196e2340276SBjoern A. Zeeb 		if (ver->fcxbtscan == 1) {
1197e2340276SBjoern A. Zeeb 			pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1198e2340276SBjoern A. Zeeb 			for (i = 0; i < BTC_SCAN_MAX1; i++) {
1199e2340276SBjoern A. Zeeb 				bt->scan_info_v1[i] = pscan_v1->scan[i];
1200e2340276SBjoern A. Zeeb 				if (bt->scan_info_v1[i].win == 0 &&
1201e2340276SBjoern A. Zeeb 				    bt->scan_info_v1[i].intvl == 0)
1202e2340276SBjoern A. Zeeb 					scan_update = false;
1203e2340276SBjoern A. Zeeb 			}
1204e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtscan == 2) {
1205e2340276SBjoern A. Zeeb 			pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1206e2340276SBjoern A. Zeeb 			for (i = 0; i < CXSCAN_MAX; i++) {
1207e2340276SBjoern A. Zeeb 				bt->scan_info_v2[i] = pscan_v2->para[i];
1208e2340276SBjoern A. Zeeb 				if ((pscan_v2->type & BIT(i)) &&
1209e2340276SBjoern A. Zeeb 				    pscan_v2->para[i].win == 0 &&
1210e2340276SBjoern A. Zeeb 				    pscan_v2->para[i].intvl == 0)
1211e2340276SBjoern A. Zeeb 					scan_update = false;
1212e2340276SBjoern A. Zeeb 			}
1213*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxbtscan == 7) {
1214*6d67aabdSBjoern A. Zeeb 			pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1215*6d67aabdSBjoern A. Zeeb 			for (i = 0; i < CXSCAN_MAX; i++) {
1216*6d67aabdSBjoern A. Zeeb 				bt->scan_info_v2[i] = pscan_v7->para[i];
1217*6d67aabdSBjoern A. Zeeb 				if ((pscan_v7->type & BIT(i)) &&
1218*6d67aabdSBjoern A. Zeeb 				    pscan_v7->para[i].win == 0 &&
1219*6d67aabdSBjoern A. Zeeb 				    pscan_v7->para[i].intvl == 0)
1220*6d67aabdSBjoern A. Zeeb 					scan_update = false;
1221*6d67aabdSBjoern A. Zeeb 			}
1222e2340276SBjoern A. Zeeb 		}
1223e2340276SBjoern A. Zeeb 		if (scan_update)
1224e2340276SBjoern A. Zeeb 			bt->scan_info_update = 1;
12258e93258fSBjoern A. Zeeb 		break;
12268e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_AFH:
1227e2340276SBjoern A. Zeeb 		if (ver->fcxbtafh == 2) {
1228e2340276SBjoern A. Zeeb 			pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1229e2340276SBjoern A. Zeeb 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1230e2340276SBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1231e2340276SBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1232e2340276SBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1233e2340276SBjoern A. Zeeb 			}
1234e2340276SBjoern A. Zeeb 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1235e2340276SBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1236e2340276SBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1237e2340276SBjoern A. Zeeb 			}
1238*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxbtafh == 7) {
1239*6d67aabdSBjoern A. Zeeb 			pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1240*6d67aabdSBjoern A. Zeeb 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1241*6d67aabdSBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1242*6d67aabdSBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1243*6d67aabdSBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1244*6d67aabdSBjoern A. Zeeb 			}
1245*6d67aabdSBjoern A. Zeeb 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1246*6d67aabdSBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1247*6d67aabdSBjoern A. Zeeb 				memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1248*6d67aabdSBjoern A. Zeeb 			}
1249e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtafh == 1) {
1250e2340276SBjoern A. Zeeb 			pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1251e2340276SBjoern A. Zeeb 			memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1252e2340276SBjoern A. Zeeb 			memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1253e2340276SBjoern A. Zeeb 			memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1254e2340276SBjoern A. Zeeb 		}
12558e93258fSBjoern A. Zeeb 		break;
12568e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_DEVICE:
1257*6d67aabdSBjoern A. Zeeb 		pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
12588e93258fSBjoern A. Zeeb 		a2dp->device_name = le32_to_cpu(pdev->dev_name);
12598e93258fSBjoern A. Zeeb 		a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
12608e93258fSBjoern A. Zeeb 		a2dp->flush_time = le32_to_cpu(pdev->flush_time);
12618e93258fSBjoern A. Zeeb 		break;
12628e93258fSBjoern A. Zeeb 	default:
12638e93258fSBjoern A. Zeeb 		break;
12648e93258fSBjoern A. Zeeb 	}
12658e93258fSBjoern A. Zeeb }
12668e93258fSBjoern A. Zeeb 
1267*6d67aabdSBjoern A. Zeeb static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1268*6d67aabdSBjoern A. Zeeb {
1269*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
1270*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
1271*6d67aabdSBjoern A. Zeeb 
1272*6d67aabdSBjoern A. Zeeb 	if (ver->fwevntrptl == 1)
1273*6d67aabdSBjoern A. Zeeb 		return;
1274*6d67aabdSBjoern A. Zeeb 
1275*6d67aabdSBjoern A. Zeeb 	if (*index <= __BTC_RPT_TYPE_V0_SAME)
1276*6d67aabdSBjoern A. Zeeb 		return;
1277*6d67aabdSBjoern A. Zeeb 	else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1278*6d67aabdSBjoern A. Zeeb 		(*index)++;
1279*6d67aabdSBjoern A. Zeeb 	else
1280*6d67aabdSBjoern A. Zeeb 		*index = BTC_RPT_TYPE_MAX;
1281*6d67aabdSBjoern A. Zeeb }
1282*6d67aabdSBjoern A. Zeeb 
12838e93258fSBjoern A. Zeeb #define BTC_LEAK_AP_TH 10
12848e93258fSBjoern A. Zeeb #define BTC_CYSTA_CHK_PERIOD 100
12858e93258fSBjoern A. Zeeb 
12868e93258fSBjoern A. Zeeb struct rtw89_btc_prpt {
12878e93258fSBjoern A. Zeeb 	u8 type;
12888e93258fSBjoern A. Zeeb 	__le16 len;
12898e93258fSBjoern A. Zeeb 	u8 content[];
12908e93258fSBjoern A. Zeeb } __packed;
12918e93258fSBjoern A. Zeeb 
12928e93258fSBjoern A. Zeeb static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
12938e93258fSBjoern A. Zeeb 			   struct rtw89_btc_btf_fwinfo *pfwinfo,
12948e93258fSBjoern A. Zeeb 			   u8 *prptbuf, u32 index)
12958e93258fSBjoern A. Zeeb {
12968e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
1297e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
12988e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
12998e93258fSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
13008e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
13018e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1302e2340276SBjoern A. Zeeb 	union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1303e2340276SBjoern A. Zeeb 	union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
13048e93258fSBjoern A. Zeeb 	struct rtw89_btc_prpt *btc_prpt = NULL;
1305e2340276SBjoern A. Zeeb 	void *rpt_content = NULL, *pfinfo = NULL;
1306e2340276SBjoern A. Zeeb 	u8 rpt_type = 0;
1307*6d67aabdSBjoern A. Zeeb 	u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1308*6d67aabdSBjoern A. Zeeb 	u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1309e2340276SBjoern A. Zeeb 	u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1310*6d67aabdSBjoern A. Zeeb 	u8 i, val = 0, val1, val2;
13118e93258fSBjoern A. Zeeb 
13128e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
13138e93258fSBjoern A. Zeeb 		    "[BTC], %s(): index:%d\n",
13148e93258fSBjoern A. Zeeb 		    __func__, index);
13158e93258fSBjoern A. Zeeb 
13168e93258fSBjoern A. Zeeb 	if (!prptbuf) {
13178e93258fSBjoern A. Zeeb 		pfwinfo->err[BTFRE_INVALID_INPUT]++;
13188e93258fSBjoern A. Zeeb 		return 0;
13198e93258fSBjoern A. Zeeb 	}
13208e93258fSBjoern A. Zeeb 
13218e93258fSBjoern A. Zeeb 	btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
13228e93258fSBjoern A. Zeeb 	rpt_type = btc_prpt->type;
13238e93258fSBjoern A. Zeeb 	rpt_len = le16_to_cpu(btc_prpt->len);
13248e93258fSBjoern A. Zeeb 	rpt_content = btc_prpt->content;
13258e93258fSBjoern A. Zeeb 
13268e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
13278e93258fSBjoern A. Zeeb 		    "[BTC], %s(): rpt_type:%d\n",
13288e93258fSBjoern A. Zeeb 		    __func__, rpt_type);
13298e93258fSBjoern A. Zeeb 
1330*6d67aabdSBjoern A. Zeeb 	rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1331*6d67aabdSBjoern A. Zeeb 
13328e93258fSBjoern A. Zeeb 	switch (rpt_type) {
13338e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_CTRL:
13348e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1335e2340276SBjoern A. Zeeb 		prpt = &pfwinfo->rpt_ctrl.finfo;
1336e2340276SBjoern A. Zeeb 		if (ver->fcxbtcrpt == 1) {
1337e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1338e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1339e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 4) {
1340e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1341e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1342e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 5) {
1343e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1344e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1345e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 105) {
1346e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1347e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1348e2340276SBjoern A. Zeeb 			pcinfo->req_fver = 5;
1349e2340276SBjoern A. Zeeb 			break;
1350*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 8) {
1351*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1352*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1353*6d67aabdSBjoern A. Zeeb 			break;
13548e93258fSBjoern A. Zeeb 		} else {
1355e2340276SBjoern A. Zeeb 			goto err;
13568e93258fSBjoern A. Zeeb 		}
1357e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxbtcrpt;
13588e93258fSBjoern A. Zeeb 		break;
13598e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_TDMA:
13608e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1361e2340276SBjoern A. Zeeb 		if (ver->fcxtdma == 1) {
1362e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1363e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1364*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
1365e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1366e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
13678e93258fSBjoern A. Zeeb 		} else {
1368e2340276SBjoern A. Zeeb 			goto err;
13698e93258fSBjoern A. Zeeb 		}
1370e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxtdma;
13718e93258fSBjoern A. Zeeb 		break;
13728e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_SLOT:
13738e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1374*6d67aabdSBjoern A. Zeeb 		if (ver->fcxslots == 1) {
1375*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1376*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1377*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxslots == 7) {
1378*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1379*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1380*6d67aabdSBjoern A. Zeeb 		} else {
1381*6d67aabdSBjoern A. Zeeb 			goto err;
1382*6d67aabdSBjoern A. Zeeb 		}
1383e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxslots;
13848e93258fSBjoern A. Zeeb 		break;
13858e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_CYSTA:
13868e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1387e2340276SBjoern A. Zeeb 		pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1388e2340276SBjoern A. Zeeb 		if (ver->fcxcysta == 2) {
1389e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1390e2340276SBjoern A. Zeeb 			pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1391e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1392e2340276SBjoern A. Zeeb 		} else if (ver->fcxcysta == 3) {
1393e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1394e2340276SBjoern A. Zeeb 			pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1395e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1396e2340276SBjoern A. Zeeb 		} else if (ver->fcxcysta == 4) {
1397e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1398e2340276SBjoern A. Zeeb 			pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1399e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1400e2340276SBjoern A. Zeeb 		} else if (ver->fcxcysta == 5) {
1401e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1402e2340276SBjoern A. Zeeb 			pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1403e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1404*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxcysta == 7) {
1405*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1406*6d67aabdSBjoern A. Zeeb 			pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1407*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
14088e93258fSBjoern A. Zeeb 		} else {
1409e2340276SBjoern A. Zeeb 			goto err;
14108e93258fSBjoern A. Zeeb 		}
1411e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxcysta;
14128e93258fSBjoern A. Zeeb 		break;
14138e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_STEP:
14148e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1415*6d67aabdSBjoern A. Zeeb 		if (ver->fcxctrl != 7)
1416*6d67aabdSBjoern A. Zeeb 			trace_step = btc->ctrl.ctrl.trace_step;
1417*6d67aabdSBjoern A. Zeeb 
1418e2340276SBjoern A. Zeeb 		if (ver->fcxstep == 2) {
1419e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1420e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1421e2340276SBjoern A. Zeeb 					  trace_step +
1422e2340276SBjoern A. Zeeb 					  offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1423e2340276SBjoern A. Zeeb 		} else if (ver->fcxstep == 3) {
1424e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1425e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1426e2340276SBjoern A. Zeeb 					  trace_step +
1427e2340276SBjoern A. Zeeb 					  offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1428e2340276SBjoern A. Zeeb 		} else {
1429e2340276SBjoern A. Zeeb 			goto err;
1430e2340276SBjoern A. Zeeb 		}
1431e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxstep;
14328e93258fSBjoern A. Zeeb 		break;
14338e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_NULLSTA:
14348e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1435e2340276SBjoern A. Zeeb 		if (ver->fcxnullsta == 1) {
1436e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1437e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1438e2340276SBjoern A. Zeeb 		} else if (ver->fcxnullsta == 2) {
1439e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1440e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1441*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxnullsta == 7) {
1442*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1443*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1444e2340276SBjoern A. Zeeb 		} else {
1445e2340276SBjoern A. Zeeb 			goto err;
1446e2340276SBjoern A. Zeeb 		}
1447e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxnullsta;
14488e93258fSBjoern A. Zeeb 		break;
14498e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_MREG:
14508e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1451e2340276SBjoern A. Zeeb 		if (ver->fcxmreg == 1) {
1452e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1453e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1454e2340276SBjoern A. Zeeb 		} else if (ver->fcxmreg == 2) {
1455e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1456e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1457*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxmreg == 7) {
1458*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1459*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1460e2340276SBjoern A. Zeeb 		} else {
1461e2340276SBjoern A. Zeeb 			goto err;
1462e2340276SBjoern A. Zeeb 		}
1463e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxmreg;
14648e93258fSBjoern A. Zeeb 		break;
14658e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_GPIO_DBG:
14668e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1467*6d67aabdSBjoern A. Zeeb 		if (ver->fcxgpiodbg == 7) {
1468*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1469*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1470*6d67aabdSBjoern A. Zeeb 		} else {
1471*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1472*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1473*6d67aabdSBjoern A. Zeeb 		}
1474e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxgpiodbg;
14758e93258fSBjoern A. Zeeb 		break;
14768e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_VER:
14778e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1478*6d67aabdSBjoern A. Zeeb 		if (ver->fcxbtver == 1) {
1479*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1480*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1481*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxbtver == 7) {
1482*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1483*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1484*6d67aabdSBjoern A. Zeeb 		}
1485e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxbtver;
14868e93258fSBjoern A. Zeeb 		break;
14878e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_SCAN:
14888e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1489e2340276SBjoern A. Zeeb 		if (ver->fcxbtscan == 1) {
1490e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1491e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1492e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtscan == 2) {
1493e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1494e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1495*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxbtscan == 7) {
1496*6d67aabdSBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1497*6d67aabdSBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1498*6d67aabdSBjoern A. Zeeb 		} else {
1499*6d67aabdSBjoern A. Zeeb 			goto err;
1500e2340276SBjoern A. Zeeb 		}
1501e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxbtscan;
15028e93258fSBjoern A. Zeeb 		break;
15038e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_AFH:
15048e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1505e2340276SBjoern A. Zeeb 		if (ver->fcxbtafh == 1) {
1506e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1507e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1508e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtafh == 2) {
1509e2340276SBjoern A. Zeeb 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1510e2340276SBjoern A. Zeeb 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1511e2340276SBjoern A. Zeeb 		} else {
1512e2340276SBjoern A. Zeeb 			goto err;
1513e2340276SBjoern A. Zeeb 		}
1514e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxbtafh;
15158e93258fSBjoern A. Zeeb 		break;
15168e93258fSBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_DEVICE:
15178e93258fSBjoern A. Zeeb 		pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1518e2340276SBjoern A. Zeeb 		pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
15198e93258fSBjoern A. Zeeb 		pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1520e2340276SBjoern A. Zeeb 		pcinfo->req_fver = ver->fcxbtdevinfo;
15218e93258fSBjoern A. Zeeb 		break;
15228e93258fSBjoern A. Zeeb 	default:
15238e93258fSBjoern A. Zeeb 		pfwinfo->err[BTFRE_UNDEF_TYPE]++;
15248e93258fSBjoern A. Zeeb 		return 0;
15258e93258fSBjoern A. Zeeb 	}
15268e93258fSBjoern A. Zeeb 
1527e2340276SBjoern A. Zeeb 	pcinfo->rx_len = rpt_len;
1528e2340276SBjoern A. Zeeb 	pcinfo->rx_cnt++;
1529e2340276SBjoern A. Zeeb 
15308e93258fSBjoern A. Zeeb 	if (rpt_len != pcinfo->req_len) {
15318e93258fSBjoern A. Zeeb 		if (rpt_type < BTC_RPT_TYPE_MAX)
15328e93258fSBjoern A. Zeeb 			pfwinfo->len_mismch |= (0x1 << rpt_type);
15338e93258fSBjoern A. Zeeb 		else
15348e93258fSBjoern A. Zeeb 			pfwinfo->len_mismch |= BIT(31);
15358e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
15368e93258fSBjoern A. Zeeb 			    "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
15378e93258fSBjoern A. Zeeb 			    __func__, rpt_type, rpt_len, pcinfo->req_len);
15388e93258fSBjoern A. Zeeb 
15398e93258fSBjoern A. Zeeb 		pcinfo->valid = 0;
15408e93258fSBjoern A. Zeeb 		return 0;
15418e93258fSBjoern A. Zeeb 	} else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
15428e93258fSBjoern A. Zeeb 		pfwinfo->err[BTFRE_EXCEPTION]++;
15438e93258fSBjoern A. Zeeb 		pcinfo->valid = 0;
15448e93258fSBjoern A. Zeeb 		return 0;
15458e93258fSBjoern A. Zeeb 	}
15468e93258fSBjoern A. Zeeb 
15478e93258fSBjoern A. Zeeb 	memcpy(pfinfo, rpt_content, pcinfo->req_len);
15488e93258fSBjoern A. Zeeb 	pcinfo->valid = 1;
15498e93258fSBjoern A. Zeeb 
1550e2340276SBjoern A. Zeeb 	switch (rpt_type) {
1551e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_CTRL:
1552e2340276SBjoern A. Zeeb 		if (ver->fcxbtcrpt == 1) {
1553e2340276SBjoern A. Zeeb 			prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
1554e2340276SBjoern A. Zeeb 			btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
1555e2340276SBjoern A. Zeeb 			wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
1556e2340276SBjoern A. Zeeb 			wl->ver_info.fw = prpt->v1.wl_fw_ver;
1557e2340276SBjoern A. Zeeb 			dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
1558e2340276SBjoern A. Zeeb 
1559e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1560e2340276SBjoern A. Zeeb 				     pfwinfo->event[BTF_EVNT_RPT]);
1561e2340276SBjoern A. Zeeb 
1562e2340276SBjoern A. Zeeb 			/* To avoid I/O if WL LPS or power-off */
1563e2340276SBjoern A. Zeeb 			if (wl->status.map.lps != BTC_LPS_RF_OFF &&
1564e2340276SBjoern A. Zeeb 			    !wl->status.map.rf_off) {
1565e2340276SBjoern A. Zeeb 				rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1566e2340276SBjoern A. Zeeb 				_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1567e2340276SBjoern A. Zeeb 
1568e2340276SBjoern A. Zeeb 				btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1569e2340276SBjoern A. Zeeb 					rtw89_mac_get_plt_cnt(rtwdev,
1570e2340276SBjoern A. Zeeb 							      RTW89_MAC_0);
1571e2340276SBjoern A. Zeeb 			}
1572e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 4) {
1573e2340276SBjoern A. Zeeb 			prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
1574e2340276SBjoern A. Zeeb 			btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
1575e2340276SBjoern A. Zeeb 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
1576e2340276SBjoern A. Zeeb 			wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
1577e2340276SBjoern A. Zeeb 			dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
1578e2340276SBjoern A. Zeeb 
1579e2340276SBjoern A. Zeeb 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1580e2340276SBjoern A. Zeeb 				memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i],
1581e2340276SBjoern A. Zeeb 				       sizeof(dm->gnt.band[i]));
1582e2340276SBjoern A. Zeeb 
1583e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1584e2340276SBjoern A. Zeeb 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
1585e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1586e2340276SBjoern A. Zeeb 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
1587e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1588e2340276SBjoern A. Zeeb 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
1589e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1590e2340276SBjoern A. Zeeb 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
1591e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1592e2340276SBjoern A. Zeeb 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
1593e2340276SBjoern A. Zeeb 
1594e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1595e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1596e2340276SBjoern A. Zeeb 				     pfwinfo->event[BTF_EVNT_RPT]);
1597e2340276SBjoern A. Zeeb 
1598e2340276SBjoern A. Zeeb 			if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1599e2340276SBjoern A. Zeeb 				bt->rfk_info.map.timeout = 1;
1600e2340276SBjoern A. Zeeb 			else
1601e2340276SBjoern A. Zeeb 				bt->rfk_info.map.timeout = 0;
1602e2340276SBjoern A. Zeeb 
1603e2340276SBjoern A. Zeeb 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1604e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 5) {
1605e2340276SBjoern A. Zeeb 			prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
1606e2340276SBjoern A. Zeeb 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
1607e2340276SBjoern A. Zeeb 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
1608e2340276SBjoern A. Zeeb 			wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
1609e2340276SBjoern A. Zeeb 			dm->wl_fw_cx_offload = 0;
1610e2340276SBjoern A. Zeeb 
1611e2340276SBjoern A. Zeeb 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1612e2340276SBjoern A. Zeeb 				memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0],
1613e2340276SBjoern A. Zeeb 				       sizeof(dm->gnt.band[i]));
1614e2340276SBjoern A. Zeeb 
1615e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1616e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
1617e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1618e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
1619e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1620e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
1621e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1622e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
1623e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1624e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
1625e2340276SBjoern A. Zeeb 
1626e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1627e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1628e2340276SBjoern A. Zeeb 				     pfwinfo->event[BTF_EVNT_RPT]);
1629e2340276SBjoern A. Zeeb 
1630e2340276SBjoern A. Zeeb 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1631e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 105) {
1632e2340276SBjoern A. Zeeb 			prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
1633e2340276SBjoern A. Zeeb 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
1634e2340276SBjoern A. Zeeb 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
1635e2340276SBjoern A. Zeeb 			wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
1636e2340276SBjoern A. Zeeb 			dm->wl_fw_cx_offload = 0;
1637e2340276SBjoern A. Zeeb 
1638e2340276SBjoern A. Zeeb 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1639e2340276SBjoern A. Zeeb 				memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0],
1640e2340276SBjoern A. Zeeb 				       sizeof(dm->gnt.band[i]));
1641e2340276SBjoern A. Zeeb 
1642e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1643e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
1644e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1645e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
1646e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1647e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
1648e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1649e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
1650e2340276SBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1651e2340276SBjoern A. Zeeb 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1652e2340276SBjoern A. Zeeb 
1653e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1654e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1655e2340276SBjoern A. Zeeb 				     pfwinfo->event[BTF_EVNT_RPT]);
1656e2340276SBjoern A. Zeeb 
1657e2340276SBjoern A. Zeeb 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1658*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxbtcrpt == 8) {
1659*6d67aabdSBjoern A. Zeeb 			prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
1660*6d67aabdSBjoern A. Zeeb 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
1661*6d67aabdSBjoern A. Zeeb 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
1662*6d67aabdSBjoern A. Zeeb 			wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
1663*6d67aabdSBjoern A. Zeeb 
1664*6d67aabdSBjoern A. Zeeb 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1665*6d67aabdSBjoern A. Zeeb 				memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0],
1666*6d67aabdSBjoern A. Zeeb 				       sizeof(dm->gnt.band[i]));
1667*6d67aabdSBjoern A. Zeeb 
1668*6d67aabdSBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1669*6d67aabdSBjoern A. Zeeb 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
1670*6d67aabdSBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1671*6d67aabdSBjoern A. Zeeb 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
1672*6d67aabdSBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1673*6d67aabdSBjoern A. Zeeb 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
1674*6d67aabdSBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1675*6d67aabdSBjoern A. Zeeb 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
1676*6d67aabdSBjoern A. Zeeb 
1677*6d67aabdSBjoern A. Zeeb 			val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1678*6d67aabdSBjoern A. Zeeb 			if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1679*6d67aabdSBjoern A. Zeeb 				val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1680*6d67aabdSBjoern A. Zeeb 
1681*6d67aabdSBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1682*6d67aabdSBjoern A. Zeeb 			btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1683*6d67aabdSBjoern A. Zeeb 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1684*6d67aabdSBjoern A. Zeeb 
1685*6d67aabdSBjoern A. Zeeb 			val1 = pfwinfo->event[BTF_EVNT_RPT];
1686*6d67aabdSBjoern A. Zeeb 			if (((prpt->v8.rpt_len_max_h << 8) +
1687*6d67aabdSBjoern A. Zeeb 			      prpt->v8.rpt_len_max_l) != ver->info_buf)
1688*6d67aabdSBjoern A. Zeeb 				dm->error.map.h2c_c2h_buffer_mismatch = true;
1689*6d67aabdSBjoern A. Zeeb 			else
1690*6d67aabdSBjoern A. Zeeb 				dm->error.map.h2c_c2h_buffer_mismatch = false;
1691*6d67aabdSBjoern A. Zeeb 
1692*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1693*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1694*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1695*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1696e2340276SBjoern A. Zeeb 		} else {
1697e2340276SBjoern A. Zeeb 			goto err;
1698e2340276SBjoern A. Zeeb 		}
1699e2340276SBjoern A. Zeeb 		break;
1700e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_TDMA:
17018e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
17028e93258fSBjoern A. Zeeb 			    "[BTC], %s(): check %d %zu\n", __func__,
1703e2340276SBjoern A. Zeeb 			    BTC_DCNT_TDMA_NONSYNC,
1704e2340276SBjoern A. Zeeb 			    sizeof(dm->tdma_now));
1705e2340276SBjoern A. Zeeb 		if (ver->fcxtdma == 1)
17068e93258fSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
17078e93258fSBjoern A. Zeeb 				     memcmp(&dm->tdma_now,
1708e2340276SBjoern A. Zeeb 					    &pfwinfo->rpt_fbtc_tdma.finfo.v1,
17098e93258fSBjoern A. Zeeb 					    sizeof(dm->tdma_now)));
1710*6d67aabdSBjoern A. Zeeb 		else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
17118e93258fSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
17128e93258fSBjoern A. Zeeb 				     memcmp(&dm->tdma_now,
1713e2340276SBjoern A. Zeeb 					    &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
17148e93258fSBjoern A. Zeeb 					    sizeof(dm->tdma_now)));
1715e2340276SBjoern A. Zeeb 		else
1716e2340276SBjoern A. Zeeb 			goto err;
1717e2340276SBjoern A. Zeeb 		break;
1718e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_SLOT:
1719*6d67aabdSBjoern A. Zeeb 		if (ver->fcxslots == 7) {
17208e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
17218e93258fSBjoern A. Zeeb 				    "[BTC], %s(): check %d %zu\n",
17228e93258fSBjoern A. Zeeb 				    __func__, BTC_DCNT_SLOT_NONSYNC,
1723*6d67aabdSBjoern A. Zeeb 				    sizeof(dm->slot_now.v7));
17248e93258fSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1725*6d67aabdSBjoern A. Zeeb 				     memcmp(dm->slot_now.v7,
1726*6d67aabdSBjoern A. Zeeb 					    pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
1727*6d67aabdSBjoern A. Zeeb 					    sizeof(dm->slot_now.v7)));
1728*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxslots == 1) {
1729*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1730*6d67aabdSBjoern A. Zeeb 				    "[BTC], %s(): check %d %zu\n",
1731*6d67aabdSBjoern A. Zeeb 				    __func__, BTC_DCNT_SLOT_NONSYNC,
1732*6d67aabdSBjoern A. Zeeb 				    sizeof(dm->slot_now.v1));
1733*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1734*6d67aabdSBjoern A. Zeeb 				     memcmp(dm->slot_now.v1,
1735*6d67aabdSBjoern A. Zeeb 					    pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
1736*6d67aabdSBjoern A. Zeeb 					    sizeof(dm->slot_now.v1)));
1737*6d67aabdSBjoern A. Zeeb 		}
1738e2340276SBjoern A. Zeeb 		break;
1739e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_CYSTA:
1740e2340276SBjoern A. Zeeb 		if (ver->fcxcysta == 2) {
1741e2340276SBjoern A. Zeeb 			if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
1742e2340276SBjoern A. Zeeb 				break;
17438e93258fSBjoern A. Zeeb 			/* Check Leak-AP */
1744e2340276SBjoern A. Zeeb 			if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
1745e2340276SBjoern A. Zeeb 			    le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
1746e2340276SBjoern A. Zeeb 				if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
1747e2340276SBjoern A. Zeeb 				    BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
17488e93258fSBjoern A. Zeeb 					dm->leak_ap = 1;
17498e93258fSBjoern A. Zeeb 			}
17508e93258fSBjoern A. Zeeb 
17518e93258fSBjoern A. Zeeb 			/* Check diff time between WL slot and W1/E2G slot */
17528e93258fSBjoern A. Zeeb 			if (dm->tdma_now.type == CXTDMA_OFF &&
1753*6d67aabdSBjoern A. Zeeb 			    dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1754*6d67aabdSBjoern A. Zeeb 				if (ver->fcxslots == 1)
1755*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
1756*6d67aabdSBjoern A. Zeeb 				else if (ver->fcxslots == 7)
1757*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
1758*6d67aabdSBjoern A. Zeeb 			} else {
1759*6d67aabdSBjoern A. Zeeb 				if (ver->fcxslots == 1)
1760*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1761*6d67aabdSBjoern A. Zeeb 				else if (ver->fcxslots == 7)
1762*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1763*6d67aabdSBjoern A. Zeeb 			}
17648e93258fSBjoern A. Zeeb 
1765e2340276SBjoern A. Zeeb 			if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
1766e2340276SBjoern A. Zeeb 				diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
1767e2340276SBjoern A. Zeeb 				_chk_btc_err(rtwdev,
1768e2340276SBjoern A. Zeeb 					     BTC_DCNT_WL_SLOT_DRIFT, diff_t);
17698e93258fSBjoern A. Zeeb 			}
17708e93258fSBjoern A. Zeeb 
1771e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1772e2340276SBjoern A. Zeeb 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
1773e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1774e2340276SBjoern A. Zeeb 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
1775e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1776e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v2.cycles));
1777e2340276SBjoern A. Zeeb 		} else if (ver->fcxcysta == 3) {
1778e2340276SBjoern A. Zeeb 			if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
1779e2340276SBjoern A. Zeeb 				break;
1780e2340276SBjoern A. Zeeb 
1781e2340276SBjoern A. Zeeb 			cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
1782e2340276SBjoern A. Zeeb 			cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
1783e2340276SBjoern A. Zeeb 
17848e93258fSBjoern A. Zeeb 			/* Check Leak-AP */
17858e93258fSBjoern A. Zeeb 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
17868e93258fSBjoern A. Zeeb 			    dm->tdma_now.rxflctrl) {
17878e93258fSBjoern A. Zeeb 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
17888e93258fSBjoern A. Zeeb 					dm->leak_ap = 1;
17898e93258fSBjoern A. Zeeb 			}
17908e93258fSBjoern A. Zeeb 
17918e93258fSBjoern A. Zeeb 			/* Check diff time between real WL slot and W1 slot */
17928e93258fSBjoern A. Zeeb 			if (dm->tdma_now.type == CXTDMA_OFF) {
1793*6d67aabdSBjoern A. Zeeb 				if (ver->fcxslots == 1)
1794*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1795*6d67aabdSBjoern A. Zeeb 				else if (ver->fcxslots == 7)
1796*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1797e2340276SBjoern A. Zeeb 				wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
17988e93258fSBjoern A. Zeeb 				if (wl_slot_real > wl_slot_set) {
17998e93258fSBjoern A. Zeeb 					diff_t = wl_slot_real - wl_slot_set;
18008e93258fSBjoern A. Zeeb 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
18018e93258fSBjoern A. Zeeb 				}
18028e93258fSBjoern A. Zeeb 			}
18038e93258fSBjoern A. Zeeb 
18048e93258fSBjoern A. Zeeb 			/* Check diff time between real BT slot and EBT/E5G slot */
18058e93258fSBjoern A. Zeeb 			if (dm->tdma_now.type == CXTDMA_OFF &&
18068e93258fSBjoern A. Zeeb 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
18078e93258fSBjoern A. Zeeb 			    btc->bt_req_len != 0) {
1808e2340276SBjoern A. Zeeb 				bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
1809e2340276SBjoern A. Zeeb 				if (btc->bt_req_len > bt_slot_real) {
1810e2340276SBjoern A. Zeeb 					diff_t = btc->bt_req_len - bt_slot_real;
1811e2340276SBjoern A. Zeeb 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1812e2340276SBjoern A. Zeeb 				}
1813e2340276SBjoern A. Zeeb 			}
1814e2340276SBjoern A. Zeeb 
1815e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1816e2340276SBjoern A. Zeeb 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
1817e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1818e2340276SBjoern A. Zeeb 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
1819e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1820e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v3.cycles));
1821e2340276SBjoern A. Zeeb 		} else if (ver->fcxcysta == 4) {
1822e2340276SBjoern A. Zeeb 			if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
1823e2340276SBjoern A. Zeeb 				break;
1824e2340276SBjoern A. Zeeb 
1825e2340276SBjoern A. Zeeb 			cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
1826e2340276SBjoern A. Zeeb 			cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
1827e2340276SBjoern A. Zeeb 
1828e2340276SBjoern A. Zeeb 			/* Check Leak-AP */
1829e2340276SBjoern A. Zeeb 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1830e2340276SBjoern A. Zeeb 			    dm->tdma_now.rxflctrl) {
1831e2340276SBjoern A. Zeeb 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1832e2340276SBjoern A. Zeeb 					dm->leak_ap = 1;
1833e2340276SBjoern A. Zeeb 			}
1834e2340276SBjoern A. Zeeb 
1835e2340276SBjoern A. Zeeb 			/* Check diff time between real WL slot and W1 slot */
1836e2340276SBjoern A. Zeeb 			if (dm->tdma_now.type == CXTDMA_OFF) {
1837*6d67aabdSBjoern A. Zeeb 				if (ver->fcxslots == 1)
1838*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1839*6d67aabdSBjoern A. Zeeb 				else if (ver->fcxslots == 7)
1840*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1841e2340276SBjoern A. Zeeb 				wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
1842e2340276SBjoern A. Zeeb 				if (wl_slot_real > wl_slot_set) {
1843e2340276SBjoern A. Zeeb 					diff_t = wl_slot_real - wl_slot_set;
1844e2340276SBjoern A. Zeeb 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1845e2340276SBjoern A. Zeeb 				}
1846e2340276SBjoern A. Zeeb 			}
1847e2340276SBjoern A. Zeeb 
1848e2340276SBjoern A. Zeeb 			/* Check diff time between real BT slot and EBT/E5G slot */
1849e2340276SBjoern A. Zeeb 			if (dm->tdma_now.type == CXTDMA_OFF &&
1850e2340276SBjoern A. Zeeb 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1851e2340276SBjoern A. Zeeb 			    btc->bt_req_len != 0) {
1852e2340276SBjoern A. Zeeb 				bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
18538e93258fSBjoern A. Zeeb 
18548e93258fSBjoern A. Zeeb 				if (btc->bt_req_len > bt_slot_real) {
18558e93258fSBjoern A. Zeeb 					diff_t = btc->bt_req_len - bt_slot_real;
18568e93258fSBjoern A. Zeeb 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
18578e93258fSBjoern A. Zeeb 				}
18588e93258fSBjoern A. Zeeb 			}
18598e93258fSBjoern A. Zeeb 
1860e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1861e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
1862e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1863e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
1864e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1865e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v4.cycles));
1866e2340276SBjoern A. Zeeb 		} else if (ver->fcxcysta == 5) {
1867e2340276SBjoern A. Zeeb 			if (dm->fddt_train == BTC_FDDT_ENABLE)
1868e2340276SBjoern A. Zeeb 				break;
1869e2340276SBjoern A. Zeeb 			cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
1870e2340276SBjoern A. Zeeb 			cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
1871e2340276SBjoern A. Zeeb 
1872e2340276SBjoern A. Zeeb 			/* Check Leak-AP */
1873e2340276SBjoern A. Zeeb 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1874e2340276SBjoern A. Zeeb 			    dm->tdma_now.rxflctrl) {
1875e2340276SBjoern A. Zeeb 				if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
1876e2340276SBjoern A. Zeeb 				    cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1877e2340276SBjoern A. Zeeb 					dm->leak_ap = 1;
18788e93258fSBjoern A. Zeeb 			}
18798e93258fSBjoern A. Zeeb 
1880e2340276SBjoern A. Zeeb 			/* Check diff time between real WL slot and W1 slot */
1881e2340276SBjoern A. Zeeb 			if (dm->tdma_now.type == CXTDMA_OFF) {
1882*6d67aabdSBjoern A. Zeeb 				if (ver->fcxslots == 1)
1883*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1884*6d67aabdSBjoern A. Zeeb 				else if (ver->fcxslots == 7)
1885*6d67aabdSBjoern A. Zeeb 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1886e2340276SBjoern A. Zeeb 				wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
18878e93258fSBjoern A. Zeeb 
1888e2340276SBjoern A. Zeeb 				if (wl_slot_real > wl_slot_set)
1889e2340276SBjoern A. Zeeb 					diff_t = wl_slot_real - wl_slot_set;
18908e93258fSBjoern A. Zeeb 				else
1891e2340276SBjoern A. Zeeb 					diff_t = wl_slot_set - wl_slot_real;
1892e2340276SBjoern A. Zeeb 			}
1893e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
18948e93258fSBjoern A. Zeeb 
1895e2340276SBjoern A. Zeeb 			/* Check diff time between real BT slot and EBT/E5G slot */
1896e2340276SBjoern A. Zeeb 			bt_slot_set = btc->bt_req_len;
1897e2340276SBjoern A. Zeeb 			bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
1898e2340276SBjoern A. Zeeb 			diff_t = 0;
1899e2340276SBjoern A. Zeeb 			if (dm->tdma_now.type == CXTDMA_OFF &&
1900e2340276SBjoern A. Zeeb 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1901e2340276SBjoern A. Zeeb 			    bt_slot_set != 0) {
1902e2340276SBjoern A. Zeeb 				if (bt_slot_set > bt_slot_real)
1903e2340276SBjoern A. Zeeb 					diff_t = bt_slot_set - bt_slot_real;
1904e2340276SBjoern A. Zeeb 				else
1905e2340276SBjoern A. Zeeb 					diff_t = bt_slot_real - bt_slot_set;
19068e93258fSBjoern A. Zeeb 			}
19078e93258fSBjoern A. Zeeb 
1908e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1909e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
1910e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
1911e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1912e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
1913e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1914e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
1915e2340276SBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1916e2340276SBjoern A. Zeeb 				     le16_to_cpu(pcysta->v5.cycles));
1917*6d67aabdSBjoern A. Zeeb 		} else if (ver->fcxcysta == 7) {
1918*6d67aabdSBjoern A. Zeeb 			if (dm->fddt_train == BTC_FDDT_ENABLE)
1919*6d67aabdSBjoern A. Zeeb 				break;
1920*6d67aabdSBjoern A. Zeeb 
1921*6d67aabdSBjoern A. Zeeb 			pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1922*6d67aabdSBjoern A. Zeeb 
1923*6d67aabdSBjoern A. Zeeb 			if (dm->tdma_now.type != CXTDMA_OFF) {
1924*6d67aabdSBjoern A. Zeeb 				/* Check diff time between real WL slot and W1 slot */
1925*6d67aabdSBjoern A. Zeeb 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
1926*6d67aabdSBjoern A. Zeeb 				_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
1927*6d67aabdSBjoern A. Zeeb 
1928*6d67aabdSBjoern A. Zeeb 				/* Check Leak-AP */
1929*6d67aabdSBjoern A. Zeeb 				val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
1930*6d67aabdSBjoern A. Zeeb 				       BTC_LEAK_AP_TH;
1931*6d67aabdSBjoern A. Zeeb 				val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
1932*6d67aabdSBjoern A. Zeeb 
1933*6d67aabdSBjoern A. Zeeb 				val16 = le16_to_cpu(pcysta->v7.cycles);
1934*6d67aabdSBjoern A. Zeeb 				if (dm->tdma_now.rxflctrl &&
1935*6d67aabdSBjoern A. Zeeb 				    val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
1936*6d67aabdSBjoern A. Zeeb 					dm->leak_ap = 1;
1937*6d67aabdSBjoern A. Zeeb 			} else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1938*6d67aabdSBjoern A. Zeeb 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
1939*6d67aabdSBjoern A. Zeeb 				/* Check diff between real BT slot and EBT/E5G slot */
1940*6d67aabdSBjoern A. Zeeb 				_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
1941*6d67aabdSBjoern A. Zeeb 
1942*6d67aabdSBjoern A. Zeeb 				/* Check bt slot length for P2P mode*/
1943*6d67aabdSBjoern A. Zeeb 				val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
1944*6d67aabdSBjoern A. Zeeb 				       BTC_SLOT_REQ_TH;
1945*6d67aabdSBjoern A. Zeeb 				val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
1946*6d67aabdSBjoern A. Zeeb 
1947*6d67aabdSBjoern A. Zeeb 				val16 = le16_to_cpu(pcysta->v7.cycles);
1948*6d67aabdSBjoern A. Zeeb 				if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
1949*6d67aabdSBjoern A. Zeeb 					dm->slot_req_more = 1;
1950*6d67aabdSBjoern A. Zeeb 				else if (bt->link_info.status.map.connect == 0)
1951*6d67aabdSBjoern A. Zeeb 					dm->slot_req_more = 0;
1952*6d67aabdSBjoern A. Zeeb 			}
1953*6d67aabdSBjoern A. Zeeb 
1954*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
1955*6d67aabdSBjoern A. Zeeb 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
1956*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1957*6d67aabdSBjoern A. Zeeb 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
1958*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1959*6d67aabdSBjoern A. Zeeb 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
1960*6d67aabdSBjoern A. Zeeb 
1961*6d67aabdSBjoern A. Zeeb 			/* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
1962*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
1963*6d67aabdSBjoern A. Zeeb 				     le16_to_cpu(pcysta->v7.cycles));
1964*6d67aabdSBjoern A. Zeeb 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1965*6d67aabdSBjoern A. Zeeb 				     le16_to_cpu(pcysta->v7.cycles));
1966e2340276SBjoern A. Zeeb 		} else {
1967e2340276SBjoern A. Zeeb 			goto err;
1968e2340276SBjoern A. Zeeb 		}
1969e2340276SBjoern A. Zeeb 		break;
1970*6d67aabdSBjoern A. Zeeb 	case BTC_RPT_TYPE_MREG:
1971*6d67aabdSBjoern A. Zeeb 		if (ver->fcxmreg == 7)
1972*6d67aabdSBjoern A. Zeeb 			break;
1973*6d67aabdSBjoern A. Zeeb 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
1974*6d67aabdSBjoern A. Zeeb 		if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
1975*6d67aabdSBjoern A. Zeeb 			dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
1976*6d67aabdSBjoern A. Zeeb 		else
1977*6d67aabdSBjoern A. Zeeb 			dm->wl_btg_rx_rb = val;
1978*6d67aabdSBjoern A. Zeeb 
1979*6d67aabdSBjoern A. Zeeb 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
1980*6d67aabdSBjoern A. Zeeb 		if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
1981*6d67aabdSBjoern A. Zeeb 			dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
1982*6d67aabdSBjoern A. Zeeb 		else
1983*6d67aabdSBjoern A. Zeeb 			dm->wl_pre_agc_rb = val;
1984*6d67aabdSBjoern A. Zeeb 		break;
1985e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_VER:
1986e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_SCAN:
1987e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_AFH:
1988e2340276SBjoern A. Zeeb 	case BTC_RPT_TYPE_BT_DEVICE:
19898e93258fSBjoern A. Zeeb 		_update_bt_report(rtwdev, rpt_type, pfinfo);
1990e2340276SBjoern A. Zeeb 		break;
1991e2340276SBjoern A. Zeeb 	}
19928e93258fSBjoern A. Zeeb 	return (rpt_len + BTC_RPT_HDR_SIZE);
1993e2340276SBjoern A. Zeeb 
1994e2340276SBjoern A. Zeeb err:
1995e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1996e2340276SBjoern A. Zeeb 		    "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
1997e2340276SBjoern A. Zeeb 	return 0;
19988e93258fSBjoern A. Zeeb }
19998e93258fSBjoern A. Zeeb 
20008e93258fSBjoern A. Zeeb static void _parse_btc_report(struct rtw89_dev *rtwdev,
20018e93258fSBjoern A. Zeeb 			      struct rtw89_btc_btf_fwinfo *pfwinfo,
20028e93258fSBjoern A. Zeeb 			      u8 *pbuf, u32 buf_len)
20038e93258fSBjoern A. Zeeb {
2004e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
20058e93258fSBjoern A. Zeeb 	struct rtw89_btc_prpt *btc_prpt = NULL;
20068e93258fSBjoern A. Zeeb 	u32 index = 0, rpt_len = 0;
20078e93258fSBjoern A. Zeeb 
20088e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
20098e93258fSBjoern A. Zeeb 		    "[BTC], %s(): buf_len:%d\n",
20108e93258fSBjoern A. Zeeb 		    __func__, buf_len);
20118e93258fSBjoern A. Zeeb 
20128e93258fSBjoern A. Zeeb 	while (pbuf) {
20138e93258fSBjoern A. Zeeb 		btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2014e2340276SBjoern A. Zeeb 		if (index + 2 >= ver->info_buf)
20158e93258fSBjoern A. Zeeb 			break;
20168e93258fSBjoern A. Zeeb 		/* At least 3 bytes: type(1) & len(2) */
20178e93258fSBjoern A. Zeeb 		rpt_len = le16_to_cpu(btc_prpt->len);
20188e93258fSBjoern A. Zeeb 		if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
20198e93258fSBjoern A. Zeeb 			break;
20208e93258fSBjoern A. Zeeb 
20218e93258fSBjoern A. Zeeb 		rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
20228e93258fSBjoern A. Zeeb 		if (!rpt_len)
20238e93258fSBjoern A. Zeeb 			break;
20248e93258fSBjoern A. Zeeb 		index += rpt_len;
20258e93258fSBjoern A. Zeeb 	}
20268e93258fSBjoern A. Zeeb }
20278e93258fSBjoern A. Zeeb 
20288e93258fSBjoern A. Zeeb #define BTC_TLV_HDR_LEN 2
2029*6d67aabdSBjoern A. Zeeb #define BTC_TLV_HDR_LEN_V7 3
20308e93258fSBjoern A. Zeeb 
20318e93258fSBjoern A. Zeeb static void _append_tdma(struct rtw89_dev *rtwdev)
20328e93258fSBjoern A. Zeeb {
20338e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2034e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
20358e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
20368e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_tlv *tlv;
2037*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_tlv_v7 *tlv_v7;
20388e93258fSBjoern A. Zeeb 	struct rtw89_btc_fbtc_tdma *v;
2039e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_tdma_v3 *v3;
20408e93258fSBjoern A. Zeeb 	u16 len = btc->policy_len;
20418e93258fSBjoern A. Zeeb 
20428e93258fSBjoern A. Zeeb 	if (!btc->update_policy_force &&
20438e93258fSBjoern A. Zeeb 	    !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
20448e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev,
20458e93258fSBjoern A. Zeeb 			    RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
20468e93258fSBjoern A. Zeeb 			    __func__);
20478e93258fSBjoern A. Zeeb 		return;
20488e93258fSBjoern A. Zeeb 	}
20498e93258fSBjoern A. Zeeb 
20508e93258fSBjoern A. Zeeb 	tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
20518e93258fSBjoern A. Zeeb 	tlv->type = CXPOLICY_TDMA;
2052e2340276SBjoern A. Zeeb 	if (ver->fcxtdma == 1) {
20538e93258fSBjoern A. Zeeb 		v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
20548e93258fSBjoern A. Zeeb 		tlv->len = sizeof(*v);
2055*6d67aabdSBjoern A. Zeeb 		*v = dm->tdma;
20568e93258fSBjoern A. Zeeb 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2057*6d67aabdSBjoern A. Zeeb 	} else if (ver->fcxtdma == 7) {
2058*6d67aabdSBjoern A. Zeeb 		tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2059*6d67aabdSBjoern A. Zeeb 		tlv_v7->len = sizeof(dm->tdma);
2060*6d67aabdSBjoern A. Zeeb 		tlv_v7->ver = ver->fcxtdma;
2061*6d67aabdSBjoern A. Zeeb 		tlv_v7->type = CXPOLICY_TDMA;
2062*6d67aabdSBjoern A. Zeeb 		memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2063*6d67aabdSBjoern A. Zeeb 		btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
20648e93258fSBjoern A. Zeeb 	} else {
2065e2340276SBjoern A. Zeeb 		tlv->len = sizeof(*v3);
2066e2340276SBjoern A. Zeeb 		v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2067e2340276SBjoern A. Zeeb 		v3->fver = ver->fcxtdma;
2068*6d67aabdSBjoern A. Zeeb 		v3->tdma = dm->tdma;
2069e2340276SBjoern A. Zeeb 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
20708e93258fSBjoern A. Zeeb 	}
20718e93258fSBjoern A. Zeeb 
20728e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
20738e93258fSBjoern A. Zeeb 		    "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
20748e93258fSBjoern A. Zeeb 		    __func__, dm->tdma.type, dm->tdma.rxflctrl,
20758e93258fSBjoern A. Zeeb 		    dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
20768e93258fSBjoern A. Zeeb 		    dm->tdma.ext_ctrl);
20778e93258fSBjoern A. Zeeb }
20788e93258fSBjoern A. Zeeb 
2079*6d67aabdSBjoern A. Zeeb static void _append_slot_v1(struct rtw89_dev *rtwdev)
20808e93258fSBjoern A. Zeeb {
20818e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
20828e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
20838e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_tlv *tlv = NULL;
20848e93258fSBjoern A. Zeeb 	struct btc_fbtc_1slot *v = NULL;
20858e93258fSBjoern A. Zeeb 	u16 len = 0;
20868e93258fSBjoern A. Zeeb 	u8 i, cnt = 0;
20878e93258fSBjoern A. Zeeb 
20888e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
20898e93258fSBjoern A. Zeeb 		    "[BTC], %s(): A:btc->policy_len = %d\n",
20908e93258fSBjoern A. Zeeb 		    __func__, btc->policy_len);
20918e93258fSBjoern A. Zeeb 
20928e93258fSBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
20938e93258fSBjoern A. Zeeb 		if (!btc->update_policy_force &&
2094*6d67aabdSBjoern A. Zeeb 		    !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2095*6d67aabdSBjoern A. Zeeb 			    sizeof(dm->slot.v1[i])))
20968e93258fSBjoern A. Zeeb 			continue;
20978e93258fSBjoern A. Zeeb 
20988e93258fSBjoern A. Zeeb 		len = btc->policy_len;
20998e93258fSBjoern A. Zeeb 
21008e93258fSBjoern A. Zeeb 		tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
21018e93258fSBjoern A. Zeeb 		v = (struct btc_fbtc_1slot *)&tlv->val[0];
21028e93258fSBjoern A. Zeeb 		tlv->type = CXPOLICY_SLOT;
21038e93258fSBjoern A. Zeeb 		tlv->len = sizeof(*v);
21048e93258fSBjoern A. Zeeb 
2105*6d67aabdSBjoern A. Zeeb 		v->fver = btc->ver->fcxslots;
21068e93258fSBjoern A. Zeeb 		v->sid = i;
2107*6d67aabdSBjoern A. Zeeb 		v->slot = dm->slot.v1[i];
21088e93258fSBjoern A. Zeeb 
21098e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
21108e93258fSBjoern A. Zeeb 			    "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2111*6d67aabdSBjoern A. Zeeb 			    __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2112*6d67aabdSBjoern A. Zeeb 			    dm->slot.v1[i].cxtype);
21138e93258fSBjoern A. Zeeb 		cnt++;
21148e93258fSBjoern A. Zeeb 
21158e93258fSBjoern A. Zeeb 		btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
21168e93258fSBjoern A. Zeeb 	}
21178e93258fSBjoern A. Zeeb 
21188e93258fSBjoern A. Zeeb 	if (cnt > 0)
21198e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
21208e93258fSBjoern A. Zeeb 			    "[BTC], %s(): slot update (cnt=%d)!!\n",
21218e93258fSBjoern A. Zeeb 			    __func__, cnt);
21228e93258fSBjoern A. Zeeb }
21238e93258fSBjoern A. Zeeb 
2124*6d67aabdSBjoern A. Zeeb static void _append_slot_v7(struct rtw89_dev *rtwdev)
2125*6d67aabdSBjoern A. Zeeb {
2126*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2127*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2128*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
2129*6d67aabdSBjoern A. Zeeb 	u8 i, cnt = 0;
2130*6d67aabdSBjoern A. Zeeb 	u16 len;
2131*6d67aabdSBjoern A. Zeeb 
2132*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
2133*6d67aabdSBjoern A. Zeeb 		if (!btc->update_policy_force &&
2134*6d67aabdSBjoern A. Zeeb 		    !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2135*6d67aabdSBjoern A. Zeeb 			    sizeof(dm->slot.v7[i])))
2136*6d67aabdSBjoern A. Zeeb 			continue;
2137*6d67aabdSBjoern A. Zeeb 
2138*6d67aabdSBjoern A. Zeeb 		len = btc->policy_len;
2139*6d67aabdSBjoern A. Zeeb 
2140*6d67aabdSBjoern A. Zeeb 		if (!tlv) {
2141*6d67aabdSBjoern A. Zeeb 			if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2142*6d67aabdSBjoern A. Zeeb 				rtw89_debug(rtwdev, RTW89_DBG_BTC,
2143*6d67aabdSBjoern A. Zeeb 					    "[BTC], %s(): buff overflow!\n", __func__);
2144*6d67aabdSBjoern A. Zeeb 				break;
2145*6d67aabdSBjoern A. Zeeb 			}
2146*6d67aabdSBjoern A. Zeeb 
2147*6d67aabdSBjoern A. Zeeb 			tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2148*6d67aabdSBjoern A. Zeeb 			tlv->type = CXPOLICY_SLOT;
2149*6d67aabdSBjoern A. Zeeb 			tlv->ver = btc->ver->fcxslots;
2150*6d67aabdSBjoern A. Zeeb 			tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2151*6d67aabdSBjoern A. Zeeb 			len += BTC_TLV_HDR_LEN_V7;
2152*6d67aabdSBjoern A. Zeeb 		}
2153*6d67aabdSBjoern A. Zeeb 
2154*6d67aabdSBjoern A. Zeeb 		if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2155*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
2156*6d67aabdSBjoern A. Zeeb 				    "[BTC], %s(): buff overflow!\n", __func__);
2157*6d67aabdSBjoern A. Zeeb 			break;
2158*6d67aabdSBjoern A. Zeeb 		}
2159*6d67aabdSBjoern A. Zeeb 
2160*6d67aabdSBjoern A. Zeeb 		btc->policy[len] = i; /* slot-id */
2161*6d67aabdSBjoern A. Zeeb 		memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2162*6d67aabdSBjoern A. Zeeb 		       sizeof(dm->slot.v7[0]));
2163*6d67aabdSBjoern A. Zeeb 		len += tlv->len;
2164*6d67aabdSBjoern A. Zeeb 
2165*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2166*6d67aabdSBjoern A. Zeeb 			    "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2167*6d67aabdSBjoern A. Zeeb 			    __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2168*6d67aabdSBjoern A. Zeeb 			    dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2169*6d67aabdSBjoern A. Zeeb 		cnt++;
2170*6d67aabdSBjoern A. Zeeb 		btc->policy_len = len; /* update total length */
2171*6d67aabdSBjoern A. Zeeb 	}
2172*6d67aabdSBjoern A. Zeeb 
2173*6d67aabdSBjoern A. Zeeb 	if (cnt > 0)
2174*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2175*6d67aabdSBjoern A. Zeeb 			    "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2176*6d67aabdSBjoern A. Zeeb 			    __func__, cnt, btc->policy_len);
2177*6d67aabdSBjoern A. Zeeb }
2178*6d67aabdSBjoern A. Zeeb 
2179*6d67aabdSBjoern A. Zeeb static void _append_slot(struct rtw89_dev *rtwdev)
2180*6d67aabdSBjoern A. Zeeb {
2181*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2182*6d67aabdSBjoern A. Zeeb 
2183*6d67aabdSBjoern A. Zeeb 	if (btc->ver->fcxslots == 7)
2184*6d67aabdSBjoern A. Zeeb 		_append_slot_v7(rtwdev);
2185*6d67aabdSBjoern A. Zeeb 	else
2186*6d67aabdSBjoern A. Zeeb 		_append_slot_v1(rtwdev);
2187*6d67aabdSBjoern A. Zeeb }
2188*6d67aabdSBjoern A. Zeeb 
2189e2340276SBjoern A. Zeeb static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2190e2340276SBjoern A. Zeeb {
2191e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2192e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
2193e2340276SBjoern A. Zeeb 	u32 bit_map = 0;
2194e2340276SBjoern A. Zeeb 
2195e2340276SBjoern A. Zeeb 	switch (rpt_map) {
2196e2340276SBjoern A. Zeeb 	case RPT_EN_TDMA:
2197e2340276SBjoern A. Zeeb 		bit_map = BIT(0);
2198e2340276SBjoern A. Zeeb 		break;
2199e2340276SBjoern A. Zeeb 	case RPT_EN_CYCLE:
2200e2340276SBjoern A. Zeeb 		bit_map = BIT(1);
2201e2340276SBjoern A. Zeeb 		break;
2202e2340276SBjoern A. Zeeb 	case RPT_EN_MREG:
2203e2340276SBjoern A. Zeeb 		bit_map = BIT(2);
2204e2340276SBjoern A. Zeeb 		break;
2205e2340276SBjoern A. Zeeb 	case RPT_EN_BT_VER_INFO:
2206e2340276SBjoern A. Zeeb 		bit_map = BIT(3);
2207e2340276SBjoern A. Zeeb 		break;
2208e2340276SBjoern A. Zeeb 	case RPT_EN_BT_SCAN_INFO:
2209e2340276SBjoern A. Zeeb 		bit_map = BIT(4);
2210e2340276SBjoern A. Zeeb 		break;
2211e2340276SBjoern A. Zeeb 	case RPT_EN_BT_DEVICE_INFO:
2212e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2213e2340276SBjoern A. Zeeb 		case 0:
2214e2340276SBjoern A. Zeeb 		case 1:
2215e2340276SBjoern A. Zeeb 		case 2:
2216e2340276SBjoern A. Zeeb 			bit_map = BIT(6);
2217e2340276SBjoern A. Zeeb 			break;
2218e2340276SBjoern A. Zeeb 		case 3:
2219e2340276SBjoern A. Zeeb 			bit_map = BIT(5);
2220e2340276SBjoern A. Zeeb 			break;
2221e2340276SBjoern A. Zeeb 		default:
2222e2340276SBjoern A. Zeeb 			break;
2223e2340276SBjoern A. Zeeb 		}
2224e2340276SBjoern A. Zeeb 		break;
2225e2340276SBjoern A. Zeeb 	case RPT_EN_BT_AFH_MAP:
2226e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2227e2340276SBjoern A. Zeeb 		case 0:
2228e2340276SBjoern A. Zeeb 		case 1:
2229e2340276SBjoern A. Zeeb 		case 2:
2230e2340276SBjoern A. Zeeb 			bit_map = BIT(5);
2231e2340276SBjoern A. Zeeb 			break;
2232e2340276SBjoern A. Zeeb 		case 3:
2233e2340276SBjoern A. Zeeb 			bit_map = BIT(6);
2234e2340276SBjoern A. Zeeb 			break;
2235e2340276SBjoern A. Zeeb 		default:
2236e2340276SBjoern A. Zeeb 			break;
2237e2340276SBjoern A. Zeeb 		}
2238e2340276SBjoern A. Zeeb 		break;
2239e2340276SBjoern A. Zeeb 	case RPT_EN_BT_AFH_MAP_LE:
2240e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2241e2340276SBjoern A. Zeeb 		case 2:
2242e2340276SBjoern A. Zeeb 			bit_map = BIT(8);
2243e2340276SBjoern A. Zeeb 			break;
2244e2340276SBjoern A. Zeeb 		case 3:
2245e2340276SBjoern A. Zeeb 			bit_map = BIT(7);
2246e2340276SBjoern A. Zeeb 			break;
2247e2340276SBjoern A. Zeeb 		default:
2248e2340276SBjoern A. Zeeb 			break;
2249e2340276SBjoern A. Zeeb 		}
2250e2340276SBjoern A. Zeeb 		break;
2251e2340276SBjoern A. Zeeb 	case RPT_EN_FW_STEP_INFO:
2252e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2253e2340276SBjoern A. Zeeb 		case 1:
2254e2340276SBjoern A. Zeeb 		case 2:
2255e2340276SBjoern A. Zeeb 			bit_map = BIT(7);
2256e2340276SBjoern A. Zeeb 			break;
2257e2340276SBjoern A. Zeeb 		case 3:
2258e2340276SBjoern A. Zeeb 			bit_map = BIT(8);
2259e2340276SBjoern A. Zeeb 			break;
2260e2340276SBjoern A. Zeeb 		default:
2261e2340276SBjoern A. Zeeb 			break;
2262e2340276SBjoern A. Zeeb 		}
2263e2340276SBjoern A. Zeeb 		break;
2264e2340276SBjoern A. Zeeb 	case RPT_EN_TEST:
2265e2340276SBjoern A. Zeeb 		bit_map = BIT(31);
2266e2340276SBjoern A. Zeeb 		break;
2267e2340276SBjoern A. Zeeb 	case RPT_EN_WL_ALL:
2268e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2269e2340276SBjoern A. Zeeb 		case 0:
2270e2340276SBjoern A. Zeeb 		case 1:
2271e2340276SBjoern A. Zeeb 		case 2:
2272e2340276SBjoern A. Zeeb 			bit_map = GENMASK(2, 0);
2273e2340276SBjoern A. Zeeb 			break;
2274e2340276SBjoern A. Zeeb 		case 3:
2275e2340276SBjoern A. Zeeb 			bit_map = GENMASK(2, 0) | BIT(8);
2276e2340276SBjoern A. Zeeb 			break;
2277e2340276SBjoern A. Zeeb 		default:
2278e2340276SBjoern A. Zeeb 			break;
2279e2340276SBjoern A. Zeeb 		}
2280e2340276SBjoern A. Zeeb 		break;
2281e2340276SBjoern A. Zeeb 	case RPT_EN_BT_ALL:
2282e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2283e2340276SBjoern A. Zeeb 		case 0:
2284e2340276SBjoern A. Zeeb 		case 1:
2285e2340276SBjoern A. Zeeb 			bit_map = GENMASK(6, 3);
2286e2340276SBjoern A. Zeeb 			break;
2287e2340276SBjoern A. Zeeb 		case 2:
2288e2340276SBjoern A. Zeeb 			bit_map = GENMASK(6, 3) | BIT(8);
2289e2340276SBjoern A. Zeeb 			break;
2290e2340276SBjoern A. Zeeb 		case 3:
2291e2340276SBjoern A. Zeeb 			bit_map = GENMASK(7, 3);
2292e2340276SBjoern A. Zeeb 			break;
2293e2340276SBjoern A. Zeeb 		default:
2294e2340276SBjoern A. Zeeb 			break;
2295e2340276SBjoern A. Zeeb 		}
2296e2340276SBjoern A. Zeeb 		break;
2297e2340276SBjoern A. Zeeb 	case RPT_EN_ALL:
2298e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2299e2340276SBjoern A. Zeeb 		case 0:
2300e2340276SBjoern A. Zeeb 			bit_map = GENMASK(6, 0);
2301e2340276SBjoern A. Zeeb 			break;
2302e2340276SBjoern A. Zeeb 		case 1:
2303e2340276SBjoern A. Zeeb 			bit_map = GENMASK(7, 0);
2304e2340276SBjoern A. Zeeb 			break;
2305e2340276SBjoern A. Zeeb 		case 2:
2306e2340276SBjoern A. Zeeb 		case 3:
2307e2340276SBjoern A. Zeeb 			bit_map = GENMASK(8, 0);
2308e2340276SBjoern A. Zeeb 			break;
2309e2340276SBjoern A. Zeeb 		default:
2310e2340276SBjoern A. Zeeb 			break;
2311e2340276SBjoern A. Zeeb 		}
2312e2340276SBjoern A. Zeeb 		break;
2313e2340276SBjoern A. Zeeb 	case RPT_EN_MONITER:
2314e2340276SBjoern A. Zeeb 		switch (ver->frptmap) {
2315e2340276SBjoern A. Zeeb 		case 0:
2316e2340276SBjoern A. Zeeb 		case 1:
2317e2340276SBjoern A. Zeeb 			bit_map = GENMASK(6, 2);
2318e2340276SBjoern A. Zeeb 			break;
2319e2340276SBjoern A. Zeeb 		case 2:
2320e2340276SBjoern A. Zeeb 			bit_map = GENMASK(6, 2) | BIT(8);
2321e2340276SBjoern A. Zeeb 			break;
2322e2340276SBjoern A. Zeeb 		case 3:
2323e2340276SBjoern A. Zeeb 			bit_map = GENMASK(8, 2);
2324e2340276SBjoern A. Zeeb 			break;
2325e2340276SBjoern A. Zeeb 		default:
2326e2340276SBjoern A. Zeeb 			break;
2327e2340276SBjoern A. Zeeb 		}
2328e2340276SBjoern A. Zeeb 		break;
2329e2340276SBjoern A. Zeeb 	}
2330e2340276SBjoern A. Zeeb 
2331e2340276SBjoern A. Zeeb 	return bit_map;
2332e2340276SBjoern A. Zeeb }
2333e2340276SBjoern A. Zeeb 
2334*6d67aabdSBjoern A. Zeeb static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
2335*6d67aabdSBjoern A. Zeeb {
2336*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2337*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
2338*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
2339*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_set_slot_table *tbl;
2340*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
2341*6d67aabdSBjoern A. Zeeb 	u16 n, len;
2342*6d67aabdSBjoern A. Zeeb 
2343*6d67aabdSBjoern A. Zeeb 	if (ver->fcxslots == 7) {
2344*6d67aabdSBjoern A. Zeeb 		len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
2345*6d67aabdSBjoern A. Zeeb 		tlv_v7 = kmalloc(len, GFP_KERNEL);
2346*6d67aabdSBjoern A. Zeeb 		if (!tlv_v7)
2347*6d67aabdSBjoern A. Zeeb 			return;
2348*6d67aabdSBjoern A. Zeeb 
2349*6d67aabdSBjoern A. Zeeb 		tlv_v7->type = SET_SLOT_TABLE;
2350*6d67aabdSBjoern A. Zeeb 		tlv_v7->ver = ver->fcxslots;
2351*6d67aabdSBjoern A. Zeeb 		tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
2352*6d67aabdSBjoern A. Zeeb 		memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
2353*6d67aabdSBjoern A. Zeeb 
2354*6d67aabdSBjoern A. Zeeb 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
2355*6d67aabdSBjoern A. Zeeb 
2356*6d67aabdSBjoern A. Zeeb 		kfree(tlv_v7);
2357*6d67aabdSBjoern A. Zeeb 	} else {
2358*6d67aabdSBjoern A. Zeeb 		n = struct_size(tbl, tbls, CXST_MAX);
2359*6d67aabdSBjoern A. Zeeb 		tbl = kmalloc(n, GFP_KERNEL);
2360*6d67aabdSBjoern A. Zeeb 		if (!tbl)
2361*6d67aabdSBjoern A. Zeeb 			return;
2362*6d67aabdSBjoern A. Zeeb 
2363*6d67aabdSBjoern A. Zeeb 		tbl->fver = BTF_SET_SLOT_TABLE_VER;
2364*6d67aabdSBjoern A. Zeeb 		tbl->tbl_num = CXST_MAX;
2365*6d67aabdSBjoern A. Zeeb 		memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
2366*6d67aabdSBjoern A. Zeeb 
2367*6d67aabdSBjoern A. Zeeb 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
2368*6d67aabdSBjoern A. Zeeb 
2369*6d67aabdSBjoern A. Zeeb 		kfree(tbl);
2370*6d67aabdSBjoern A. Zeeb 	}
2371*6d67aabdSBjoern A. Zeeb }
2372*6d67aabdSBjoern A. Zeeb 
23738e93258fSBjoern A. Zeeb static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
23748e93258fSBjoern A. Zeeb 				u32 rpt_map, bool rpt_state)
23758e93258fSBjoern A. Zeeb {
23768e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2377e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
23788e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
2379*6d67aabdSBjoern A. Zeeb 	union rtw89_fbtc_rtp_ctrl r;
2380e2340276SBjoern A. Zeeb 	u32 val, bit_map;
2381*6d67aabdSBjoern A. Zeeb 	int ret;
2382e2340276SBjoern A. Zeeb 
2383e2340276SBjoern A. Zeeb 	if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0)
2384e2340276SBjoern A. Zeeb 		return;
2385e2340276SBjoern A. Zeeb 
2386e2340276SBjoern A. Zeeb 	bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map);
23878e93258fSBjoern A. Zeeb 
23888e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
23898e93258fSBjoern A. Zeeb 		    "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
23908e93258fSBjoern A. Zeeb 		    __func__, rpt_map, rpt_state);
23918e93258fSBjoern A. Zeeb 
23928e93258fSBjoern A. Zeeb 	if (rpt_state)
2393e2340276SBjoern A. Zeeb 		val = fwinfo->rpt_en_map | bit_map;
23948e93258fSBjoern A. Zeeb 	else
2395e2340276SBjoern A. Zeeb 		val = fwinfo->rpt_en_map & ~bit_map;
23968e93258fSBjoern A. Zeeb 
23978e93258fSBjoern A. Zeeb 	if (val == fwinfo->rpt_en_map)
23988e93258fSBjoern A. Zeeb 		return;
23998e93258fSBjoern A. Zeeb 
2400*6d67aabdSBjoern A. Zeeb 	if (btc->ver->fcxbtcrpt == 8) {
2401*6d67aabdSBjoern A. Zeeb 		r.v8.type = SET_REPORT_EN;
2402*6d67aabdSBjoern A. Zeeb 		r.v8.fver = btc->ver->fcxbtcrpt;
2403*6d67aabdSBjoern A. Zeeb 		r.v8.len = sizeof(r.v8.map);
2404*6d67aabdSBjoern A. Zeeb 		r.v8.map = cpu_to_le32(val);
2405*6d67aabdSBjoern A. Zeeb 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
2406*6d67aabdSBjoern A. Zeeb 				   sizeof(r.v8));
2407*6d67aabdSBjoern A. Zeeb 	} else {
2408*6d67aabdSBjoern A. Zeeb 		if (btc->ver->fcxbtcrpt == 105)
2409*6d67aabdSBjoern A. Zeeb 			r.v1.fver = 5;
2410*6d67aabdSBjoern A. Zeeb 		else
2411*6d67aabdSBjoern A. Zeeb 			r.v1.fver = btc->ver->fcxbtcrpt;
2412*6d67aabdSBjoern A. Zeeb 		r.v1.enable = cpu_to_le32(val);
2413*6d67aabdSBjoern A. Zeeb 		r.v1.para = cpu_to_le32(rpt_state);
2414*6d67aabdSBjoern A. Zeeb 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v1,
2415*6d67aabdSBjoern A. Zeeb 				   sizeof(r.v1));
24168e93258fSBjoern A. Zeeb 	}
24178e93258fSBjoern A. Zeeb 
2418*6d67aabdSBjoern A. Zeeb 	if (!ret)
2419*6d67aabdSBjoern A. Zeeb 		fwinfo->rpt_en_map = val;
24208e93258fSBjoern A. Zeeb }
24218e93258fSBjoern A. Zeeb 
24228e93258fSBjoern A. Zeeb static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
24238e93258fSBjoern A. Zeeb {
24248e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
2425e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2426*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
2427*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
2428*6d67aabdSBjoern A. Zeeb 	u8 i, n, ulen, cxmreg_max;
24298e93258fSBjoern A. Zeeb 	u16 sz = 0;
24308e93258fSBjoern A. Zeeb 
24318e93258fSBjoern A. Zeeb 	n = chip->mon_reg_num;
24328e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
24338e93258fSBjoern A. Zeeb 		    "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
2434e2340276SBjoern A. Zeeb 
2435e2340276SBjoern A. Zeeb 	if (ver->fcxmreg == 1)
2436e2340276SBjoern A. Zeeb 		cxmreg_max = CXMREG_MAX;
2437e2340276SBjoern A. Zeeb 	else
2438*6d67aabdSBjoern A. Zeeb 		cxmreg_max = CXMREG_MAX_V2;
2439e2340276SBjoern A. Zeeb 
2440e2340276SBjoern A. Zeeb 	if (n > cxmreg_max) {
24418e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
24428e93258fSBjoern A. Zeeb 			    "[BTC], %s(): mon reg count %d > %d\n",
2443e2340276SBjoern A. Zeeb 			    __func__, n, cxmreg_max);
24448e93258fSBjoern A. Zeeb 		return;
24458e93258fSBjoern A. Zeeb 	}
24468e93258fSBjoern A. Zeeb 
24478e93258fSBjoern A. Zeeb 	ulen = sizeof(struct rtw89_btc_fbtc_mreg);
24488e93258fSBjoern A. Zeeb 
2449*6d67aabdSBjoern A. Zeeb 	if (ver->fcxmreg == 7) {
2450*6d67aabdSBjoern A. Zeeb 		sz = struct_size(v7, regs, n);
2451*6d67aabdSBjoern A. Zeeb 		v7 = kmalloc(sz, GFP_KERNEL);
2452*6d67aabdSBjoern A. Zeeb 		v7->type = RPT_EN_MREG;
2453*6d67aabdSBjoern A. Zeeb 		v7->fver = ver->fcxmreg;
2454*6d67aabdSBjoern A. Zeeb 		v7->len = n;
2455*6d67aabdSBjoern A. Zeeb 		for (i = 0; i < n; i++) {
2456*6d67aabdSBjoern A. Zeeb 			v7->regs[i].type = chip->mon_reg[i].type;
2457*6d67aabdSBjoern A. Zeeb 			v7->regs[i].bytes = chip->mon_reg[i].bytes;
2458*6d67aabdSBjoern A. Zeeb 			v7->regs[i].offset = chip->mon_reg[i].offset;
2459*6d67aabdSBjoern A. Zeeb 		}
2460*6d67aabdSBjoern A. Zeeb 
2461*6d67aabdSBjoern A. Zeeb 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
2462*6d67aabdSBjoern A. Zeeb 		kfree(v7);
2463*6d67aabdSBjoern A. Zeeb 	} else {
2464*6d67aabdSBjoern A. Zeeb 		sz = struct_size(v1, regs, n);
2465*6d67aabdSBjoern A. Zeeb 		v1 = kmalloc(sz, GFP_KERNEL);
2466*6d67aabdSBjoern A. Zeeb 		v1->fver = ver->fcxmreg;
2467*6d67aabdSBjoern A. Zeeb 		v1->reg_num = n;
2468*6d67aabdSBjoern A. Zeeb 		memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
2469*6d67aabdSBjoern A. Zeeb 
2470*6d67aabdSBjoern A. Zeeb 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
2471*6d67aabdSBjoern A. Zeeb 		kfree(v1);
2472*6d67aabdSBjoern A. Zeeb 	}
2473*6d67aabdSBjoern A. Zeeb 
24748e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
24758e93258fSBjoern A. Zeeb 		    "[BTC], %s(): sz=%d ulen=%d n=%d\n",
24768e93258fSBjoern A. Zeeb 		    __func__, sz, ulen, n);
24778e93258fSBjoern A. Zeeb 
24788e93258fSBjoern A. Zeeb 	rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
24798e93258fSBjoern A. Zeeb }
24808e93258fSBjoern A. Zeeb 
24818e93258fSBjoern A. Zeeb static void _update_dm_step(struct rtw89_dev *rtwdev,
24828e93258fSBjoern A. Zeeb 			    enum btc_reason_and_action reason_or_action)
24838e93258fSBjoern A. Zeeb {
24848e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
24858e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
24868e93258fSBjoern A. Zeeb 
24878e93258fSBjoern A. Zeeb 	/* use ring-structure to store dm step */
24888e93258fSBjoern A. Zeeb 	dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
24898e93258fSBjoern A. Zeeb 	dm->dm_step.step_pos++;
24908e93258fSBjoern A. Zeeb 
24918e93258fSBjoern A. Zeeb 	if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
24928e93258fSBjoern A. Zeeb 		dm->dm_step.step_pos = 0;
24938e93258fSBjoern A. Zeeb 		dm->dm_step.step_ov = true;
24948e93258fSBjoern A. Zeeb 	}
24958e93258fSBjoern A. Zeeb }
24968e93258fSBjoern A. Zeeb 
24978e93258fSBjoern A. Zeeb static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
24988e93258fSBjoern A. Zeeb 			   enum btc_reason_and_action action)
24998e93258fSBjoern A. Zeeb {
25008e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
25018e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
2502*6d67aabdSBjoern A. Zeeb 	int ret;
25038e93258fSBjoern A. Zeeb 
25048e93258fSBjoern A. Zeeb 	dm->run_action = action;
25058e93258fSBjoern A. Zeeb 
25068e93258fSBjoern A. Zeeb 	_update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
25078e93258fSBjoern A. Zeeb 	_update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
25088e93258fSBjoern A. Zeeb 
25098e93258fSBjoern A. Zeeb 	btc->policy_len = 0;
25108e93258fSBjoern A. Zeeb 	btc->policy_type = policy_type;
25118e93258fSBjoern A. Zeeb 
25128e93258fSBjoern A. Zeeb 	_append_tdma(rtwdev);
25138e93258fSBjoern A. Zeeb 	_append_slot(rtwdev);
25148e93258fSBjoern A. Zeeb 
25158e93258fSBjoern A. Zeeb 	if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
25168e93258fSBjoern A. Zeeb 		return;
25178e93258fSBjoern A. Zeeb 
25188e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
25198e93258fSBjoern A. Zeeb 		    "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
25208e93258fSBjoern A. Zeeb 		    __func__, action, policy_type, btc->policy_len);
25218e93258fSBjoern A. Zeeb 
25228e93258fSBjoern A. Zeeb 	if (dm->tdma.rxflctrl == CXFLC_NULLP ||
25238e93258fSBjoern A. Zeeb 	    dm->tdma.rxflctrl == CXFLC_QOSNULL)
25248e93258fSBjoern A. Zeeb 		btc->lps = 1;
25258e93258fSBjoern A. Zeeb 	else
25268e93258fSBjoern A. Zeeb 		btc->lps = 0;
25278e93258fSBjoern A. Zeeb 
25288e93258fSBjoern A. Zeeb 	if (btc->lps == 1)
25298e93258fSBjoern A. Zeeb 		rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
25308e93258fSBjoern A. Zeeb 
2531*6d67aabdSBjoern A. Zeeb 	ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
25328e93258fSBjoern A. Zeeb 			   btc->policy, btc->policy_len);
2533*6d67aabdSBjoern A. Zeeb 	if (!ret) {
25348e93258fSBjoern A. Zeeb 		memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
2535*6d67aabdSBjoern A. Zeeb 		if (btc->ver->fcxslots == 7)
2536*6d67aabdSBjoern A. Zeeb 			memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
2537*6d67aabdSBjoern A. Zeeb 		else
2538*6d67aabdSBjoern A. Zeeb 			memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
2539*6d67aabdSBjoern A. Zeeb 	}
25408e93258fSBjoern A. Zeeb 
25418e93258fSBjoern A. Zeeb 	if (btc->update_policy_force)
25428e93258fSBjoern A. Zeeb 		btc->update_policy_force = false;
25438e93258fSBjoern A. Zeeb 
25448e93258fSBjoern A. Zeeb 	if (btc->lps == 0)
25458e93258fSBjoern A. Zeeb 		rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
25468e93258fSBjoern A. Zeeb }
25478e93258fSBjoern A. Zeeb 
25488e93258fSBjoern A. Zeeb static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
25498e93258fSBjoern A. Zeeb {
2550e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2551e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
2552e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
2553e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2554e2340276SBjoern A. Zeeb 	struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para;
25558e93258fSBjoern A. Zeeb 
25568e93258fSBjoern A. Zeeb 	switch (type) {
25578e93258fSBjoern A. Zeeb 	case CXDRVINFO_INIT:
2558*6d67aabdSBjoern A. Zeeb 		if (ver->fcxinit == 7)
2559*6d67aabdSBjoern A. Zeeb 			rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type);
2560*6d67aabdSBjoern A. Zeeb 		else
2561*6d67aabdSBjoern A. Zeeb 			rtw89_fw_h2c_cxdrv_init(rtwdev, type);
25628e93258fSBjoern A. Zeeb 		break;
25638e93258fSBjoern A. Zeeb 	case CXDRVINFO_ROLE:
2564e2340276SBjoern A. Zeeb 		if (ver->fwlrole == 0)
2565*6d67aabdSBjoern A. Zeeb 			rtw89_fw_h2c_cxdrv_role(rtwdev, type);
2566e2340276SBjoern A. Zeeb 		else if (ver->fwlrole == 1)
2567*6d67aabdSBjoern A. Zeeb 			rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type);
2568e2340276SBjoern A. Zeeb 		else if (ver->fwlrole == 2)
2569*6d67aabdSBjoern A. Zeeb 			rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type);
25708e93258fSBjoern A. Zeeb 		break;
25718e93258fSBjoern A. Zeeb 	case CXDRVINFO_CTRL:
2572*6d67aabdSBjoern A. Zeeb 		if (ver->drvinfo_type == 1)
2573*6d67aabdSBjoern A. Zeeb 			type = 2;
2574*6d67aabdSBjoern A. Zeeb 
2575*6d67aabdSBjoern A. Zeeb 		if (ver->fcxctrl == 7)
2576*6d67aabdSBjoern A. Zeeb 			rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type);
2577*6d67aabdSBjoern A. Zeeb 		else
2578*6d67aabdSBjoern A. Zeeb 			rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type);
25798e93258fSBjoern A. Zeeb 		break;
2580e2340276SBjoern A. Zeeb 	case CXDRVINFO_TRX:
2581*6d67aabdSBjoern A. Zeeb 		if (ver->drvinfo_type == 1)
2582*6d67aabdSBjoern A. Zeeb 			type = 3;
2583*6d67aabdSBjoern A. Zeeb 
2584e2340276SBjoern A. Zeeb 		dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power,
2585e2340276SBjoern A. Zeeb 						     RTW89_BTC_WL_DEF_TX_PWR);
2586e2340276SBjoern A. Zeeb 		dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain,
2587e2340276SBjoern A. Zeeb 						    RTW89_BTC_WL_DEF_TX_PWR);
2588e2340276SBjoern A. Zeeb 		dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power,
2589e2340276SBjoern A. Zeeb 							RTW89_BTC_WL_DEF_TX_PWR);
2590e2340276SBjoern A. Zeeb 		dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain,
2591e2340276SBjoern A. Zeeb 						       RTW89_BTC_WL_DEF_TX_PWR);
2592e2340276SBjoern A. Zeeb 		dm->trx_info.cn = wl->cn_report;
2593e2340276SBjoern A. Zeeb 		dm->trx_info.nhm = wl->nhm.pwr;
2594*6d67aabdSBjoern A. Zeeb 		rtw89_fw_h2c_cxdrv_trx(rtwdev, type);
2595e2340276SBjoern A. Zeeb 		break;
25968e93258fSBjoern A. Zeeb 	case CXDRVINFO_RFK:
2597*6d67aabdSBjoern A. Zeeb 		if (ver->drvinfo_type == 1)
2598*6d67aabdSBjoern A. Zeeb 			return;
2599*6d67aabdSBjoern A. Zeeb 
2600*6d67aabdSBjoern A. Zeeb 		rtw89_fw_h2c_cxdrv_rfk(rtwdev, type);
26018e93258fSBjoern A. Zeeb 		break;
2602*6d67aabdSBjoern A. Zeeb 	case CXDRVINFO_TXPWR:
2603*6d67aabdSBjoern A. Zeeb 	case CXDRVINFO_FDDT:
2604*6d67aabdSBjoern A. Zeeb 	case CXDRVINFO_MLO:
2605*6d67aabdSBjoern A. Zeeb 	case CXDRVINFO_OSI:
26068e93258fSBjoern A. Zeeb 	default:
26078e93258fSBjoern A. Zeeb 		break;
26088e93258fSBjoern A. Zeeb 	}
26098e93258fSBjoern A. Zeeb }
26108e93258fSBjoern A. Zeeb 
26118e93258fSBjoern A. Zeeb static
26128e93258fSBjoern A. Zeeb void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
26138e93258fSBjoern A. Zeeb {
26148e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
26158e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
26168e93258fSBjoern A. Zeeb 
26178e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
26188e93258fSBjoern A. Zeeb 		    "[BTC], %s(): evt_id:%d len:%d\n",
26198e93258fSBjoern A. Zeeb 		    __func__, evt_id, len);
26208e93258fSBjoern A. Zeeb 
26218e93258fSBjoern A. Zeeb 	if (!len || !data)
26228e93258fSBjoern A. Zeeb 		return;
26238e93258fSBjoern A. Zeeb 
26248e93258fSBjoern A. Zeeb 	switch (evt_id) {
26258e93258fSBjoern A. Zeeb 	case BTF_EVNT_RPT:
26268e93258fSBjoern A. Zeeb 		_parse_btc_report(rtwdev, pfwinfo, data, len);
26278e93258fSBjoern A. Zeeb 		break;
26288e93258fSBjoern A. Zeeb 	default:
26298e93258fSBjoern A. Zeeb 		break;
26308e93258fSBjoern A. Zeeb 	}
26318e93258fSBjoern A. Zeeb }
26328e93258fSBjoern A. Zeeb 
2633e2340276SBjoern A. Zeeb static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
26348e93258fSBjoern A. Zeeb {
26358e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
26368e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
26378e93258fSBjoern A. Zeeb 	struct rtw89_mac_ax_gnt *g = dm->gnt.band;
26388e93258fSBjoern A. Zeeb 	u8 i;
26398e93258fSBjoern A. Zeeb 
26408e93258fSBjoern A. Zeeb 	if (phy_map > BTC_PHY_ALL)
26418e93258fSBjoern A. Zeeb 		return;
26428e93258fSBjoern A. Zeeb 
26438e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_PHY_MAX; i++) {
26448e93258fSBjoern A. Zeeb 		if (!(phy_map & BIT(i)))
26458e93258fSBjoern A. Zeeb 			continue;
26468e93258fSBjoern A. Zeeb 
2647e2340276SBjoern A. Zeeb 		switch (wl_state) {
26488e93258fSBjoern A. Zeeb 		case BTC_GNT_HW:
26498e93258fSBjoern A. Zeeb 			g[i].gnt_wl_sw_en = 0;
26508e93258fSBjoern A. Zeeb 			g[i].gnt_wl = 0;
26518e93258fSBjoern A. Zeeb 			break;
26528e93258fSBjoern A. Zeeb 		case BTC_GNT_SW_LO:
26538e93258fSBjoern A. Zeeb 			g[i].gnt_wl_sw_en = 1;
26548e93258fSBjoern A. Zeeb 			g[i].gnt_wl = 0;
26558e93258fSBjoern A. Zeeb 			break;
26568e93258fSBjoern A. Zeeb 		case BTC_GNT_SW_HI:
26578e93258fSBjoern A. Zeeb 			g[i].gnt_wl_sw_en = 1;
26588e93258fSBjoern A. Zeeb 			g[i].gnt_wl = 1;
26598e93258fSBjoern A. Zeeb 			break;
26608e93258fSBjoern A. Zeeb 		}
2661e2340276SBjoern A. Zeeb 
2662e2340276SBjoern A. Zeeb 		switch (bt_state) {
2663e2340276SBjoern A. Zeeb 		case BTC_GNT_HW:
2664e2340276SBjoern A. Zeeb 			g[i].gnt_bt_sw_en = 0;
2665e2340276SBjoern A. Zeeb 			g[i].gnt_bt = 0;
2666e2340276SBjoern A. Zeeb 			break;
2667e2340276SBjoern A. Zeeb 		case BTC_GNT_SW_LO:
2668e2340276SBjoern A. Zeeb 			g[i].gnt_bt_sw_en = 1;
2669e2340276SBjoern A. Zeeb 			g[i].gnt_bt = 0;
2670e2340276SBjoern A. Zeeb 			break;
2671e2340276SBjoern A. Zeeb 		case BTC_GNT_SW_HI:
2672e2340276SBjoern A. Zeeb 			g[i].gnt_bt_sw_en = 1;
2673e2340276SBjoern A. Zeeb 			g[i].gnt_bt = 1;
2674e2340276SBjoern A. Zeeb 			break;
2675e2340276SBjoern A. Zeeb 		}
26768e93258fSBjoern A. Zeeb 	}
26778e93258fSBjoern A. Zeeb 
26788e93258fSBjoern A. Zeeb 	rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
26798e93258fSBjoern A. Zeeb }
26808e93258fSBjoern A. Zeeb 
2681*6d67aabdSBjoern A. Zeeb static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map,
2682*6d67aabdSBjoern A. Zeeb 			u8 wl_state, u8 bt_state, u8 wlact_state)
2683*6d67aabdSBjoern A. Zeeb {
2684*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2685*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
2686*6d67aabdSBjoern A. Zeeb 	struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2687*6d67aabdSBjoern A. Zeeb 	u8 i, bt_idx = dm->bt_select + 1;
2688*6d67aabdSBjoern A. Zeeb 
2689*6d67aabdSBjoern A. Zeeb 	if (phy_map > BTC_PHY_ALL)
2690*6d67aabdSBjoern A. Zeeb 		return;
2691*6d67aabdSBjoern A. Zeeb 
2692*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < RTW89_PHY_MAX; i++) {
2693*6d67aabdSBjoern A. Zeeb 		if (!(phy_map & BIT(i)))
2694*6d67aabdSBjoern A. Zeeb 			continue;
2695*6d67aabdSBjoern A. Zeeb 
2696*6d67aabdSBjoern A. Zeeb 		switch (wl_state) {
2697*6d67aabdSBjoern A. Zeeb 		case BTC_GNT_HW:
2698*6d67aabdSBjoern A. Zeeb 			g[i].gnt_wl_sw_en = 0;
2699*6d67aabdSBjoern A. Zeeb 			g[i].gnt_wl = 0;
2700*6d67aabdSBjoern A. Zeeb 			break;
2701*6d67aabdSBjoern A. Zeeb 		case BTC_GNT_SW_LO:
2702*6d67aabdSBjoern A. Zeeb 			g[i].gnt_wl_sw_en = 1;
2703*6d67aabdSBjoern A. Zeeb 			g[i].gnt_wl = 0;
2704*6d67aabdSBjoern A. Zeeb 			break;
2705*6d67aabdSBjoern A. Zeeb 		case BTC_GNT_SW_HI:
2706*6d67aabdSBjoern A. Zeeb 			g[i].gnt_wl_sw_en = 1;
2707*6d67aabdSBjoern A. Zeeb 			g[i].gnt_wl = 1;
2708*6d67aabdSBjoern A. Zeeb 			break;
2709*6d67aabdSBjoern A. Zeeb 		}
2710*6d67aabdSBjoern A. Zeeb 
2711*6d67aabdSBjoern A. Zeeb 		switch (bt_state) {
2712*6d67aabdSBjoern A. Zeeb 		case BTC_GNT_HW:
2713*6d67aabdSBjoern A. Zeeb 			g[i].gnt_bt_sw_en = 0;
2714*6d67aabdSBjoern A. Zeeb 			g[i].gnt_bt = 0;
2715*6d67aabdSBjoern A. Zeeb 			break;
2716*6d67aabdSBjoern A. Zeeb 		case BTC_GNT_SW_LO:
2717*6d67aabdSBjoern A. Zeeb 			g[i].gnt_bt_sw_en = 1;
2718*6d67aabdSBjoern A. Zeeb 			g[i].gnt_bt = 0;
2719*6d67aabdSBjoern A. Zeeb 			break;
2720*6d67aabdSBjoern A. Zeeb 		case BTC_GNT_SW_HI:
2721*6d67aabdSBjoern A. Zeeb 			g[i].gnt_bt_sw_en = 1;
2722*6d67aabdSBjoern A. Zeeb 			g[i].gnt_bt = 1;
2723*6d67aabdSBjoern A. Zeeb 			break;
2724*6d67aabdSBjoern A. Zeeb 		}
2725*6d67aabdSBjoern A. Zeeb 	}
2726*6d67aabdSBjoern A. Zeeb 
2727*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) {
2728*6d67aabdSBjoern A. Zeeb 		for (i = 0; i < 2; i++) {
2729*6d67aabdSBjoern A. Zeeb 			if (!(bt_idx & BIT(i)))
2730*6d67aabdSBjoern A. Zeeb 				continue;
2731*6d67aabdSBjoern A. Zeeb 
2732*6d67aabdSBjoern A. Zeeb 			switch (wlact_state) {
2733*6d67aabdSBjoern A. Zeeb 			case BTC_WLACT_HW:
2734*6d67aabdSBjoern A. Zeeb 				dm->gnt.bt[i].wlan_act_en = 0;
2735*6d67aabdSBjoern A. Zeeb 				dm->gnt.bt[i].wlan_act = 0;
2736*6d67aabdSBjoern A. Zeeb 				break;
2737*6d67aabdSBjoern A. Zeeb 			case BTC_WLACT_SW_LO:
2738*6d67aabdSBjoern A. Zeeb 				dm->gnt.bt[i].wlan_act_en = 1;
2739*6d67aabdSBjoern A. Zeeb 				dm->gnt.bt[i].wlan_act = 0;
2740*6d67aabdSBjoern A. Zeeb 				break;
2741*6d67aabdSBjoern A. Zeeb 			case BTC_WLACT_SW_HI:
2742*6d67aabdSBjoern A. Zeeb 				dm->gnt.bt[i].wlan_act_en = 1;
2743*6d67aabdSBjoern A. Zeeb 				dm->gnt.bt[i].wlan_act = 1;
2744*6d67aabdSBjoern A. Zeeb 				break;
2745*6d67aabdSBjoern A. Zeeb 			}
2746*6d67aabdSBjoern A. Zeeb 		}
2747*6d67aabdSBjoern A. Zeeb 	}
2748*6d67aabdSBjoern A. Zeeb 	rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
2749*6d67aabdSBjoern A. Zeeb }
2750*6d67aabdSBjoern A. Zeeb 
27518e93258fSBjoern A. Zeeb #define BTC_TDMA_WLROLE_MAX 2
27528e93258fSBjoern A. Zeeb 
27538e93258fSBjoern A. Zeeb static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
27548e93258fSBjoern A. Zeeb {
27558e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
27568e93258fSBjoern A. Zeeb 		    "[BTC], %s(): set bt %s wlan_act\n", __func__,
27578e93258fSBjoern A. Zeeb 		    enable ? "ignore" : "do not ignore");
27588e93258fSBjoern A. Zeeb 
27598e93258fSBjoern A. Zeeb 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
27608e93258fSBjoern A. Zeeb }
27618e93258fSBjoern A. Zeeb 
27628e93258fSBjoern A. Zeeb #define WL_TX_POWER_NO_BTC_CTRL	GENMASK(31, 0)
27638e93258fSBjoern A. Zeeb #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
27648e93258fSBjoern A. Zeeb #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
27658e93258fSBjoern A. Zeeb #define WL_TX_POWER_INT_PART GENMASK(8, 2)
27668e93258fSBjoern A. Zeeb #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
27678e93258fSBjoern A. Zeeb #define B_BTC_WL_TX_POWER_SIGN BIT(7)
27688e93258fSBjoern A. Zeeb #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
27698e93258fSBjoern A. Zeeb 
27708e93258fSBjoern A. Zeeb static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
27718e93258fSBjoern A. Zeeb {
27728e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
27738e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
27748e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
27758e93258fSBjoern A. Zeeb 	u32 pwr_val;
27768e93258fSBjoern A. Zeeb 
27778e93258fSBjoern A. Zeeb 	if (wl->rf_para.tx_pwr_freerun == level)
27788e93258fSBjoern A. Zeeb 		return;
27798e93258fSBjoern A. Zeeb 
27808e93258fSBjoern A. Zeeb 	wl->rf_para.tx_pwr_freerun = level;
27818e93258fSBjoern A. Zeeb 	btc->dm.rf_trx_para.wl_tx_power = level;
27828e93258fSBjoern A. Zeeb 
27838e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
27848e93258fSBjoern A. Zeeb 		    "[BTC], %s(): level = %d\n",
27858e93258fSBjoern A. Zeeb 		    __func__, level);
27868e93258fSBjoern A. Zeeb 
27878e93258fSBjoern A. Zeeb 	if (level == RTW89_BTC_WL_DEF_TX_PWR) {
27888e93258fSBjoern A. Zeeb 		pwr_val = WL_TX_POWER_NO_BTC_CTRL;
27898e93258fSBjoern A. Zeeb 	} else { /* only apply "force tx power" */
27908e93258fSBjoern A. Zeeb 		pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
27918e93258fSBjoern A. Zeeb 		if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
27928e93258fSBjoern A. Zeeb 			pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
27938e93258fSBjoern A. Zeeb 
27948e93258fSBjoern A. Zeeb 		if (level & B_BTC_WL_TX_POWER_SIGN)
27958e93258fSBjoern A. Zeeb 			pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
27968e93258fSBjoern A. Zeeb 		pwr_val |= WL_TX_POWER_WITH_BT;
27978e93258fSBjoern A. Zeeb 	}
27988e93258fSBjoern A. Zeeb 
27998e93258fSBjoern A. Zeeb 	chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
28008e93258fSBjoern A. Zeeb }
28018e93258fSBjoern A. Zeeb 
28028e93258fSBjoern A. Zeeb static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
28038e93258fSBjoern A. Zeeb {
2804e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
28058e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
28068e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
28078e93258fSBjoern A. Zeeb 
28088e93258fSBjoern A. Zeeb 	if (wl->rf_para.rx_gain_freerun == level)
28098e93258fSBjoern A. Zeeb 		return;
28108e93258fSBjoern A. Zeeb 
28118e93258fSBjoern A. Zeeb 	wl->rf_para.rx_gain_freerun = level;
28128e93258fSBjoern A. Zeeb 	btc->dm.rf_trx_para.wl_rx_gain = level;
28138e93258fSBjoern A. Zeeb 
28148e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
28158e93258fSBjoern A. Zeeb 		    "[BTC], %s(): level = %d\n",
28168e93258fSBjoern A. Zeeb 		    __func__, level);
2817e2340276SBjoern A. Zeeb 
2818e2340276SBjoern A. Zeeb 	chip->ops->btc_set_wl_rx_gain(rtwdev, level);
28198e93258fSBjoern A. Zeeb }
28208e93258fSBjoern A. Zeeb 
28218e93258fSBjoern A. Zeeb static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
28228e93258fSBjoern A. Zeeb {
28238e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
28248e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2825*6d67aabdSBjoern A. Zeeb 	int ret;
28268e93258fSBjoern A. Zeeb 	u8 buf;
28278e93258fSBjoern A. Zeeb 
2828*6d67aabdSBjoern A. Zeeb 	if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
2829*6d67aabdSBjoern A. Zeeb 		return;
2830*6d67aabdSBjoern A. Zeeb 
28318e93258fSBjoern A. Zeeb 	if (bt->rf_para.tx_pwr_freerun == level)
28328e93258fSBjoern A. Zeeb 		return;
28338e93258fSBjoern A. Zeeb 
28348e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
28358e93258fSBjoern A. Zeeb 		    "[BTC], %s(): level = %d\n",
28368e93258fSBjoern A. Zeeb 		    __func__, level);
28378e93258fSBjoern A. Zeeb 
28388e93258fSBjoern A. Zeeb 	buf = (s8)(-level);
2839*6d67aabdSBjoern A. Zeeb 	ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
2840*6d67aabdSBjoern A. Zeeb 	if (!ret) {
2841*6d67aabdSBjoern A. Zeeb 		bt->rf_para.tx_pwr_freerun = level;
2842*6d67aabdSBjoern A. Zeeb 		btc->dm.rf_trx_para.bt_tx_power = level;
2843*6d67aabdSBjoern A. Zeeb 	}
28448e93258fSBjoern A. Zeeb }
28458e93258fSBjoern A. Zeeb 
28468e93258fSBjoern A. Zeeb #define BTC_BT_RX_NORMAL_LVL 7
28478e93258fSBjoern A. Zeeb 
28488e93258fSBjoern A. Zeeb static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
28498e93258fSBjoern A. Zeeb {
28508e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
28518e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
28528e93258fSBjoern A. Zeeb 
2853*6d67aabdSBjoern A. Zeeb 	if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
2854*6d67aabdSBjoern A. Zeeb 		return;
2855*6d67aabdSBjoern A. Zeeb 
2856*6d67aabdSBjoern A. Zeeb 	if ((bt->rf_para.rx_gain_freerun == level ||
2857*6d67aabdSBjoern A. Zeeb 	     level > BTC_BT_RX_NORMAL_LVL) &&
2858*6d67aabdSBjoern A. Zeeb 	    (!rtwdev->chip->scbd || bt->lna_constrain == level))
28598e93258fSBjoern A. Zeeb 		return;
28608e93258fSBjoern A. Zeeb 
28618e93258fSBjoern A. Zeeb 	bt->rf_para.rx_gain_freerun = level;
28628e93258fSBjoern A. Zeeb 	btc->dm.rf_trx_para.bt_rx_gain = level;
28638e93258fSBjoern A. Zeeb 
28648e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
28658e93258fSBjoern A. Zeeb 		    "[BTC], %s(): level = %d\n",
28668e93258fSBjoern A. Zeeb 		    __func__, level);
28678e93258fSBjoern A. Zeeb 
28688e93258fSBjoern A. Zeeb 	if (level == BTC_BT_RX_NORMAL_LVL)
28698e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
28708e93258fSBjoern A. Zeeb 	else
28718e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
28728e93258fSBjoern A. Zeeb 
2873*6d67aabdSBjoern A. Zeeb 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level));
28748e93258fSBjoern A. Zeeb }
28758e93258fSBjoern A. Zeeb 
28768e93258fSBjoern A. Zeeb static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
28778e93258fSBjoern A. Zeeb {
28788e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
28798e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2880*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
28818e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
28828e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
28838e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2884e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
2885*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
28868e93258fSBjoern A. Zeeb 	struct rtw89_btc_rf_trx_para para;
28878e93258fSBjoern A. Zeeb 	u32 wl_stb_chg = 0;
2888*6d67aabdSBjoern A. Zeeb 	u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0;
28898e93258fSBjoern A. Zeeb 
2890*6d67aabdSBjoern A. Zeeb 	if (ver->fwlrole == 0) {
2891*6d67aabdSBjoern A. Zeeb 		link_mode = wl->role_info.link_mode;
2892*6d67aabdSBjoern A. Zeeb 		for (i = 0; i < RTW89_PHY_MAX; i++) {
2893*6d67aabdSBjoern A. Zeeb 			if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G)
2894*6d67aabdSBjoern A. Zeeb 				dbcc_2g_phy = i;
2895*6d67aabdSBjoern A. Zeeb 		}
2896*6d67aabdSBjoern A. Zeeb 	} else if (ver->fwlrole == 1) {
2897*6d67aabdSBjoern A. Zeeb 		link_mode = wl->role_info_v1.link_mode;
2898*6d67aabdSBjoern A. Zeeb 		dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy;
2899*6d67aabdSBjoern A. Zeeb 	} else if (ver->fwlrole == 2) {
2900*6d67aabdSBjoern A. Zeeb 		link_mode = wl->role_info_v2.link_mode;
2901*6d67aabdSBjoern A. Zeeb 		dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy;
29028e93258fSBjoern A. Zeeb 	}
29038e93258fSBjoern A. Zeeb 
2904*6d67aabdSBjoern A. Zeeb 	/* decide trx_para_level */
2905*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
2906*6d67aabdSBjoern A. Zeeb 		/* fix LNA2 + TIA gain not change by GNT_BT */
2907*6d67aabdSBjoern A. Zeeb 		if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) ||
2908*6d67aabdSBjoern A. Zeeb 		    dm->bt_only == 1)
2909*6d67aabdSBjoern A. Zeeb 			dm->trx_para_level = 1; /* for better BT ACI issue */
2910*6d67aabdSBjoern A. Zeeb 		else
2911*6d67aabdSBjoern A. Zeeb 			dm->trx_para_level = 0;
2912*6d67aabdSBjoern A. Zeeb 	} else { /* non-shared antenna  */
2913*6d67aabdSBjoern A. Zeeb 		dm->trx_para_level = 5;
2914*6d67aabdSBjoern A. Zeeb 		/* modify trx_para if WK 2.4G-STA-DL + bt link */
2915*6d67aabdSBjoern A. Zeeb 		if (b->profile_cnt.now != 0 &&
2916*6d67aabdSBjoern A. Zeeb 		    link_mode == BTC_WLINK_2G_STA &&
2917*6d67aabdSBjoern A. Zeeb 		    wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
2918*6d67aabdSBjoern A. Zeeb 			if (wl->rssi_level == 4 && bt->rssi_level > 2)
2919*6d67aabdSBjoern A. Zeeb 				dm->trx_para_level = 6;
2920*6d67aabdSBjoern A. Zeeb 			else if (wl->rssi_level == 3 && bt->rssi_level > 3)
2921*6d67aabdSBjoern A. Zeeb 				dm->trx_para_level = 7;
2922*6d67aabdSBjoern A. Zeeb 		}
2923*6d67aabdSBjoern A. Zeeb 	}
29248e93258fSBjoern A. Zeeb 
2925*6d67aabdSBjoern A. Zeeb 	level_id = dm->trx_para_level;
29268e93258fSBjoern A. Zeeb 	if (level_id >= chip->rf_para_dlink_num ||
29278e93258fSBjoern A. Zeeb 	    level_id >= chip->rf_para_ulink_num) {
29288e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
29298e93258fSBjoern A. Zeeb 			    "[BTC], %s(): invalid level_id: %d\n",
29308e93258fSBjoern A. Zeeb 			    __func__, level_id);
29318e93258fSBjoern A. Zeeb 		return;
29328e93258fSBjoern A. Zeeb 	}
29338e93258fSBjoern A. Zeeb 
29348e93258fSBjoern A. Zeeb 	if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
29358e93258fSBjoern A. Zeeb 		para = chip->rf_para_ulink[level_id];
29368e93258fSBjoern A. Zeeb 	else
29378e93258fSBjoern A. Zeeb 		para = chip->rf_para_dlink[level_id];
29388e93258fSBjoern A. Zeeb 
2939*6d67aabdSBjoern A. Zeeb 	if (dm->fddt_train) {
2940*6d67aabdSBjoern A. Zeeb 		_set_wl_rx_gain(rtwdev, 1);
2941*6d67aabdSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
2942*6d67aabdSBjoern A. Zeeb 	} else {
29438e93258fSBjoern A. Zeeb 		_set_wl_tx_power(rtwdev, para.wl_tx_power);
29448e93258fSBjoern A. Zeeb 		_set_wl_rx_gain(rtwdev, para.wl_rx_gain);
29458e93258fSBjoern A. Zeeb 		_set_bt_tx_power(rtwdev, para.bt_tx_power);
29468e93258fSBjoern A. Zeeb 		_set_bt_rx_gain(rtwdev, para.bt_rx_gain);
2947*6d67aabdSBjoern A. Zeeb 	}
29488e93258fSBjoern A. Zeeb 
2949*6d67aabdSBjoern A. Zeeb 	if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
2950*6d67aabdSBjoern A. Zeeb 	    wl_smap->lps == BTC_LPS_RF_OFF ||
2951*6d67aabdSBjoern A. Zeeb 	    link_mode == BTC_WLINK_5G ||
2952*6d67aabdSBjoern A. Zeeb 	    link_mode == BTC_WLINK_NOLINK ||
2953*6d67aabdSBjoern A. Zeeb 	    (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1))
29548e93258fSBjoern A. Zeeb 		wl_stb_chg = 0;
29558e93258fSBjoern A. Zeeb 	else
29568e93258fSBjoern A. Zeeb 		wl_stb_chg = 1;
29578e93258fSBjoern A. Zeeb 
29588e93258fSBjoern A. Zeeb 	if (wl_stb_chg != dm->wl_stb_chg) {
29598e93258fSBjoern A. Zeeb 		dm->wl_stb_chg = wl_stb_chg;
29608e93258fSBjoern A. Zeeb 		chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
29618e93258fSBjoern A. Zeeb 	}
29628e93258fSBjoern A. Zeeb }
29638e93258fSBjoern A. Zeeb 
29648e93258fSBjoern A. Zeeb static void _update_btc_state_map(struct rtw89_dev *rtwdev)
29658e93258fSBjoern A. Zeeb {
29668e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
29678e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
29688e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
29698e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
29708e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
29718e93258fSBjoern A. Zeeb 
29728e93258fSBjoern A. Zeeb 	if (wl->status.map.connecting || wl->status.map._4way ||
29738e93258fSBjoern A. Zeeb 	    wl->status.map.roaming) {
29748e93258fSBjoern A. Zeeb 		cx->state_map = BTC_WLINKING;
29758e93258fSBjoern A. Zeeb 	} else if (wl->status.map.scan) { /* wl scan */
29768e93258fSBjoern A. Zeeb 		if (bt_linfo->status.map.inq_pag)
29778e93258fSBjoern A. Zeeb 			cx->state_map = BTC_WSCAN_BSCAN;
29788e93258fSBjoern A. Zeeb 		else
29798e93258fSBjoern A. Zeeb 			cx->state_map = BTC_WSCAN_BNOSCAN;
29808e93258fSBjoern A. Zeeb 	} else if (wl->status.map.busy) { /* only busy */
29818e93258fSBjoern A. Zeeb 		if (bt_linfo->status.map.inq_pag)
29828e93258fSBjoern A. Zeeb 			cx->state_map = BTC_WBUSY_BSCAN;
29838e93258fSBjoern A. Zeeb 		else
29848e93258fSBjoern A. Zeeb 			cx->state_map = BTC_WBUSY_BNOSCAN;
29858e93258fSBjoern A. Zeeb 	} else { /* wl idle */
29868e93258fSBjoern A. Zeeb 		cx->state_map = BTC_WIDLE;
29878e93258fSBjoern A. Zeeb 	}
29888e93258fSBjoern A. Zeeb }
29898e93258fSBjoern A. Zeeb 
29908e93258fSBjoern A. Zeeb static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
29918e93258fSBjoern A. Zeeb {
29928e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
29938e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
2994e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
29958e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
29968e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
29978e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
29988e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
29998e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3000e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3001*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
30028e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_active_role *r;
30038e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_active_role_v1 *r1;
3004e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_active_role_v2 *r2;
3005*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_rlink *rlink;
30068e93258fSBjoern A. Zeeb 	u8 en = 0, i, ch = 0, bw = 0;
30078e93258fSBjoern A. Zeeb 	u8 mode, connect_cnt;
30088e93258fSBjoern A. Zeeb 
3009*6d67aabdSBjoern A. Zeeb 	if (btc->manual_ctrl || wl->status.map.scan)
30108e93258fSBjoern A. Zeeb 		return;
30118e93258fSBjoern A. Zeeb 
3012e2340276SBjoern A. Zeeb 	if (ver->fwlrole == 0) {
30138e93258fSBjoern A. Zeeb 		mode = wl_rinfo->link_mode;
30148e93258fSBjoern A. Zeeb 		connect_cnt = wl_rinfo->connect_cnt;
3015e2340276SBjoern A. Zeeb 	} else if (ver->fwlrole == 1) {
30168e93258fSBjoern A. Zeeb 		mode = wl_rinfo_v1->link_mode;
30178e93258fSBjoern A. Zeeb 		connect_cnt = wl_rinfo_v1->connect_cnt;
3018e2340276SBjoern A. Zeeb 	} else if (ver->fwlrole == 2) {
3019e2340276SBjoern A. Zeeb 		mode = wl_rinfo_v2->link_mode;
3020e2340276SBjoern A. Zeeb 		connect_cnt = wl_rinfo_v2->connect_cnt;
3021*6d67aabdSBjoern A. Zeeb 	} else if (ver->fwlrole == 8) {
3022*6d67aabdSBjoern A. Zeeb 		mode = wl_rinfo_v8->link_mode;
3023*6d67aabdSBjoern A. Zeeb 		connect_cnt = wl_rinfo_v8->connect_cnt;
3024e2340276SBjoern A. Zeeb 	} else {
3025e2340276SBjoern A. Zeeb 		return;
30268e93258fSBjoern A. Zeeb 	}
30278e93258fSBjoern A. Zeeb 
30288e93258fSBjoern A. Zeeb 	if (wl->status.map.rf_off || bt->whql_test ||
30298e93258fSBjoern A. Zeeb 	    mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
30308e93258fSBjoern A. Zeeb 	    connect_cnt > BTC_TDMA_WLROLE_MAX) {
30318e93258fSBjoern A. Zeeb 		en = false;
30328e93258fSBjoern A. Zeeb 	} else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
30338e93258fSBjoern A. Zeeb 		en = true;
30348e93258fSBjoern A. Zeeb 		/* get p2p channel */
30358e93258fSBjoern A. Zeeb 		for (i = 0; i < RTW89_PORT_NUM; i++) {
30368e93258fSBjoern A. Zeeb 			r = &wl_rinfo->active_role[i];
30378e93258fSBjoern A. Zeeb 			r1 = &wl_rinfo_v1->active_role_v1[i];
3038e2340276SBjoern A. Zeeb 			r2 = &wl_rinfo_v2->active_role_v2[i];
3039*6d67aabdSBjoern A. Zeeb 			rlink = &wl_rinfo_v8->rlink[i][0];
30408e93258fSBjoern A. Zeeb 
3041e2340276SBjoern A. Zeeb 			if (ver->fwlrole == 0 &&
30428e93258fSBjoern A. Zeeb 			    (r->role == RTW89_WIFI_ROLE_P2P_GO ||
30438e93258fSBjoern A. Zeeb 			     r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
30448e93258fSBjoern A. Zeeb 				ch = r->ch;
30458e93258fSBjoern A. Zeeb 				bw = r->bw;
30468e93258fSBjoern A. Zeeb 				break;
3047e2340276SBjoern A. Zeeb 			} else if (ver->fwlrole == 1 &&
30488e93258fSBjoern A. Zeeb 				   (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
30498e93258fSBjoern A. Zeeb 				    r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
30508e93258fSBjoern A. Zeeb 				ch = r1->ch;
30518e93258fSBjoern A. Zeeb 				bw = r1->bw;
30528e93258fSBjoern A. Zeeb 				break;
3053e2340276SBjoern A. Zeeb 			} else if (ver->fwlrole == 2 &&
3054e2340276SBjoern A. Zeeb 				   (r2->role == RTW89_WIFI_ROLE_P2P_GO ||
3055e2340276SBjoern A. Zeeb 				    r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3056e2340276SBjoern A. Zeeb 				ch = r2->ch;
3057e2340276SBjoern A. Zeeb 				bw = r2->bw;
3058e2340276SBjoern A. Zeeb 				break;
3059*6d67aabdSBjoern A. Zeeb 			} else if (ver->fwlrole == 8 &&
3060*6d67aabdSBjoern A. Zeeb 				   (rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3061*6d67aabdSBjoern A. Zeeb 				    rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3062*6d67aabdSBjoern A. Zeeb 				ch = rlink->ch;
3063*6d67aabdSBjoern A. Zeeb 				bw = rlink->bw;
3064*6d67aabdSBjoern A. Zeeb 				break;
30658e93258fSBjoern A. Zeeb 			}
30668e93258fSBjoern A. Zeeb 		}
30678e93258fSBjoern A. Zeeb 	} else {
30688e93258fSBjoern A. Zeeb 		en = true;
30698e93258fSBjoern A. Zeeb 		/* get 2g channel  */
30708e93258fSBjoern A. Zeeb 		for (i = 0; i < RTW89_PORT_NUM; i++) {
30718e93258fSBjoern A. Zeeb 			r = &wl_rinfo->active_role[i];
30728e93258fSBjoern A. Zeeb 			r1 = &wl_rinfo_v1->active_role_v1[i];
3073e2340276SBjoern A. Zeeb 			r2 = &wl_rinfo_v2->active_role_v2[i];
3074*6d67aabdSBjoern A. Zeeb 			rlink = &wl_rinfo_v8->rlink[i][0];
30758e93258fSBjoern A. Zeeb 
3076e2340276SBjoern A. Zeeb 			if (ver->fwlrole == 0 &&
30778e93258fSBjoern A. Zeeb 			    r->connected && r->band == RTW89_BAND_2G) {
30788e93258fSBjoern A. Zeeb 				ch = r->ch;
30798e93258fSBjoern A. Zeeb 				bw = r->bw;
30808e93258fSBjoern A. Zeeb 				break;
3081e2340276SBjoern A. Zeeb 			} else if (ver->fwlrole == 1 &&
30828e93258fSBjoern A. Zeeb 				   r1->connected && r1->band == RTW89_BAND_2G) {
30838e93258fSBjoern A. Zeeb 				ch = r1->ch;
30848e93258fSBjoern A. Zeeb 				bw = r1->bw;
30858e93258fSBjoern A. Zeeb 				break;
3086e2340276SBjoern A. Zeeb 			} else if (ver->fwlrole == 2 &&
3087e2340276SBjoern A. Zeeb 				   r2->connected && r2->band == RTW89_BAND_2G) {
3088e2340276SBjoern A. Zeeb 				ch = r2->ch;
3089e2340276SBjoern A. Zeeb 				bw = r2->bw;
3090e2340276SBjoern A. Zeeb 				break;
3091*6d67aabdSBjoern A. Zeeb 			} else if (ver->fwlrole == 8 &&
3092*6d67aabdSBjoern A. Zeeb 				   rlink->connected && rlink->rf_band == RTW89_BAND_2G) {
3093*6d67aabdSBjoern A. Zeeb 				ch = rlink->ch;
3094*6d67aabdSBjoern A. Zeeb 				bw = rlink->bw;
3095*6d67aabdSBjoern A. Zeeb 				break;
30968e93258fSBjoern A. Zeeb 			}
30978e93258fSBjoern A. Zeeb 		}
30988e93258fSBjoern A. Zeeb 	}
30998e93258fSBjoern A. Zeeb 
31008e93258fSBjoern A. Zeeb 	switch (bw) {
31018e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_20:
31028e93258fSBjoern A. Zeeb 		bw = 20 + chip->afh_guard_ch * 2;
31038e93258fSBjoern A. Zeeb 		break;
31048e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_40:
31058e93258fSBjoern A. Zeeb 		bw = 40 + chip->afh_guard_ch * 2;
31068e93258fSBjoern A. Zeeb 		break;
31078e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_5:
31088e93258fSBjoern A. Zeeb 		bw = 5 + chip->afh_guard_ch * 2;
31098e93258fSBjoern A. Zeeb 		break;
31108e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_10:
31118e93258fSBjoern A. Zeeb 		bw = 10 + chip->afh_guard_ch * 2;
31128e93258fSBjoern A. Zeeb 		break;
31138e93258fSBjoern A. Zeeb 	default:
31148e93258fSBjoern A. Zeeb 		bw = 0;
31158e93258fSBjoern A. Zeeb 		en = false; /* turn off AFH info if BW > 40 */
31168e93258fSBjoern A. Zeeb 		break;
31178e93258fSBjoern A. Zeeb 	}
31188e93258fSBjoern A. Zeeb 
31198e93258fSBjoern A. Zeeb 	if (wl->afh_info.en == en &&
31208e93258fSBjoern A. Zeeb 	    wl->afh_info.ch == ch &&
31218e93258fSBjoern A. Zeeb 	    wl->afh_info.bw == bw &&
31228e93258fSBjoern A. Zeeb 	    b->profile_cnt.last == b->profile_cnt.now) {
31238e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
31248e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return because no change!\n",
31258e93258fSBjoern A. Zeeb 			    __func__);
31268e93258fSBjoern A. Zeeb 		return;
31278e93258fSBjoern A. Zeeb 	}
31288e93258fSBjoern A. Zeeb 
31298e93258fSBjoern A. Zeeb 	wl->afh_info.en = en;
31308e93258fSBjoern A. Zeeb 	wl->afh_info.ch = ch;
31318e93258fSBjoern A. Zeeb 	wl->afh_info.bw = bw;
31328e93258fSBjoern A. Zeeb 
31338e93258fSBjoern A. Zeeb 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
31348e93258fSBjoern A. Zeeb 
31358e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
31368e93258fSBjoern A. Zeeb 		    "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
31378e93258fSBjoern A. Zeeb 		    __func__, en, ch, bw);
31388e93258fSBjoern A. Zeeb 	btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
31398e93258fSBjoern A. Zeeb }
31408e93258fSBjoern A. Zeeb 
31418e93258fSBjoern A. Zeeb static bool _check_freerun(struct rtw89_dev *rtwdev)
31428e93258fSBjoern A. Zeeb {
31438e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
31448e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
31458e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
31468e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
31478e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3148*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3149*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
31508e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
31518e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
3152*6d67aabdSBjoern A. Zeeb 	union rtw89_btc_module_info *md = &btc->mdinfo;
3153*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
3154*6d67aabdSBjoern A. Zeeb 	u8 isolation, connect_cnt = 0;
31558e93258fSBjoern A. Zeeb 
3156*6d67aabdSBjoern A. Zeeb 	if (ver->fcxinit == 7)
3157*6d67aabdSBjoern A. Zeeb 		isolation = md->md_v7.ant.isolation;
3158*6d67aabdSBjoern A. Zeeb 	else
3159*6d67aabdSBjoern A. Zeeb 		isolation = md->md.ant.isolation;
3160*6d67aabdSBjoern A. Zeeb 
3161*6d67aabdSBjoern A. Zeeb 	if (ver->fwlrole == 0)
3162*6d67aabdSBjoern A. Zeeb 		connect_cnt = wl_rinfo->connect_cnt;
3163*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 1)
3164*6d67aabdSBjoern A. Zeeb 		connect_cnt = wl_rinfo_v1->connect_cnt;
3165*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 2)
3166*6d67aabdSBjoern A. Zeeb 		connect_cnt = wl_rinfo_v2->connect_cnt;
3167*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 8)
3168*6d67aabdSBjoern A. Zeeb 		connect_cnt = wl_rinfo_v8->connect_cnt;
3169*6d67aabdSBjoern A. Zeeb 
3170*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
31718e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 0;
31728e93258fSBjoern A. Zeeb 		return false;
31738e93258fSBjoern A. Zeeb 	}
31748e93258fSBjoern A. Zeeb 
31758e93258fSBjoern A. Zeeb 	/* The below is dedicated antenna case */
3176*6d67aabdSBjoern A. Zeeb 	if (connect_cnt > BTC_TDMA_WLROLE_MAX) {
31778e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 5;
31788e93258fSBjoern A. Zeeb 		return true;
31798e93258fSBjoern A. Zeeb 	}
31808e93258fSBjoern A. Zeeb 
31818e93258fSBjoern A. Zeeb 	if (bt_linfo->profile_cnt.now == 0) {
31828e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 5;
31838e93258fSBjoern A. Zeeb 		return true;
31848e93258fSBjoern A. Zeeb 	}
31858e93258fSBjoern A. Zeeb 
31868e93258fSBjoern A. Zeeb 	if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
31878e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 5;
31888e93258fSBjoern A. Zeeb 		return true;
31898e93258fSBjoern A. Zeeb 	}
31908e93258fSBjoern A. Zeeb 
31918e93258fSBjoern A. Zeeb 	/* TODO get isolation by BT psd */
3192*6d67aabdSBjoern A. Zeeb 	if (isolation >= BTC_FREERUN_ANTISO_MIN) {
31938e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 5;
31948e93258fSBjoern A. Zeeb 		return true;
31958e93258fSBjoern A. Zeeb 	}
31968e93258fSBjoern A. Zeeb 
31978e93258fSBjoern A. Zeeb 	if (!wl->status.map.busy) {/* wl idle -> freerun */
31988e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 5;
31998e93258fSBjoern A. Zeeb 		return true;
32008e93258fSBjoern A. Zeeb 	} else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
32018e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 0;
32028e93258fSBjoern A. Zeeb 		return false;
32038e93258fSBjoern A. Zeeb 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
32048e93258fSBjoern A. Zeeb 		if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
32058e93258fSBjoern A. Zeeb 			btc->dm.trx_para_level = 6;
32068e93258fSBjoern A. Zeeb 			return true;
32078e93258fSBjoern A. Zeeb 		} else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
32088e93258fSBjoern A. Zeeb 			btc->dm.trx_para_level = 7;
32098e93258fSBjoern A. Zeeb 			return true;
32108e93258fSBjoern A. Zeeb 		}
32118e93258fSBjoern A. Zeeb 		btc->dm.trx_para_level = 0;
32128e93258fSBjoern A. Zeeb 		return false;
32138e93258fSBjoern A. Zeeb 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
32148e93258fSBjoern A. Zeeb 		if (bt_linfo->rssi > 28) {
32158e93258fSBjoern A. Zeeb 			btc->dm.trx_para_level = 6;
32168e93258fSBjoern A. Zeeb 			return true;
32178e93258fSBjoern A. Zeeb 		}
32188e93258fSBjoern A. Zeeb 	}
32198e93258fSBjoern A. Zeeb 
32208e93258fSBjoern A. Zeeb 	btc->dm.trx_para_level = 0;
32218e93258fSBjoern A. Zeeb 	return false;
32228e93258fSBjoern A. Zeeb }
32238e93258fSBjoern A. Zeeb 
32248e93258fSBjoern A. Zeeb #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
32258e93258fSBjoern A. Zeeb #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
32268e93258fSBjoern A. Zeeb #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
32278e93258fSBjoern A. Zeeb #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
32288e93258fSBjoern A. Zeeb 
32298e93258fSBjoern A. Zeeb struct btc_btinfo_lb2 {
32308e93258fSBjoern A. Zeeb 	u8 connect: 1;
32318e93258fSBjoern A. Zeeb 	u8 sco_busy: 1;
32328e93258fSBjoern A. Zeeb 	u8 inq_pag: 1;
32338e93258fSBjoern A. Zeeb 	u8 acl_busy: 1;
32348e93258fSBjoern A. Zeeb 	u8 hfp: 1;
32358e93258fSBjoern A. Zeeb 	u8 hid: 1;
32368e93258fSBjoern A. Zeeb 	u8 a2dp: 1;
32378e93258fSBjoern A. Zeeb 	u8 pan: 1;
32388e93258fSBjoern A. Zeeb };
32398e93258fSBjoern A. Zeeb 
32408e93258fSBjoern A. Zeeb struct btc_btinfo_lb3 {
32418e93258fSBjoern A. Zeeb 	u8 retry: 4;
32428e93258fSBjoern A. Zeeb 	u8 cqddr: 1;
32438e93258fSBjoern A. Zeeb 	u8 inq: 1;
32448e93258fSBjoern A. Zeeb 	u8 mesh_busy: 1;
32458e93258fSBjoern A. Zeeb 	u8 pag: 1;
32468e93258fSBjoern A. Zeeb };
32478e93258fSBjoern A. Zeeb 
32488e93258fSBjoern A. Zeeb struct btc_btinfo_hb0 {
32498e93258fSBjoern A. Zeeb 	s8 rssi;
32508e93258fSBjoern A. Zeeb };
32518e93258fSBjoern A. Zeeb 
32528e93258fSBjoern A. Zeeb struct btc_btinfo_hb1 {
32538e93258fSBjoern A. Zeeb 	u8 ble_connect: 1;
32548e93258fSBjoern A. Zeeb 	u8 reinit: 1;
32558e93258fSBjoern A. Zeeb 	u8 relink: 1;
32568e93258fSBjoern A. Zeeb 	u8 igno_wl: 1;
32578e93258fSBjoern A. Zeeb 	u8 voice: 1;
32588e93258fSBjoern A. Zeeb 	u8 ble_scan: 1;
32598e93258fSBjoern A. Zeeb 	u8 role_sw: 1;
32608e93258fSBjoern A. Zeeb 	u8 multi_link: 1;
32618e93258fSBjoern A. Zeeb };
32628e93258fSBjoern A. Zeeb 
32638e93258fSBjoern A. Zeeb struct btc_btinfo_hb2 {
32648e93258fSBjoern A. Zeeb 	u8 pan_active: 1;
32658e93258fSBjoern A. Zeeb 	u8 afh_update: 1;
32668e93258fSBjoern A. Zeeb 	u8 a2dp_active: 1;
32678e93258fSBjoern A. Zeeb 	u8 slave: 1;
32688e93258fSBjoern A. Zeeb 	u8 hid_slot: 2;
32698e93258fSBjoern A. Zeeb 	u8 hid_cnt: 2;
32708e93258fSBjoern A. Zeeb };
32718e93258fSBjoern A. Zeeb 
32728e93258fSBjoern A. Zeeb struct btc_btinfo_hb3 {
32738e93258fSBjoern A. Zeeb 	u8 a2dp_bitpool: 6;
32748e93258fSBjoern A. Zeeb 	u8 tx_3m: 1;
32758e93258fSBjoern A. Zeeb 	u8 a2dp_sink: 1;
32768e93258fSBjoern A. Zeeb };
32778e93258fSBjoern A. Zeeb 
32788e93258fSBjoern A. Zeeb union btc_btinfo {
32798e93258fSBjoern A. Zeeb 	u8 val;
32808e93258fSBjoern A. Zeeb 	struct btc_btinfo_lb2 lb2;
32818e93258fSBjoern A. Zeeb 	struct btc_btinfo_lb3 lb3;
32828e93258fSBjoern A. Zeeb 	struct btc_btinfo_hb0 hb0;
32838e93258fSBjoern A. Zeeb 	struct btc_btinfo_hb1 hb1;
32848e93258fSBjoern A. Zeeb 	struct btc_btinfo_hb2 hb2;
32858e93258fSBjoern A. Zeeb 	struct btc_btinfo_hb3 hb3;
32868e93258fSBjoern A. Zeeb };
32878e93258fSBjoern A. Zeeb 
32888e93258fSBjoern A. Zeeb static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
32898e93258fSBjoern A. Zeeb 			enum btc_reason_and_action action)
32908e93258fSBjoern A. Zeeb {
32918e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
32928e93258fSBjoern A. Zeeb 
32938e93258fSBjoern A. Zeeb 	chip->ops->btc_set_policy(rtwdev, policy_type);
32948e93258fSBjoern A. Zeeb 	_fw_set_policy(rtwdev, policy_type, action);
32958e93258fSBjoern A. Zeeb }
32968e93258fSBjoern A. Zeeb 
32978e93258fSBjoern A. Zeeb #define BTC_B1_MAX 250 /* unit ms */
32988e93258fSBjoern A. Zeeb void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
32998e93258fSBjoern A. Zeeb {
33008e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
33018e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
33028e93258fSBjoern A. Zeeb 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3303*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
33048e93258fSBjoern A. Zeeb 	u8 type;
33058e93258fSBjoern A. Zeeb 	u32 tbl_w1, tbl_b1, tbl_b4;
33068e93258fSBjoern A. Zeeb 
3307*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
33088e93258fSBjoern A. Zeeb 		if (btc->cx.wl.status.map._4way)
33098e93258fSBjoern A. Zeeb 			tbl_w1 = cxtbl[1];
33108e93258fSBjoern A. Zeeb 		else
33118e93258fSBjoern A. Zeeb 			tbl_w1 = cxtbl[8];
33128e93258fSBjoern A. Zeeb 		tbl_b1 = cxtbl[3];
33138e93258fSBjoern A. Zeeb 		tbl_b4 = cxtbl[3];
33148e93258fSBjoern A. Zeeb 	} else {
33158e93258fSBjoern A. Zeeb 		tbl_w1 = cxtbl[16];
33168e93258fSBjoern A. Zeeb 		tbl_b1 = cxtbl[17];
33178e93258fSBjoern A. Zeeb 		tbl_b4 = cxtbl[17];
33188e93258fSBjoern A. Zeeb 	}
33198e93258fSBjoern A. Zeeb 
33208e93258fSBjoern A. Zeeb 	type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
33218e93258fSBjoern A. Zeeb 	btc->bt_req_en = false;
33228e93258fSBjoern A. Zeeb 
33238e93258fSBjoern A. Zeeb 	switch (type) {
33248e93258fSBjoern A. Zeeb 	case BTC_CXP_USERDEF0:
33258e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF];
33268e93258fSBjoern A. Zeeb 		s[CXST_OFF] = s_def[CXST_OFF];
33278e93258fSBjoern A. Zeeb 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
33288e93258fSBjoern A. Zeeb 		btc->update_policy_force = true;
33298e93258fSBjoern A. Zeeb 		break;
33308e93258fSBjoern A. Zeeb 	case BTC_CXP_OFF: /* TDMA off */
33318e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
33328e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF];
33338e93258fSBjoern A. Zeeb 		s[CXST_OFF] = s_def[CXST_OFF];
33348e93258fSBjoern A. Zeeb 
33358e93258fSBjoern A. Zeeb 		switch (policy_type) {
33368e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_BT:
33378e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
33388e93258fSBjoern A. Zeeb 			break;
33398e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_WL:
33408e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
33418e93258fSBjoern A. Zeeb 			break;
33428e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ0:
33438e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
33448e93258fSBjoern A. Zeeb 			break;
33458e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ1:
33468e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
33478e93258fSBjoern A. Zeeb 			break;
33488e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ2:
33498e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
33508e93258fSBjoern A. Zeeb 			break;
33518e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ3:
33528e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
33538e93258fSBjoern A. Zeeb 			break;
33548e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_BWB0:
33558e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
33568e93258fSBjoern A. Zeeb 			break;
33578e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_BWB1:
33588e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
33598e93258fSBjoern A. Zeeb 			break;
3360e2340276SBjoern A. Zeeb 		case BTC_CXP_OFF_BWB3:
3361e2340276SBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3362e2340276SBjoern A. Zeeb 			break;
33638e93258fSBjoern A. Zeeb 		}
33648e93258fSBjoern A. Zeeb 		break;
33658e93258fSBjoern A. Zeeb 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
33668e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
33678e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF_B2];
33688e93258fSBjoern A. Zeeb 		s[CXST_OFF] = s_def[CXST_OFF];
33698e93258fSBjoern A. Zeeb 		switch (policy_type) {
33708e93258fSBjoern A. Zeeb 		case BTC_CXP_OFFB_BWB0:
33718e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
33728e93258fSBjoern A. Zeeb 			break;
33738e93258fSBjoern A. Zeeb 		}
33748e93258fSBjoern A. Zeeb 		break;
33758e93258fSBjoern A. Zeeb 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
33768e93258fSBjoern A. Zeeb 		btc->bt_req_en = true;
33778e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
33788e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF_EXT];
33798e93258fSBjoern A. Zeeb 		switch (policy_type) {
33808e93258fSBjoern A. Zeeb 		case BTC_CXP_OFFE_DEF:
33818e93258fSBjoern A. Zeeb 			s[CXST_E2G] = s_def[CXST_E2G];
33828e93258fSBjoern A. Zeeb 			s[CXST_E5G] = s_def[CXST_E5G];
33838e93258fSBjoern A. Zeeb 			s[CXST_EBT] = s_def[CXST_EBT];
33848e93258fSBjoern A. Zeeb 			s[CXST_ENULL] = s_def[CXST_ENULL];
33858e93258fSBjoern A. Zeeb 			break;
33868e93258fSBjoern A. Zeeb 		case BTC_CXP_OFFE_DEF2:
33878e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
33888e93258fSBjoern A. Zeeb 			s[CXST_E5G] = s_def[CXST_E5G];
33898e93258fSBjoern A. Zeeb 			s[CXST_EBT] = s_def[CXST_EBT];
33908e93258fSBjoern A. Zeeb 			s[CXST_ENULL] = s_def[CXST_ENULL];
33918e93258fSBjoern A. Zeeb 			break;
33928e93258fSBjoern A. Zeeb 		}
33938e93258fSBjoern A. Zeeb 		break;
33948e93258fSBjoern A. Zeeb 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
33958e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
33968e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_FIX];
33978e93258fSBjoern A. Zeeb 		switch (policy_type) {
33988e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD3030:
33998e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
34008e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
34018e93258fSBjoern A. Zeeb 			break;
34028e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD5050:
34038e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
34048e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
34058e93258fSBjoern A. Zeeb 			break;
34068e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD2030:
34078e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
34088e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
34098e93258fSBjoern A. Zeeb 			break;
34108e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010:
34118e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
34128e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
34138e93258fSBjoern A. Zeeb 			break;
3414*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010ISO:
3415*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3416*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3417*6d67aabdSBjoern A. Zeeb 			break;
3418*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010ISO_DL:
3419*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3420*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3421*6d67aabdSBjoern A. Zeeb 			break;
3422*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010ISO_UL:
3423*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3424*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
34258e93258fSBjoern A. Zeeb 			break;
34268e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD7010:
34278e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
34288e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
34298e93258fSBjoern A. Zeeb 			break;
34308e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD2060:
34318e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
34328e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
34338e93258fSBjoern A. Zeeb 			break;
34348e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD3060:
34358e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
34368e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
34378e93258fSBjoern A. Zeeb 			break;
34388e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD2080:
34398e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
34408e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
34418e93258fSBjoern A. Zeeb 			break;
34428e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
34438e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
34448e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
34458e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
34468e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
34478e93258fSBjoern A. Zeeb 			break;
34488e93258fSBjoern A. Zeeb 		}
34498e93258fSBjoern A. Zeeb 		break;
34508e93258fSBjoern A. Zeeb 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
34518e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
34528e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_PFIX];
34538e93258fSBjoern A. Zeeb 		if (btc->cx.wl.role_info.role_map.role.ap)
34548e93258fSBjoern A. Zeeb 			_tdma_set_flctrl(btc, CXFLC_QOSNULL);
34558e93258fSBjoern A. Zeeb 
34568e93258fSBjoern A. Zeeb 		switch (policy_type) {
34578e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD3030:
34588e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
34598e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
34608e93258fSBjoern A. Zeeb 			break;
34618e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD5050:
34628e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
34638e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
34648e93258fSBjoern A. Zeeb 			break;
34658e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD2030:
34668e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
34678e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
34688e93258fSBjoern A. Zeeb 			break;
34698e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD2060:
34708e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
34718e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
34728e93258fSBjoern A. Zeeb 			break;
34738e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD3070:
34748e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
34758e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
34768e93258fSBjoern A. Zeeb 			break;
34778e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD2080:
34788e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
34798e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
34808e93258fSBjoern A. Zeeb 			break;
34818e93258fSBjoern A. Zeeb 		}
34828e93258fSBjoern A. Zeeb 		break;
34838e93258fSBjoern A. Zeeb 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
34848e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
34858e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_AUTO];
34868e93258fSBjoern A. Zeeb 		switch (policy_type) {
34878e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TD50B1:
34888e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
34898e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
34908e93258fSBjoern A. Zeeb 			break;
34918e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TD60B1:
34928e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
34938e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
34948e93258fSBjoern A. Zeeb 			break;
34958e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TD20B1:
34968e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
34978e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
34988e93258fSBjoern A. Zeeb 			break;
34998e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
35008e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
35018e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
35028e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
35038e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
35048e93258fSBjoern A. Zeeb 			break;
35058e93258fSBjoern A. Zeeb 		}
35068e93258fSBjoern A. Zeeb 		break;
35078e93258fSBjoern A. Zeeb 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
35088e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
35098e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_PAUTO];
35108e93258fSBjoern A. Zeeb 		switch (policy_type) {
35118e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TD50B1:
35128e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
35138e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35148e93258fSBjoern A. Zeeb 			break;
35158e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TD60B1:
35168e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
35178e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35188e93258fSBjoern A. Zeeb 			break;
35198e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TD20B1:
35208e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
35218e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35228e93258fSBjoern A. Zeeb 			break;
35238e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TDW1B1:
35248e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
35258e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
35268e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
35278e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
35288e93258fSBjoern A. Zeeb 			break;
35298e93258fSBjoern A. Zeeb 		}
35308e93258fSBjoern A. Zeeb 		break;
35318e93258fSBjoern A. Zeeb 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
35328e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
35338e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_AUTO2];
35348e93258fSBjoern A. Zeeb 		switch (policy_type) {
35358e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD3050:
35368e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
35378e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
35388e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35398e93258fSBjoern A. Zeeb 			break;
35408e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD3070:
35418e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
35428e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
35438e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35448e93258fSBjoern A. Zeeb 			break;
35458e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD5050:
35468e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
35478e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
35488e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35498e93258fSBjoern A. Zeeb 			break;
35508e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD6060:
35518e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
35528e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
35538e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35548e93258fSBjoern A. Zeeb 			break;
35558e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD2080:
35568e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
35578e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
35588e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35598e93258fSBjoern A. Zeeb 			break;
35608e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
35618e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
35628e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
35638e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
35648e93258fSBjoern A. Zeeb 				  tbl_b4, SLOT_MIX);
35658e93258fSBjoern A. Zeeb 			break;
35668e93258fSBjoern A. Zeeb 		}
35678e93258fSBjoern A. Zeeb 		break;
35688e93258fSBjoern A. Zeeb 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
35698e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
35708e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_PAUTO2];
35718e93258fSBjoern A. Zeeb 		switch (policy_type) {
35728e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD3050:
35738e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
35748e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
35758e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35768e93258fSBjoern A. Zeeb 			break;
35778e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD3070:
35788e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
35798e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
35808e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35818e93258fSBjoern A. Zeeb 			break;
35828e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD5050:
35838e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
35848e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
35858e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35868e93258fSBjoern A. Zeeb 			break;
35878e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD6060:
35888e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
35898e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
35908e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35918e93258fSBjoern A. Zeeb 			break;
35928e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD2080:
35938e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
35948e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
35958e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
35968e93258fSBjoern A. Zeeb 			break;
35978e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
35988e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
35998e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
36008e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
36018e93258fSBjoern A. Zeeb 				  tbl_b4, SLOT_MIX);
36028e93258fSBjoern A. Zeeb 			break;
36038e93258fSBjoern A. Zeeb 		}
36048e93258fSBjoern A. Zeeb 		break;
36058e93258fSBjoern A. Zeeb 	}
36068e93258fSBjoern A. Zeeb }
36078e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_btc_set_policy);
36088e93258fSBjoern A. Zeeb 
36098e93258fSBjoern A. Zeeb void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
36108e93258fSBjoern A. Zeeb {
36118e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
36128e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
36138e93258fSBjoern A. Zeeb 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
36148e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
36158e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
36168e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
3617*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
36188e93258fSBjoern A. Zeeb 	u8 type, null_role;
36198e93258fSBjoern A. Zeeb 	u32 tbl_w1, tbl_b1, tbl_b4;
3620*6d67aabdSBjoern A. Zeeb 	u16 dur_2;
36218e93258fSBjoern A. Zeeb 
36228e93258fSBjoern A. Zeeb 	type = FIELD_GET(BTC_CXP_MASK, policy_type);
36238e93258fSBjoern A. Zeeb 
3624*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
36258e93258fSBjoern A. Zeeb 		if (btc->cx.wl.status.map._4way)
36268e93258fSBjoern A. Zeeb 			tbl_w1 = cxtbl[1];
36278e93258fSBjoern A. Zeeb 		else if (hid->exist && hid->type == BTC_HID_218)
36288e93258fSBjoern A. Zeeb 			tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
36298e93258fSBjoern A. Zeeb 		else
36308e93258fSBjoern A. Zeeb 			tbl_w1 = cxtbl[8];
36318e93258fSBjoern A. Zeeb 
36328e93258fSBjoern A. Zeeb 		if (dm->leak_ap &&
36338e93258fSBjoern A. Zeeb 		    (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
36348e93258fSBjoern A. Zeeb 			tbl_b1 = cxtbl[3];
36358e93258fSBjoern A. Zeeb 			tbl_b4 = cxtbl[3];
36368e93258fSBjoern A. Zeeb 		} else if (hid->exist && hid->type == BTC_HID_218) {
36378e93258fSBjoern A. Zeeb 			tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
36388e93258fSBjoern A. Zeeb 			tbl_b4 = cxtbl[4];
36398e93258fSBjoern A. Zeeb 		} else {
36408e93258fSBjoern A. Zeeb 			tbl_b1 = cxtbl[2];
36418e93258fSBjoern A. Zeeb 			tbl_b4 = cxtbl[2];
36428e93258fSBjoern A. Zeeb 		}
36438e93258fSBjoern A. Zeeb 	} else {
36448e93258fSBjoern A. Zeeb 		tbl_b1 = cxtbl[17];
36458e93258fSBjoern A. Zeeb 		tbl_b4 = cxtbl[17];
3646*6d67aabdSBjoern A. Zeeb 
3647*6d67aabdSBjoern A. Zeeb 		if (wl->bg_mode)
3648*6d67aabdSBjoern A. Zeeb 			tbl_w1 = cxtbl[8];
3649*6d67aabdSBjoern A. Zeeb 		else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
3650*6d67aabdSBjoern A. Zeeb 			 hid->exist)
3651*6d67aabdSBjoern A. Zeeb 			tbl_w1 = cxtbl[19];
3652*6d67aabdSBjoern A. Zeeb 		else
3653*6d67aabdSBjoern A. Zeeb 			tbl_w1 = cxtbl[16];
36548e93258fSBjoern A. Zeeb 	}
36558e93258fSBjoern A. Zeeb 
36568e93258fSBjoern A. Zeeb 	btc->bt_req_en = false;
36578e93258fSBjoern A. Zeeb 
36588e93258fSBjoern A. Zeeb 	switch (type) {
36598e93258fSBjoern A. Zeeb 	case BTC_CXP_USERDEF0:
36608e93258fSBjoern A. Zeeb 		btc->update_policy_force = true;
36618e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF];
3662*6d67aabdSBjoern A. Zeeb 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3663*6d67aabdSBjoern A. Zeeb 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
36648e93258fSBjoern A. Zeeb 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
36658e93258fSBjoern A. Zeeb 		break;
36668e93258fSBjoern A. Zeeb 	case BTC_CXP_OFF: /* TDMA off */
36678e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
36688e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF];
3669*6d67aabdSBjoern A. Zeeb 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3670*6d67aabdSBjoern A. Zeeb 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
36718e93258fSBjoern A. Zeeb 
36728e93258fSBjoern A. Zeeb 		switch (policy_type) {
36738e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_BT:
36748e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
36758e93258fSBjoern A. Zeeb 			break;
36768e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_WL:
36778e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
36788e93258fSBjoern A. Zeeb 			break;
36798e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ0:
36808e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3681e2340276SBjoern A. Zeeb 			_slot_set_type(btc, CXST_OFF, SLOT_ISO);
36828e93258fSBjoern A. Zeeb 			break;
36838e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ1:
36848e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
36858e93258fSBjoern A. Zeeb 			break;
36868e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ2:
3687e2340276SBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
36888e93258fSBjoern A. Zeeb 			break;
36898e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_EQ3:
3690e2340276SBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
36918e93258fSBjoern A. Zeeb 			break;
36928e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_BWB0:
36938e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
36948e93258fSBjoern A. Zeeb 			break;
36958e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_BWB1:
36968e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
36978e93258fSBjoern A. Zeeb 			break;
36988e93258fSBjoern A. Zeeb 		case BTC_CXP_OFF_BWB2:
36998e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
37008e93258fSBjoern A. Zeeb 			break;
3701e2340276SBjoern A. Zeeb 		case BTC_CXP_OFF_BWB3:
3702e2340276SBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3703e2340276SBjoern A. Zeeb 			break;
37048e93258fSBjoern A. Zeeb 		default:
37058e93258fSBjoern A. Zeeb 			break;
37068e93258fSBjoern A. Zeeb 		}
37078e93258fSBjoern A. Zeeb 		break;
37088e93258fSBjoern A. Zeeb 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
37098e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
37108e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF_B2];
3711*6d67aabdSBjoern A. Zeeb 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3712*6d67aabdSBjoern A. Zeeb 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
37138e93258fSBjoern A. Zeeb 
37148e93258fSBjoern A. Zeeb 		switch (policy_type) {
37158e93258fSBjoern A. Zeeb 		case BTC_CXP_OFFB_BWB0:
37168e93258fSBjoern A. Zeeb 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
37178e93258fSBjoern A. Zeeb 			break;
37188e93258fSBjoern A. Zeeb 		default:
37198e93258fSBjoern A. Zeeb 			break;
37208e93258fSBjoern A. Zeeb 		}
37218e93258fSBjoern A. Zeeb 		break;
37228e93258fSBjoern A. Zeeb 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
37238e93258fSBjoern A. Zeeb 		btc->bt_req_en = true;
37248e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
37258e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_OFF_EXT];
37268e93258fSBjoern A. Zeeb 
37278e93258fSBjoern A. Zeeb 		/* To avoid wl-s0 tx break by hid/hfp tx */
37288e93258fSBjoern A. Zeeb 		if (hid->exist || hfp->exist)
37298e93258fSBjoern A. Zeeb 			tbl_w1 = cxtbl[16];
37308e93258fSBjoern A. Zeeb 
3731*6d67aabdSBjoern A. Zeeb 		dur_2 = dm->e2g_slot_limit;
3732*6d67aabdSBjoern A. Zeeb 
37338e93258fSBjoern A. Zeeb 		switch (policy_type) {
3734*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
3735*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_ISO);
3736*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3737*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3738*6d67aabdSBjoern A. Zeeb 			_slot_set_dur(btc, CXST_EBT, dur_2);
3739*6d67aabdSBjoern A. Zeeb 			break;
3740*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
3741*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_ISO);
3742*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3743*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3744*6d67aabdSBjoern A. Zeeb 			_slot_set_dur(btc, CXST_EBT, dur_2);
3745*6d67aabdSBjoern A. Zeeb 			break;
37468e93258fSBjoern A. Zeeb 		case BTC_CXP_OFFE_DEF:
3747*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
3748*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
3749*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
3750*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
3751*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3752*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3753*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
3754*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
37558e93258fSBjoern A. Zeeb 			break;
37568e93258fSBjoern A. Zeeb 		case BTC_CXP_OFFE_DEF2:
37578e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3758*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
3759*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
3760*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3761*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3762*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
3763*6d67aabdSBjoern A. Zeeb 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
3764*6d67aabdSBjoern A. Zeeb 			break;
3765*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_OFFE_2GBWMIXB:
3766*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_E2G, 0, 0x55555555, SLOT_MIX);
3767*6d67aabdSBjoern A. Zeeb 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3768*6d67aabdSBjoern A. Zeeb 				     cpu_to_le32(0x55555555), s_def[CXST_EBT].cxtype);
3769*6d67aabdSBjoern A. Zeeb 			break;
3770*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_OFFE_WL: /* for 4-way */
3771*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_MIX);
3772*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_EBT, 0, cxtbl[1], SLOT_MIX);
37738e93258fSBjoern A. Zeeb 			break;
37748e93258fSBjoern A. Zeeb 		default:
37758e93258fSBjoern A. Zeeb 			break;
37768e93258fSBjoern A. Zeeb 		}
3777*6d67aabdSBjoern A. Zeeb 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3778*6d67aabdSBjoern A. Zeeb 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
37798e93258fSBjoern A. Zeeb 		break;
37808e93258fSBjoern A. Zeeb 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
37818e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
37828e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_FIX];
37838e93258fSBjoern A. Zeeb 
37848e93258fSBjoern A. Zeeb 		switch (policy_type) {
37858e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD3030:
37868e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
37878e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
37888e93258fSBjoern A. Zeeb 			break;
37898e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD5050:
37908e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
37918e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
37928e93258fSBjoern A. Zeeb 			break;
37938e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD2030:
37948e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
37958e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
37968e93258fSBjoern A. Zeeb 			break;
37978e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010:
37988e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
37998e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
38008e93258fSBjoern A. Zeeb 			break;
38018e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010ISO:
38028e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
38038e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
38048e93258fSBjoern A. Zeeb 			break;
3805*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010ISO_DL:
3806*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3807*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3808*6d67aabdSBjoern A. Zeeb 			break;
3809*6d67aabdSBjoern A. Zeeb 		case BTC_CXP_FIX_TD4010ISO_UL:
3810*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3811*6d67aabdSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3812e2340276SBjoern A. Zeeb 			break;
38138e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD7010:
38148e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
38158e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
38168e93258fSBjoern A. Zeeb 			break;
38178e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD2060:
38188e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
38198e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
38208e93258fSBjoern A. Zeeb 			break;
38218e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD3060:
38228e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
38238e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
38248e93258fSBjoern A. Zeeb 			break;
38258e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TD2080:
38268e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
38278e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
38288e93258fSBjoern A. Zeeb 			break;
38298e93258fSBjoern A. Zeeb 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
38308e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
38318e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
38328e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
38338e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
38348e93258fSBjoern A. Zeeb 			break;
38358e93258fSBjoern A. Zeeb 		default:
38368e93258fSBjoern A. Zeeb 			break;
38378e93258fSBjoern A. Zeeb 		}
38388e93258fSBjoern A. Zeeb 		break;
38398e93258fSBjoern A. Zeeb 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
38408e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
38418e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_PFIX];
38428e93258fSBjoern A. Zeeb 
38438e93258fSBjoern A. Zeeb 		switch (policy_type) {
38448e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD3030:
38458e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
38468e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
38478e93258fSBjoern A. Zeeb 			break;
38488e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD5050:
38498e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
38508e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
38518e93258fSBjoern A. Zeeb 			break;
38528e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD2030:
38538e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
38548e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
38558e93258fSBjoern A. Zeeb 			break;
38568e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD2060:
38578e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
38588e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
38598e93258fSBjoern A. Zeeb 			break;
38608e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD3070:
38618e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
38628e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
38638e93258fSBjoern A. Zeeb 			break;
38648e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TD2080:
38658e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
38668e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
38678e93258fSBjoern A. Zeeb 			break;
38688e93258fSBjoern A. Zeeb 		case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
38698e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
38708e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
38718e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
38728e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
38738e93258fSBjoern A. Zeeb 			break;
38748e93258fSBjoern A. Zeeb 		default:
38758e93258fSBjoern A. Zeeb 			break;
38768e93258fSBjoern A. Zeeb 		}
38778e93258fSBjoern A. Zeeb 		break;
38788e93258fSBjoern A. Zeeb 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
38798e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
38808e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_AUTO];
38818e93258fSBjoern A. Zeeb 
38828e93258fSBjoern A. Zeeb 		switch (policy_type) {
38838e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TD50B1:
38848e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
38858e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
38868e93258fSBjoern A. Zeeb 			break;
38878e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TD60B1:
38888e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
38898e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
38908e93258fSBjoern A. Zeeb 			break;
38918e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TD20B1:
38928e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
38938e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
38948e93258fSBjoern A. Zeeb 			break;
38958e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
38968e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
38978e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
38988e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
38998e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
39008e93258fSBjoern A. Zeeb 			break;
39018e93258fSBjoern A. Zeeb 		default:
39028e93258fSBjoern A. Zeeb 			break;
39038e93258fSBjoern A. Zeeb 		}
39048e93258fSBjoern A. Zeeb 		break;
39058e93258fSBjoern A. Zeeb 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
39068e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
39078e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_PAUTO];
39088e93258fSBjoern A. Zeeb 
39098e93258fSBjoern A. Zeeb 		switch (policy_type) {
39108e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TD50B1:
39118e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
39128e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39138e93258fSBjoern A. Zeeb 			break;
39148e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TD60B1:
39158e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
39168e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39178e93258fSBjoern A. Zeeb 			break;
39188e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TD20B1:
39198e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
39208e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39218e93258fSBjoern A. Zeeb 			break;
39228e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO_TDW1B1:
39238e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
39248e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
39258e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
39268e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
39278e93258fSBjoern A. Zeeb 			break;
39288e93258fSBjoern A. Zeeb 		default:
39298e93258fSBjoern A. Zeeb 			break;
39308e93258fSBjoern A. Zeeb 		}
39318e93258fSBjoern A. Zeeb 		break;
39328e93258fSBjoern A. Zeeb 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
39338e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
39348e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_AUTO2];
39358e93258fSBjoern A. Zeeb 
39368e93258fSBjoern A. Zeeb 		switch (policy_type) {
39378e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD3050:
39388e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
39398e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39408e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
39418e93258fSBjoern A. Zeeb 			break;
39428e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD3070:
39438e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
39448e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39458e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
39468e93258fSBjoern A. Zeeb 			break;
39478e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD5050:
39488e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
39498e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39508e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
39518e93258fSBjoern A. Zeeb 			break;
39528e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD6060:
39538e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
39548e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39558e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
39568e93258fSBjoern A. Zeeb 			break;
39578e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TD2080:
39588e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
39598e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39608e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
39618e93258fSBjoern A. Zeeb 			break;
39628e93258fSBjoern A. Zeeb 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
39638e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
39648e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
39658e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
39668e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
39678e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
39688e93258fSBjoern A. Zeeb 				  tbl_b4, SLOT_MIX);
39698e93258fSBjoern A. Zeeb 			break;
39708e93258fSBjoern A. Zeeb 		default:
39718e93258fSBjoern A. Zeeb 			break;
39728e93258fSBjoern A. Zeeb 		}
39738e93258fSBjoern A. Zeeb 		break;
39748e93258fSBjoern A. Zeeb 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
39758e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
39768e93258fSBjoern A. Zeeb 		*t = t_def[CXTD_PAUTO2];
39778e93258fSBjoern A. Zeeb 
39788e93258fSBjoern A. Zeeb 		switch (policy_type) {
39798e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD3050:
39808e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
39818e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39828e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
39838e93258fSBjoern A. Zeeb 			break;
39848e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD3070:
39858e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
39868e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39878e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
39888e93258fSBjoern A. Zeeb 			break;
39898e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD5050:
39908e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
39918e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39928e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
39938e93258fSBjoern A. Zeeb 			break;
39948e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD6060:
39958e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
39968e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
39978e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
39988e93258fSBjoern A. Zeeb 			break;
39998e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TD2080:
40008e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
40018e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
40028e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
40038e93258fSBjoern A. Zeeb 			break;
40048e93258fSBjoern A. Zeeb 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
40058e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
40068e93258fSBjoern A. Zeeb 				  tbl_w1, SLOT_ISO);
40078e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
40088e93258fSBjoern A. Zeeb 				  tbl_b1, SLOT_MIX);
40098e93258fSBjoern A. Zeeb 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
40108e93258fSBjoern A. Zeeb 				  tbl_b4, SLOT_MIX);
40118e93258fSBjoern A. Zeeb 			break;
40128e93258fSBjoern A. Zeeb 		default:
40138e93258fSBjoern A. Zeeb 			break;
40148e93258fSBjoern A. Zeeb 		}
40158e93258fSBjoern A. Zeeb 		break;
40168e93258fSBjoern A. Zeeb 	}
40178e93258fSBjoern A. Zeeb 
40188e93258fSBjoern A. Zeeb 	if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
40198e93258fSBjoern A. Zeeb 		null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
40208e93258fSBjoern A. Zeeb 			    FIELD_PREP(0xf0, dm->wl_scc.null_role2);
40218e93258fSBjoern A. Zeeb 		_tdma_set_flctrl_role(btc, null_role);
40228e93258fSBjoern A. Zeeb 	}
40238e93258fSBjoern A. Zeeb 
40248e93258fSBjoern A. Zeeb 	/* enter leak_slot after each null-1 */
40258e93258fSBjoern A. Zeeb 	if (dm->leak_ap && dm->tdma.leak_n > 1)
40268e93258fSBjoern A. Zeeb 		_tdma_set_lek(btc, 1);
40278e93258fSBjoern A. Zeeb 
40288e93258fSBjoern A. Zeeb 	if (dm->tdma_instant_excute) {
40298e93258fSBjoern A. Zeeb 		btc->dm.tdma.option_ctrl |= BIT(0);
40308e93258fSBjoern A. Zeeb 		btc->update_policy_force = true;
40318e93258fSBjoern A. Zeeb 	}
40328e93258fSBjoern A. Zeeb }
40338e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
40348e93258fSBjoern A. Zeeb 
40358e93258fSBjoern A. Zeeb static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
40368e93258fSBjoern A. Zeeb 			 u8 tx_val, u8 rx_val)
40378e93258fSBjoern A. Zeeb {
4038*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
40398e93258fSBjoern A. Zeeb 	struct rtw89_mac_ax_plt plt;
40408e93258fSBjoern A. Zeeb 
40418e93258fSBjoern A. Zeeb 	plt.tx = tx_val;
40428e93258fSBjoern A. Zeeb 	plt.rx = rx_val;
40438e93258fSBjoern A. Zeeb 
4044*6d67aabdSBjoern A. Zeeb 	if (rtwdev->btc.ver->fwlrole == 8) {
4045*6d67aabdSBjoern A. Zeeb 		plt.band = wl->pta_req_mac;
4046*6d67aabdSBjoern A. Zeeb 		if (wl->bt_polut_type[plt.band] == tx_val)
4047*6d67aabdSBjoern A. Zeeb 			return;
4048*6d67aabdSBjoern A. Zeeb 
4049*6d67aabdSBjoern A. Zeeb 		wl->bt_polut_type[plt.band] = tx_val;
4050*6d67aabdSBjoern A. Zeeb 		rtw89_mac_cfg_plt(rtwdev, &plt);
4051*6d67aabdSBjoern A. Zeeb 	} else {
4052*6d67aabdSBjoern A. Zeeb 		plt.band = RTW89_MAC_0;
4053*6d67aabdSBjoern A. Zeeb 
40548e93258fSBjoern A. Zeeb 		if (phy_map & BTC_PHY_0)
40558e93258fSBjoern A. Zeeb 			rtw89_mac_cfg_plt(rtwdev, &plt);
40568e93258fSBjoern A. Zeeb 
40578e93258fSBjoern A. Zeeb 		if (!rtwdev->dbcc_en)
40588e93258fSBjoern A. Zeeb 			return;
40598e93258fSBjoern A. Zeeb 
40608e93258fSBjoern A. Zeeb 		plt.band = RTW89_MAC_1;
40618e93258fSBjoern A. Zeeb 		if (phy_map & BTC_PHY_1)
40628e93258fSBjoern A. Zeeb 			rtw89_mac_cfg_plt(rtwdev, &plt);
40638e93258fSBjoern A. Zeeb 	}
4064*6d67aabdSBjoern A. Zeeb }
40658e93258fSBjoern A. Zeeb 
4066*6d67aabdSBjoern A. Zeeb static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
40678e93258fSBjoern A. Zeeb 			u8 phy_map, u8 type)
40688e93258fSBjoern A. Zeeb {
40698e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
40708e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
40718e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
40728e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
40738e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
40748e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
40758e93258fSBjoern A. Zeeb 	u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
4076*6d67aabdSBjoern A. Zeeb 	bool dbcc_chg = false;
40778e93258fSBjoern A. Zeeb 	u32 ant_path_type;
40788e93258fSBjoern A. Zeeb 
40798e93258fSBjoern A. Zeeb 	ant_path_type = ((phy_map << 8) + type);
40808e93258fSBjoern A. Zeeb 
4081*6d67aabdSBjoern A. Zeeb 	if (btc->ver->fwlrole == 1)
4082*6d67aabdSBjoern A. Zeeb 		dbcc_chg = wl->role_info_v1.dbcc_chg;
4083*6d67aabdSBjoern A. Zeeb 	else if (btc->ver->fwlrole == 2)
4084*6d67aabdSBjoern A. Zeeb 		dbcc_chg = wl->role_info_v2.dbcc_chg;
4085*6d67aabdSBjoern A. Zeeb 	else if (btc->ver->fwlrole == 8)
4086*6d67aabdSBjoern A. Zeeb 		dbcc_chg = wl->role_info_v8.dbcc_chg;
4087*6d67aabdSBjoern A. Zeeb 
40888e93258fSBjoern A. Zeeb 	if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
40898e93258fSBjoern A. Zeeb 	    btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4090*6d67aabdSBjoern A. Zeeb 	    btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
40918e93258fSBjoern A. Zeeb 		force_exec = FC_EXEC;
40928e93258fSBjoern A. Zeeb 
40938e93258fSBjoern A. Zeeb 	if (!force_exec && ant_path_type == dm->set_ant_path) {
40948e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
40958e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return by no change!!\n",
40968e93258fSBjoern A. Zeeb 			     __func__);
40978e93258fSBjoern A. Zeeb 		return;
40988e93258fSBjoern A. Zeeb 	} else if (bt->rfk_info.map.run) {
40998e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
41008e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return by bt rfk!!\n", __func__);
41018e93258fSBjoern A. Zeeb 		return;
41028e93258fSBjoern A. Zeeb 	} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
41038e93258fSBjoern A. Zeeb 		   wl->rfk_info.state != BTC_WRFK_STOP) {
41048e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
41058e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return by wl rfk!!\n", __func__);
41068e93258fSBjoern A. Zeeb 		return;
41078e93258fSBjoern A. Zeeb 	}
41088e93258fSBjoern A. Zeeb 
41098e93258fSBjoern A. Zeeb 	dm->set_ant_path = ant_path_type;
41108e93258fSBjoern A. Zeeb 
41118e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev,
41128e93258fSBjoern A. Zeeb 		    RTW89_DBG_BTC,
41138e93258fSBjoern A. Zeeb 		    "[BTC], %s(): path=0x%x, set_type=0x%x\n",
41148e93258fSBjoern A. Zeeb 		    __func__, phy_map, dm->set_ant_path & 0xff);
41158e93258fSBjoern A. Zeeb 
41168e93258fSBjoern A. Zeeb 	switch (type) {
41178e93258fSBjoern A. Zeeb 	case BTC_ANT_WPOWERON:
4118e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
41198e93258fSBjoern A. Zeeb 		break;
41208e93258fSBjoern A. Zeeb 	case BTC_ANT_WINIT:
4121e2340276SBjoern A. Zeeb 		if (bt->enable.now)
4122e2340276SBjoern A. Zeeb 			_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4123e2340276SBjoern A. Zeeb 		else
4124e2340276SBjoern A. Zeeb 			_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4125e2340276SBjoern A. Zeeb 
4126e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
41278e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
41288e93258fSBjoern A. Zeeb 		break;
41298e93258fSBjoern A. Zeeb 	case BTC_ANT_WONLY:
4130e2340276SBjoern A. Zeeb 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4131e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
41328e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
41338e93258fSBjoern A. Zeeb 		break;
41348e93258fSBjoern A. Zeeb 	case BTC_ANT_WOFF:
4135e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
41368e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
41378e93258fSBjoern A. Zeeb 		break;
41388e93258fSBjoern A. Zeeb 	case BTC_ANT_W2G:
4139e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
41408e93258fSBjoern A. Zeeb 		if (rtwdev->dbcc_en) {
41418e93258fSBjoern A. Zeeb 			for (i = 0; i < RTW89_PHY_MAX; i++) {
41428e93258fSBjoern A. Zeeb 				b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
41438e93258fSBjoern A. Zeeb 
41448e93258fSBjoern A. Zeeb 				gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
41458e93258fSBjoern A. Zeeb 				gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
41468e93258fSBjoern A. Zeeb 				/* BT should control by GNT_BT if WL_2G at S0 */
41478e93258fSBjoern A. Zeeb 				if (i == 1 &&
41488e93258fSBjoern A. Zeeb 				    wl_dinfo->real_band[0] == RTW89_BAND_2G &&
41498e93258fSBjoern A. Zeeb 				    wl_dinfo->real_band[1] == RTW89_BAND_5G)
41508e93258fSBjoern A. Zeeb 					gnt_bt_ctrl = BTC_GNT_HW;
4151e2340276SBjoern A. Zeeb 				_set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
41528e93258fSBjoern A. Zeeb 				plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
41538e93258fSBjoern A. Zeeb 				_set_bt_plut(rtwdev, BIT(i),
41548e93258fSBjoern A. Zeeb 					     plt_ctrl, plt_ctrl);
41558e93258fSBjoern A. Zeeb 			}
41568e93258fSBjoern A. Zeeb 		} else {
4157e2340276SBjoern A. Zeeb 			_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
41588e93258fSBjoern A. Zeeb 			_set_bt_plut(rtwdev, BTC_PHY_ALL,
41598e93258fSBjoern A. Zeeb 				     BTC_PLT_BT, BTC_PLT_BT);
41608e93258fSBjoern A. Zeeb 		}
41618e93258fSBjoern A. Zeeb 		break;
41628e93258fSBjoern A. Zeeb 	case BTC_ANT_W5G:
4163e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4164e2340276SBjoern A. Zeeb 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
41658e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
41668e93258fSBjoern A. Zeeb 		break;
41678e93258fSBjoern A. Zeeb 	case BTC_ANT_W25G:
4168e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4169e2340276SBjoern A. Zeeb 		_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
41708e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, BTC_PHY_ALL,
41718e93258fSBjoern A. Zeeb 			     BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
41728e93258fSBjoern A. Zeeb 		break;
41738e93258fSBjoern A. Zeeb 	case BTC_ANT_FREERUN:
4174e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4175e2340276SBjoern A. Zeeb 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
41768e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
41778e93258fSBjoern A. Zeeb 		break;
41788e93258fSBjoern A. Zeeb 	case BTC_ANT_WRFK:
4179e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4180e2340276SBjoern A. Zeeb 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
41818e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
41828e93258fSBjoern A. Zeeb 		break;
41838e93258fSBjoern A. Zeeb 	case BTC_ANT_BRFK:
4184e2340276SBjoern A. Zeeb 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4185e2340276SBjoern A. Zeeb 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
41868e93258fSBjoern A. Zeeb 		_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
41878e93258fSBjoern A. Zeeb 		break;
41888e93258fSBjoern A. Zeeb 	default:
41898e93258fSBjoern A. Zeeb 		break;
41908e93258fSBjoern A. Zeeb 	}
41918e93258fSBjoern A. Zeeb }
41928e93258fSBjoern A. Zeeb 
4193*6d67aabdSBjoern A. Zeeb static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
4194*6d67aabdSBjoern A. Zeeb 			u8 phy_map, u8 type)
4195*6d67aabdSBjoern A. Zeeb {
4196*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
4197*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4198*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4199*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
4200*6d67aabdSBjoern A. Zeeb 	u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
4201*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4202*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
4203*6d67aabdSBjoern A. Zeeb 	u8 gwl = BTC_GNT_HW;
4204*6d67aabdSBjoern A. Zeeb 
4205*6d67aabdSBjoern A. Zeeb 	if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4206*6d67aabdSBjoern A. Zeeb 	    btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4207*6d67aabdSBjoern A. Zeeb 	    btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
4208*6d67aabdSBjoern A. Zeeb 		force_exec = FC_EXEC;
4209*6d67aabdSBjoern A. Zeeb 
4210*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
4211*6d67aabdSBjoern A. Zeeb 	    btc->dm.wl_btg_rx == 2)
4212*6d67aabdSBjoern A. Zeeb 		force_exec = FC_EXEC;
4213*6d67aabdSBjoern A. Zeeb 
4214*6d67aabdSBjoern A. Zeeb 	if (!force_exec && ant_path_type == dm->set_ant_path) {
4215*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4216*6d67aabdSBjoern A. Zeeb 			    "[BTC], %s(): return by no change!!\n",
4217*6d67aabdSBjoern A. Zeeb 			     __func__);
4218*6d67aabdSBjoern A. Zeeb 		return;
4219*6d67aabdSBjoern A. Zeeb 	} else if (bt->rfk_info.map.run) {
4220*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4221*6d67aabdSBjoern A. Zeeb 			    "[BTC], %s(): return by bt rfk!!\n", __func__);
4222*6d67aabdSBjoern A. Zeeb 		return;
4223*6d67aabdSBjoern A. Zeeb 	} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4224*6d67aabdSBjoern A. Zeeb 		   wl->rfk_info.state != BTC_WRFK_STOP) {
4225*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4226*6d67aabdSBjoern A. Zeeb 			    "[BTC], %s(): return by wl rfk!!\n", __func__);
4227*6d67aabdSBjoern A. Zeeb 		return;
4228*6d67aabdSBjoern A. Zeeb 	}
4229*6d67aabdSBjoern A. Zeeb 
4230*6d67aabdSBjoern A. Zeeb 	dm->set_ant_path = ant_path_type;
4231*6d67aabdSBjoern A. Zeeb 
4232*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
4233*6d67aabdSBjoern A. Zeeb 		    "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4234*6d67aabdSBjoern A. Zeeb 		    __func__, phy_map, dm->set_ant_path & 0xff);
4235*6d67aabdSBjoern A. Zeeb 
4236*6d67aabdSBjoern A. Zeeb 	switch (type) {
4237*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_WINIT:
4238*6d67aabdSBjoern A. Zeeb 		/* To avoid BT MP driver case (bt_enable but no mailbox) */
4239*6d67aabdSBjoern A. Zeeb 		if (bt->enable.now && bt->run_patch_code)
4240*6d67aabdSBjoern A. Zeeb 			_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4241*6d67aabdSBjoern A. Zeeb 				    BTC_WLACT_SW_LO);
4242*6d67aabdSBjoern A. Zeeb 		else
4243*6d67aabdSBjoern A. Zeeb 			_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4244*6d67aabdSBjoern A. Zeeb 				    BTC_WLACT_SW_HI);
4245*6d67aabdSBjoern A. Zeeb 		break;
4246*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_WONLY:
4247*6d67aabdSBjoern A. Zeeb 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4248*6d67aabdSBjoern A. Zeeb 			    BTC_WLACT_SW_HI);
4249*6d67aabdSBjoern A. Zeeb 		break;
4250*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_WOFF:
4251*6d67aabdSBjoern A. Zeeb 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4252*6d67aabdSBjoern A. Zeeb 			    BTC_WLACT_SW_LO);
4253*6d67aabdSBjoern A. Zeeb 		break;
4254*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_W2G:
4255*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_W25G:
4256*6d67aabdSBjoern A. Zeeb 		if (wl_rinfo->dbcc_en) {
4257*6d67aabdSBjoern A. Zeeb 			if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
4258*6d67aabdSBjoern A. Zeeb 				gwl = BTC_GNT_HW;
4259*6d67aabdSBjoern A. Zeeb 			else
4260*6d67aabdSBjoern A. Zeeb 				gwl = BTC_GNT_SW_HI;
4261*6d67aabdSBjoern A. Zeeb 			_set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4262*6d67aabdSBjoern A. Zeeb 
4263*6d67aabdSBjoern A. Zeeb 			if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
4264*6d67aabdSBjoern A. Zeeb 				gwl = BTC_GNT_HW;
4265*6d67aabdSBjoern A. Zeeb 			else
4266*6d67aabdSBjoern A. Zeeb 				gwl = BTC_GNT_SW_HI;
4267*6d67aabdSBjoern A. Zeeb 			_set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4268*6d67aabdSBjoern A. Zeeb 		} else {
4269*6d67aabdSBjoern A. Zeeb 			gwl = BTC_GNT_HW;
4270*6d67aabdSBjoern A. Zeeb 			_set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4271*6d67aabdSBjoern A. Zeeb 		}
4272*6d67aabdSBjoern A. Zeeb 		break;
4273*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_W5G:
4274*6d67aabdSBjoern A. Zeeb 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
4275*6d67aabdSBjoern A. Zeeb 		break;
4276*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_FREERUN:
4277*6d67aabdSBjoern A. Zeeb 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
4278*6d67aabdSBjoern A. Zeeb 			    BTC_WLACT_SW_LO);
4279*6d67aabdSBjoern A. Zeeb 		break;
4280*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_WRFK:
4281*6d67aabdSBjoern A. Zeeb 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4282*6d67aabdSBjoern A. Zeeb 			    BTC_WLACT_HW);
4283*6d67aabdSBjoern A. Zeeb 		break;
4284*6d67aabdSBjoern A. Zeeb 	case BTC_ANT_WRFK2:
4285*6d67aabdSBjoern A. Zeeb 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4286*6d67aabdSBjoern A. Zeeb 			    BTC_WLACT_SW_HI); /* no BT-Tx */
4287*6d67aabdSBjoern A. Zeeb 		break;
4288*6d67aabdSBjoern A. Zeeb 	default:
4289*6d67aabdSBjoern A. Zeeb 		return;
4290*6d67aabdSBjoern A. Zeeb 	}
4291*6d67aabdSBjoern A. Zeeb 
4292*6d67aabdSBjoern A. Zeeb 	_set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4293*6d67aabdSBjoern A. Zeeb }
4294*6d67aabdSBjoern A. Zeeb 
4295*6d67aabdSBjoern A. Zeeb static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
4296*6d67aabdSBjoern A. Zeeb 		     u8 phy_map, u8 type)
4297*6d67aabdSBjoern A. Zeeb {
4298*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8922A)
4299*6d67aabdSBjoern A. Zeeb 		_set_ant_v1(rtwdev, force_exec, phy_map, type);
4300*6d67aabdSBjoern A. Zeeb 	else
4301*6d67aabdSBjoern A. Zeeb 		_set_ant_v0(rtwdev, force_exec, phy_map, type);
4302*6d67aabdSBjoern A. Zeeb }
4303*6d67aabdSBjoern A. Zeeb 
43048e93258fSBjoern A. Zeeb static void _action_wl_only(struct rtw89_dev *rtwdev)
43058e93258fSBjoern A. Zeeb {
43068e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
43078e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
43088e93258fSBjoern A. Zeeb }
43098e93258fSBjoern A. Zeeb 
43108e93258fSBjoern A. Zeeb static void _action_wl_init(struct rtw89_dev *rtwdev)
43118e93258fSBjoern A. Zeeb {
43128e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
43138e93258fSBjoern A. Zeeb 
43148e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
43158e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
43168e93258fSBjoern A. Zeeb }
43178e93258fSBjoern A. Zeeb 
4318*6d67aabdSBjoern A. Zeeb static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
43198e93258fSBjoern A. Zeeb {
43208e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
43218e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
43228e93258fSBjoern A. Zeeb 
43238e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
43248e93258fSBjoern A. Zeeb 
4325*6d67aabdSBjoern A. Zeeb 	if (wl->status.map.rf_off || btc->dm.bt_only) {
43268e93258fSBjoern A. Zeeb 		_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
4327*6d67aabdSBjoern A. Zeeb 	} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4328*6d67aabdSBjoern A. Zeeb 		if (mode == BTC_WLINK_5G)
4329*6d67aabdSBjoern A. Zeeb 			_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4330*6d67aabdSBjoern A. Zeeb 		else
4331*6d67aabdSBjoern A. Zeeb 			_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4332*6d67aabdSBjoern A. Zeeb 	}
43338e93258fSBjoern A. Zeeb 
4334*6d67aabdSBjoern A. Zeeb 	if (mode == BTC_WLINK_5G) {
4335*6d67aabdSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
4336*6d67aabdSBjoern A. Zeeb 	} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4337*6d67aabdSBjoern A. Zeeb 		if (btc->cx.bt.link_info.a2dp_desc.active)
43388e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4339*6d67aabdSBjoern A. Zeeb 		else
4340*6d67aabdSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF);
4341*6d67aabdSBjoern A. Zeeb 	} else {
4342*6d67aabdSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4343*6d67aabdSBjoern A. Zeeb 	}
43448e93258fSBjoern A. Zeeb }
43458e93258fSBjoern A. Zeeb 
43468e93258fSBjoern A. Zeeb static void _action_freerun(struct rtw89_dev *rtwdev)
43478e93258fSBjoern A. Zeeb {
43488e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
43498e93258fSBjoern A. Zeeb 
43508e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
43518e93258fSBjoern A. Zeeb 
43528e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
43538e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
43548e93258fSBjoern A. Zeeb 
43558e93258fSBjoern A. Zeeb 	btc->dm.freerun = true;
43568e93258fSBjoern A. Zeeb }
43578e93258fSBjoern A. Zeeb 
43588e93258fSBjoern A. Zeeb static void _action_bt_whql(struct rtw89_dev *rtwdev)
43598e93258fSBjoern A. Zeeb {
43608e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
43618e93258fSBjoern A. Zeeb 
43628e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
43638e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
43648e93258fSBjoern A. Zeeb }
43658e93258fSBjoern A. Zeeb 
43668e93258fSBjoern A. Zeeb static void _action_bt_off(struct rtw89_dev *rtwdev)
43678e93258fSBjoern A. Zeeb {
43688e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
43698e93258fSBjoern A. Zeeb 
43708e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
43718e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
43728e93258fSBjoern A. Zeeb }
43738e93258fSBjoern A. Zeeb 
43748e93258fSBjoern A. Zeeb static void _action_bt_idle(struct rtw89_dev *rtwdev)
43758e93258fSBjoern A. Zeeb {
43768e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
43778e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
4378*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
43798e93258fSBjoern A. Zeeb 
43808e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
43818e93258fSBjoern A. Zeeb 
4382*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
43838e93258fSBjoern A. Zeeb 		switch (btc->cx.state_map) {
43848e93258fSBjoern A. Zeeb 		case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
4385*6d67aabdSBjoern A. Zeeb 		case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
4386*6d67aabdSBjoern A. Zeeb 			if (b->status.map.connect)
4387*6d67aabdSBjoern A. Zeeb 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
4388*6d67aabdSBjoern A. Zeeb 			else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
4389*6d67aabdSBjoern A. Zeeb 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
43908e93258fSBjoern A. Zeeb 			else
4391*6d67aabdSBjoern A. Zeeb 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
43928e93258fSBjoern A. Zeeb 			break;
43938e93258fSBjoern A. Zeeb 		case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
43948e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
43958e93258fSBjoern A. Zeeb 				    BTC_ACT_BT_IDLE);
43968e93258fSBjoern A. Zeeb 			break;
43978e93258fSBjoern A. Zeeb 		case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
43988e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_FIX_TD5050,
43998e93258fSBjoern A. Zeeb 				    BTC_ACT_BT_IDLE);
44008e93258fSBjoern A. Zeeb 			break;
44018e93258fSBjoern A. Zeeb 		case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
44028e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_FIX_TD7010,
44038e93258fSBjoern A. Zeeb 				    BTC_ACT_BT_IDLE);
44048e93258fSBjoern A. Zeeb 			break;
44058e93258fSBjoern A. Zeeb 		case BTC_WIDLE:  /* wl-idle + bt-idle */
44068e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
44078e93258fSBjoern A. Zeeb 			break;
44088e93258fSBjoern A. Zeeb 		}
44098e93258fSBjoern A. Zeeb 	} else { /* dedicated-antenna */
44108e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
44118e93258fSBjoern A. Zeeb 	}
44128e93258fSBjoern A. Zeeb }
44138e93258fSBjoern A. Zeeb 
44148e93258fSBjoern A. Zeeb static void _action_bt_hfp(struct rtw89_dev *rtwdev)
44158e93258fSBjoern A. Zeeb {
44168e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
4417e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
44188e93258fSBjoern A. Zeeb 
44198e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
44208e93258fSBjoern A. Zeeb 
4421*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
4422e2340276SBjoern A. Zeeb 		if (btc->cx.wl.status.map._4way) {
44238e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
4424e2340276SBjoern A. Zeeb 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4425e2340276SBjoern A. Zeeb 			btc->cx.bt.scan_rx_low_pri = true;
4426e2340276SBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
4427e2340276SBjoern A. Zeeb 		} else {
4428e2340276SBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4429e2340276SBjoern A. Zeeb 		}
44308e93258fSBjoern A. Zeeb 	} else {
4431*6d67aabdSBjoern A. Zeeb 		if (wl->bg_mode)
4432*6d67aabdSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4433*6d67aabdSBjoern A. Zeeb 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4434*6d67aabdSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
4435*6d67aabdSBjoern A. Zeeb 		else
44368e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
44378e93258fSBjoern A. Zeeb 	}
44388e93258fSBjoern A. Zeeb }
44398e93258fSBjoern A. Zeeb 
44408e93258fSBjoern A. Zeeb static void _action_bt_hid(struct rtw89_dev *rtwdev)
44418e93258fSBjoern A. Zeeb {
4442e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
44438e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
4444e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4445e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4446e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
4447e2340276SBjoern A. Zeeb 	u16 policy_type = BTC_CXP_OFF_BT;
44488e93258fSBjoern A. Zeeb 
44498e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
44508e93258fSBjoern A. Zeeb 
4451*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4452e2340276SBjoern A. Zeeb 		if (wl->status.map._4way) {
4453e2340276SBjoern A. Zeeb 			policy_type = BTC_CXP_OFF_WL;
4454e2340276SBjoern A. Zeeb 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4455e2340276SBjoern A. Zeeb 			btc->cx.bt.scan_rx_low_pri = true;
4456e2340276SBjoern A. Zeeb 			if (hid->type & BTC_HID_BLE)
4457e2340276SBjoern A. Zeeb 				policy_type = BTC_CXP_OFF_BWB0;
44588e93258fSBjoern A. Zeeb 			else
4459e2340276SBjoern A. Zeeb 				policy_type = BTC_CXP_OFF_BWB2;
4460e2340276SBjoern A. Zeeb 		} else if (hid->type == BTC_HID_218) {
4461e2340276SBjoern A. Zeeb 			bt->scan_rx_low_pri = true;
4462e2340276SBjoern A. Zeeb 			policy_type = BTC_CXP_OFF_BWB2;
4463e2340276SBjoern A. Zeeb 		} else if (chip->para_ver == 0x1) {
4464e2340276SBjoern A. Zeeb 			policy_type = BTC_CXP_OFF_BWB3;
4465e2340276SBjoern A. Zeeb 		} else {
4466e2340276SBjoern A. Zeeb 			policy_type = BTC_CXP_OFF_BWB1;
4467e2340276SBjoern A. Zeeb 		}
4468e2340276SBjoern A. Zeeb 	} else { /* dedicated-antenna */
4469*6d67aabdSBjoern A. Zeeb 		if (wl->bg_mode)
4470*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFF_BWB1;
4471*6d67aabdSBjoern A. Zeeb 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4472*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFF_EQ4;
4473*6d67aabdSBjoern A. Zeeb 		else
4474e2340276SBjoern A. Zeeb 			policy_type = BTC_CXP_OFF_EQ3;
4475e2340276SBjoern A. Zeeb 	}
4476e2340276SBjoern A. Zeeb 
4477e2340276SBjoern A. Zeeb 	_set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
44788e93258fSBjoern A. Zeeb }
44798e93258fSBjoern A. Zeeb 
44808e93258fSBjoern A. Zeeb static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
44818e93258fSBjoern A. Zeeb {
44828e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
44838e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
44848e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
44858e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
44868e93258fSBjoern A. Zeeb 
44878e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
44888e93258fSBjoern A. Zeeb 
44898e93258fSBjoern A. Zeeb 	switch (btc->cx.state_map) {
44908e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
44918e93258fSBjoern A. Zeeb 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
44928e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_W1] = 40;
44938e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_B1] = 200;
44948e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
44958e93258fSBjoern A. Zeeb 				    BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
44968e93258fSBjoern A. Zeeb 		} else {
44978e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
44988e93258fSBjoern A. Zeeb 				    BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
44998e93258fSBjoern A. Zeeb 		}
45008e93258fSBjoern A. Zeeb 		break;
45018e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
45028e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
45038e93258fSBjoern A. Zeeb 		break;
45048e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
45058e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
45068e93258fSBjoern A. Zeeb 		break;
45078e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
45088e93258fSBjoern A. Zeeb 	case BTC_WLINKING: /* wl-connecting + bt-A2DP */
45098e93258fSBjoern A. Zeeb 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
45108e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_W1] = 40;
45118e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_B1] = 200;
45128e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
45138e93258fSBjoern A. Zeeb 				    BTC_ACT_BT_A2DP);
45148e93258fSBjoern A. Zeeb 		} else {
45158e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
45168e93258fSBjoern A. Zeeb 				    BTC_ACT_BT_A2DP);
45178e93258fSBjoern A. Zeeb 		}
45188e93258fSBjoern A. Zeeb 		break;
45198e93258fSBjoern A. Zeeb 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
45208e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
45218e93258fSBjoern A. Zeeb 		break;
45228e93258fSBjoern A. Zeeb 	}
45238e93258fSBjoern A. Zeeb }
45248e93258fSBjoern A. Zeeb 
45258e93258fSBjoern A. Zeeb static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
45268e93258fSBjoern A. Zeeb {
45278e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
45288e93258fSBjoern A. Zeeb 
45298e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
45308e93258fSBjoern A. Zeeb 
45318e93258fSBjoern A. Zeeb 	switch (btc->cx.state_map) {
45328e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
45338e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
45348e93258fSBjoern A. Zeeb 		break;
45358e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
45368e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
45378e93258fSBjoern A. Zeeb 		break;
45388e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
45398e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
45408e93258fSBjoern A. Zeeb 		break;
45418e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
45428e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
45438e93258fSBjoern A. Zeeb 		break;
45448e93258fSBjoern A. Zeeb 	case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
45458e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
45468e93258fSBjoern A. Zeeb 		break;
45478e93258fSBjoern A. Zeeb 	case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
45488e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
45498e93258fSBjoern A. Zeeb 		break;
45508e93258fSBjoern A. Zeeb 	}
45518e93258fSBjoern A. Zeeb }
45528e93258fSBjoern A. Zeeb 
45538e93258fSBjoern A. Zeeb static void _action_bt_pan(struct rtw89_dev *rtwdev)
45548e93258fSBjoern A. Zeeb {
45558e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
45568e93258fSBjoern A. Zeeb 
45578e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
45588e93258fSBjoern A. Zeeb 
45598e93258fSBjoern A. Zeeb 	switch (btc->cx.state_map) {
45608e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
45618e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
45628e93258fSBjoern A. Zeeb 		break;
45638e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
45648e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
45658e93258fSBjoern A. Zeeb 		break;
45668e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
45678e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
45688e93258fSBjoern A. Zeeb 		break;
45698e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
45708e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
45718e93258fSBjoern A. Zeeb 		break;
45728e93258fSBjoern A. Zeeb 	case BTC_WLINKING: /* wl-connecting + bt-PAN */
4573*6d67aabdSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
45748e93258fSBjoern A. Zeeb 		break;
45758e93258fSBjoern A. Zeeb 	case BTC_WIDLE: /* wl-idle + bt-pan */
45768e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
45778e93258fSBjoern A. Zeeb 		break;
45788e93258fSBjoern A. Zeeb 	}
45798e93258fSBjoern A. Zeeb }
45808e93258fSBjoern A. Zeeb 
45818e93258fSBjoern A. Zeeb static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
45828e93258fSBjoern A. Zeeb {
45838e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
45848e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
45858e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
45868e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
45878e93258fSBjoern A. Zeeb 
45888e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
45898e93258fSBjoern A. Zeeb 
45908e93258fSBjoern A. Zeeb 	switch (btc->cx.state_map) {
45918e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
45928e93258fSBjoern A. Zeeb 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
45938e93258fSBjoern A. Zeeb 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
45948e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_W1] = 40;
45958e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_B1] = 200;
45968e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
45978e93258fSBjoern A. Zeeb 				    BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
45988e93258fSBjoern A. Zeeb 		} else {
45998e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
46008e93258fSBjoern A. Zeeb 				    BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
46018e93258fSBjoern A. Zeeb 		}
46028e93258fSBjoern A. Zeeb 		break;
46038e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
46048e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
46058e93258fSBjoern A. Zeeb 		break;
46068e93258fSBjoern A. Zeeb 
46078e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
46088e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
46098e93258fSBjoern A. Zeeb 		break;
46108e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
46118e93258fSBjoern A. Zeeb 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
46128e93258fSBjoern A. Zeeb 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
46138e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_W1] = 40;
46148e93258fSBjoern A. Zeeb 			dm->slot_dur[CXST_B1] = 200;
46158e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
46168e93258fSBjoern A. Zeeb 				    BTC_ACT_BT_A2DP_HID);
46178e93258fSBjoern A. Zeeb 		} else {
46188e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
46198e93258fSBjoern A. Zeeb 				    BTC_ACT_BT_A2DP_HID);
46208e93258fSBjoern A. Zeeb 		}
46218e93258fSBjoern A. Zeeb 		break;
46228e93258fSBjoern A. Zeeb 	}
46238e93258fSBjoern A. Zeeb }
46248e93258fSBjoern A. Zeeb 
46258e93258fSBjoern A. Zeeb static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
46268e93258fSBjoern A. Zeeb {
46278e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
46288e93258fSBjoern A. Zeeb 
46298e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
46308e93258fSBjoern A. Zeeb 
46318e93258fSBjoern A. Zeeb 	switch (btc->cx.state_map) {
46328e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
46338e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
46348e93258fSBjoern A. Zeeb 		break;
46358e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
46368e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
46378e93258fSBjoern A. Zeeb 		break;
46388e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
46398e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
46408e93258fSBjoern A. Zeeb 		break;
46418e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
46428e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
46438e93258fSBjoern A. Zeeb 		break;
46448e93258fSBjoern A. Zeeb 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
46458e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
46468e93258fSBjoern A. Zeeb 		break;
46478e93258fSBjoern A. Zeeb 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN */
46488e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
46498e93258fSBjoern A. Zeeb 		break;
46508e93258fSBjoern A. Zeeb 	}
46518e93258fSBjoern A. Zeeb }
46528e93258fSBjoern A. Zeeb 
46538e93258fSBjoern A. Zeeb static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
46548e93258fSBjoern A. Zeeb {
46558e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
46568e93258fSBjoern A. Zeeb 
46578e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
46588e93258fSBjoern A. Zeeb 
46598e93258fSBjoern A. Zeeb 	switch (btc->cx.state_map) {
46608e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
46618e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
46628e93258fSBjoern A. Zeeb 		break;
46638e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
46648e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
46658e93258fSBjoern A. Zeeb 		break;
46668e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
46678e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
46688e93258fSBjoern A. Zeeb 		break;
46698e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
46708e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
46718e93258fSBjoern A. Zeeb 		break;
46728e93258fSBjoern A. Zeeb 	case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
46738e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
46748e93258fSBjoern A. Zeeb 		break;
46758e93258fSBjoern A. Zeeb 	case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
46768e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
46778e93258fSBjoern A. Zeeb 		break;
46788e93258fSBjoern A. Zeeb 	}
46798e93258fSBjoern A. Zeeb }
46808e93258fSBjoern A. Zeeb 
46818e93258fSBjoern A. Zeeb static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
46828e93258fSBjoern A. Zeeb {
46838e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
46848e93258fSBjoern A. Zeeb 
46858e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
46868e93258fSBjoern A. Zeeb 
46878e93258fSBjoern A. Zeeb 	switch (btc->cx.state_map) {
46888e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
46898e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
46908e93258fSBjoern A. Zeeb 			    BTC_ACT_BT_A2DP_PAN_HID);
46918e93258fSBjoern A. Zeeb 		break;
46928e93258fSBjoern A. Zeeb 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
46938e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
46948e93258fSBjoern A. Zeeb 			    BTC_ACT_BT_A2DP_PAN_HID);
46958e93258fSBjoern A. Zeeb 		break;
46968e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
46978e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
46988e93258fSBjoern A. Zeeb 			    BTC_ACT_BT_A2DP_PAN_HID);
46998e93258fSBjoern A. Zeeb 		break;
47008e93258fSBjoern A. Zeeb 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
47018e93258fSBjoern A. Zeeb 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
47028e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
47038e93258fSBjoern A. Zeeb 			    BTC_ACT_BT_A2DP_PAN_HID);
47048e93258fSBjoern A. Zeeb 		break;
47058e93258fSBjoern A. Zeeb 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN+HID */
47068e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
47078e93258fSBjoern A. Zeeb 			    BTC_ACT_BT_A2DP_PAN_HID);
47088e93258fSBjoern A. Zeeb 		break;
47098e93258fSBjoern A. Zeeb 	}
47108e93258fSBjoern A. Zeeb }
47118e93258fSBjoern A. Zeeb 
47128e93258fSBjoern A. Zeeb static void _action_wl_5g(struct rtw89_dev *rtwdev)
47138e93258fSBjoern A. Zeeb {
47148e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
47158e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
47168e93258fSBjoern A. Zeeb }
47178e93258fSBjoern A. Zeeb 
47188e93258fSBjoern A. Zeeb static void _action_wl_other(struct rtw89_dev *rtwdev)
47198e93258fSBjoern A. Zeeb {
47208e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
47218e93258fSBjoern A. Zeeb 
47228e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
47238e93258fSBjoern A. Zeeb 
4724*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED)
47258e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
47268e93258fSBjoern A. Zeeb 	else
47278e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
47288e93258fSBjoern A. Zeeb }
47298e93258fSBjoern A. Zeeb 
47308e93258fSBjoern A. Zeeb static void _action_wl_nc(struct rtw89_dev *rtwdev)
47318e93258fSBjoern A. Zeeb {
47328e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
47338e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
47348e93258fSBjoern A. Zeeb }
47358e93258fSBjoern A. Zeeb 
47368e93258fSBjoern A. Zeeb static void _action_wl_rfk(struct rtw89_dev *rtwdev)
47378e93258fSBjoern A. Zeeb {
47388e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
47398e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
47408e93258fSBjoern A. Zeeb 
47418e93258fSBjoern A. Zeeb 	if (rfk.state != BTC_WRFK_START)
47428e93258fSBjoern A. Zeeb 		return;
47438e93258fSBjoern A. Zeeb 
47448e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
47458e93258fSBjoern A. Zeeb 		    __func__, rfk.band);
47468e93258fSBjoern A. Zeeb 
47478e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
47488e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
47498e93258fSBjoern A. Zeeb }
47508e93258fSBjoern A. Zeeb 
47518e93258fSBjoern A. Zeeb static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
47528e93258fSBjoern A. Zeeb {
47538e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
47548e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
47558e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4756e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
4757*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
4758*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info;
47598e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4760*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
4761*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
4762*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4763*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
4764*6d67aabdSBjoern A. Zeeb 	struct _wl_rinfo_now wl_rinfo;
4765*6d67aabdSBjoern A. Zeeb 	u32 run_reason = btc->dm.run_reason;
4766*6d67aabdSBjoern A. Zeeb 	u32 is_btg;
4767*6d67aabdSBjoern A. Zeeb 	u8 i, val;
47688e93258fSBjoern A. Zeeb 
4769*6d67aabdSBjoern A. Zeeb 	if (btc->manual_ctrl)
47708e93258fSBjoern A. Zeeb 		return;
47718e93258fSBjoern A. Zeeb 
4772e2340276SBjoern A. Zeeb 	if (ver->fwlrole == 0)
4773*6d67aabdSBjoern A. Zeeb 		wl_rinfo.link_mode = wl_rinfo_v0->link_mode;
4774e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 1)
4775*6d67aabdSBjoern A. Zeeb 		wl_rinfo.link_mode = wl_rinfo_v1->link_mode;
4776e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 2)
4777*6d67aabdSBjoern A. Zeeb 		wl_rinfo.link_mode = wl_rinfo_v2->link_mode;
4778*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 8)
4779*6d67aabdSBjoern A. Zeeb 		wl_rinfo.link_mode = wl_rinfo_v8->link_mode;
4780e2340276SBjoern A. Zeeb 	else
4781e2340276SBjoern A. Zeeb 		return;
47828e93258fSBjoern A. Zeeb 
4783*6d67aabdSBjoern A. Zeeb 	if (rtwdev->dbcc_en) {
4784*6d67aabdSBjoern A. Zeeb 		if (ver->fwlrole == 0) {
4785*6d67aabdSBjoern A. Zeeb 			for (i = 0; i < RTW89_PHY_MAX; i++) {
4786*6d67aabdSBjoern A. Zeeb 				if (wl_dinfo->real_band[i] == RTW89_BAND_2G)
4787*6d67aabdSBjoern A. Zeeb 					wl_rinfo.dbcc_2g_phy = i;
4788*6d67aabdSBjoern A. Zeeb 			}
4789*6d67aabdSBjoern A. Zeeb 		} else if (ver->fwlrole == 1) {
4790*6d67aabdSBjoern A. Zeeb 			wl_rinfo.dbcc_2g_phy = wl_rinfo_v1->dbcc_2g_phy;
4791*6d67aabdSBjoern A. Zeeb 		} else if (ver->fwlrole == 2) {
4792*6d67aabdSBjoern A. Zeeb 			wl_rinfo.dbcc_2g_phy = wl_rinfo_v2->dbcc_2g_phy;
4793*6d67aabdSBjoern A. Zeeb 		} else if (ver->fwlrole == 8) {
4794*6d67aabdSBjoern A. Zeeb 			wl_rinfo.dbcc_2g_phy = wl_rinfo_v8->dbcc_2g_phy;
4795*6d67aabdSBjoern A. Zeeb 		} else {
4796*6d67aabdSBjoern A. Zeeb 			return;
4797*6d67aabdSBjoern A. Zeeb 		}
4798*6d67aabdSBjoern A. Zeeb 	}
4799*6d67aabdSBjoern A. Zeeb 
4800*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo.link_mode == BTC_WLINK_25G_MCC)
4801*6d67aabdSBjoern A. Zeeb 		is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
4802*6d67aabdSBjoern A. Zeeb 	else if (!(bt->run_patch_code && bt->enable.now))
4803*6d67aabdSBjoern A. Zeeb 		is_btg = BTC_BTGCTRL_DISABLE;
4804*6d67aabdSBjoern A. Zeeb 	else if (wl_rinfo.link_mode == BTC_WLINK_5G)
4805*6d67aabdSBjoern A. Zeeb 		is_btg = BTC_BTGCTRL_DISABLE;
4806*6d67aabdSBjoern A. Zeeb 	else if (dm->freerun)
4807*6d67aabdSBjoern A. Zeeb 		is_btg = BTC_BTGCTRL_DISABLE;
4808*6d67aabdSBjoern A. Zeeb 	else if (rtwdev->dbcc_en && wl_rinfo.dbcc_2g_phy != RTW89_PHY_1)
4809*6d67aabdSBjoern A. Zeeb 		is_btg = BTC_BTGCTRL_DISABLE;
48108e93258fSBjoern A. Zeeb 	else
4811*6d67aabdSBjoern A. Zeeb 		is_btg = BTC_BTGCTRL_ENABLE;
48128e93258fSBjoern A. Zeeb 
4813*6d67aabdSBjoern A. Zeeb 	if (dm->wl_btg_rx_rb != dm->wl_btg_rx &&
4814*6d67aabdSBjoern A. Zeeb 	    dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) {
4815*6d67aabdSBjoern A. Zeeb 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX, &val);
4816*6d67aabdSBjoern A. Zeeb 		dm->wl_btg_rx_rb = val;
4817*6d67aabdSBjoern A. Zeeb 	}
4818*6d67aabdSBjoern A. Zeeb 
4819*6d67aabdSBjoern A. Zeeb 	if (run_reason == BTC_RSN_NTFY_INIT ||
4820*6d67aabdSBjoern A. Zeeb 	    run_reason == BTC_RSN_NTFY_SWBAND ||
4821*6d67aabdSBjoern A. Zeeb 	    dm->wl_btg_rx_rb != dm->wl_btg_rx ||
4822*6d67aabdSBjoern A. Zeeb 	    is_btg != dm->wl_btg_rx) {
4823*6d67aabdSBjoern A. Zeeb 
4824*6d67aabdSBjoern A. Zeeb 		dm->wl_btg_rx = is_btg;
4825*6d67aabdSBjoern A. Zeeb 
4826*6d67aabdSBjoern A. Zeeb 		if (is_btg > BTC_BTGCTRL_ENABLE)
48278e93258fSBjoern A. Zeeb 			return;
48288e93258fSBjoern A. Zeeb 
4829*6d67aabdSBjoern A. Zeeb 		chip->ops->ctrl_btg_bt_rx(rtwdev, is_btg, RTW89_PHY_0);
4830*6d67aabdSBjoern A. Zeeb 	}
4831*6d67aabdSBjoern A. Zeeb }
48328e93258fSBjoern A. Zeeb 
4833*6d67aabdSBjoern A. Zeeb static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
4834*6d67aabdSBjoern A. Zeeb {
4835*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
4836*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4837*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4838*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
4839*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
4840*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
4841*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4842*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
4843*6d67aabdSBjoern A. Zeeb 	u8 is_preagc, val;
4844*6d67aabdSBjoern A. Zeeb 
4845*6d67aabdSBjoern A. Zeeb 	if (btc->manual_ctrl)
48468e93258fSBjoern A. Zeeb 		return;
48478e93258fSBjoern A. Zeeb 
4848*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo->link_mode == BTC_WLINK_25G_MCC)
4849*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_BB_FWCTRL;
4850*6d67aabdSBjoern A. Zeeb 	else if (!(bt->run_patch_code && bt->enable.now))
4851*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_DISABLE;
4852*6d67aabdSBjoern A. Zeeb 	else if (wl_rinfo->link_mode == BTC_WLINK_5G)
4853*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_DISABLE;
4854*6d67aabdSBjoern A. Zeeb 	else if (wl_rinfo->link_mode == BTC_WLINK_NOLINK ||
4855*6d67aabdSBjoern A. Zeeb 		 btc->cx.bt.link_info.profile_cnt.now == 0)
4856*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_DISABLE;
4857*6d67aabdSBjoern A. Zeeb 	else if (dm->tdma_now.type != CXTDMA_OFF &&
4858*6d67aabdSBjoern A. Zeeb 		 !bt_linfo->hfp_desc.exist &&
4859*6d67aabdSBjoern A. Zeeb 		 !bt_linfo->hid_desc.exist &&
4860*6d67aabdSBjoern A. Zeeb 		 dm->fddt_train == BTC_FDDT_DISABLE)
4861*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_DISABLE;
4862*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 2 && wl_rinfo->dbcc_en &&
4863*6d67aabdSBjoern A. Zeeb 		 wl_rinfo->dbcc_2g_phy != RTW89_PHY_1)
4864*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_DISABLE;
4865*6d67aabdSBjoern A. Zeeb 	else if (btc->ant_type == BTC_ANT_SHARED)
4866*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_DISABLE;
4867*6d67aabdSBjoern A. Zeeb 	else
4868*6d67aabdSBjoern A. Zeeb 		is_preagc = BTC_PREAGC_ENABLE;
4869*6d67aabdSBjoern A. Zeeb 
4870*6d67aabdSBjoern A. Zeeb 	if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
4871*6d67aabdSBjoern A. Zeeb 	    dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
4872*6d67aabdSBjoern A. Zeeb 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
4873*6d67aabdSBjoern A. Zeeb 		dm->wl_pre_agc_rb = val;
4874*6d67aabdSBjoern A. Zeeb 	}
4875*6d67aabdSBjoern A. Zeeb 
4876*6d67aabdSBjoern A. Zeeb 	if ((wl->coex_mode == BTC_MODE_NORMAL &&
4877*6d67aabdSBjoern A. Zeeb 	     (dm->run_reason == BTC_RSN_NTFY_INIT ||
4878*6d67aabdSBjoern A. Zeeb 	      dm->run_reason == BTC_RSN_NTFY_SWBAND ||
4879*6d67aabdSBjoern A. Zeeb 	      dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
4880*6d67aabdSBjoern A. Zeeb 	    is_preagc != dm->wl_pre_agc) {
4881*6d67aabdSBjoern A. Zeeb 		dm->wl_pre_agc = is_preagc;
4882*6d67aabdSBjoern A. Zeeb 
4883*6d67aabdSBjoern A. Zeeb 		if (is_preagc > BTC_PREAGC_ENABLE)
4884*6d67aabdSBjoern A. Zeeb 			return;
4885*6d67aabdSBjoern A. Zeeb 		chip->ops->ctrl_nbtg_bt_tx(rtwdev, dm->wl_pre_agc, RTW89_PHY_0);
4886*6d67aabdSBjoern A. Zeeb 	}
48878e93258fSBjoern A. Zeeb }
48888e93258fSBjoern A. Zeeb 
48898e93258fSBjoern A. Zeeb struct rtw89_txtime_data {
48908e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev;
48918e93258fSBjoern A. Zeeb 	int type;
48928e93258fSBjoern A. Zeeb 	u32 tx_time;
48938e93258fSBjoern A. Zeeb 	u8 tx_retry;
48948e93258fSBjoern A. Zeeb 	u16 enable;
48958e93258fSBjoern A. Zeeb 	bool reenable;
48968e93258fSBjoern A. Zeeb };
48978e93258fSBjoern A. Zeeb 
48988e93258fSBjoern A. Zeeb static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
48998e93258fSBjoern A. Zeeb {
49008e93258fSBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
49018e93258fSBjoern A. Zeeb 	struct rtw89_txtime_data *iter_data =
49028e93258fSBjoern A. Zeeb 				(struct rtw89_txtime_data *)data;
49038e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
49048e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
49058e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
49068e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
49078e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
49088e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *plink = NULL;
49098e93258fSBjoern A. Zeeb 	u8 port = rtwvif->port;
49108e93258fSBjoern A. Zeeb 	u32 tx_time = iter_data->tx_time;
49118e93258fSBjoern A. Zeeb 	u8 tx_retry = iter_data->tx_retry;
49128e93258fSBjoern A. Zeeb 	u16 enable = iter_data->enable;
49138e93258fSBjoern A. Zeeb 	bool reenable = iter_data->reenable;
49148e93258fSBjoern A. Zeeb 
4915*6d67aabdSBjoern A. Zeeb 	if (btc->ver->fwlrole == 8)
4916*6d67aabdSBjoern A. Zeeb 		plink = &wl->rlink_info[port][0];
4917*6d67aabdSBjoern A. Zeeb 	else
49188e93258fSBjoern A. Zeeb 		plink = &wl->link_info[port];
49198e93258fSBjoern A. Zeeb 
49208e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
49218e93258fSBjoern A. Zeeb 		    "[BTC], %s(): port = %d\n", __func__, port);
49228e93258fSBjoern A. Zeeb 
49238e93258fSBjoern A. Zeeb 	if (!plink->connected) {
49248e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
49258e93258fSBjoern A. Zeeb 			    "[BTC], %s(): connected = %d\n",
49268e93258fSBjoern A. Zeeb 			    __func__, plink->connected);
49278e93258fSBjoern A. Zeeb 		return;
49288e93258fSBjoern A. Zeeb 	}
49298e93258fSBjoern A. Zeeb 
49308e93258fSBjoern A. Zeeb 	/* backup the original tx time before tx-limit on */
49318e93258fSBjoern A. Zeeb 	if (reenable) {
49328e93258fSBjoern A. Zeeb 		rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time);
49338e93258fSBjoern A. Zeeb 		rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry);
49348e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
49358e93258fSBjoern A. Zeeb 			    "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
49368e93258fSBjoern A. Zeeb 			    __func__, plink->tx_time, plink->tx_retry);
49378e93258fSBjoern A. Zeeb 	}
49388e93258fSBjoern A. Zeeb 
49398e93258fSBjoern A. Zeeb 	/* restore the original tx time if no tx-limit */
49408e93258fSBjoern A. Zeeb 	if (!enable) {
49418e93258fSBjoern A. Zeeb 		rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time);
49428e93258fSBjoern A. Zeeb 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true,
49438e93258fSBjoern A. Zeeb 					     plink->tx_retry);
49448e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
49458e93258fSBjoern A. Zeeb 			    "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
49468e93258fSBjoern A. Zeeb 			    __func__, plink->tx_time, plink->tx_retry);
49478e93258fSBjoern A. Zeeb 
49488e93258fSBjoern A. Zeeb 	} else {
49498e93258fSBjoern A. Zeeb 		rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time);
49508e93258fSBjoern A. Zeeb 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry);
49518e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
49528e93258fSBjoern A. Zeeb 			    "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
49538e93258fSBjoern A. Zeeb 			    __func__, tx_time, tx_retry);
49548e93258fSBjoern A. Zeeb 	}
49558e93258fSBjoern A. Zeeb }
49568e93258fSBjoern A. Zeeb 
49578e93258fSBjoern A. Zeeb static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
49588e93258fSBjoern A. Zeeb {
49598e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
4960e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
49618e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
49628e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
49638e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
49648e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
49658e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
49668e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
49678e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
49688e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
49698e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4970e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
4971*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
49728e93258fSBjoern A. Zeeb 	struct rtw89_txtime_data data = {.rtwdev = rtwdev};
4973*6d67aabdSBjoern A. Zeeb 	u8 mode, igno_bt, tx_retry;
49748e93258fSBjoern A. Zeeb 	u32 tx_time;
49758e93258fSBjoern A. Zeeb 	u16 enable;
49768e93258fSBjoern A. Zeeb 	bool reenable = false;
49778e93258fSBjoern A. Zeeb 
4978*6d67aabdSBjoern A. Zeeb 	if (btc->manual_ctrl)
49798e93258fSBjoern A. Zeeb 		return;
49808e93258fSBjoern A. Zeeb 
4981e2340276SBjoern A. Zeeb 	if (ver->fwlrole == 0)
49828e93258fSBjoern A. Zeeb 		mode = wl_rinfo->link_mode;
4983e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 1)
49848e93258fSBjoern A. Zeeb 		mode = wl_rinfo_v1->link_mode;
4985e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 2)
4986e2340276SBjoern A. Zeeb 		mode = wl_rinfo_v2->link_mode;
4987*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 8)
4988*6d67aabdSBjoern A. Zeeb 		mode = wl_rinfo_v8->link_mode;
4989e2340276SBjoern A. Zeeb 	else
4990e2340276SBjoern A. Zeeb 		return;
49918e93258fSBjoern A. Zeeb 
4992*6d67aabdSBjoern A. Zeeb 	if (ver->fcxctrl == 7)
4993*6d67aabdSBjoern A. Zeeb 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
4994*6d67aabdSBjoern A. Zeeb 	else
4995*6d67aabdSBjoern A. Zeeb 		igno_bt = btc->ctrl.ctrl.igno_bt;
4996*6d67aabdSBjoern A. Zeeb 
4997*6d67aabdSBjoern A. Zeeb 	if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 ||
49988e93258fSBjoern A. Zeeb 	    mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
49998e93258fSBjoern A. Zeeb 		enable = 0;
50008e93258fSBjoern A. Zeeb 		tx_time = BTC_MAX_TX_TIME_DEF;
50018e93258fSBjoern A. Zeeb 		tx_retry = BTC_MAX_TX_RETRY_DEF;
50028e93258fSBjoern A. Zeeb 	} else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
50038e93258fSBjoern A. Zeeb 		enable = 1;
50048e93258fSBjoern A. Zeeb 		tx_time = BTC_MAX_TX_TIME_L2;
50058e93258fSBjoern A. Zeeb 		tx_retry = BTC_MAX_TX_RETRY_L1;
50068e93258fSBjoern A. Zeeb 	} else if (hfp->exist || hid->exist) {
50078e93258fSBjoern A. Zeeb 		enable = 1;
50088e93258fSBjoern A. Zeeb 		tx_time = BTC_MAX_TX_TIME_L3;
50098e93258fSBjoern A. Zeeb 		tx_retry = BTC_MAX_TX_RETRY_L1;
50108e93258fSBjoern A. Zeeb 	} else {
50118e93258fSBjoern A. Zeeb 		enable = 0;
50128e93258fSBjoern A. Zeeb 		tx_time = BTC_MAX_TX_TIME_DEF;
50138e93258fSBjoern A. Zeeb 		tx_retry = BTC_MAX_TX_RETRY_DEF;
50148e93258fSBjoern A. Zeeb 	}
50158e93258fSBjoern A. Zeeb 
50168e93258fSBjoern A. Zeeb 	if (dm->wl_tx_limit.enable == enable &&
50178e93258fSBjoern A. Zeeb 	    dm->wl_tx_limit.tx_time == tx_time &&
50188e93258fSBjoern A. Zeeb 	    dm->wl_tx_limit.tx_retry == tx_retry)
50198e93258fSBjoern A. Zeeb 		return;
50208e93258fSBjoern A. Zeeb 
50218e93258fSBjoern A. Zeeb 	if (!dm->wl_tx_limit.enable && enable)
50228e93258fSBjoern A. Zeeb 		reenable = true;
50238e93258fSBjoern A. Zeeb 
50248e93258fSBjoern A. Zeeb 	dm->wl_tx_limit.enable = enable;
50258e93258fSBjoern A. Zeeb 	dm->wl_tx_limit.tx_time = tx_time;
50268e93258fSBjoern A. Zeeb 	dm->wl_tx_limit.tx_retry = tx_retry;
50278e93258fSBjoern A. Zeeb 
50288e93258fSBjoern A. Zeeb 	data.enable = enable;
50298e93258fSBjoern A. Zeeb 	data.tx_time = tx_time;
50308e93258fSBjoern A. Zeeb 	data.tx_retry = tx_retry;
50318e93258fSBjoern A. Zeeb 	data.reenable = reenable;
50328e93258fSBjoern A. Zeeb 
50338e93258fSBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
50348e93258fSBjoern A. Zeeb 					  rtw89_tx_time_iter,
50358e93258fSBjoern A. Zeeb 					  &data);
50368e93258fSBjoern A. Zeeb }
50378e93258fSBjoern A. Zeeb 
50388e93258fSBjoern A. Zeeb static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
50398e93258fSBjoern A. Zeeb {
50408e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
5041e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
50428e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
50438e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
50448e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5045e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5046*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
50478e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
50488e93258fSBjoern A. Zeeb 	bool bt_hi_lna_rx = false;
50498e93258fSBjoern A. Zeeb 	u8 mode;
50508e93258fSBjoern A. Zeeb 
5051e2340276SBjoern A. Zeeb 	if (ver->fwlrole == 0)
50528e93258fSBjoern A. Zeeb 		mode = wl_rinfo->link_mode;
5053e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 1)
50548e93258fSBjoern A. Zeeb 		mode = wl_rinfo_v1->link_mode;
5055e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 2)
5056e2340276SBjoern A. Zeeb 		mode = wl_rinfo_v2->link_mode;
5057*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 8)
5058*6d67aabdSBjoern A. Zeeb 		mode = wl_rinfo_v8->link_mode;
5059e2340276SBjoern A. Zeeb 	else
5060e2340276SBjoern A. Zeeb 		return;
50618e93258fSBjoern A. Zeeb 
50628e93258fSBjoern A. Zeeb 	if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
50638e93258fSBjoern A. Zeeb 		bt_hi_lna_rx = true;
50648e93258fSBjoern A. Zeeb 
50658e93258fSBjoern A. Zeeb 	if (bt_hi_lna_rx == bt->hi_lna_rx)
50668e93258fSBjoern A. Zeeb 		return;
50678e93258fSBjoern A. Zeeb 
50688e93258fSBjoern A. Zeeb 	_write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
50698e93258fSBjoern A. Zeeb }
50708e93258fSBjoern A. Zeeb 
5071e2340276SBjoern A. Zeeb static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
5072e2340276SBjoern A. Zeeb {
5073e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
5074e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5075e2340276SBjoern A. Zeeb 
5076e2340276SBjoern A. Zeeb 	_write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
5077e2340276SBjoern A. Zeeb }
5078e2340276SBjoern A. Zeeb 
50798e93258fSBjoern A. Zeeb static void _action_common(struct rtw89_dev *rtwdev)
50808e93258fSBjoern A. Zeeb {
5081e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
5082e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5083*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
5084*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5085*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
5086*6d67aabdSBjoern A. Zeeb 	u32 bt_rom_code_id, bt_fw_ver;
5087e2340276SBjoern A. Zeeb 
50888e93258fSBjoern A. Zeeb 	_set_btg_ctrl(rtwdev);
5089*6d67aabdSBjoern A. Zeeb 	_set_wl_preagc_ctrl(rtwdev);
50908e93258fSBjoern A. Zeeb 	_set_wl_tx_limit(rtwdev);
50918e93258fSBjoern A. Zeeb 	_set_bt_afh_info(rtwdev);
50928e93258fSBjoern A. Zeeb 	_set_bt_rx_agc(rtwdev);
50938e93258fSBjoern A. Zeeb 	_set_rf_trx_para(rtwdev);
5094e2340276SBjoern A. Zeeb 	_set_bt_rx_scan_pri(rtwdev);
5095e2340276SBjoern A. Zeeb 
5096*6d67aabdSBjoern A. Zeeb 	bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
5097*6d67aabdSBjoern A. Zeeb 	bt_fw_ver = bt->ver_info.fw & 0xffff;
5098*6d67aabdSBjoern A. Zeeb 	if (bt->enable.now &&
5099*6d67aabdSBjoern A. Zeeb 	    (bt_fw_ver == 0 ||
5100*6d67aabdSBjoern A. Zeeb 	     (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd)))
5101*6d67aabdSBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1);
5102*6d67aabdSBjoern A. Zeeb 	else
5103*6d67aabdSBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0);
5104*6d67aabdSBjoern A. Zeeb 
5105*6d67aabdSBjoern A. Zeeb 	if (dm->run_reason == BTC_RSN_NTFY_INIT ||
5106*6d67aabdSBjoern A. Zeeb 	    dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5107*6d67aabdSBjoern A. Zeeb 	    dm->run_reason == BTC_RSN_NTFY_POWEROFF) {
5108*6d67aabdSBjoern A. Zeeb 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5109*6d67aabdSBjoern A. Zeeb 
5110*6d67aabdSBjoern A. Zeeb 		if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF)
5111*6d67aabdSBjoern A. Zeeb 			rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
5112*6d67aabdSBjoern A. Zeeb 		else
5113*6d67aabdSBjoern A. Zeeb 			rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
5114*6d67aabdSBjoern A. Zeeb 	}
5115*6d67aabdSBjoern A. Zeeb 
5116e2340276SBjoern A. Zeeb 	if (wl->scbd_change) {
5117e2340276SBjoern A. Zeeb 		rtw89_mac_cfg_sb(rtwdev, wl->scbd);
5118e2340276SBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
5119e2340276SBjoern A. Zeeb 			    wl->scbd);
5120e2340276SBjoern A. Zeeb 		wl->scbd_change = false;
5121e2340276SBjoern A. Zeeb 		btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
5122e2340276SBjoern A. Zeeb 	}
5123e2340276SBjoern A. Zeeb 	btc->dm.tdma_instant_excute = 0;
51248e93258fSBjoern A. Zeeb }
51258e93258fSBjoern A. Zeeb 
51268e93258fSBjoern A. Zeeb static void _action_by_bt(struct rtw89_dev *rtwdev)
51278e93258fSBjoern A. Zeeb {
51288e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
51298e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
51308e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
51318e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
51328e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
51338e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
51348e93258fSBjoern A. Zeeb 	u8 profile_map = 0;
51358e93258fSBjoern A. Zeeb 
51368e93258fSBjoern A. Zeeb 	if (bt_linfo->hfp_desc.exist)
51378e93258fSBjoern A. Zeeb 		profile_map |= BTC_BT_HFP;
51388e93258fSBjoern A. Zeeb 
51398e93258fSBjoern A. Zeeb 	if (bt_linfo->hid_desc.exist)
51408e93258fSBjoern A. Zeeb 		profile_map |= BTC_BT_HID;
51418e93258fSBjoern A. Zeeb 
51428e93258fSBjoern A. Zeeb 	if (bt_linfo->a2dp_desc.exist)
51438e93258fSBjoern A. Zeeb 		profile_map |= BTC_BT_A2DP;
51448e93258fSBjoern A. Zeeb 
51458e93258fSBjoern A. Zeeb 	if (bt_linfo->pan_desc.exist)
51468e93258fSBjoern A. Zeeb 		profile_map |= BTC_BT_PAN;
51478e93258fSBjoern A. Zeeb 
51488e93258fSBjoern A. Zeeb 	switch (profile_map) {
51498e93258fSBjoern A. Zeeb 	case BTC_BT_NOPROFILE:
51508e93258fSBjoern A. Zeeb 		if (_check_freerun(rtwdev))
51518e93258fSBjoern A. Zeeb 			_action_freerun(rtwdev);
5152e2340276SBjoern A. Zeeb 		else if (pan.active)
51538e93258fSBjoern A. Zeeb 			_action_bt_pan(rtwdev);
51548e93258fSBjoern A. Zeeb 		else
51558e93258fSBjoern A. Zeeb 			_action_bt_idle(rtwdev);
51568e93258fSBjoern A. Zeeb 		break;
51578e93258fSBjoern A. Zeeb 	case BTC_BT_HFP:
51588e93258fSBjoern A. Zeeb 		if (_check_freerun(rtwdev))
51598e93258fSBjoern A. Zeeb 			_action_freerun(rtwdev);
51608e93258fSBjoern A. Zeeb 		else
51618e93258fSBjoern A. Zeeb 			_action_bt_hfp(rtwdev);
51628e93258fSBjoern A. Zeeb 		break;
51638e93258fSBjoern A. Zeeb 	case BTC_BT_HFP | BTC_BT_HID:
51648e93258fSBjoern A. Zeeb 	case BTC_BT_HID:
51658e93258fSBjoern A. Zeeb 		if (_check_freerun(rtwdev))
51668e93258fSBjoern A. Zeeb 			_action_freerun(rtwdev);
51678e93258fSBjoern A. Zeeb 		else
51688e93258fSBjoern A. Zeeb 			_action_bt_hid(rtwdev);
51698e93258fSBjoern A. Zeeb 		break;
51708e93258fSBjoern A. Zeeb 	case BTC_BT_A2DP:
51718e93258fSBjoern A. Zeeb 		if (_check_freerun(rtwdev))
51728e93258fSBjoern A. Zeeb 			_action_freerun(rtwdev);
51738e93258fSBjoern A. Zeeb 		else if (a2dp.sink)
51748e93258fSBjoern A. Zeeb 			_action_bt_a2dpsink(rtwdev);
51758e93258fSBjoern A. Zeeb 		else if (bt_linfo->multi_link.now && !hid.pair_cnt)
51768e93258fSBjoern A. Zeeb 			_action_bt_a2dp_pan(rtwdev);
51778e93258fSBjoern A. Zeeb 		else
51788e93258fSBjoern A. Zeeb 			_action_bt_a2dp(rtwdev);
51798e93258fSBjoern A. Zeeb 		break;
51808e93258fSBjoern A. Zeeb 	case BTC_BT_PAN:
51818e93258fSBjoern A. Zeeb 		_action_bt_pan(rtwdev);
51828e93258fSBjoern A. Zeeb 		break;
51838e93258fSBjoern A. Zeeb 	case BTC_BT_A2DP | BTC_BT_HFP:
51848e93258fSBjoern A. Zeeb 	case BTC_BT_A2DP | BTC_BT_HID:
51858e93258fSBjoern A. Zeeb 	case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
51868e93258fSBjoern A. Zeeb 		if (_check_freerun(rtwdev))
51878e93258fSBjoern A. Zeeb 			_action_freerun(rtwdev);
51888e93258fSBjoern A. Zeeb 		else
51898e93258fSBjoern A. Zeeb 			_action_bt_a2dp_hid(rtwdev);
51908e93258fSBjoern A. Zeeb 		break;
51918e93258fSBjoern A. Zeeb 	case BTC_BT_A2DP | BTC_BT_PAN:
51928e93258fSBjoern A. Zeeb 		_action_bt_a2dp_pan(rtwdev);
51938e93258fSBjoern A. Zeeb 		break;
51948e93258fSBjoern A. Zeeb 	case BTC_BT_PAN | BTC_BT_HFP:
51958e93258fSBjoern A. Zeeb 	case BTC_BT_PAN | BTC_BT_HID:
51968e93258fSBjoern A. Zeeb 	case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
51978e93258fSBjoern A. Zeeb 		_action_bt_pan_hid(rtwdev);
51988e93258fSBjoern A. Zeeb 		break;
51998e93258fSBjoern A. Zeeb 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
52008e93258fSBjoern A. Zeeb 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
52018e93258fSBjoern A. Zeeb 	default:
52028e93258fSBjoern A. Zeeb 		_action_bt_a2dp_pan_hid(rtwdev);
52038e93258fSBjoern A. Zeeb 		break;
52048e93258fSBjoern A. Zeeb 	}
52058e93258fSBjoern A. Zeeb }
52068e93258fSBjoern A. Zeeb 
52078e93258fSBjoern A. Zeeb static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
52088e93258fSBjoern A. Zeeb {
52098e93258fSBjoern A. Zeeb 	_action_by_bt(rtwdev);
52108e93258fSBjoern A. Zeeb }
52118e93258fSBjoern A. Zeeb 
5212*6d67aabdSBjoern A. Zeeb static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
5213*6d67aabdSBjoern A. Zeeb {
5214*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
5215*6d67aabdSBjoern A. Zeeb 	u16 policy_type = BTC_CXP_OFF_BT;
5216*6d67aabdSBjoern A. Zeeb 
5217*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
5218*6d67aabdSBjoern A. Zeeb 		if (btc->cx.wl.status.map._4way)
5219*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFFE_WL;
5220*6d67aabdSBjoern A. Zeeb 		else if (btc->cx.wl.status.val & btc_scanning_map.val)
5221*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFFE_2GBWMIXB;
5222*6d67aabdSBjoern A. Zeeb 		else if (btc->cx.bt.link_info.profile_cnt.now == 0)
5223*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFFE_2GISOB;
5224*6d67aabdSBjoern A. Zeeb 		else
5225*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFFE_2GBWISOB;
5226*6d67aabdSBjoern A. Zeeb 	} else { /* dedicated-antenna */
5227*6d67aabdSBjoern A. Zeeb 		policy_type = BTC_CXP_OFF_EQ0;
5228*6d67aabdSBjoern A. Zeeb 	}
5229*6d67aabdSBjoern A. Zeeb 
5230*6d67aabdSBjoern A. Zeeb 	btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5231*6d67aabdSBjoern A. Zeeb 
5232*6d67aabdSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
5233*6d67aabdSBjoern A. Zeeb 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
5234*6d67aabdSBjoern A. Zeeb }
5235*6d67aabdSBjoern A. Zeeb 
52368e93258fSBjoern A. Zeeb static void _action_wl_scan(struct rtw89_dev *rtwdev)
52378e93258fSBjoern A. Zeeb {
52388e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
52398e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
52408e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
52418e93258fSBjoern A. Zeeb 
52428e93258fSBjoern A. Zeeb 	if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
5243*6d67aabdSBjoern A. Zeeb 		_action_wl_25g_mcc(rtwdev);
52448e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
52458e93258fSBjoern A. Zeeb 	} else if (rtwdev->dbcc_en) {
52468e93258fSBjoern A. Zeeb 		if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
52478e93258fSBjoern A. Zeeb 		    wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
52488e93258fSBjoern A. Zeeb 			_action_wl_5g(rtwdev);
52498e93258fSBjoern A. Zeeb 		else
52508e93258fSBjoern A. Zeeb 			_action_by_bt(rtwdev);
52518e93258fSBjoern A. Zeeb 	} else {
52528e93258fSBjoern A. Zeeb 		if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
52538e93258fSBjoern A. Zeeb 			_action_wl_5g(rtwdev);
52548e93258fSBjoern A. Zeeb 		else
52558e93258fSBjoern A. Zeeb 			_action_by_bt(rtwdev);
52568e93258fSBjoern A. Zeeb 	}
52578e93258fSBjoern A. Zeeb }
52588e93258fSBjoern A. Zeeb 
52598e93258fSBjoern A. Zeeb static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
52608e93258fSBjoern A. Zeeb {	struct rtw89_btc *btc = &rtwdev->btc;
52618e93258fSBjoern A. Zeeb 
52628e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
52638e93258fSBjoern A. Zeeb 
5264*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
52658e93258fSBjoern A. Zeeb 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
52668e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
52678e93258fSBjoern A. Zeeb 				    BTC_ACT_WL_2G_MCC);
52688e93258fSBjoern A. Zeeb 		else
52698e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF,
52708e93258fSBjoern A. Zeeb 				    BTC_ACT_WL_2G_MCC);
52718e93258fSBjoern A. Zeeb 	} else { /* dedicated-antenna */
52728e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
52738e93258fSBjoern A. Zeeb 	}
52748e93258fSBjoern A. Zeeb }
52758e93258fSBjoern A. Zeeb 
52768e93258fSBjoern A. Zeeb static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
52778e93258fSBjoern A. Zeeb {
52788e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
52798e93258fSBjoern A. Zeeb 
52808e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
52818e93258fSBjoern A. Zeeb 
5282*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
52838e93258fSBjoern A. Zeeb 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
52848e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
52858e93258fSBjoern A. Zeeb 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
52868e93258fSBjoern A. Zeeb 		else
52878e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
52888e93258fSBjoern A. Zeeb 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
52898e93258fSBjoern A. Zeeb 	} else { /* dedicated-antenna */
52908e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
52918e93258fSBjoern A. Zeeb 	}
52928e93258fSBjoern A. Zeeb }
52938e93258fSBjoern A. Zeeb 
52948e93258fSBjoern A. Zeeb static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
52958e93258fSBjoern A. Zeeb {
52968e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
52978e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
52988e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
52998e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
53008e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
53018e93258fSBjoern A. Zeeb 	u16 policy_type = BTC_CXP_OFF_BT;
53028e93258fSBjoern A. Zeeb 	u32 dur;
53038e93258fSBjoern A. Zeeb 
5304*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_DEDICATED) {
53058e93258fSBjoern A. Zeeb 		policy_type = BTC_CXP_OFF_EQ0;
53068e93258fSBjoern A. Zeeb 	} else {
53078e93258fSBjoern A. Zeeb 		/* shared-antenna */
53088e93258fSBjoern A. Zeeb 		switch (wl_rinfo->mrole_type) {
53098e93258fSBjoern A. Zeeb 		case BTC_WLMROLE_STA_GC:
53108e93258fSBjoern A. Zeeb 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
53118e93258fSBjoern A. Zeeb 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
53128e93258fSBjoern A. Zeeb 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
53138e93258fSBjoern A. Zeeb 			_action_by_bt(rtwdev);
53148e93258fSBjoern A. Zeeb 			return;
53158e93258fSBjoern A. Zeeb 		case BTC_WLMROLE_STA_STA:
53168e93258fSBjoern A. Zeeb 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
53178e93258fSBjoern A. Zeeb 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
53188e93258fSBjoern A. Zeeb 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
53198e93258fSBjoern A. Zeeb 			_action_by_bt(rtwdev);
53208e93258fSBjoern A. Zeeb 			return;
53218e93258fSBjoern A. Zeeb 		case BTC_WLMROLE_STA_GC_NOA:
53228e93258fSBjoern A. Zeeb 		case BTC_WLMROLE_STA_GO:
53238e93258fSBjoern A. Zeeb 		case BTC_WLMROLE_STA_GO_NOA:
53248e93258fSBjoern A. Zeeb 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
53258e93258fSBjoern A. Zeeb 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
53268e93258fSBjoern A. Zeeb 			dur = wl_rinfo->mrole_noa_duration;
53278e93258fSBjoern A. Zeeb 
53288e93258fSBjoern A. Zeeb 			if (wl->status.map._4way) {
53298e93258fSBjoern A. Zeeb 				dm->wl_scc.ebt_null = 0;
53308e93258fSBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_WL;
53318e93258fSBjoern A. Zeeb 			} else if (bt->link_info.status.map.connect == 0) {
53328e93258fSBjoern A. Zeeb 				dm->wl_scc.ebt_null = 0;
53338e93258fSBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GISOB;
53348e93258fSBjoern A. Zeeb 			} else if (bt->link_info.a2dp_desc.exist &&
53358e93258fSBjoern A. Zeeb 				   dur < btc->bt_req_len) {
53368e93258fSBjoern A. Zeeb 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
53378e93258fSBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GBWMIXB2;
53388e93258fSBjoern A. Zeeb 			} else if (bt->link_info.a2dp_desc.exist ||
53398e93258fSBjoern A. Zeeb 				   bt->link_info.pan_desc.exist) {
53408e93258fSBjoern A. Zeeb 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
53418e93258fSBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GBWISOB;
53428e93258fSBjoern A. Zeeb 			} else {
53438e93258fSBjoern A. Zeeb 				dm->wl_scc.ebt_null = 0;
53448e93258fSBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GBWISOB;
53458e93258fSBjoern A. Zeeb 			}
53468e93258fSBjoern A. Zeeb 			break;
53478e93258fSBjoern A. Zeeb 		default:
53488e93258fSBjoern A. Zeeb 			break;
53498e93258fSBjoern A. Zeeb 		}
53508e93258fSBjoern A. Zeeb 	}
53518e93258fSBjoern A. Zeeb 
53528e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
53538e93258fSBjoern A. Zeeb 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
53548e93258fSBjoern A. Zeeb }
53558e93258fSBjoern A. Zeeb 
5356e2340276SBjoern A. Zeeb static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
5357e2340276SBjoern A. Zeeb {
5358e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
5359e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5360e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5361e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
5362e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
5363e2340276SBjoern A. Zeeb 	u16 policy_type = BTC_CXP_OFF_BT;
5364e2340276SBjoern A. Zeeb 	u32 dur;
5365e2340276SBjoern A. Zeeb 
5366*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_DEDICATED) {
5367e2340276SBjoern A. Zeeb 		policy_type = BTC_CXP_OFF_EQ0;
5368e2340276SBjoern A. Zeeb 	} else {
5369e2340276SBjoern A. Zeeb 		/* shared-antenna */
5370e2340276SBjoern A. Zeeb 		switch (wl_rinfo->mrole_type) {
5371e2340276SBjoern A. Zeeb 		case BTC_WLMROLE_STA_GC:
5372e2340276SBjoern A. Zeeb 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5373e2340276SBjoern A. Zeeb 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5374e2340276SBjoern A. Zeeb 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5375e2340276SBjoern A. Zeeb 			_action_by_bt(rtwdev);
5376e2340276SBjoern A. Zeeb 			return;
5377e2340276SBjoern A. Zeeb 		case BTC_WLMROLE_STA_STA:
5378e2340276SBjoern A. Zeeb 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5379e2340276SBjoern A. Zeeb 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5380e2340276SBjoern A. Zeeb 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5381e2340276SBjoern A. Zeeb 			_action_by_bt(rtwdev);
5382e2340276SBjoern A. Zeeb 			return;
5383e2340276SBjoern A. Zeeb 		case BTC_WLMROLE_STA_GC_NOA:
5384e2340276SBjoern A. Zeeb 		case BTC_WLMROLE_STA_GO:
5385e2340276SBjoern A. Zeeb 		case BTC_WLMROLE_STA_GO_NOA:
5386e2340276SBjoern A. Zeeb 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5387e2340276SBjoern A. Zeeb 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5388e2340276SBjoern A. Zeeb 			dur = wl_rinfo->mrole_noa_duration;
5389e2340276SBjoern A. Zeeb 
5390e2340276SBjoern A. Zeeb 			if (wl->status.map._4way) {
5391e2340276SBjoern A. Zeeb 				dm->wl_scc.ebt_null = 0;
5392e2340276SBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_WL;
5393e2340276SBjoern A. Zeeb 			} else if (bt->link_info.status.map.connect == 0) {
5394e2340276SBjoern A. Zeeb 				dm->wl_scc.ebt_null = 0;
5395e2340276SBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GISOB;
5396e2340276SBjoern A. Zeeb 			} else if (bt->link_info.a2dp_desc.exist &&
5397e2340276SBjoern A. Zeeb 				   dur < btc->bt_req_len) {
5398e2340276SBjoern A. Zeeb 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5399e2340276SBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5400e2340276SBjoern A. Zeeb 			} else if (bt->link_info.a2dp_desc.exist ||
5401e2340276SBjoern A. Zeeb 				   bt->link_info.pan_desc.exist) {
5402e2340276SBjoern A. Zeeb 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5403e2340276SBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5404e2340276SBjoern A. Zeeb 			} else {
5405e2340276SBjoern A. Zeeb 				dm->wl_scc.ebt_null = 0;
5406e2340276SBjoern A. Zeeb 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5407e2340276SBjoern A. Zeeb 			}
5408e2340276SBjoern A. Zeeb 			break;
5409e2340276SBjoern A. Zeeb 		default:
5410e2340276SBjoern A. Zeeb 			break;
5411e2340276SBjoern A. Zeeb 		}
5412e2340276SBjoern A. Zeeb 	}
5413e2340276SBjoern A. Zeeb 
5414e2340276SBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5415e2340276SBjoern A. Zeeb 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5416e2340276SBjoern A. Zeeb }
5417e2340276SBjoern A. Zeeb 
5418*6d67aabdSBjoern A. Zeeb static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
5419*6d67aabdSBjoern A. Zeeb {
5420*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
5421*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5422*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5423*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
5424*6d67aabdSBjoern A. Zeeb 	u16 policy_type = BTC_CXP_OFF_BT;
5425*6d67aabdSBjoern A. Zeeb 
5426*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
5427*6d67aabdSBjoern A. Zeeb 		if (wl->status.map._4way)
5428*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFFE_WL;
5429*6d67aabdSBjoern A. Zeeb 		else if (bt->link_info.status.map.connect == 0)
5430*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFFE_2GISOB;
5431*6d67aabdSBjoern A. Zeeb 		else
5432*6d67aabdSBjoern A. Zeeb 			policy_type = BTC_CXP_OFFE_2GBWISOB;
5433*6d67aabdSBjoern A. Zeeb 	} else {
5434*6d67aabdSBjoern A. Zeeb 		policy_type = BTC_CXP_OFF_EQ0;
5435*6d67aabdSBjoern A. Zeeb 	}
5436*6d67aabdSBjoern A. Zeeb 
5437*6d67aabdSBjoern A. Zeeb 	dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5438*6d67aabdSBjoern A. Zeeb 
5439*6d67aabdSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5440*6d67aabdSBjoern A. Zeeb 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5441*6d67aabdSBjoern A. Zeeb }
5442*6d67aabdSBjoern A. Zeeb 
54438e93258fSBjoern A. Zeeb static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
54448e93258fSBjoern A. Zeeb {
54458e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
54468e93258fSBjoern A. Zeeb 
54478e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
54488e93258fSBjoern A. Zeeb 
5449*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) {
54508e93258fSBjoern A. Zeeb 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
54518e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
54528e93258fSBjoern A. Zeeb 				    BTC_ACT_WL_2G_AP);
54538e93258fSBjoern A. Zeeb 		else
54548e93258fSBjoern A. Zeeb 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
54558e93258fSBjoern A. Zeeb 	} else {/* dedicated-antenna */
54568e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
54578e93258fSBjoern A. Zeeb 	}
54588e93258fSBjoern A. Zeeb }
54598e93258fSBjoern A. Zeeb 
54608e93258fSBjoern A. Zeeb static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
54618e93258fSBjoern A. Zeeb {
54628e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
54638e93258fSBjoern A. Zeeb 
54648e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
54658e93258fSBjoern A. Zeeb 
5466*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
54678e93258fSBjoern A. Zeeb 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
54688e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
54698e93258fSBjoern A. Zeeb 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
54708e93258fSBjoern A. Zeeb 		else
54718e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
54728e93258fSBjoern A. Zeeb 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
54738e93258fSBjoern A. Zeeb 	} else { /* dedicated-antenna */
54748e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
54758e93258fSBjoern A. Zeeb 	}
54768e93258fSBjoern A. Zeeb }
54778e93258fSBjoern A. Zeeb 
54788e93258fSBjoern A. Zeeb static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
54798e93258fSBjoern A. Zeeb {
54808e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
54818e93258fSBjoern A. Zeeb 
54828e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
54838e93258fSBjoern A. Zeeb 
5484*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
54858e93258fSBjoern A. Zeeb 		_action_by_bt(rtwdev);
54868e93258fSBjoern A. Zeeb 	} else {/* dedicated-antenna */
54878e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
54888e93258fSBjoern A. Zeeb 	}
54898e93258fSBjoern A. Zeeb }
54908e93258fSBjoern A. Zeeb 
54918e93258fSBjoern A. Zeeb static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
54928e93258fSBjoern A. Zeeb {
54938e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
54948e93258fSBjoern A. Zeeb 
54958e93258fSBjoern A. Zeeb 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
54968e93258fSBjoern A. Zeeb 
5497*6d67aabdSBjoern A. Zeeb 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
54988e93258fSBjoern A. Zeeb 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
54998e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
55008e93258fSBjoern A. Zeeb 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
55018e93258fSBjoern A. Zeeb 		else
55028e93258fSBjoern A. Zeeb 			_set_policy(rtwdev,
55038e93258fSBjoern A. Zeeb 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
55048e93258fSBjoern A. Zeeb 	} else { /* dedicated-antenna */
55058e93258fSBjoern A. Zeeb 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
55068e93258fSBjoern A. Zeeb 	}
55078e93258fSBjoern A. Zeeb }
55088e93258fSBjoern A. Zeeb 
55098e93258fSBjoern A. Zeeb static u32 _read_scbd(struct rtw89_dev *rtwdev)
55108e93258fSBjoern A. Zeeb {
55118e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
55128e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
55138e93258fSBjoern A. Zeeb 	u32 scbd_val = 0;
55148e93258fSBjoern A. Zeeb 
55158e93258fSBjoern A. Zeeb 	if (!chip->scbd)
55168e93258fSBjoern A. Zeeb 		return 0;
55178e93258fSBjoern A. Zeeb 
55188e93258fSBjoern A. Zeeb 	scbd_val = rtw89_mac_get_sb(rtwdev);
55198e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
55208e93258fSBjoern A. Zeeb 		    scbd_val);
55218e93258fSBjoern A. Zeeb 
55228e93258fSBjoern A. Zeeb 	btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
55238e93258fSBjoern A. Zeeb 	return scbd_val;
55248e93258fSBjoern A. Zeeb }
55258e93258fSBjoern A. Zeeb 
55268e93258fSBjoern A. Zeeb static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
55278e93258fSBjoern A. Zeeb {
55288e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
55298e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
55308e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
55318e93258fSBjoern A. Zeeb 	u32 scbd_val = 0;
5532e2340276SBjoern A. Zeeb 	u8 force_exec = false;
55338e93258fSBjoern A. Zeeb 
55348e93258fSBjoern A. Zeeb 	if (!chip->scbd)
55358e93258fSBjoern A. Zeeb 		return;
55368e93258fSBjoern A. Zeeb 
55378e93258fSBjoern A. Zeeb 	scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
55388e93258fSBjoern A. Zeeb 
5539e2340276SBjoern A. Zeeb 	if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
5540e2340276SBjoern A. Zeeb 		force_exec = true;
55418e93258fSBjoern A. Zeeb 
5542e2340276SBjoern A. Zeeb 	if (scbd_val != wl->scbd || force_exec) {
5543e2340276SBjoern A. Zeeb 		wl->scbd = scbd_val;
5544e2340276SBjoern A. Zeeb 		wl->scbd_change = true;
5545e2340276SBjoern A. Zeeb 	}
55468e93258fSBjoern A. Zeeb }
55478e93258fSBjoern A. Zeeb 
55488e93258fSBjoern A. Zeeb static u8
55498e93258fSBjoern A. Zeeb _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
55508e93258fSBjoern A. Zeeb {
55518e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
55528e93258fSBjoern A. Zeeb 	u8 next_state, tol = chip->rssi_tol;
55538e93258fSBjoern A. Zeeb 
55548e93258fSBjoern A. Zeeb 	if (pre_state == BTC_RSSI_ST_LOW ||
55558e93258fSBjoern A. Zeeb 	    pre_state == BTC_RSSI_ST_STAY_LOW) {
55568e93258fSBjoern A. Zeeb 		if (rssi >= (thresh + tol))
55578e93258fSBjoern A. Zeeb 			next_state = BTC_RSSI_ST_HIGH;
55588e93258fSBjoern A. Zeeb 		else
55598e93258fSBjoern A. Zeeb 			next_state = BTC_RSSI_ST_STAY_LOW;
55608e93258fSBjoern A. Zeeb 	} else {
55618e93258fSBjoern A. Zeeb 		if (rssi < thresh)
55628e93258fSBjoern A. Zeeb 			next_state = BTC_RSSI_ST_LOW;
55638e93258fSBjoern A. Zeeb 		else
55648e93258fSBjoern A. Zeeb 			next_state = BTC_RSSI_ST_STAY_HIGH;
55658e93258fSBjoern A. Zeeb 	}
55668e93258fSBjoern A. Zeeb 
55678e93258fSBjoern A. Zeeb 	return next_state;
55688e93258fSBjoern A. Zeeb }
55698e93258fSBjoern A. Zeeb 
55708e93258fSBjoern A. Zeeb static
55718e93258fSBjoern A. Zeeb void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
55728e93258fSBjoern A. Zeeb {
55738e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
55748e93258fSBjoern A. Zeeb 
55758e93258fSBjoern A. Zeeb 	btc->cx.wl.dbcc_info.real_band[phy_idx] =
55768e93258fSBjoern A. Zeeb 		btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
55778e93258fSBjoern A. Zeeb 		btc->cx.wl.dbcc_info.scan_band[phy_idx] :
55788e93258fSBjoern A. Zeeb 		btc->cx.wl.dbcc_info.op_band[phy_idx];
55798e93258fSBjoern A. Zeeb }
55808e93258fSBjoern A. Zeeb 
55818e93258fSBjoern A. Zeeb static void _update_wl_info(struct rtw89_dev *rtwdev)
55828e93258fSBjoern A. Zeeb {
55838e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
55848e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
55858e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
55868e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
55878e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
55888e93258fSBjoern A. Zeeb 	u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
55898e93258fSBjoern A. Zeeb 	u8 cnt_2g = 0, cnt_5g = 0, phy;
55908e93258fSBjoern A. Zeeb 	u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
55918e93258fSBjoern A. Zeeb 	bool b2g = false, b5g = false, client_joined = false;
55928e93258fSBjoern A. Zeeb 
55938e93258fSBjoern A. Zeeb 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
55948e93258fSBjoern A. Zeeb 
55958e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_PORT_NUM; i++) {
55968e93258fSBjoern A. Zeeb 		/* check if role active? */
55978e93258fSBjoern A. Zeeb 		if (!wl_linfo[i].active)
55988e93258fSBjoern A. Zeeb 			continue;
55998e93258fSBjoern A. Zeeb 
56008e93258fSBjoern A. Zeeb 		cnt_active++;
56018e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
56028e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
56038e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
56048e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
56058e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
56068e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].connected = 0;
56078e93258fSBjoern A. Zeeb 
56088e93258fSBjoern A. Zeeb 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
56098e93258fSBjoern A. Zeeb 
56108e93258fSBjoern A. Zeeb 		phy = wl_linfo[i].phy;
56118e93258fSBjoern A. Zeeb 
56128e93258fSBjoern A. Zeeb 		/* check dbcc role */
56138e93258fSBjoern A. Zeeb 		if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
56148e93258fSBjoern A. Zeeb 			wl_dinfo->role[phy] = wl_linfo[i].role;
56158e93258fSBjoern A. Zeeb 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
56168e93258fSBjoern A. Zeeb 			_update_dbcc_band(rtwdev, phy);
56178e93258fSBjoern A. Zeeb 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
56188e93258fSBjoern A. Zeeb 		}
56198e93258fSBjoern A. Zeeb 
56208e93258fSBjoern A. Zeeb 		if (wl_linfo[i].connected == MLME_NO_LINK) {
56218e93258fSBjoern A. Zeeb 			continue;
56228e93258fSBjoern A. Zeeb 		} else if (wl_linfo[i].connected == MLME_LINKING) {
56238e93258fSBjoern A. Zeeb 			cnt_connecting++;
56248e93258fSBjoern A. Zeeb 		} else {
56258e93258fSBjoern A. Zeeb 			cnt_connect++;
56268e93258fSBjoern A. Zeeb 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
56278e93258fSBjoern A. Zeeb 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
56288e93258fSBjoern A. Zeeb 			     wl_linfo[i].client_cnt > 1)
56298e93258fSBjoern A. Zeeb 				client_joined = true;
56308e93258fSBjoern A. Zeeb 		}
56318e93258fSBjoern A. Zeeb 
56328e93258fSBjoern A. Zeeb 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
56338e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
56348e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
56358e93258fSBjoern A. Zeeb 		wl_rinfo->active_role[cnt_active - 1].connected = 1;
56368e93258fSBjoern A. Zeeb 
56378e93258fSBjoern A. Zeeb 		/* only care 2 roles + BT coex */
56388e93258fSBjoern A. Zeeb 		if (wl_linfo[i].band != RTW89_BAND_2G) {
56398e93258fSBjoern A. Zeeb 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
56408e93258fSBjoern A. Zeeb 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
56418e93258fSBjoern A. Zeeb 			cnt_5g++;
56428e93258fSBjoern A. Zeeb 			b5g = true;
56438e93258fSBjoern A. Zeeb 		} else {
56448e93258fSBjoern A. Zeeb 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
56458e93258fSBjoern A. Zeeb 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
56468e93258fSBjoern A. Zeeb 			cnt_2g++;
56478e93258fSBjoern A. Zeeb 			b2g = true;
56488e93258fSBjoern A. Zeeb 		}
56498e93258fSBjoern A. Zeeb 	}
56508e93258fSBjoern A. Zeeb 
56518e93258fSBjoern A. Zeeb 	wl_rinfo->connect_cnt = cnt_connect;
56528e93258fSBjoern A. Zeeb 
56538e93258fSBjoern A. Zeeb 	/* Be careful to change the following sequence!! */
56548e93258fSBjoern A. Zeeb 	if (cnt_connect == 0) {
56558e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
56568e93258fSBjoern A. Zeeb 		wl_rinfo->role_map.role.none = 1;
56578e93258fSBjoern A. Zeeb 	} else if (!b2g && b5g) {
56588e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_5G;
56598e93258fSBjoern A. Zeeb 	} else if (wl_rinfo->role_map.role.nan) {
56608e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
56618e93258fSBjoern A. Zeeb 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
56628e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
56638e93258fSBjoern A. Zeeb 	} else  if (b2g && b5g && cnt_connect == 2) {
56648e93258fSBjoern A. Zeeb 		if (rtwdev->dbcc_en) {
56658e93258fSBjoern A. Zeeb 			switch (wl_dinfo->role[RTW89_PHY_0]) {
56668e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_STATION:
56678e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
56688e93258fSBjoern A. Zeeb 				break;
56698e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_P2P_GO:
56708e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
56718e93258fSBjoern A. Zeeb 				break;
56728e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_P2P_CLIENT:
56738e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
56748e93258fSBjoern A. Zeeb 				break;
56758e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_AP:
56768e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
56778e93258fSBjoern A. Zeeb 				break;
56788e93258fSBjoern A. Zeeb 			default:
56798e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
56808e93258fSBjoern A. Zeeb 				break;
56818e93258fSBjoern A. Zeeb 			}
56828e93258fSBjoern A. Zeeb 		} else {
56838e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
56848e93258fSBjoern A. Zeeb 		}
56858e93258fSBjoern A. Zeeb 	} else if (!b5g && cnt_connect == 2) {
56868e93258fSBjoern A. Zeeb 		if (wl_rinfo->role_map.role.station &&
56878e93258fSBjoern A. Zeeb 		    (wl_rinfo->role_map.role.p2p_go ||
56888e93258fSBjoern A. Zeeb 		    wl_rinfo->role_map.role.p2p_gc ||
56898e93258fSBjoern A. Zeeb 		    wl_rinfo->role_map.role.ap)) {
56908e93258fSBjoern A. Zeeb 			if (wl_2g_ch[0] == wl_2g_ch[1])
56918e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
56928e93258fSBjoern A. Zeeb 			else
56938e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
56948e93258fSBjoern A. Zeeb 		} else {
56958e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
56968e93258fSBjoern A. Zeeb 		}
56978e93258fSBjoern A. Zeeb 	} else if (!b5g && cnt_connect == 1) {
56988e93258fSBjoern A. Zeeb 		if (wl_rinfo->role_map.role.station)
56998e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
57008e93258fSBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.ap)
57018e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
57028e93258fSBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.p2p_go)
57038e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
57048e93258fSBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.p2p_gc)
57058e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
57068e93258fSBjoern A. Zeeb 		else
57078e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
57088e93258fSBjoern A. Zeeb 	}
57098e93258fSBjoern A. Zeeb 
57108e93258fSBjoern A. Zeeb 	/* if no client_joined, don't care P2P-GO/AP role */
57118e93258fSBjoern A. Zeeb 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
57128e93258fSBjoern A. Zeeb 		if (!client_joined) {
57138e93258fSBjoern A. Zeeb 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
57148e93258fSBjoern A. Zeeb 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
57158e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
57168e93258fSBjoern A. Zeeb 				wl_rinfo->connect_cnt = 1;
57178e93258fSBjoern A. Zeeb 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
57188e93258fSBjoern A. Zeeb 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
57198e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
57208e93258fSBjoern A. Zeeb 				wl_rinfo->connect_cnt = 0;
57218e93258fSBjoern A. Zeeb 			}
57228e93258fSBjoern A. Zeeb 		}
57238e93258fSBjoern A. Zeeb 	}
57248e93258fSBjoern A. Zeeb 
57258e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
5726700acdc7SBjoern A. Zeeb 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
5727700acdc7SBjoern A. Zeeb 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
57288e93258fSBjoern A. Zeeb 
57298e93258fSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
57308e93258fSBjoern A. Zeeb }
57318e93258fSBjoern A. Zeeb 
57328e93258fSBjoern A. Zeeb static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
57338e93258fSBjoern A. Zeeb {
57348e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
57358e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
57368e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
57378e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
57388e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
57398e93258fSBjoern A. Zeeb 	u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
57408e93258fSBjoern A. Zeeb 	u8 cnt_2g = 0, cnt_5g = 0, phy;
57418e93258fSBjoern A. Zeeb 	u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
57428e93258fSBjoern A. Zeeb 	bool b2g = false, b5g = false, client_joined = false;
57438e93258fSBjoern A. Zeeb 	u8 i;
57448e93258fSBjoern A. Zeeb 
57458e93258fSBjoern A. Zeeb 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
57468e93258fSBjoern A. Zeeb 
57478e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_PORT_NUM; i++) {
57488e93258fSBjoern A. Zeeb 		if (!wl_linfo[i].active)
57498e93258fSBjoern A. Zeeb 			continue;
57508e93258fSBjoern A. Zeeb 
57518e93258fSBjoern A. Zeeb 		cnt_active++;
57528e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
57538e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
57548e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
57558e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
57568e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
57578e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
57588e93258fSBjoern A. Zeeb 
57598e93258fSBjoern A. Zeeb 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
57608e93258fSBjoern A. Zeeb 
57618e93258fSBjoern A. Zeeb 		phy = wl_linfo[i].phy;
57628e93258fSBjoern A. Zeeb 
57638e93258fSBjoern A. Zeeb 		if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
57648e93258fSBjoern A. Zeeb 			wl_dinfo->role[phy] = wl_linfo[i].role;
57658e93258fSBjoern A. Zeeb 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
57668e93258fSBjoern A. Zeeb 			_update_dbcc_band(rtwdev, phy);
57678e93258fSBjoern A. Zeeb 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
57688e93258fSBjoern A. Zeeb 		}
57698e93258fSBjoern A. Zeeb 
57708e93258fSBjoern A. Zeeb 		if (wl_linfo[i].connected == MLME_NO_LINK) {
57718e93258fSBjoern A. Zeeb 			continue;
57728e93258fSBjoern A. Zeeb 		} else if (wl_linfo[i].connected == MLME_LINKING) {
57738e93258fSBjoern A. Zeeb 			cnt_connecting++;
57748e93258fSBjoern A. Zeeb 		} else {
57758e93258fSBjoern A. Zeeb 			cnt_connect++;
57768e93258fSBjoern A. Zeeb 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
57778e93258fSBjoern A. Zeeb 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
57788e93258fSBjoern A. Zeeb 			     wl_linfo[i].client_cnt > 1)
57798e93258fSBjoern A. Zeeb 				client_joined = true;
57808e93258fSBjoern A. Zeeb 		}
57818e93258fSBjoern A. Zeeb 
57828e93258fSBjoern A. Zeeb 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
57838e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
57848e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
57858e93258fSBjoern A. Zeeb 		wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
57868e93258fSBjoern A. Zeeb 
57878e93258fSBjoern A. Zeeb 		/* only care 2 roles + BT coex */
57888e93258fSBjoern A. Zeeb 		if (wl_linfo[i].band != RTW89_BAND_2G) {
57898e93258fSBjoern A. Zeeb 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
57908e93258fSBjoern A. Zeeb 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
57918e93258fSBjoern A. Zeeb 			cnt_5g++;
57928e93258fSBjoern A. Zeeb 			b5g = true;
57938e93258fSBjoern A. Zeeb 		} else {
57948e93258fSBjoern A. Zeeb 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
57958e93258fSBjoern A. Zeeb 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
57968e93258fSBjoern A. Zeeb 			cnt_2g++;
57978e93258fSBjoern A. Zeeb 			b2g = true;
57988e93258fSBjoern A. Zeeb 		}
57998e93258fSBjoern A. Zeeb 	}
58008e93258fSBjoern A. Zeeb 
58018e93258fSBjoern A. Zeeb 	wl_rinfo->connect_cnt = cnt_connect;
58028e93258fSBjoern A. Zeeb 
58038e93258fSBjoern A. Zeeb 	/* Be careful to change the following sequence!! */
58048e93258fSBjoern A. Zeeb 	if (cnt_connect == 0) {
58058e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
58068e93258fSBjoern A. Zeeb 		wl_rinfo->role_map.role.none = 1;
58078e93258fSBjoern A. Zeeb 	} else if (!b2g && b5g) {
58088e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_5G;
58098e93258fSBjoern A. Zeeb 	} else if (wl_rinfo->role_map.role.nan) {
58108e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
58118e93258fSBjoern A. Zeeb 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
58128e93258fSBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
58138e93258fSBjoern A. Zeeb 	} else  if (b2g && b5g && cnt_connect == 2) {
58148e93258fSBjoern A. Zeeb 		if (rtwdev->dbcc_en) {
58158e93258fSBjoern A. Zeeb 			switch (wl_dinfo->role[RTW89_PHY_0]) {
58168e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_STATION:
58178e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
58188e93258fSBjoern A. Zeeb 				break;
58198e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_P2P_GO:
58208e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
58218e93258fSBjoern A. Zeeb 				break;
58228e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_P2P_CLIENT:
58238e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
58248e93258fSBjoern A. Zeeb 				break;
58258e93258fSBjoern A. Zeeb 			case RTW89_WIFI_ROLE_AP:
58268e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
58278e93258fSBjoern A. Zeeb 				break;
58288e93258fSBjoern A. Zeeb 			default:
58298e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
58308e93258fSBjoern A. Zeeb 				break;
58318e93258fSBjoern A. Zeeb 			}
58328e93258fSBjoern A. Zeeb 		} else {
58338e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
58348e93258fSBjoern A. Zeeb 		}
58358e93258fSBjoern A. Zeeb 	} else if (!b5g && cnt_connect == 2) {
58368e93258fSBjoern A. Zeeb 		if (wl_rinfo->role_map.role.station &&
58378e93258fSBjoern A. Zeeb 		    (wl_rinfo->role_map.role.p2p_go ||
58388e93258fSBjoern A. Zeeb 		    wl_rinfo->role_map.role.p2p_gc ||
58398e93258fSBjoern A. Zeeb 		    wl_rinfo->role_map.role.ap)) {
58408e93258fSBjoern A. Zeeb 			if (wl_2g_ch[0] == wl_2g_ch[1])
58418e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
58428e93258fSBjoern A. Zeeb 			else
58438e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
58448e93258fSBjoern A. Zeeb 		} else {
58458e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
58468e93258fSBjoern A. Zeeb 		}
58478e93258fSBjoern A. Zeeb 	} else if (!b5g && cnt_connect == 1) {
58488e93258fSBjoern A. Zeeb 		if (wl_rinfo->role_map.role.station)
58498e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
58508e93258fSBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.ap)
58518e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
58528e93258fSBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.p2p_go)
58538e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
58548e93258fSBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.p2p_gc)
58558e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
58568e93258fSBjoern A. Zeeb 		else
58578e93258fSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
58588e93258fSBjoern A. Zeeb 	}
58598e93258fSBjoern A. Zeeb 
58608e93258fSBjoern A. Zeeb 	/* if no client_joined, don't care P2P-GO/AP role */
58618e93258fSBjoern A. Zeeb 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
58628e93258fSBjoern A. Zeeb 		if (!client_joined) {
58638e93258fSBjoern A. Zeeb 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
58648e93258fSBjoern A. Zeeb 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
58658e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
58668e93258fSBjoern A. Zeeb 				wl_rinfo->connect_cnt = 1;
58678e93258fSBjoern A. Zeeb 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
58688e93258fSBjoern A. Zeeb 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
58698e93258fSBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
58708e93258fSBjoern A. Zeeb 				wl_rinfo->connect_cnt = 0;
58718e93258fSBjoern A. Zeeb 			}
58728e93258fSBjoern A. Zeeb 		}
58738e93258fSBjoern A. Zeeb 	}
58748e93258fSBjoern A. Zeeb 
58758e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
58768e93258fSBjoern A. Zeeb 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
58778e93258fSBjoern A. Zeeb 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
58788e93258fSBjoern A. Zeeb 
58798e93258fSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
58808e93258fSBjoern A. Zeeb }
58818e93258fSBjoern A. Zeeb 
5882e2340276SBjoern A. Zeeb static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
5883e2340276SBjoern A. Zeeb {
5884e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
5885e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5886e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
5887e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
5888e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5889e2340276SBjoern A. Zeeb 	u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
5890e2340276SBjoern A. Zeeb 	u8 cnt_2g = 0, cnt_5g = 0, phy;
5891e2340276SBjoern A. Zeeb 	u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
5892e2340276SBjoern A. Zeeb 	bool b2g = false, b5g = false, client_joined = false;
5893e2340276SBjoern A. Zeeb 	u8 i;
5894e2340276SBjoern A. Zeeb 
5895e2340276SBjoern A. Zeeb 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
5896e2340276SBjoern A. Zeeb 
5897e2340276SBjoern A. Zeeb 	for (i = 0; i < RTW89_PORT_NUM; i++) {
5898e2340276SBjoern A. Zeeb 		if (!wl_linfo[i].active)
5899e2340276SBjoern A. Zeeb 			continue;
5900e2340276SBjoern A. Zeeb 
5901e2340276SBjoern A. Zeeb 		cnt_active++;
5902e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role;
5903e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid;
5904e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy;
5905e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band;
5906e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
5907e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].connected = 0;
5908e2340276SBjoern A. Zeeb 
5909e2340276SBjoern A. Zeeb 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
5910e2340276SBjoern A. Zeeb 
5911e2340276SBjoern A. Zeeb 		phy = wl_linfo[i].phy;
5912e2340276SBjoern A. Zeeb 
5913e2340276SBjoern A. Zeeb 		if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
5914e2340276SBjoern A. Zeeb 			wl_dinfo->role[phy] = wl_linfo[i].role;
5915e2340276SBjoern A. Zeeb 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
5916e2340276SBjoern A. Zeeb 			_update_dbcc_band(rtwdev, phy);
5917e2340276SBjoern A. Zeeb 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
5918e2340276SBjoern A. Zeeb 		}
5919e2340276SBjoern A. Zeeb 
5920e2340276SBjoern A. Zeeb 		if (wl_linfo[i].connected == MLME_NO_LINK) {
5921e2340276SBjoern A. Zeeb 			continue;
5922e2340276SBjoern A. Zeeb 		} else if (wl_linfo[i].connected == MLME_LINKING) {
5923e2340276SBjoern A. Zeeb 			cnt_connecting++;
5924e2340276SBjoern A. Zeeb 		} else {
5925e2340276SBjoern A. Zeeb 			cnt_connect++;
5926e2340276SBjoern A. Zeeb 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
5927e2340276SBjoern A. Zeeb 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
5928e2340276SBjoern A. Zeeb 			     wl_linfo[i].client_cnt > 1)
5929e2340276SBjoern A. Zeeb 				client_joined = true;
5930e2340276SBjoern A. Zeeb 		}
5931e2340276SBjoern A. Zeeb 
5932e2340276SBjoern A. Zeeb 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
5933e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch;
5934e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw;
5935e2340276SBjoern A. Zeeb 		wl_rinfo->active_role_v2[cnt_active - 1].connected = 1;
5936e2340276SBjoern A. Zeeb 
5937e2340276SBjoern A. Zeeb 		/* only care 2 roles + BT coex */
5938e2340276SBjoern A. Zeeb 		if (wl_linfo[i].band != RTW89_BAND_2G) {
5939e2340276SBjoern A. Zeeb 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
5940e2340276SBjoern A. Zeeb 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
5941e2340276SBjoern A. Zeeb 			cnt_5g++;
5942e2340276SBjoern A. Zeeb 			b5g = true;
5943e2340276SBjoern A. Zeeb 		} else {
5944e2340276SBjoern A. Zeeb 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
5945e2340276SBjoern A. Zeeb 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
5946e2340276SBjoern A. Zeeb 			cnt_2g++;
5947e2340276SBjoern A. Zeeb 			b2g = true;
5948e2340276SBjoern A. Zeeb 		}
5949e2340276SBjoern A. Zeeb 	}
5950e2340276SBjoern A. Zeeb 
5951e2340276SBjoern A. Zeeb 	wl_rinfo->connect_cnt = cnt_connect;
5952e2340276SBjoern A. Zeeb 
5953e2340276SBjoern A. Zeeb 	/* Be careful to change the following sequence!! */
5954e2340276SBjoern A. Zeeb 	if (cnt_connect == 0) {
5955e2340276SBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5956e2340276SBjoern A. Zeeb 		wl_rinfo->role_map.role.none = 1;
5957e2340276SBjoern A. Zeeb 	} else if (!b2g && b5g) {
5958e2340276SBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_5G;
5959e2340276SBjoern A. Zeeb 	} else if (wl_rinfo->role_map.role.nan) {
5960e2340276SBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
5961e2340276SBjoern A. Zeeb 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
5962e2340276SBjoern A. Zeeb 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
5963e2340276SBjoern A. Zeeb 	} else  if (b2g && b5g && cnt_connect == 2) {
5964e2340276SBjoern A. Zeeb 		if (rtwdev->dbcc_en) {
5965e2340276SBjoern A. Zeeb 			switch (wl_dinfo->role[RTW89_PHY_0]) {
5966e2340276SBjoern A. Zeeb 			case RTW89_WIFI_ROLE_STATION:
5967e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5968e2340276SBjoern A. Zeeb 				break;
5969e2340276SBjoern A. Zeeb 			case RTW89_WIFI_ROLE_P2P_GO:
5970e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5971e2340276SBjoern A. Zeeb 				break;
5972e2340276SBjoern A. Zeeb 			case RTW89_WIFI_ROLE_P2P_CLIENT:
5973e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5974e2340276SBjoern A. Zeeb 				break;
5975e2340276SBjoern A. Zeeb 			case RTW89_WIFI_ROLE_AP:
5976e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5977e2340276SBjoern A. Zeeb 				break;
5978e2340276SBjoern A. Zeeb 			default:
5979e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
5980e2340276SBjoern A. Zeeb 				break;
5981e2340276SBjoern A. Zeeb 			}
5982e2340276SBjoern A. Zeeb 		} else {
5983e2340276SBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
5984e2340276SBjoern A. Zeeb 		}
5985e2340276SBjoern A. Zeeb 	} else if (!b5g && cnt_connect == 2) {
5986e2340276SBjoern A. Zeeb 		if (wl_rinfo->role_map.role.station &&
5987e2340276SBjoern A. Zeeb 		    (wl_rinfo->role_map.role.p2p_go ||
5988e2340276SBjoern A. Zeeb 		    wl_rinfo->role_map.role.p2p_gc ||
5989e2340276SBjoern A. Zeeb 		    wl_rinfo->role_map.role.ap)) {
5990e2340276SBjoern A. Zeeb 			if (wl_2g_ch[0] == wl_2g_ch[1])
5991e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
5992e2340276SBjoern A. Zeeb 			else
5993e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5994e2340276SBjoern A. Zeeb 		} else {
5995e2340276SBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5996e2340276SBjoern A. Zeeb 		}
5997e2340276SBjoern A. Zeeb 	} else if (!b5g && cnt_connect == 1) {
5998e2340276SBjoern A. Zeeb 		if (wl_rinfo->role_map.role.station)
5999e2340276SBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6000e2340276SBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.ap)
6001e2340276SBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6002e2340276SBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.p2p_go)
6003e2340276SBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6004e2340276SBjoern A. Zeeb 		else if (wl_rinfo->role_map.role.p2p_gc)
6005e2340276SBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6006e2340276SBjoern A. Zeeb 		else
6007e2340276SBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
6008e2340276SBjoern A. Zeeb 	}
6009e2340276SBjoern A. Zeeb 
6010e2340276SBjoern A. Zeeb 	/* if no client_joined, don't care P2P-GO/AP role */
6011e2340276SBjoern A. Zeeb 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6012e2340276SBjoern A. Zeeb 		if (!client_joined) {
6013e2340276SBjoern A. Zeeb 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6014e2340276SBjoern A. Zeeb 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6015e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6016e2340276SBjoern A. Zeeb 				wl_rinfo->connect_cnt = 1;
6017e2340276SBjoern A. Zeeb 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6018e2340276SBjoern A. Zeeb 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6019e2340276SBjoern A. Zeeb 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6020e2340276SBjoern A. Zeeb 				wl_rinfo->connect_cnt = 0;
6021e2340276SBjoern A. Zeeb 			}
6022e2340276SBjoern A. Zeeb 		}
6023e2340276SBjoern A. Zeeb 	}
6024e2340276SBjoern A. Zeeb 
6025e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6026e2340276SBjoern A. Zeeb 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6027e2340276SBjoern A. Zeeb 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6028e2340276SBjoern A. Zeeb 
6029e2340276SBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6030e2340276SBjoern A. Zeeb }
6031e2340276SBjoern A. Zeeb 
60328e93258fSBjoern A. Zeeb #define BTC_CHK_HANG_MAX 3
60338e93258fSBjoern A. Zeeb #define BTC_SCB_INV_VALUE GENMASK(31, 0)
60348e93258fSBjoern A. Zeeb 
6035*6d67aabdSBjoern A. Zeeb static u8 _get_role_link_mode(u8 role)
6036*6d67aabdSBjoern A. Zeeb {
6037*6d67aabdSBjoern A. Zeeb 	switch (role) {
6038*6d67aabdSBjoern A. Zeeb 	case RTW89_WIFI_ROLE_STATION:
6039*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_2G_STA;
6040*6d67aabdSBjoern A. Zeeb 	case RTW89_WIFI_ROLE_P2P_GO:
6041*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_2G_GO;
6042*6d67aabdSBjoern A. Zeeb 	case RTW89_WIFI_ROLE_P2P_CLIENT:
6043*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_2G_GC;
6044*6d67aabdSBjoern A. Zeeb 	case RTW89_WIFI_ROLE_AP:
6045*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_2G_AP;
6046*6d67aabdSBjoern A. Zeeb 	default:
6047*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_OTHER;
6048*6d67aabdSBjoern A. Zeeb 	}
6049*6d67aabdSBjoern A. Zeeb }
6050*6d67aabdSBjoern A. Zeeb 
6051*6d67aabdSBjoern A. Zeeb static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
6052*6d67aabdSBjoern A. Zeeb 			       const struct rtw89_btc_chdef *r2)
6053*6d67aabdSBjoern A. Zeeb {
6054*6d67aabdSBjoern A. Zeeb 	if (r1->chan != r2->chan) { /* primary ch is different */
6055*6d67aabdSBjoern A. Zeeb 		return false;
6056*6d67aabdSBjoern A. Zeeb 	} else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
6057*6d67aabdSBjoern A. Zeeb 		   r2->bw == RTW89_CHANNEL_WIDTH_40) {
6058*6d67aabdSBjoern A. Zeeb 		if (r1->offset != r2->offset)
6059*6d67aabdSBjoern A. Zeeb 			return false;
6060*6d67aabdSBjoern A. Zeeb 	}
6061*6d67aabdSBjoern A. Zeeb 	return true;
6062*6d67aabdSBjoern A. Zeeb }
6063*6d67aabdSBjoern A. Zeeb 
6064*6d67aabdSBjoern A. Zeeb static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
6065*6d67aabdSBjoern A. Zeeb 		    u8 *phy, u8 *role, u8 *dbcc_2g_phy)
6066*6d67aabdSBjoern A. Zeeb {
6067*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6068*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6069*6d67aabdSBjoern A. Zeeb 	bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
6070*6d67aabdSBjoern A. Zeeb 	u8 j, k, dbcc_2g_cid, dbcc_2g_cid2;
6071*6d67aabdSBjoern A. Zeeb 
6072*6d67aabdSBjoern A. Zeeb 	/* find out the 2G-PHY by connect-id ->ch  */
6073*6d67aabdSBjoern A. Zeeb 	for (j = 0; j < wl_rinfo->connect_cnt; j++) {
6074*6d67aabdSBjoern A. Zeeb 		if (ch[j].center_ch <= 14) {
6075*6d67aabdSBjoern A. Zeeb 			is_2g_ch_exist = true;
6076*6d67aabdSBjoern A. Zeeb 			break;
6077*6d67aabdSBjoern A. Zeeb 		}
6078*6d67aabdSBjoern A. Zeeb 	}
6079*6d67aabdSBjoern A. Zeeb 
6080*6d67aabdSBjoern A. Zeeb 	/* If no any 2G-port exist, it's impossible because 5G-exclude */
6081*6d67aabdSBjoern A. Zeeb 	if (!is_2g_ch_exist)
6082*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_OTHER;
6083*6d67aabdSBjoern A. Zeeb 
6084*6d67aabdSBjoern A. Zeeb 	dbcc_2g_cid = j;
6085*6d67aabdSBjoern A. Zeeb 	*dbcc_2g_phy = phy[dbcc_2g_cid];
6086*6d67aabdSBjoern A. Zeeb 
6087*6d67aabdSBjoern A. Zeeb 	/* connect_cnt <= 2 */
6088*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo->connect_cnt < BTC_TDMA_WLROLE_MAX)
6089*6d67aabdSBjoern A. Zeeb 		return (_get_role_link_mode((role[dbcc_2g_cid])));
6090*6d67aabdSBjoern A. Zeeb 
6091*6d67aabdSBjoern A. Zeeb 	/* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
6092*6d67aabdSBjoern A. Zeeb 	for (k = 0; k < wl_rinfo->connect_cnt; k++) {
6093*6d67aabdSBjoern A. Zeeb 		if (k == dbcc_2g_cid)
6094*6d67aabdSBjoern A. Zeeb 			continue;
6095*6d67aabdSBjoern A. Zeeb 
6096*6d67aabdSBjoern A. Zeeb 		if (phy[k] == *dbcc_2g_phy) {
6097*6d67aabdSBjoern A. Zeeb 			is_multi_role_in_2g_phy = true;
6098*6d67aabdSBjoern A. Zeeb 			dbcc_2g_cid2 = k;
6099*6d67aabdSBjoern A. Zeeb 			break;
6100*6d67aabdSBjoern A. Zeeb 		}
6101*6d67aabdSBjoern A. Zeeb 	}
6102*6d67aabdSBjoern A. Zeeb 
6103*6d67aabdSBjoern A. Zeeb 	/* Single-role in 2G-PHY */
6104*6d67aabdSBjoern A. Zeeb 	if (!is_multi_role_in_2g_phy)
6105*6d67aabdSBjoern A. Zeeb 		return (_get_role_link_mode(role[dbcc_2g_cid]));
6106*6d67aabdSBjoern A. Zeeb 
6107*6d67aabdSBjoern A. Zeeb 	/* 2-role in 2G-PHY */
6108*6d67aabdSBjoern A. Zeeb 	if (ch[dbcc_2g_cid2].center_ch > 14)
6109*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_25G_MCC;
6110*6d67aabdSBjoern A. Zeeb 	else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
6111*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_2G_SCC;
6112*6d67aabdSBjoern A. Zeeb 	else
6113*6d67aabdSBjoern A. Zeeb 		return BTC_WLINK_2G_MCC;
6114*6d67aabdSBjoern A. Zeeb }
6115*6d67aabdSBjoern A. Zeeb 
6116*6d67aabdSBjoern A. Zeeb static void _update_role_link_mode(struct rtw89_dev *rtwdev,
6117*6d67aabdSBjoern A. Zeeb 				   bool client_joined, u32 noa)
6118*6d67aabdSBjoern A. Zeeb {
6119*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &rtwdev->btc.cx.wl.role_info_v8;
6120*6d67aabdSBjoern A. Zeeb 	u32 type = BTC_WLMROLE_NONE, dur = 0;
6121*6d67aabdSBjoern A. Zeeb 	u32 wl_role = wl_rinfo->role_map;
6122*6d67aabdSBjoern A. Zeeb 
6123*6d67aabdSBjoern A. Zeeb 	/* if no client_joined, don't care P2P-GO/AP role */
6124*6d67aabdSBjoern A. Zeeb 	if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6125*6d67aabdSBjoern A. Zeeb 	     (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
6126*6d67aabdSBjoern A. Zeeb 		if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC) {
6127*6d67aabdSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6128*6d67aabdSBjoern A. Zeeb 			wl_rinfo->connect_cnt--;
6129*6d67aabdSBjoern A. Zeeb 		} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6130*6d67aabdSBjoern A. Zeeb 			wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6131*6d67aabdSBjoern A. Zeeb 			wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6132*6d67aabdSBjoern A. Zeeb 			wl_rinfo->connect_cnt--;
6133*6d67aabdSBjoern A. Zeeb 		}
6134*6d67aabdSBjoern A. Zeeb 	}
6135*6d67aabdSBjoern A. Zeeb 
6136*6d67aabdSBjoern A. Zeeb 	/* Identify 2-Role type  */
6137*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo->connect_cnt >= 2 &&
6138*6d67aabdSBjoern A. Zeeb 	    (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6139*6d67aabdSBjoern A. Zeeb 	     wl_rinfo->link_mode == BTC_WLINK_2G_MCC ||
6140*6d67aabdSBjoern A. Zeeb 	     wl_rinfo->link_mode == BTC_WLINK_25G_MCC ||
6141*6d67aabdSBjoern A. Zeeb 	     wl_rinfo->link_mode == BTC_WLINK_5G)) {
6142*6d67aabdSBjoern A. Zeeb 		if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6143*6d67aabdSBjoern A. Zeeb 		    (wl_role & BIT(RTW89_WIFI_ROLE_AP)))
6144*6d67aabdSBjoern A. Zeeb 			type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
6145*6d67aabdSBjoern A. Zeeb 		else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
6146*6d67aabdSBjoern A. Zeeb 			type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
6147*6d67aabdSBjoern A. Zeeb 		else
6148*6d67aabdSBjoern A. Zeeb 			type = BTC_WLMROLE_STA_STA;
6149*6d67aabdSBjoern A. Zeeb 
6150*6d67aabdSBjoern A. Zeeb 		dur = noa;
6151*6d67aabdSBjoern A. Zeeb 	}
6152*6d67aabdSBjoern A. Zeeb 
6153*6d67aabdSBjoern A. Zeeb 	wl_rinfo->mrole_type = type;
6154*6d67aabdSBjoern A. Zeeb 	wl_rinfo->mrole_noa_duration = dur;
6155*6d67aabdSBjoern A. Zeeb }
6156*6d67aabdSBjoern A. Zeeb 
6157*6d67aabdSBjoern A. Zeeb static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
6158*6d67aabdSBjoern A. Zeeb 			       enum btc_role_state state)
6159*6d67aabdSBjoern A. Zeeb {
6160*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
6161*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6162*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6163*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6164*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6165*6d67aabdSBjoern A. Zeeb 	bool client_joined = false, b2g = false, b5g = false;
6166*6d67aabdSBjoern A. Zeeb 	u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6167*6d67aabdSBjoern A. Zeeb 	u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6168*6d67aabdSBjoern A. Zeeb 	u8 dbcc_en = 0, pta_req_band = RTW89_MAC_0;
6169*6d67aabdSBjoern A. Zeeb 	u8 i, j, cnt = 0, cnt_2g = 0, cnt_5g = 0;
6170*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *wl_linfo;
6171*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_rlink *rlink = NULL;
6172*6d67aabdSBjoern A. Zeeb 	u8 dbcc_2g_phy = RTW89_PHY_0;
6173*6d67aabdSBjoern A. Zeeb 	u8 mode = BTC_WLINK_NOLINK;
6174*6d67aabdSBjoern A. Zeeb 	u32 noa_dur = 0;
6175*6d67aabdSBjoern A. Zeeb 
6176*6d67aabdSBjoern A. Zeeb 	if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id > RTW89_MAC_1)
6177*6d67aabdSBjoern A. Zeeb 		return;
6178*6d67aabdSBjoern A. Zeeb 
6179*6d67aabdSBjoern A. Zeeb 	/* Extract wl->link_info[role_id][rlink_id] to wl->role_info
6180*6d67aabdSBjoern A. Zeeb 	 * role_id: role index
6181*6d67aabdSBjoern A. Zeeb 	 * rlink_id: rlink index (= HW-band index)
6182*6d67aabdSBjoern A. Zeeb 	 * pid: port_index
6183*6d67aabdSBjoern A. Zeeb 	 */
6184*6d67aabdSBjoern A. Zeeb 
6185*6d67aabdSBjoern A. Zeeb 	wl_linfo = &wl->rlink_info[role_id][rlink_id];
6186*6d67aabdSBjoern A. Zeeb 	if (wl_linfo->connected == MLME_LINKING)
6187*6d67aabdSBjoern A. Zeeb 		return;
6188*6d67aabdSBjoern A. Zeeb 
6189*6d67aabdSBjoern A. Zeeb 	rlink = &wl_rinfo->rlink[role_id][rlink_id];
6190*6d67aabdSBjoern A. Zeeb 	rlink->role = wl_linfo->role;
6191*6d67aabdSBjoern A. Zeeb 	rlink->active = wl_linfo->active; /* Doze or not */
6192*6d67aabdSBjoern A. Zeeb 	rlink->pid = wl_linfo->pid;
6193*6d67aabdSBjoern A. Zeeb 	rlink->phy = wl_linfo->phy;
6194*6d67aabdSBjoern A. Zeeb 	rlink->rf_band = wl_linfo->band;
6195*6d67aabdSBjoern A. Zeeb 	rlink->ch = wl_linfo->ch;
6196*6d67aabdSBjoern A. Zeeb 	rlink->bw = wl_linfo->bw;
6197*6d67aabdSBjoern A. Zeeb 	rlink->noa = wl_linfo->noa;
6198*6d67aabdSBjoern A. Zeeb 	rlink->noa_dur = wl_linfo->noa_duration / 1000;
6199*6d67aabdSBjoern A. Zeeb 	rlink->client_cnt = wl_linfo->client_cnt;
6200*6d67aabdSBjoern A. Zeeb 	rlink->mode = wl_linfo->mode;
6201*6d67aabdSBjoern A. Zeeb 
6202*6d67aabdSBjoern A. Zeeb 	switch (wl_linfo->connected) {
6203*6d67aabdSBjoern A. Zeeb 	case MLME_NO_LINK:
6204*6d67aabdSBjoern A. Zeeb 		rlink->connected = 0;
6205*6d67aabdSBjoern A. Zeeb 		if (rlink->role == RTW89_WIFI_ROLE_STATION)
6206*6d67aabdSBjoern A. Zeeb 			btc->dm.leak_ap = 0;
6207*6d67aabdSBjoern A. Zeeb 		break;
6208*6d67aabdSBjoern A. Zeeb 	case MLME_LINKED:
6209*6d67aabdSBjoern A. Zeeb 		rlink->connected = 1;
6210*6d67aabdSBjoern A. Zeeb 		break;
6211*6d67aabdSBjoern A. Zeeb 	default:
6212*6d67aabdSBjoern A. Zeeb 		return;
6213*6d67aabdSBjoern A. Zeeb 	}
6214*6d67aabdSBjoern A. Zeeb 
6215*6d67aabdSBjoern A. Zeeb 	wl->is_5g_hi_channel = false;
6216*6d67aabdSBjoern A. Zeeb 	wl->bg_mode = false;
6217*6d67aabdSBjoern A. Zeeb 	wl_rinfo->role_map = 0;
6218*6d67aabdSBjoern A. Zeeb 	wl_rinfo->p2p_2g = 0;
6219*6d67aabdSBjoern A. Zeeb 	memset(cid_ch, 0, sizeof(cid_ch));
6220*6d67aabdSBjoern A. Zeeb 
6221*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
6222*6d67aabdSBjoern A. Zeeb 		for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
6223*6d67aabdSBjoern A. Zeeb 			rlink = &wl_rinfo->rlink[i][j];
6224*6d67aabdSBjoern A. Zeeb 
6225*6d67aabdSBjoern A. Zeeb 			if (!rlink->active || !rlink->connected)
6226*6d67aabdSBjoern A. Zeeb 				continue;
6227*6d67aabdSBjoern A. Zeeb 
6228*6d67aabdSBjoern A. Zeeb 			cnt++;
6229*6d67aabdSBjoern A. Zeeb 			wl_rinfo->role_map |= BIT(rlink->role);
6230*6d67aabdSBjoern A. Zeeb 
6231*6d67aabdSBjoern A. Zeeb 			/* only if client connect for p2p-Go/AP */
6232*6d67aabdSBjoern A. Zeeb 			if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
6233*6d67aabdSBjoern A. Zeeb 			     rlink->role == RTW89_WIFI_ROLE_AP) &&
6234*6d67aabdSBjoern A. Zeeb 			     rlink->client_cnt > 1)
6235*6d67aabdSBjoern A. Zeeb 				client_joined = true;
6236*6d67aabdSBjoern A. Zeeb 
6237*6d67aabdSBjoern A. Zeeb 			/* Identufy if P2P-Go (GO/GC/AP) exist at 2G band*/
6238*6d67aabdSBjoern A. Zeeb 			if (rlink->rf_band == RTW89_BAND_2G &&
6239*6d67aabdSBjoern A. Zeeb 			    (client_joined || rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT))
6240*6d67aabdSBjoern A. Zeeb 				wl_rinfo->p2p_2g = 1;
6241*6d67aabdSBjoern A. Zeeb 
6242*6d67aabdSBjoern A. Zeeb 			/* only one noa-role exist */
6243*6d67aabdSBjoern A. Zeeb 			if (rlink->noa && rlink->noa_dur > 0)
6244*6d67aabdSBjoern A. Zeeb 				noa_dur = rlink->noa_dur;
6245*6d67aabdSBjoern A. Zeeb 
6246*6d67aabdSBjoern A. Zeeb 			/* for WL 5G-Rx interfered with BT issue */
6247*6d67aabdSBjoern A. Zeeb 			if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100)
6248*6d67aabdSBjoern A. Zeeb 				wl->is_5g_hi_channel = 1;
6249*6d67aabdSBjoern A. Zeeb 
6250*6d67aabdSBjoern A. Zeeb 			if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
6251*6d67aabdSBjoern A. Zeeb 			    (rlink->mode & BIT(BTC_WL_MODE_11G)))
6252*6d67aabdSBjoern A. Zeeb 				wl->bg_mode = 1;
6253*6d67aabdSBjoern A. Zeeb 
6254*6d67aabdSBjoern A. Zeeb 			if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT)
6255*6d67aabdSBjoern A. Zeeb 				continue;
6256*6d67aabdSBjoern A. Zeeb 
6257*6d67aabdSBjoern A. Zeeb 			cid_ch[cnt - 1] = wl_linfo->chdef;
6258*6d67aabdSBjoern A. Zeeb 			cid_phy[cnt - 1] = rlink->phy;
6259*6d67aabdSBjoern A. Zeeb 			cid_role[cnt - 1] = rlink->role;
6260*6d67aabdSBjoern A. Zeeb 
6261*6d67aabdSBjoern A. Zeeb 			if (rlink->rf_band != RTW89_BAND_2G) {
6262*6d67aabdSBjoern A. Zeeb 				cnt_5g++;
6263*6d67aabdSBjoern A. Zeeb 				b5g = true;
6264*6d67aabdSBjoern A. Zeeb 			} else {
6265*6d67aabdSBjoern A. Zeeb 				cnt_2g++;
6266*6d67aabdSBjoern A. Zeeb 				b2g = true;
6267*6d67aabdSBjoern A. Zeeb 			}
6268*6d67aabdSBjoern A. Zeeb 		}
6269*6d67aabdSBjoern A. Zeeb 	}
6270*6d67aabdSBjoern A. Zeeb 
6271*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
6272*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6273*6d67aabdSBjoern A. Zeeb 			    "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6274*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "not support MLO feature yet");
6275*6d67aabdSBjoern A. Zeeb 	} else {
6276*6d67aabdSBjoern A. Zeeb 		dbcc_en = rtwdev->dbcc_en;
6277*6d67aabdSBjoern A. Zeeb 
6278*6d67aabdSBjoern A. Zeeb 		/* Be careful to change the following sequence!! */
6279*6d67aabdSBjoern A. Zeeb 		if (cnt == 0) {
6280*6d67aabdSBjoern A. Zeeb 			mode = BTC_WLINK_NOLINK;
6281*6d67aabdSBjoern A. Zeeb 		} else if (!b2g && b5g) {
6282*6d67aabdSBjoern A. Zeeb 			mode = BTC_WLINK_5G;
6283*6d67aabdSBjoern A. Zeeb 		} else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6284*6d67aabdSBjoern A. Zeeb 			mode = BTC_WLINK_2G_NAN;
6285*6d67aabdSBjoern A. Zeeb 		} else if (cnt > BTC_TDMA_WLROLE_MAX) {
6286*6d67aabdSBjoern A. Zeeb 			mode = BTC_WLINK_OTHER;
6287*6d67aabdSBjoern A. Zeeb 		} else if (dbcc_en) {
6288*6d67aabdSBjoern A. Zeeb 			mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role,
6289*6d67aabdSBjoern A. Zeeb 					 &dbcc_2g_phy);
6290*6d67aabdSBjoern A. Zeeb 		} else if (b2g && b5g && cnt == 2) {
6291*6d67aabdSBjoern A. Zeeb 			mode = BTC_WLINK_25G_MCC;
6292*6d67aabdSBjoern A. Zeeb 		} else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6293*6d67aabdSBjoern A. Zeeb 			if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6294*6d67aabdSBjoern A. Zeeb 				mode = BTC_WLINK_2G_SCC;
6295*6d67aabdSBjoern A. Zeeb 			else
6296*6d67aabdSBjoern A. Zeeb 				mode = BTC_WLINK_2G_MCC;
6297*6d67aabdSBjoern A. Zeeb 		} else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6298*6d67aabdSBjoern A. Zeeb 			mode = _get_role_link_mode(cid_role[0]);
6299*6d67aabdSBjoern A. Zeeb 		}
6300*6d67aabdSBjoern A. Zeeb 	}
6301*6d67aabdSBjoern A. Zeeb 
6302*6d67aabdSBjoern A. Zeeb 	wl_rinfo->link_mode = mode;
6303*6d67aabdSBjoern A. Zeeb 	wl_rinfo->connect_cnt = cnt;
6304*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo->connect_cnt == 0)
6305*6d67aabdSBjoern A. Zeeb 		wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6306*6d67aabdSBjoern A. Zeeb 	_update_role_link_mode(rtwdev, client_joined, noa_dur);
6307*6d67aabdSBjoern A. Zeeb 
6308*6d67aabdSBjoern A. Zeeb 	wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6309*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo->dbcc_en != dbcc_en) {
6310*6d67aabdSBjoern A. Zeeb 		wl_rinfo->dbcc_en = dbcc_en;
6311*6d67aabdSBjoern A. Zeeb 		wl_rinfo->dbcc_chg = 1;
6312*6d67aabdSBjoern A. Zeeb 		btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6313*6d67aabdSBjoern A. Zeeb 	} else {
6314*6d67aabdSBjoern A. Zeeb 		wl_rinfo->dbcc_chg = 0;
6315*6d67aabdSBjoern A. Zeeb 	}
6316*6d67aabdSBjoern A. Zeeb 
6317*6d67aabdSBjoern A. Zeeb 	if (wl_rinfo->dbcc_en) {
6318*6d67aabdSBjoern A. Zeeb 		memset(wl_dinfo, 0, sizeof(struct rtw89_btc_wl_dbcc_info));
6319*6d67aabdSBjoern A. Zeeb 
6320*6d67aabdSBjoern A. Zeeb 		if (mode == BTC_WLINK_5G) {
6321*6d67aabdSBjoern A. Zeeb 			pta_req_band = RTW89_PHY_0;
6322*6d67aabdSBjoern A. Zeeb 			wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
6323*6d67aabdSBjoern A. Zeeb 			wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
6324*6d67aabdSBjoern A. Zeeb 		} else if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_1) {
6325*6d67aabdSBjoern A. Zeeb 			pta_req_band = RTW89_PHY_1;
6326*6d67aabdSBjoern A. Zeeb 			wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
6327*6d67aabdSBjoern A. Zeeb 			wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
6328*6d67aabdSBjoern A. Zeeb 		} else {
6329*6d67aabdSBjoern A. Zeeb 			pta_req_band = RTW89_PHY_0;
6330*6d67aabdSBjoern A. Zeeb 			wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_2G;
6331*6d67aabdSBjoern A. Zeeb 			wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_5G;
6332*6d67aabdSBjoern A. Zeeb 		}
6333*6d67aabdSBjoern A. Zeeb 		_update_dbcc_band(rtwdev, RTW89_PHY_0);
6334*6d67aabdSBjoern A. Zeeb 		_update_dbcc_band(rtwdev, RTW89_PHY_1);
6335*6d67aabdSBjoern A. Zeeb 	}
6336*6d67aabdSBjoern A. Zeeb 
6337*6d67aabdSBjoern A. Zeeb 	wl_rinfo->pta_req_band = pta_req_band;
6338*6d67aabdSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6339*6d67aabdSBjoern A. Zeeb }
6340*6d67aabdSBjoern A. Zeeb 
63418e93258fSBjoern A. Zeeb void rtw89_coex_act1_work(struct work_struct *work)
63428e93258fSBjoern A. Zeeb {
63438e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
63448e93258fSBjoern A. Zeeb 						coex_act1_work.work);
63458e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
63468e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
63478e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
63488e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
63498e93258fSBjoern A. Zeeb 
63508e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
63518e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
63528e93258fSBjoern A. Zeeb 	dm->cnt_notify[BTC_NCNT_TIMER]++;
63538e93258fSBjoern A. Zeeb 	if (wl->status.map._4way)
63548e93258fSBjoern A. Zeeb 		wl->status.map._4way = false;
63558e93258fSBjoern A. Zeeb 	if (wl->status.map.connecting)
63568e93258fSBjoern A. Zeeb 		wl->status.map.connecting = false;
63578e93258fSBjoern A. Zeeb 
63588e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_ACT1_WORK);
63598e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
63608e93258fSBjoern A. Zeeb }
63618e93258fSBjoern A. Zeeb 
63628e93258fSBjoern A. Zeeb void rtw89_coex_bt_devinfo_work(struct work_struct *work)
63638e93258fSBjoern A. Zeeb {
63648e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
63658e93258fSBjoern A. Zeeb 						coex_bt_devinfo_work.work);
63668e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
63678e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
63688e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
63698e93258fSBjoern A. Zeeb 
63708e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
63718e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
63728e93258fSBjoern A. Zeeb 	dm->cnt_notify[BTC_NCNT_TIMER]++;
63738e93258fSBjoern A. Zeeb 	a2dp->play_latency = 0;
63748e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
63758e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
63768e93258fSBjoern A. Zeeb }
63778e93258fSBjoern A. Zeeb 
63788e93258fSBjoern A. Zeeb void rtw89_coex_rfk_chk_work(struct work_struct *work)
63798e93258fSBjoern A. Zeeb {
63808e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
63818e93258fSBjoern A. Zeeb 						coex_rfk_chk_work.work);
63828e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
63838e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
63848e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
63858e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
63868e93258fSBjoern A. Zeeb 
63878e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
63888e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
63898e93258fSBjoern A. Zeeb 	dm->cnt_notify[BTC_NCNT_TIMER]++;
63908e93258fSBjoern A. Zeeb 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
63918e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
63928e93258fSBjoern A. Zeeb 			    "[BTC], %s(): RFK timeout\n", __func__);
63938e93258fSBjoern A. Zeeb 		cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
63948e93258fSBjoern A. Zeeb 		dm->error.map.wl_rfk_timeout = true;
63958e93258fSBjoern A. Zeeb 		wl->rfk_info.state = BTC_WRFK_STOP;
63968e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
63978e93258fSBjoern A. Zeeb 		_run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
63988e93258fSBjoern A. Zeeb 	}
63998e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
64008e93258fSBjoern A. Zeeb }
64018e93258fSBjoern A. Zeeb 
64028e93258fSBjoern A. Zeeb static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
64038e93258fSBjoern A. Zeeb {
64048e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
64058e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
64068e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
64078e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
64088e93258fSBjoern A. Zeeb 	u32 val;
64098e93258fSBjoern A. Zeeb 	bool status_change = false;
64108e93258fSBjoern A. Zeeb 
64118e93258fSBjoern A. Zeeb 	if (!chip->scbd)
64128e93258fSBjoern A. Zeeb 		return;
64138e93258fSBjoern A. Zeeb 
64148e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
64158e93258fSBjoern A. Zeeb 
64168e93258fSBjoern A. Zeeb 	val = _read_scbd(rtwdev);
64178e93258fSBjoern A. Zeeb 	if (val == BTC_SCB_INV_VALUE) {
64188e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
64198e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return by invalid scbd value\n",
64208e93258fSBjoern A. Zeeb 			    __func__);
64218e93258fSBjoern A. Zeeb 		return;
64228e93258fSBjoern A. Zeeb 	}
64238e93258fSBjoern A. Zeeb 
6424*6d67aabdSBjoern A. Zeeb 	if (!(val & BTC_BSCB_ON))
64258e93258fSBjoern A. Zeeb 		bt->enable.now = 0;
64268e93258fSBjoern A. Zeeb 	else
64278e93258fSBjoern A. Zeeb 		bt->enable.now = 1;
64288e93258fSBjoern A. Zeeb 
64298e93258fSBjoern A. Zeeb 	if (bt->enable.now != bt->enable.last)
64308e93258fSBjoern A. Zeeb 		status_change = true;
64318e93258fSBjoern A. Zeeb 
64328e93258fSBjoern A. Zeeb 	/* reset bt info if bt re-enable */
64338e93258fSBjoern A. Zeeb 	if (bt->enable.now && !bt->enable.last) {
64348e93258fSBjoern A. Zeeb 		_reset_btc_var(rtwdev, BTC_RESET_BTINFO);
64358e93258fSBjoern A. Zeeb 		cx->cnt_bt[BTC_BCNT_REENABLE]++;
64368e93258fSBjoern A. Zeeb 		bt->enable.now = 1;
64378e93258fSBjoern A. Zeeb 	}
64388e93258fSBjoern A. Zeeb 
64398e93258fSBjoern A. Zeeb 	bt->enable.last = bt->enable.now;
64408e93258fSBjoern A. Zeeb 	bt->scbd = val;
64418e93258fSBjoern A. Zeeb 	bt->mbx_avl = !!(val & BTC_BSCB_ACT);
64428e93258fSBjoern A. Zeeb 
64438e93258fSBjoern A. Zeeb 	if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
64448e93258fSBjoern A. Zeeb 		status_change = true;
64458e93258fSBjoern A. Zeeb 
64468e93258fSBjoern A. Zeeb 	bt->whql_test = !!(val & BTC_BSCB_WHQL);
64478e93258fSBjoern A. Zeeb 	bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
6448e2340276SBjoern A. Zeeb 	bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
64498e93258fSBjoern A. Zeeb 
6450*6d67aabdSBjoern A. Zeeb 	bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) +
6451*6d67aabdSBjoern A. Zeeb 			    !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4;
6452*6d67aabdSBjoern A. Zeeb 
64538e93258fSBjoern A. Zeeb 	/* if rfk run 1->0 */
64548e93258fSBjoern A. Zeeb 	if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
64558e93258fSBjoern A. Zeeb 		status_change = true;
64568e93258fSBjoern A. Zeeb 
64578e93258fSBjoern A. Zeeb 	bt->rfk_info.map.run  = !!(val & BTC_BSCB_RFK_RUN);
64588e93258fSBjoern A. Zeeb 	bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
64598e93258fSBjoern A. Zeeb 	bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
64608e93258fSBjoern A. Zeeb 	bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
64618e93258fSBjoern A. Zeeb 	bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
64628e93258fSBjoern A. Zeeb 
64638e93258fSBjoern A. Zeeb 	if (!only_update && status_change)
64648e93258fSBjoern A. Zeeb 		_run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
64658e93258fSBjoern A. Zeeb }
64668e93258fSBjoern A. Zeeb 
64678e93258fSBjoern A. Zeeb static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
64688e93258fSBjoern A. Zeeb {
64698e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
64708e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
64718e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
64728e93258fSBjoern A. Zeeb 
64738e93258fSBjoern A. Zeeb 	_update_bt_scbd(rtwdev, true);
64748e93258fSBjoern A. Zeeb 
64758e93258fSBjoern A. Zeeb 	cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
64768e93258fSBjoern A. Zeeb 
64778e93258fSBjoern A. Zeeb 	if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
64788e93258fSBjoern A. Zeeb 	    !bt->rfk_info.map.timeout) {
64798e93258fSBjoern A. Zeeb 		cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
64808e93258fSBjoern A. Zeeb 	} else {
64818e93258fSBjoern A. Zeeb 		cx->cnt_wl[BTC_WCNT_RFK_GO]++;
64828e93258fSBjoern A. Zeeb 		return true;
64838e93258fSBjoern A. Zeeb 	}
64848e93258fSBjoern A. Zeeb 	return false;
64858e93258fSBjoern A. Zeeb }
64868e93258fSBjoern A. Zeeb 
64878e93258fSBjoern A. Zeeb static
64888e93258fSBjoern A. Zeeb void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
64898e93258fSBjoern A. Zeeb {
64908e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
6491e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
64928e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
64938e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
64948e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6495e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
64968e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
64978e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
6498e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
6499*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
6500*6d67aabdSBjoern A. Zeeb 	u8 mode, igno_bt, always_freerun;
65018e93258fSBjoern A. Zeeb 
65028e93258fSBjoern A. Zeeb 	lockdep_assert_held(&rtwdev->mutex);
65038e93258fSBjoern A. Zeeb 
65048e93258fSBjoern A. Zeeb 	dm->run_reason = reason;
65058e93258fSBjoern A. Zeeb 	_update_dm_step(rtwdev, reason);
65068e93258fSBjoern A. Zeeb 	_update_btc_state_map(rtwdev);
65078e93258fSBjoern A. Zeeb 
6508e2340276SBjoern A. Zeeb 	if (ver->fwlrole == 0)
65098e93258fSBjoern A. Zeeb 		mode = wl_rinfo->link_mode;
6510e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 1)
65118e93258fSBjoern A. Zeeb 		mode = wl_rinfo_v1->link_mode;
6512e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 2)
6513e2340276SBjoern A. Zeeb 		mode = wl_rinfo_v2->link_mode;
6514*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 8)
6515*6d67aabdSBjoern A. Zeeb 		mode = wl_rinfo_v8->link_mode;
6516e2340276SBjoern A. Zeeb 	else
6517e2340276SBjoern A. Zeeb 		return;
65188e93258fSBjoern A. Zeeb 
6519*6d67aabdSBjoern A. Zeeb 	if (ver->fcxctrl == 7) {
6520*6d67aabdSBjoern A. Zeeb 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
6521*6d67aabdSBjoern A. Zeeb 		always_freerun = btc->ctrl.ctrl_v7.always_freerun;
6522*6d67aabdSBjoern A. Zeeb 	} else {
6523*6d67aabdSBjoern A. Zeeb 		igno_bt = btc->ctrl.ctrl.igno_bt;
6524*6d67aabdSBjoern A. Zeeb 		always_freerun = btc->ctrl.ctrl.always_freerun;
6525*6d67aabdSBjoern A. Zeeb 	}
6526*6d67aabdSBjoern A. Zeeb 
65278e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
65288e93258fSBjoern A. Zeeb 		    __func__, reason, mode);
65298e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
65308e93258fSBjoern A. Zeeb 		    __func__, dm->wl_only, dm->bt_only);
65318e93258fSBjoern A. Zeeb 
65328e93258fSBjoern A. Zeeb 	/* Be careful to change the following function sequence!! */
6533*6d67aabdSBjoern A. Zeeb 	if (btc->manual_ctrl) {
65348e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
65358e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return for Manual CTRL!!\n",
65368e93258fSBjoern A. Zeeb 			    __func__);
65378e93258fSBjoern A. Zeeb 		return;
65388e93258fSBjoern A. Zeeb 	}
65398e93258fSBjoern A. Zeeb 
6540*6d67aabdSBjoern A. Zeeb 	if (igno_bt &&
65418e93258fSBjoern A. Zeeb 	    (reason == BTC_RSN_UPDATE_BT_INFO ||
65428e93258fSBjoern A. Zeeb 	     reason == BTC_RSN_UPDATE_BT_SCBD)) {
65438e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
65448e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return for Stop Coex DM!!\n",
65458e93258fSBjoern A. Zeeb 			    __func__);
65468e93258fSBjoern A. Zeeb 		return;
65478e93258fSBjoern A. Zeeb 	}
65488e93258fSBjoern A. Zeeb 
65498e93258fSBjoern A. Zeeb 	if (!wl->status.map.init_ok) {
65508e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
65518e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return for WL init fail!!\n",
65528e93258fSBjoern A. Zeeb 			    __func__);
65538e93258fSBjoern A. Zeeb 		return;
65548e93258fSBjoern A. Zeeb 	}
65558e93258fSBjoern A. Zeeb 
65568e93258fSBjoern A. Zeeb 	if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
6557*6d67aabdSBjoern A. Zeeb 	    wl->status.map.lps_pre == wl->status.map.lps) {
6558*6d67aabdSBjoern A. Zeeb 		if (reason == BTC_RSN_NTFY_POWEROFF ||
6559*6d67aabdSBjoern A. Zeeb 		    reason == BTC_RSN_NTFY_RADIO_STATE) {
65608e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
65618e93258fSBjoern A. Zeeb 				    "[BTC], %s(): return for WL rf off state no change!!\n",
65628e93258fSBjoern A. Zeeb 				    __func__);
65638e93258fSBjoern A. Zeeb 			return;
65648e93258fSBjoern A. Zeeb 		}
6565*6d67aabdSBjoern A. Zeeb 		if (wl->status.map.rf_off == 1 ||
6566*6d67aabdSBjoern A. Zeeb 		    wl->status.map.lps == BTC_LPS_RF_OFF) {
6567*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
6568*6d67aabdSBjoern A. Zeeb 				    "[BTC], %s(): return for WL rf off state!!\n",
6569*6d67aabdSBjoern A. Zeeb 				    __func__);
6570*6d67aabdSBjoern A. Zeeb 			return;
6571*6d67aabdSBjoern A. Zeeb 		}
6572*6d67aabdSBjoern A. Zeeb 	}
65738e93258fSBjoern A. Zeeb 
6574*6d67aabdSBjoern A. Zeeb 	dm->freerun = false;
65758e93258fSBjoern A. Zeeb 	dm->cnt_dm[BTC_DCNT_RUN]++;
6576e2340276SBjoern A. Zeeb 	dm->fddt_train = BTC_FDDT_DISABLE;
6577*6d67aabdSBjoern A. Zeeb 	bt->scan_rx_low_pri = false;
6578*6d67aabdSBjoern A. Zeeb 	igno_bt = false;
65798e93258fSBjoern A. Zeeb 
6580*6d67aabdSBjoern A. Zeeb 	if (always_freerun) {
65818e93258fSBjoern A. Zeeb 		_action_freerun(rtwdev);
6582*6d67aabdSBjoern A. Zeeb 		igno_bt = true;
65838e93258fSBjoern A. Zeeb 		goto exit;
65848e93258fSBjoern A. Zeeb 	}
65858e93258fSBjoern A. Zeeb 
65868e93258fSBjoern A. Zeeb 	if (dm->wl_only) {
65878e93258fSBjoern A. Zeeb 		_action_wl_only(rtwdev);
6588*6d67aabdSBjoern A. Zeeb 		igno_bt = true;
65898e93258fSBjoern A. Zeeb 		goto exit;
65908e93258fSBjoern A. Zeeb 	}
65918e93258fSBjoern A. Zeeb 
65928e93258fSBjoern A. Zeeb 	if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
6593*6d67aabdSBjoern A. Zeeb 		_action_wl_off(rtwdev, mode);
6594*6d67aabdSBjoern A. Zeeb 		igno_bt = true;
65958e93258fSBjoern A. Zeeb 		goto exit;
65968e93258fSBjoern A. Zeeb 	}
65978e93258fSBjoern A. Zeeb 
65988e93258fSBjoern A. Zeeb 	if (reason == BTC_RSN_NTFY_INIT) {
65998e93258fSBjoern A. Zeeb 		_action_wl_init(rtwdev);
66008e93258fSBjoern A. Zeeb 		goto exit;
66018e93258fSBjoern A. Zeeb 	}
66028e93258fSBjoern A. Zeeb 
66038e93258fSBjoern A. Zeeb 	if (!cx->bt.enable.now && !cx->other.type) {
66048e93258fSBjoern A. Zeeb 		_action_bt_off(rtwdev);
66058e93258fSBjoern A. Zeeb 		goto exit;
66068e93258fSBjoern A. Zeeb 	}
66078e93258fSBjoern A. Zeeb 
66088e93258fSBjoern A. Zeeb 	if (cx->bt.whql_test) {
66098e93258fSBjoern A. Zeeb 		_action_bt_whql(rtwdev);
66108e93258fSBjoern A. Zeeb 		goto exit;
66118e93258fSBjoern A. Zeeb 	}
66128e93258fSBjoern A. Zeeb 
66138e93258fSBjoern A. Zeeb 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
66148e93258fSBjoern A. Zeeb 		_action_wl_rfk(rtwdev);
66158e93258fSBjoern A. Zeeb 		goto exit;
66168e93258fSBjoern A. Zeeb 	}
66178e93258fSBjoern A. Zeeb 
66188e93258fSBjoern A. Zeeb 	if (cx->state_map == BTC_WLINKING) {
66198e93258fSBjoern A. Zeeb 		if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
66208e93258fSBjoern A. Zeeb 		    mode == BTC_WLINK_5G) {
66218e93258fSBjoern A. Zeeb 			_action_wl_scan(rtwdev);
6622*6d67aabdSBjoern A. Zeeb 			bt->scan_rx_low_pri = false;
66238e93258fSBjoern A. Zeeb 			goto exit;
66248e93258fSBjoern A. Zeeb 		}
66258e93258fSBjoern A. Zeeb 	}
66268e93258fSBjoern A. Zeeb 
66278e93258fSBjoern A. Zeeb 	if (wl->status.map.scan) {
66288e93258fSBjoern A. Zeeb 		_action_wl_scan(rtwdev);
6629*6d67aabdSBjoern A. Zeeb 		bt->scan_rx_low_pri = false;
66308e93258fSBjoern A. Zeeb 		goto exit;
66318e93258fSBjoern A. Zeeb 	}
66328e93258fSBjoern A. Zeeb 
66338e93258fSBjoern A. Zeeb 	switch (mode) {
66348e93258fSBjoern A. Zeeb 	case BTC_WLINK_NOLINK:
66358e93258fSBjoern A. Zeeb 		_action_wl_nc(rtwdev);
66368e93258fSBjoern A. Zeeb 		break;
66378e93258fSBjoern A. Zeeb 	case BTC_WLINK_2G_STA:
6638e2340276SBjoern A. Zeeb 		if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
6639e2340276SBjoern A. Zeeb 			bt->scan_rx_low_pri = true;
66408e93258fSBjoern A. Zeeb 		_action_wl_2g_sta(rtwdev);
66418e93258fSBjoern A. Zeeb 		break;
66428e93258fSBjoern A. Zeeb 	case BTC_WLINK_2G_AP:
6643e2340276SBjoern A. Zeeb 		bt->scan_rx_low_pri = true;
66448e93258fSBjoern A. Zeeb 		_action_wl_2g_ap(rtwdev);
66458e93258fSBjoern A. Zeeb 		break;
66468e93258fSBjoern A. Zeeb 	case BTC_WLINK_2G_GO:
6647e2340276SBjoern A. Zeeb 		bt->scan_rx_low_pri = true;
66488e93258fSBjoern A. Zeeb 		_action_wl_2g_go(rtwdev);
66498e93258fSBjoern A. Zeeb 		break;
66508e93258fSBjoern A. Zeeb 	case BTC_WLINK_2G_GC:
6651e2340276SBjoern A. Zeeb 		bt->scan_rx_low_pri = true;
66528e93258fSBjoern A. Zeeb 		_action_wl_2g_gc(rtwdev);
66538e93258fSBjoern A. Zeeb 		break;
66548e93258fSBjoern A. Zeeb 	case BTC_WLINK_2G_SCC:
6655e2340276SBjoern A. Zeeb 		bt->scan_rx_low_pri = true;
6656e2340276SBjoern A. Zeeb 		if (ver->fwlrole == 0)
66578e93258fSBjoern A. Zeeb 			_action_wl_2g_scc(rtwdev);
6658e2340276SBjoern A. Zeeb 		else if (ver->fwlrole == 1)
66598e93258fSBjoern A. Zeeb 			_action_wl_2g_scc_v1(rtwdev);
6660e2340276SBjoern A. Zeeb 		else if (ver->fwlrole == 2)
6661e2340276SBjoern A. Zeeb 			_action_wl_2g_scc_v2(rtwdev);
6662*6d67aabdSBjoern A. Zeeb 		else if (ver->fwlrole == 8)
6663*6d67aabdSBjoern A. Zeeb 			_action_wl_2g_scc_v8(rtwdev);
66648e93258fSBjoern A. Zeeb 		break;
66658e93258fSBjoern A. Zeeb 	case BTC_WLINK_2G_MCC:
6666e2340276SBjoern A. Zeeb 		bt->scan_rx_low_pri = true;
66678e93258fSBjoern A. Zeeb 		_action_wl_2g_mcc(rtwdev);
66688e93258fSBjoern A. Zeeb 		break;
66698e93258fSBjoern A. Zeeb 	case BTC_WLINK_25G_MCC:
6670e2340276SBjoern A. Zeeb 		bt->scan_rx_low_pri = true;
66718e93258fSBjoern A. Zeeb 		_action_wl_25g_mcc(rtwdev);
66728e93258fSBjoern A. Zeeb 		break;
66738e93258fSBjoern A. Zeeb 	case BTC_WLINK_5G:
66748e93258fSBjoern A. Zeeb 		_action_wl_5g(rtwdev);
66758e93258fSBjoern A. Zeeb 		break;
66768e93258fSBjoern A. Zeeb 	case BTC_WLINK_2G_NAN:
66778e93258fSBjoern A. Zeeb 		_action_wl_2g_nan(rtwdev);
66788e93258fSBjoern A. Zeeb 		break;
66798e93258fSBjoern A. Zeeb 	default:
66808e93258fSBjoern A. Zeeb 		_action_wl_other(rtwdev);
66818e93258fSBjoern A. Zeeb 		break;
66828e93258fSBjoern A. Zeeb 	}
66838e93258fSBjoern A. Zeeb 
66848e93258fSBjoern A. Zeeb exit:
66858e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
6686*6d67aabdSBjoern A. Zeeb 	if (ver->fcxctrl == 7)
6687*6d67aabdSBjoern A. Zeeb 		btc->ctrl.ctrl_v7.igno_bt = igno_bt;
6688*6d67aabdSBjoern A. Zeeb 	else
6689*6d67aabdSBjoern A. Zeeb 		btc->ctrl.ctrl.igno_bt = igno_bt;
66908e93258fSBjoern A. Zeeb 	_action_common(rtwdev);
66918e93258fSBjoern A. Zeeb }
66928e93258fSBjoern A. Zeeb 
66938e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
66948e93258fSBjoern A. Zeeb {
66958e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
66968e93258fSBjoern A. Zeeb 
66978e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
66988e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
66998e93258fSBjoern A. Zeeb }
67008e93258fSBjoern A. Zeeb 
67018e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
67028e93258fSBjoern A. Zeeb {
67038e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
67048e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
67058e93258fSBjoern A. Zeeb 
67068e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
67078e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
67088e93258fSBjoern A. Zeeb 
67098e93258fSBjoern A. Zeeb 	btc->cx.wl.status.map.rf_off = 1;
67108e93258fSBjoern A. Zeeb 	btc->cx.wl.status.map.busy = 0;
67118e93258fSBjoern A. Zeeb 	wl->status.map.lps = BTC_LPS_OFF;
67128e93258fSBjoern A. Zeeb 
67138e93258fSBjoern A. Zeeb 	_write_scbd(rtwdev, BTC_WSCB_ALL, false);
67148e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
67158e93258fSBjoern A. Zeeb 
67168e93258fSBjoern A. Zeeb 	rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
67178e93258fSBjoern A. Zeeb 
67188e93258fSBjoern A. Zeeb 	btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
67198e93258fSBjoern A. Zeeb }
67208e93258fSBjoern A. Zeeb 
67218e93258fSBjoern A. Zeeb static void _set_init_info(struct rtw89_dev *rtwdev)
67228e93258fSBjoern A. Zeeb {
67238e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
67248e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
6725*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
67268e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
67278e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
67288e93258fSBjoern A. Zeeb 
6729*6d67aabdSBjoern A. Zeeb 	if (ver->fcxinit == 7) {
6730*6d67aabdSBjoern A. Zeeb 		dm->init_info.init_v7.wl_only = (u8)dm->wl_only;
6731*6d67aabdSBjoern A. Zeeb 		dm->init_info.init_v7.bt_only = (u8)dm->bt_only;
6732*6d67aabdSBjoern A. Zeeb 		dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok;
6733*6d67aabdSBjoern A. Zeeb 		dm->init_info.init_v7.cx_other = btc->cx.other.type;
6734*6d67aabdSBjoern A. Zeeb 		dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch;
6735*6d67aabdSBjoern A. Zeeb 		dm->init_info.init_v7.module = btc->mdinfo.md_v7;
6736*6d67aabdSBjoern A. Zeeb 	} else {
6737*6d67aabdSBjoern A. Zeeb 		dm->init_info.init.wl_only = (u8)dm->wl_only;
6738*6d67aabdSBjoern A. Zeeb 		dm->init_info.init.bt_only = (u8)dm->bt_only;
6739*6d67aabdSBjoern A. Zeeb 		dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok;
6740*6d67aabdSBjoern A. Zeeb 		dm->init_info.init.dbcc_en = rtwdev->dbcc_en;
6741*6d67aabdSBjoern A. Zeeb 		dm->init_info.init.cx_other = btc->cx.other.type;
6742*6d67aabdSBjoern A. Zeeb 		dm->init_info.init.wl_guard_ch = chip->afh_guard_ch;
6743*6d67aabdSBjoern A. Zeeb 		dm->init_info.init.module = btc->mdinfo.md;
6744*6d67aabdSBjoern A. Zeeb 	}
67458e93258fSBjoern A. Zeeb }
67468e93258fSBjoern A. Zeeb 
67478e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
67488e93258fSBjoern A. Zeeb {
67498e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
67508e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
67518e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
67528e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
6753*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
67548e93258fSBjoern A. Zeeb 
67558e93258fSBjoern A. Zeeb 	_reset_btc_var(rtwdev, BTC_RESET_ALL);
67568e93258fSBjoern A. Zeeb 	btc->dm.run_reason = BTC_RSN_NONE;
67578e93258fSBjoern A. Zeeb 	btc->dm.run_action = BTC_ACT_NONE;
6758*6d67aabdSBjoern A. Zeeb 	if (ver->fcxctrl == 7)
6759*6d67aabdSBjoern A. Zeeb 		btc->ctrl.ctrl_v7.igno_bt = true;
6760*6d67aabdSBjoern A. Zeeb 	else
6761*6d67aabdSBjoern A. Zeeb 		btc->ctrl.ctrl.igno_bt = true;
67628e93258fSBjoern A. Zeeb 
67638e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
67648e93258fSBjoern A. Zeeb 		    "[BTC], %s(): mode=%d\n", __func__, mode);
67658e93258fSBjoern A. Zeeb 
6766*6d67aabdSBjoern A. Zeeb 	wl->coex_mode = mode;
67678e93258fSBjoern A. Zeeb 	dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
67688e93258fSBjoern A. Zeeb 	dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
67698e93258fSBjoern A. Zeeb 	dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
67708e93258fSBjoern A. Zeeb 	wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
67718e93258fSBjoern A. Zeeb 
67728e93258fSBjoern A. Zeeb 	chip->ops->btc_set_rfe(rtwdev);
67738e93258fSBjoern A. Zeeb 	chip->ops->btc_init_cfg(rtwdev);
67748e93258fSBjoern A. Zeeb 
67758e93258fSBjoern A. Zeeb 	if (!wl->status.map.init_ok) {
67768e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
67778e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return for WL init fail!!\n",
67788e93258fSBjoern A. Zeeb 			    __func__);
67798e93258fSBjoern A. Zeeb 		dm->error.map.init = true;
67808e93258fSBjoern A. Zeeb 		return;
67818e93258fSBjoern A. Zeeb 	}
67828e93258fSBjoern A. Zeeb 
67838e93258fSBjoern A. Zeeb 	_write_scbd(rtwdev,
67848e93258fSBjoern A. Zeeb 		    BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
67858e93258fSBjoern A. Zeeb 	_update_bt_scbd(rtwdev, true);
67868e93258fSBjoern A. Zeeb 	if (rtw89_mac_get_ctrl_path(rtwdev)) {
67878e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
67888e93258fSBjoern A. Zeeb 			    "[BTC], %s(): PTA owner warning!!\n",
67898e93258fSBjoern A. Zeeb 			    __func__);
67908e93258fSBjoern A. Zeeb 		dm->error.map.pta_owner = true;
67918e93258fSBjoern A. Zeeb 	}
67928e93258fSBjoern A. Zeeb 
67938e93258fSBjoern A. Zeeb 	_set_init_info(rtwdev);
67948e93258fSBjoern A. Zeeb 	_set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
67958e93258fSBjoern A. Zeeb 	btc_fw_set_monreg(rtwdev);
6796*6d67aabdSBjoern A. Zeeb 	rtw89_btc_fw_set_slots(rtwdev);
67978e93258fSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
67988e93258fSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
67998e93258fSBjoern A. Zeeb 
68008e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_INIT);
68018e93258fSBjoern A. Zeeb }
68028e93258fSBjoern A. Zeeb 
68038e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
68048e93258fSBjoern A. Zeeb {
68058e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
68068e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
68078e93258fSBjoern A. Zeeb 
68088e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
68098e93258fSBjoern A. Zeeb 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
68108e93258fSBjoern A. Zeeb 		    __func__, phy_idx, band);
6811*6d67aabdSBjoern A. Zeeb 
6812*6d67aabdSBjoern A. Zeeb 	if (phy_idx >= RTW89_PHY_MAX)
6813*6d67aabdSBjoern A. Zeeb 		return;
6814*6d67aabdSBjoern A. Zeeb 
68158e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
68168e93258fSBjoern A. Zeeb 	wl->status.map.scan = true;
68178e93258fSBjoern A. Zeeb 	wl->scan_info.band[phy_idx] = band;
68188e93258fSBjoern A. Zeeb 	wl->scan_info.phy_map |= BIT(phy_idx);
68198e93258fSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
68208e93258fSBjoern A. Zeeb 
68218e93258fSBjoern A. Zeeb 	if (rtwdev->dbcc_en) {
68228e93258fSBjoern A. Zeeb 		wl->dbcc_info.scan_band[phy_idx] = band;
68238e93258fSBjoern A. Zeeb 		_update_dbcc_band(rtwdev, phy_idx);
68248e93258fSBjoern A. Zeeb 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
68258e93258fSBjoern A. Zeeb 	}
68268e93258fSBjoern A. Zeeb 
68278e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
68288e93258fSBjoern A. Zeeb }
68298e93258fSBjoern A. Zeeb 
68308e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
68318e93258fSBjoern A. Zeeb {
68328e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
68338e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
68348e93258fSBjoern A. Zeeb 
68358e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
68368e93258fSBjoern A. Zeeb 		    "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
68378e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
68388e93258fSBjoern A. Zeeb 
68398e93258fSBjoern A. Zeeb 	wl->status.map.scan = false;
68408e93258fSBjoern A. Zeeb 	wl->scan_info.phy_map &= ~BIT(phy_idx);
68418e93258fSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
68428e93258fSBjoern A. Zeeb 
68438e93258fSBjoern A. Zeeb 	if (rtwdev->dbcc_en) {
68448e93258fSBjoern A. Zeeb 		_update_dbcc_band(rtwdev, phy_idx);
68458e93258fSBjoern A. Zeeb 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
68468e93258fSBjoern A. Zeeb 	}
68478e93258fSBjoern A. Zeeb 
68488e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
68498e93258fSBjoern A. Zeeb }
68508e93258fSBjoern A. Zeeb 
68518e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
68528e93258fSBjoern A. Zeeb {
68538e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
68548e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
68558e93258fSBjoern A. Zeeb 
68568e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
68578e93258fSBjoern A. Zeeb 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
68588e93258fSBjoern A. Zeeb 		    __func__, phy_idx, band);
6859*6d67aabdSBjoern A. Zeeb 
6860*6d67aabdSBjoern A. Zeeb 	if (phy_idx >= RTW89_PHY_MAX)
6861*6d67aabdSBjoern A. Zeeb 		return;
6862*6d67aabdSBjoern A. Zeeb 
68638e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
68648e93258fSBjoern A. Zeeb 
68658e93258fSBjoern A. Zeeb 	wl->scan_info.band[phy_idx] = band;
68668e93258fSBjoern A. Zeeb 	wl->scan_info.phy_map |= BIT(phy_idx);
68678e93258fSBjoern A. Zeeb 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
68688e93258fSBjoern A. Zeeb 
68698e93258fSBjoern A. Zeeb 	if (rtwdev->dbcc_en) {
68708e93258fSBjoern A. Zeeb 		wl->dbcc_info.scan_band[phy_idx] = band;
68718e93258fSBjoern A. Zeeb 		_update_dbcc_band(rtwdev, phy_idx);
68728e93258fSBjoern A. Zeeb 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
68738e93258fSBjoern A. Zeeb 	}
68748e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
68758e93258fSBjoern A. Zeeb }
68768e93258fSBjoern A. Zeeb 
68778e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
68788e93258fSBjoern A. Zeeb 				    enum btc_pkt_type pkt_type)
68798e93258fSBjoern A. Zeeb {
68808e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
68818e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
68828e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
68838e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
68848e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
68858e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
68868e93258fSBjoern A. Zeeb 	u32 cnt;
68878e93258fSBjoern A. Zeeb 	u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
68888e93258fSBjoern A. Zeeb 	bool delay_work = false;
68898e93258fSBjoern A. Zeeb 
68908e93258fSBjoern A. Zeeb 	switch (pkt_type) {
68918e93258fSBjoern A. Zeeb 	case PACKET_DHCP:
68928e93258fSBjoern A. Zeeb 		cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
68938e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
68948e93258fSBjoern A. Zeeb 			    "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
68958e93258fSBjoern A. Zeeb 		wl->status.map.connecting = true;
68968e93258fSBjoern A. Zeeb 		delay_work = true;
68978e93258fSBjoern A. Zeeb 		break;
68988e93258fSBjoern A. Zeeb 	case PACKET_EAPOL:
68998e93258fSBjoern A. Zeeb 		cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
69008e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
69018e93258fSBjoern A. Zeeb 			    "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
69028e93258fSBjoern A. Zeeb 		wl->status.map._4way = true;
69038e93258fSBjoern A. Zeeb 		delay_work = true;
69048e93258fSBjoern A. Zeeb 		if (hfp->exist || hid->exist)
69058e93258fSBjoern A. Zeeb 			delay /= 2;
69068e93258fSBjoern A. Zeeb 		break;
69078e93258fSBjoern A. Zeeb 	case PACKET_EAPOL_END:
69088e93258fSBjoern A. Zeeb 		cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
69098e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
69108e93258fSBjoern A. Zeeb 			    "[BTC], %s(): EAPOL_End cnt=%d\n",
69118e93258fSBjoern A. Zeeb 			    __func__, cnt);
69128e93258fSBjoern A. Zeeb 		wl->status.map._4way = false;
69138e93258fSBjoern A. Zeeb 		cancel_delayed_work(&rtwdev->coex_act1_work);
69148e93258fSBjoern A. Zeeb 		break;
69158e93258fSBjoern A. Zeeb 	case PACKET_ARP:
69168e93258fSBjoern A. Zeeb 		cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
69178e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
69188e93258fSBjoern A. Zeeb 			    "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
69198e93258fSBjoern A. Zeeb 		return;
69208e93258fSBjoern A. Zeeb 	case PACKET_ICMP:
69218e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
69228e93258fSBjoern A. Zeeb 			    "[BTC], %s(): ICMP pkt\n", __func__);
69238e93258fSBjoern A. Zeeb 		return;
69248e93258fSBjoern A. Zeeb 	default:
69258e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
69268e93258fSBjoern A. Zeeb 			    "[BTC], %s(): unknown packet type %d\n",
69278e93258fSBjoern A. Zeeb 			    __func__, pkt_type);
69288e93258fSBjoern A. Zeeb 		return;
69298e93258fSBjoern A. Zeeb 	}
69308e93258fSBjoern A. Zeeb 
69318e93258fSBjoern A. Zeeb 	if (delay_work) {
69328e93258fSBjoern A. Zeeb 		cancel_delayed_work(&rtwdev->coex_act1_work);
69338e93258fSBjoern A. Zeeb 		ieee80211_queue_delayed_work(rtwdev->hw,
69348e93258fSBjoern A. Zeeb 					     &rtwdev->coex_act1_work, delay);
69358e93258fSBjoern A. Zeeb 	}
69368e93258fSBjoern A. Zeeb 
69378e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
69388e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
69398e93258fSBjoern A. Zeeb }
69408e93258fSBjoern A. Zeeb 
69418e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
69428e93258fSBjoern A. Zeeb {
69438e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
69448e93258fSBjoern A. Zeeb 						btc.eapol_notify_work);
69458e93258fSBjoern A. Zeeb 
69468e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
69478e93258fSBjoern A. Zeeb 	rtw89_leave_ps_mode(rtwdev);
69488e93258fSBjoern A. Zeeb 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
69498e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
69508e93258fSBjoern A. Zeeb }
69518e93258fSBjoern A. Zeeb 
69528e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
69538e93258fSBjoern A. Zeeb {
69548e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
69558e93258fSBjoern A. Zeeb 						btc.arp_notify_work);
69568e93258fSBjoern A. Zeeb 
69578e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
69588e93258fSBjoern A. Zeeb 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
69598e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
69608e93258fSBjoern A. Zeeb }
69618e93258fSBjoern A. Zeeb 
69628e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
69638e93258fSBjoern A. Zeeb {
69648e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
69658e93258fSBjoern A. Zeeb 						btc.dhcp_notify_work);
69668e93258fSBjoern A. Zeeb 
69678e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
69688e93258fSBjoern A. Zeeb 	rtw89_leave_ps_mode(rtwdev);
69698e93258fSBjoern A. Zeeb 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
69708e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
69718e93258fSBjoern A. Zeeb }
69728e93258fSBjoern A. Zeeb 
69738e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
69748e93258fSBjoern A. Zeeb {
69758e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
69768e93258fSBjoern A. Zeeb 						btc.icmp_notify_work);
69778e93258fSBjoern A. Zeeb 
69788e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
69798e93258fSBjoern A. Zeeb 	rtw89_leave_ps_mode(rtwdev);
69808e93258fSBjoern A. Zeeb 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
69818e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
69828e93258fSBjoern A. Zeeb }
69838e93258fSBjoern A. Zeeb 
6984*6d67aabdSBjoern A. Zeeb static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
6985*6d67aabdSBjoern A. Zeeb {
6986*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
6987*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
6988*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6989*6d67aabdSBjoern A. Zeeb 	u8 *rssi_st, rssi_th, rssi_level = 0;
6990*6d67aabdSBjoern A. Zeeb 	u8 i;
6991*6d67aabdSBjoern A. Zeeb 
6992*6d67aabdSBjoern A. Zeeb 	/* for rssi locate in which {40, 36, 31, 28}
6993*6d67aabdSBjoern A. Zeeb 	 * if rssi >= 40% (-60dBm) --> rssi_level = 4
6994*6d67aabdSBjoern A. Zeeb 	 * if 36% <= rssi < 40%    --> rssi_level = 3
6995*6d67aabdSBjoern A. Zeeb 	 * if 31% <= rssi < 36%    --> rssi_level = 2
6996*6d67aabdSBjoern A. Zeeb 	 * if 28% <= rssi < 31%    --> rssi_level = 1
6997*6d67aabdSBjoern A. Zeeb 	 * if rssi < 28%           --> rssi_level = 0
6998*6d67aabdSBjoern A. Zeeb 	 */
6999*6d67aabdSBjoern A. Zeeb 
7000*6d67aabdSBjoern A. Zeeb 	/* check if rssi across bt_rssi_thres boundary */
7001*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
7002*6d67aabdSBjoern A. Zeeb 		rssi_th = chip->bt_rssi_thres[i];
7003*6d67aabdSBjoern A. Zeeb 		rssi_st = &bt->link_info.rssi_state[i];
7004*6d67aabdSBjoern A. Zeeb 
7005*6d67aabdSBjoern A. Zeeb 		*rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
7006*6d67aabdSBjoern A. Zeeb 
7007*6d67aabdSBjoern A. Zeeb 		if (BTC_RSSI_HIGH(*rssi_st)) {
7008*6d67aabdSBjoern A. Zeeb 			rssi_level = BTC_BT_RSSI_THMAX - i;
7009*6d67aabdSBjoern A. Zeeb 			break;
7010*6d67aabdSBjoern A. Zeeb 		}
7011*6d67aabdSBjoern A. Zeeb 	}
7012*6d67aabdSBjoern A. Zeeb 	return rssi_level;
7013*6d67aabdSBjoern A. Zeeb }
7014*6d67aabdSBjoern A. Zeeb 
7015*6d67aabdSBjoern A. Zeeb static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
7016*6d67aabdSBjoern A. Zeeb {
7017*6d67aabdSBjoern A. Zeeb 	u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
7018*6d67aabdSBjoern A. Zeeb 	u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
7019*6d67aabdSBjoern A. Zeeb 
7020*6d67aabdSBjoern A. Zeeb 	if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
7021*6d67aabdSBjoern A. Zeeb 		zb_tbl0 = 0xffffffff;
7022*6d67aabdSBjoern A. Zeeb 		zb_tbl1 = 0xffffffff;
7023*6d67aabdSBjoern A. Zeeb 	} else if (mode == BTC_WLINK_25G_MCC) {
7024*6d67aabdSBjoern A. Zeeb 		zb_tbl0 = 0xffffffff; /* for E5G slot */
7025*6d67aabdSBjoern A. Zeeb 		zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
7026*6d67aabdSBjoern A. Zeeb 	}
7027*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
7028*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
7029*6d67aabdSBjoern A. Zeeb }
7030*6d67aabdSBjoern A. Zeeb 
7031e2340276SBjoern A. Zeeb #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
7032e2340276SBjoern A. Zeeb 
70338e93258fSBjoern A. Zeeb static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
70348e93258fSBjoern A. Zeeb {
70358e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
70368e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
70378e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
70388e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
70398e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
70408e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
70418e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
70428e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
70438e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
70448e93258fSBjoern A. Zeeb 	union btc_btinfo btinfo;
70458e93258fSBjoern A. Zeeb 
70468e93258fSBjoern A. Zeeb 	if (buf[BTC_BTINFO_L1] != 6)
70478e93258fSBjoern A. Zeeb 		return;
70488e93258fSBjoern A. Zeeb 
70498e93258fSBjoern A. Zeeb 	if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
70508e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
70518e93258fSBjoern A. Zeeb 			    "[BTC], %s(): return by bt-info duplicate!!\n",
70528e93258fSBjoern A. Zeeb 			    __func__);
70538e93258fSBjoern A. Zeeb 		cx->cnt_bt[BTC_BCNT_INFOSAME]++;
70548e93258fSBjoern A. Zeeb 		return;
70558e93258fSBjoern A. Zeeb 	}
70568e93258fSBjoern A. Zeeb 
70578e93258fSBjoern A. Zeeb 	memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
70588e93258fSBjoern A. Zeeb 
70598e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
70608e93258fSBjoern A. Zeeb 		    "[BTC], %s(): bt_info[2]=0x%02x\n",
70618e93258fSBjoern A. Zeeb 		    __func__, bt->raw_info[2]);
70628e93258fSBjoern A. Zeeb 
70638e93258fSBjoern A. Zeeb 	/* reset to mo-connect before update */
70648e93258fSBjoern A. Zeeb 	b->status.val = BTC_BLINK_NOCONNECT;
70658e93258fSBjoern A. Zeeb 	b->profile_cnt.last = b->profile_cnt.now;
70668e93258fSBjoern A. Zeeb 	b->relink.last = b->relink.now;
70678e93258fSBjoern A. Zeeb 	a2dp->exist_last = a2dp->exist;
70688e93258fSBjoern A. Zeeb 	b->multi_link.last = b->multi_link.now;
70698e93258fSBjoern A. Zeeb 	bt->inq_pag.last = bt->inq_pag.now;
70708e93258fSBjoern A. Zeeb 	b->profile_cnt.now = 0;
70718e93258fSBjoern A. Zeeb 	hid->type = 0;
70728e93258fSBjoern A. Zeeb 
70738e93258fSBjoern A. Zeeb 	/* parse raw info low-Byte2 */
70748e93258fSBjoern A. Zeeb 	btinfo.val = bt->raw_info[BTC_BTINFO_L2];
70758e93258fSBjoern A. Zeeb 	b->status.map.connect = btinfo.lb2.connect;
70768e93258fSBjoern A. Zeeb 	b->status.map.sco_busy = btinfo.lb2.sco_busy;
70778e93258fSBjoern A. Zeeb 	b->status.map.acl_busy = btinfo.lb2.acl_busy;
70788e93258fSBjoern A. Zeeb 	b->status.map.inq_pag = btinfo.lb2.inq_pag;
70798e93258fSBjoern A. Zeeb 	bt->inq_pag.now = btinfo.lb2.inq_pag;
70808e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
70818e93258fSBjoern A. Zeeb 
70828e93258fSBjoern A. Zeeb 	hfp->exist = btinfo.lb2.hfp;
70838e93258fSBjoern A. Zeeb 	b->profile_cnt.now += (u8)hfp->exist;
70848e93258fSBjoern A. Zeeb 	hid->exist = btinfo.lb2.hid;
70858e93258fSBjoern A. Zeeb 	b->profile_cnt.now += (u8)hid->exist;
70868e93258fSBjoern A. Zeeb 	a2dp->exist = btinfo.lb2.a2dp;
70878e93258fSBjoern A. Zeeb 	b->profile_cnt.now += (u8)a2dp->exist;
70888e93258fSBjoern A. Zeeb 	pan->active = btinfo.lb2.pan;
7089e2340276SBjoern A. Zeeb 	btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
70908e93258fSBjoern A. Zeeb 
70918e93258fSBjoern A. Zeeb 	/* parse raw info low-Byte3 */
70928e93258fSBjoern A. Zeeb 	btinfo.val = bt->raw_info[BTC_BTINFO_L3];
70938e93258fSBjoern A. Zeeb 	if (btinfo.lb3.retry != 0)
70948e93258fSBjoern A. Zeeb 		cx->cnt_bt[BTC_BCNT_RETRY]++;
70958e93258fSBjoern A. Zeeb 	b->cqddr = btinfo.lb3.cqddr;
70968e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
70978e93258fSBjoern A. Zeeb 	bt->inq = btinfo.lb3.inq;
70988e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
70998e93258fSBjoern A. Zeeb 	bt->pag = btinfo.lb3.pag;
71008e93258fSBjoern A. Zeeb 
71018e93258fSBjoern A. Zeeb 	b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
71028e93258fSBjoern A. Zeeb 	/* parse raw info high-Byte0 */
71038e93258fSBjoern A. Zeeb 	btinfo.val = bt->raw_info[BTC_BTINFO_H0];
71048e93258fSBjoern A. Zeeb 	/* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
71058e93258fSBjoern A. Zeeb 	b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
7106*6d67aabdSBjoern A. Zeeb 	bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
7107*6d67aabdSBjoern A. Zeeb 	btc->dm.trx_info.bt_rssi = bt->rssi_level;
71088e93258fSBjoern A. Zeeb 
71098e93258fSBjoern A. Zeeb 	/* parse raw info high-Byte1 */
71108e93258fSBjoern A. Zeeb 	btinfo.val = bt->raw_info[BTC_BTINFO_H1];
71118e93258fSBjoern A. Zeeb 	b->status.map.ble_connect = btinfo.hb1.ble_connect;
71128e93258fSBjoern A. Zeeb 	if (btinfo.hb1.ble_connect)
71138e93258fSBjoern A. Zeeb 		hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
71148e93258fSBjoern A. Zeeb 
71158e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
71168e93258fSBjoern A. Zeeb 	bt->reinit = btinfo.hb1.reinit;
71178e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
71188e93258fSBjoern A. Zeeb 	b->relink.now = btinfo.hb1.relink;
71198e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
71208e93258fSBjoern A. Zeeb 	bt->igno_wl = btinfo.hb1.igno_wl;
71218e93258fSBjoern A. Zeeb 
71228e93258fSBjoern A. Zeeb 	if (bt->igno_wl && !cx->wl.status.map.rf_off)
71238e93258fSBjoern A. Zeeb 		_set_bt_ignore_wlan_act(rtwdev, false);
71248e93258fSBjoern A. Zeeb 
71258e93258fSBjoern A. Zeeb 	hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
71268e93258fSBjoern A. Zeeb 	bt->ble_scan_en = btinfo.hb1.ble_scan;
71278e93258fSBjoern A. Zeeb 
71288e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
71298e93258fSBjoern A. Zeeb 	b->role_sw = btinfo.hb1.role_sw;
71308e93258fSBjoern A. Zeeb 
71318e93258fSBjoern A. Zeeb 	b->multi_link.now = btinfo.hb1.multi_link;
71328e93258fSBjoern A. Zeeb 
71338e93258fSBjoern A. Zeeb 	/* parse raw info high-Byte2 */
71348e93258fSBjoern A. Zeeb 	btinfo.val = bt->raw_info[BTC_BTINFO_H2];
71358e93258fSBjoern A. Zeeb 	pan->exist = btinfo.hb2.pan_active;
71368e93258fSBjoern A. Zeeb 	b->profile_cnt.now += (u8)pan->exist;
71378e93258fSBjoern A. Zeeb 
71388e93258fSBjoern A. Zeeb 	cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
71398e93258fSBjoern A. Zeeb 	b->afh_update = btinfo.hb2.afh_update;
71408e93258fSBjoern A. Zeeb 	a2dp->active = btinfo.hb2.a2dp_active;
71418e93258fSBjoern A. Zeeb 	b->slave_role = btinfo.hb2.slave;
71428e93258fSBjoern A. Zeeb 	hid->slot_info = btinfo.hb2.hid_slot;
71438e93258fSBjoern A. Zeeb 	hid->pair_cnt = btinfo.hb2.hid_cnt;
71448e93258fSBjoern A. Zeeb 	hid->type |= (hid->slot_info == BTC_HID_218 ?
71458e93258fSBjoern A. Zeeb 		      BTC_HID_218 : BTC_HID_418);
71468e93258fSBjoern A. Zeeb 	/* parse raw info high-Byte3 */
71478e93258fSBjoern A. Zeeb 	btinfo.val = bt->raw_info[BTC_BTINFO_H3];
71488e93258fSBjoern A. Zeeb 	a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
71498e93258fSBjoern A. Zeeb 
71508e93258fSBjoern A. Zeeb 	if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
71518e93258fSBjoern A. Zeeb 		cx->cnt_bt[BTC_BCNT_RATECHG]++;
71528e93258fSBjoern A. Zeeb 	b->tx_3m = (u32)btinfo.hb3.tx_3m;
71538e93258fSBjoern A. Zeeb 
71548e93258fSBjoern A. Zeeb 	a2dp->sink = btinfo.hb3.a2dp_sink;
71558e93258fSBjoern A. Zeeb 
71568e93258fSBjoern A. Zeeb 	if (!a2dp->exist_last && a2dp->exist) {
71578e93258fSBjoern A. Zeeb 		a2dp->vendor_id = 0;
71588e93258fSBjoern A. Zeeb 		a2dp->flush_time = 0;
71598e93258fSBjoern A. Zeeb 		a2dp->play_latency = 1;
71608e93258fSBjoern A. Zeeb 		ieee80211_queue_delayed_work(rtwdev->hw,
71618e93258fSBjoern A. Zeeb 					     &rtwdev->coex_bt_devinfo_work,
71628e93258fSBjoern A. Zeeb 					     RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
71638e93258fSBjoern A. Zeeb 	}
71648e93258fSBjoern A. Zeeb 
71658e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
71668e93258fSBjoern A. Zeeb }
71678e93258fSBjoern A. Zeeb 
71688e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
71698e93258fSBjoern A. Zeeb 			      struct rtw89_sta *rtwsta, enum btc_role_state state)
71708e93258fSBjoern A. Zeeb {
7171*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
7172*6d67aabdSBjoern A. Zeeb 						       rtwvif->sub_entity_idx);
71738e93258fSBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
71748e93258fSBjoern A. Zeeb 	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
71758e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
7176e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
71778e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
71788e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info r = {0};
71798e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *wlinfo = NULL;
7180*6d67aabdSBjoern A. Zeeb 	u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
71818e93258fSBjoern A. Zeeb 
71828e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
71838e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
71848e93258fSBjoern A. Zeeb 		    "[BTC], role is STA=%d\n",
71858e93258fSBjoern A. Zeeb 		    vif->type == NL80211_IFTYPE_STATION);
71868e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
71878e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
71888e93258fSBjoern A. Zeeb 		    chan->band_type, chan->channel, chan->band_width);
71898e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
71908e93258fSBjoern A. Zeeb 		    state == BTC_ROLE_MSTS_STA_CONN_END);
71918e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
71928e93258fSBjoern A. Zeeb 		    "[BTC], bcn_period=%d dtim_period=%d\n",
71938e93258fSBjoern A. Zeeb 		    vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
71948e93258fSBjoern A. Zeeb 
71958e93258fSBjoern A. Zeeb 	if (rtwsta) {
71968e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
71978e93258fSBjoern A. Zeeb 			    rtwsta->mac_id);
71988e93258fSBjoern A. Zeeb 
71998e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
72008e93258fSBjoern A. Zeeb 			    "[BTC], STA support HE=%d VHT=%d HT=%d\n",
72018e93258fSBjoern A. Zeeb 			    sta->deflink.he_cap.has_he,
72028e93258fSBjoern A. Zeeb 			    sta->deflink.vht_cap.vht_supported,
72038e93258fSBjoern A. Zeeb 			    sta->deflink.ht_cap.ht_supported);
72048e93258fSBjoern A. Zeeb 		if (sta->deflink.he_cap.has_he)
72058e93258fSBjoern A. Zeeb 			mode |= BIT(BTC_WL_MODE_HE);
72068e93258fSBjoern A. Zeeb 		if (sta->deflink.vht_cap.vht_supported)
72078e93258fSBjoern A. Zeeb 			mode |= BIT(BTC_WL_MODE_VHT);
72088e93258fSBjoern A. Zeeb 		if (sta->deflink.ht_cap.ht_supported)
72098e93258fSBjoern A. Zeeb 			mode |= BIT(BTC_WL_MODE_HT);
72108e93258fSBjoern A. Zeeb 
72118e93258fSBjoern A. Zeeb 		r.mode = mode;
72128e93258fSBjoern A. Zeeb 	}
72138e93258fSBjoern A. Zeeb 
72148e93258fSBjoern A. Zeeb 	if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
72158e93258fSBjoern A. Zeeb 		return;
72168e93258fSBjoern A. Zeeb 
72178e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
72188e93258fSBjoern A. Zeeb 		    "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
72198e93258fSBjoern A. Zeeb 
72208e93258fSBjoern A. Zeeb 	r.role = rtwvif->wifi_role;
72218e93258fSBjoern A. Zeeb 	r.phy = rtwvif->phy_idx;
72228e93258fSBjoern A. Zeeb 	r.pid = rtwvif->port;
72238e93258fSBjoern A. Zeeb 	r.active = true;
72248e93258fSBjoern A. Zeeb 	r.connected = MLME_LINKED;
72258e93258fSBjoern A. Zeeb 	r.bcn_period = vif->bss_conf.beacon_int;
72268e93258fSBjoern A. Zeeb 	r.dtim_period = vif->bss_conf.dtim_period;
72278e93258fSBjoern A. Zeeb 	r.band = chan->band_type;
72288e93258fSBjoern A. Zeeb 	r.ch = chan->channel;
72298e93258fSBjoern A. Zeeb 	r.bw = chan->band_width;
7230*6d67aabdSBjoern A. Zeeb 	r.chdef.band = chan->band_type;
7231*6d67aabdSBjoern A. Zeeb 	r.chdef.center_ch = chan->channel;
7232*6d67aabdSBjoern A. Zeeb 	r.chdef.bw = chan->band_width;
7233*6d67aabdSBjoern A. Zeeb 	r.chdef.chan = chan->primary_channel;
72348e93258fSBjoern A. Zeeb 	ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
72358e93258fSBjoern A. Zeeb 
72368e93258fSBjoern A. Zeeb 	if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
72378e93258fSBjoern A. Zeeb 		r.mac_id = rtwsta->mac_id;
72388e93258fSBjoern A. Zeeb 
72398e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
72408e93258fSBjoern A. Zeeb 
72418e93258fSBjoern A. Zeeb 	wlinfo = &wl->link_info[r.pid];
72428e93258fSBjoern A. Zeeb 
7243*6d67aabdSBjoern A. Zeeb 	rlink_id = 0; /* to do */
7244*6d67aabdSBjoern A. Zeeb 	if (ver->fwlrole == 0) {
7245*6d67aabdSBjoern A. Zeeb 		*wlinfo = r;
72468e93258fSBjoern A. Zeeb 		_update_wl_info(rtwdev);
7247*6d67aabdSBjoern A. Zeeb 	} else if (ver->fwlrole == 1) {
7248*6d67aabdSBjoern A. Zeeb 		*wlinfo = r;
72498e93258fSBjoern A. Zeeb 		_update_wl_info_v1(rtwdev);
7250*6d67aabdSBjoern A. Zeeb 	} else if (ver->fwlrole == 2) {
7251*6d67aabdSBjoern A. Zeeb 		*wlinfo = r;
7252e2340276SBjoern A. Zeeb 		_update_wl_info_v2(rtwdev);
7253*6d67aabdSBjoern A. Zeeb 	} else if (ver->fwlrole == 8) {
7254*6d67aabdSBjoern A. Zeeb 		wlinfo = &wl->rlink_info[r.pid][rlink_id];
7255*6d67aabdSBjoern A. Zeeb 		*wlinfo = r;
7256*6d67aabdSBjoern A. Zeeb 		link_mode_ori = wl->role_info_v8.link_mode;
7257*6d67aabdSBjoern A. Zeeb 		pta_req_mac_ori = wl->pta_req_mac;
7258*6d67aabdSBjoern A. Zeeb 		_update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
7259*6d67aabdSBjoern A. Zeeb 
7260*6d67aabdSBjoern A. Zeeb 		if (wl->role_info_v8.link_mode != link_mode_ori) {
7261*6d67aabdSBjoern A. Zeeb 			wl->role_info_v8.link_mode_chg = 1;
7262*6d67aabdSBjoern A. Zeeb 			if (ver->fcxinit == 7)
7263*6d67aabdSBjoern A. Zeeb 				wa_type = btc->mdinfo.md_v7.wa_type;
7264*6d67aabdSBjoern A. Zeeb 			else
7265*6d67aabdSBjoern A. Zeeb 				wa_type = btc->mdinfo.md.wa_type;
7266*6d67aabdSBjoern A. Zeeb 
7267*6d67aabdSBjoern A. Zeeb 			if (wa_type & BTC_WA_HFP_ZB)
7268*6d67aabdSBjoern A. Zeeb 				_update_zb_coex_tbl(rtwdev);
7269*6d67aabdSBjoern A. Zeeb 		}
7270*6d67aabdSBjoern A. Zeeb 
7271*6d67aabdSBjoern A. Zeeb 		if (wl->pta_req_mac != pta_req_mac_ori)
7272*6d67aabdSBjoern A. Zeeb 			wl->pta_reg_mac_chg = 1;
7273*6d67aabdSBjoern A. Zeeb 	}
72748e93258fSBjoern A. Zeeb 
72758e93258fSBjoern A. Zeeb 	if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
72768e93258fSBjoern A. Zeeb 	    wlinfo->connected == MLME_NO_LINK)
72778e93258fSBjoern A. Zeeb 		btc->dm.leak_ap = 0;
72788e93258fSBjoern A. Zeeb 
72798e93258fSBjoern A. Zeeb 	if (state == BTC_ROLE_MSTS_STA_CONN_START)
72808e93258fSBjoern A. Zeeb 		wl->status.map.connecting = 1;
72818e93258fSBjoern A. Zeeb 	else
72828e93258fSBjoern A. Zeeb 		wl->status.map.connecting = 0;
72838e93258fSBjoern A. Zeeb 
72848e93258fSBjoern A. Zeeb 	if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
72858e93258fSBjoern A. Zeeb 		wl->status.map._4way = false;
72868e93258fSBjoern A. Zeeb 
72878e93258fSBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
72888e93258fSBjoern A. Zeeb }
72898e93258fSBjoern A. Zeeb 
72908e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
72918e93258fSBjoern A. Zeeb {
72928e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
72938e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
72948e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
72958e93258fSBjoern A. Zeeb 	u32 val;
72968e93258fSBjoern A. Zeeb 
72978e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
72988e93258fSBjoern A. Zeeb 		    __func__, rf_state);
72998e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
73008e93258fSBjoern A. Zeeb 
73018e93258fSBjoern A. Zeeb 	switch (rf_state) {
73028e93258fSBjoern A. Zeeb 	case BTC_RFCTRL_WL_OFF:
73038e93258fSBjoern A. Zeeb 		wl->status.map.rf_off = 1;
73048e93258fSBjoern A. Zeeb 		wl->status.map.lps = BTC_LPS_OFF;
73058e93258fSBjoern A. Zeeb 		wl->status.map.busy = 0;
73068e93258fSBjoern A. Zeeb 		break;
73078e93258fSBjoern A. Zeeb 	case BTC_RFCTRL_FW_CTRL:
73088e93258fSBjoern A. Zeeb 		wl->status.map.rf_off = 0;
73098e93258fSBjoern A. Zeeb 		wl->status.map.lps = BTC_LPS_RF_OFF;
73108e93258fSBjoern A. Zeeb 		wl->status.map.busy = 0;
73118e93258fSBjoern A. Zeeb 		break;
7312e2340276SBjoern A. Zeeb 	case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
7313e2340276SBjoern A. Zeeb 		wl->status.map.rf_off = 0;
7314e2340276SBjoern A. Zeeb 		wl->status.map.lps = BTC_LPS_RF_ON;
7315e2340276SBjoern A. Zeeb 		wl->status.map.busy = 0;
7316e2340276SBjoern A. Zeeb 		break;
73178e93258fSBjoern A. Zeeb 	case BTC_RFCTRL_WL_ON:
73188e93258fSBjoern A. Zeeb 	default:
73198e93258fSBjoern A. Zeeb 		wl->status.map.rf_off = 0;
73208e93258fSBjoern A. Zeeb 		wl->status.map.lps = BTC_LPS_OFF;
73218e93258fSBjoern A. Zeeb 		break;
73228e93258fSBjoern A. Zeeb 	}
73238e93258fSBjoern A. Zeeb 
73248e93258fSBjoern A. Zeeb 	if (rf_state == BTC_RFCTRL_WL_ON) {
7325e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true);
73268e93258fSBjoern A. Zeeb 		val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
73278e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, val, true);
73288e93258fSBjoern A. Zeeb 		_update_bt_scbd(rtwdev, true);
73298e93258fSBjoern A. Zeeb 		chip->ops->btc_init_cfg(rtwdev);
73308e93258fSBjoern A. Zeeb 	} else {
73318e93258fSBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
7332*6d67aabdSBjoern A. Zeeb 		if (rf_state == BTC_RFCTRL_FW_CTRL)
7333*6d67aabdSBjoern A. Zeeb 			_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
7334*6d67aabdSBjoern A. Zeeb 		else if (rf_state == BTC_RFCTRL_WL_OFF)
73358e93258fSBjoern A. Zeeb 			_write_scbd(rtwdev, BTC_WSCB_ALL, false);
7336*6d67aabdSBjoern A. Zeeb 		else
7337*6d67aabdSBjoern A. Zeeb 			_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
7338*6d67aabdSBjoern A. Zeeb 
7339*6d67aabdSBjoern A. Zeeb 		if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
7340e2340276SBjoern A. Zeeb 		    wl->status.map.lps_pre != BTC_LPS_OFF)
7341e2340276SBjoern A. Zeeb 			_update_bt_scbd(rtwdev, true);
73428e93258fSBjoern A. Zeeb 	}
73438e93258fSBjoern A. Zeeb 
7344e2340276SBjoern A. Zeeb 	btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
7345e2340276SBjoern A. Zeeb 	btc->dm.tdma_instant_excute = 1;
73468e93258fSBjoern A. Zeeb 
7347e2340276SBjoern A. Zeeb 	_run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
73488e93258fSBjoern A. Zeeb 	wl->status.map.rf_off_pre = wl->status.map.rf_off;
73498e93258fSBjoern A. Zeeb 	wl->status.map.lps_pre = wl->status.map.lps;
73508e93258fSBjoern A. Zeeb }
73518e93258fSBjoern A. Zeeb 
73528e93258fSBjoern A. Zeeb static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
73538e93258fSBjoern A. Zeeb 			 enum btc_wl_rfk_type type,
73548e93258fSBjoern A. Zeeb 			 enum btc_wl_rfk_state state)
73558e93258fSBjoern A. Zeeb {
73568e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
73578e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
73588e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
73598e93258fSBjoern A. Zeeb 	bool result = BTC_WRFK_REJECT;
73608e93258fSBjoern A. Zeeb 
73618e93258fSBjoern A. Zeeb 	wl->rfk_info.type = type;
73628e93258fSBjoern A. Zeeb 	wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
73638e93258fSBjoern A. Zeeb 	wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
73648e93258fSBjoern A. Zeeb 	wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
73658e93258fSBjoern A. Zeeb 
73668e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
73678e93258fSBjoern A. Zeeb 		    "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
73688e93258fSBjoern A. Zeeb 		    __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
73698e93258fSBjoern A. Zeeb 		    type, state);
73708e93258fSBjoern A. Zeeb 
73718e93258fSBjoern A. Zeeb 	switch (state) {
73728e93258fSBjoern A. Zeeb 	case BTC_WRFK_START:
73738e93258fSBjoern A. Zeeb 		result = _chk_wl_rfk_request(rtwdev);
73748e93258fSBjoern A. Zeeb 		wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
73758e93258fSBjoern A. Zeeb 
73768e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
73778e93258fSBjoern A. Zeeb 
73788e93258fSBjoern A. Zeeb 		btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
73798e93258fSBjoern A. Zeeb 		break;
73808e93258fSBjoern A. Zeeb 	case BTC_WRFK_ONESHOT_START:
73818e93258fSBjoern A. Zeeb 	case BTC_WRFK_ONESHOT_STOP:
73828e93258fSBjoern A. Zeeb 		if (wl->rfk_info.state == BTC_WRFK_STOP) {
73838e93258fSBjoern A. Zeeb 			result = BTC_WRFK_REJECT;
73848e93258fSBjoern A. Zeeb 		} else {
73858e93258fSBjoern A. Zeeb 			result = BTC_WRFK_ALLOW;
73868e93258fSBjoern A. Zeeb 			wl->rfk_info.state = state;
73878e93258fSBjoern A. Zeeb 		}
73888e93258fSBjoern A. Zeeb 		break;
73898e93258fSBjoern A. Zeeb 	case BTC_WRFK_STOP:
73908e93258fSBjoern A. Zeeb 		result = BTC_WRFK_ALLOW;
73918e93258fSBjoern A. Zeeb 		wl->rfk_info.state = BTC_WRFK_STOP;
73928e93258fSBjoern A. Zeeb 
73938e93258fSBjoern A. Zeeb 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
73948e93258fSBjoern A. Zeeb 		cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
73958e93258fSBjoern A. Zeeb 		break;
73968e93258fSBjoern A. Zeeb 	default:
73978e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
73988e93258fSBjoern A. Zeeb 			    "[BTC], %s() warning state=%d\n", __func__, state);
73998e93258fSBjoern A. Zeeb 		break;
74008e93258fSBjoern A. Zeeb 	}
74018e93258fSBjoern A. Zeeb 
74028e93258fSBjoern A. Zeeb 	if (result == BTC_WRFK_ALLOW) {
74038e93258fSBjoern A. Zeeb 		if (wl->rfk_info.state == BTC_WRFK_START ||
74048e93258fSBjoern A. Zeeb 		    wl->rfk_info.state == BTC_WRFK_STOP)
74058e93258fSBjoern A. Zeeb 			_run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
74068e93258fSBjoern A. Zeeb 
74078e93258fSBjoern A. Zeeb 		if (wl->rfk_info.state == BTC_WRFK_START)
74088e93258fSBjoern A. Zeeb 			ieee80211_queue_delayed_work(rtwdev->hw,
74098e93258fSBjoern A. Zeeb 						     &rtwdev->coex_rfk_chk_work,
74108e93258fSBjoern A. Zeeb 						     RTW89_COEX_RFK_CHK_WORK_PERIOD);
74118e93258fSBjoern A. Zeeb 	}
74128e93258fSBjoern A. Zeeb 
74138e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
74148e93258fSBjoern A. Zeeb 		    "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
74158e93258fSBjoern A. Zeeb 		    __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
74168e93258fSBjoern A. Zeeb 
74178e93258fSBjoern A. Zeeb 	return result == BTC_WRFK_ALLOW;
74188e93258fSBjoern A. Zeeb }
74198e93258fSBjoern A. Zeeb 
74208e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
74218e93258fSBjoern A. Zeeb 			   enum btc_wl_rfk_type type,
74228e93258fSBjoern A. Zeeb 			   enum btc_wl_rfk_state state)
74238e93258fSBjoern A. Zeeb {
74248e93258fSBjoern A. Zeeb 	u8 band;
74258e93258fSBjoern A. Zeeb 	bool allow;
74268e93258fSBjoern A. Zeeb 	int ret;
74278e93258fSBjoern A. Zeeb 
74288e93258fSBjoern A. Zeeb 	band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
74298e93258fSBjoern A. Zeeb 
74308e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
74318e93258fSBjoern A. Zeeb 		    "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
74328e93258fSBjoern A. Zeeb 		    band == RTW89_BAND_2G ? "2G" :
74338e93258fSBjoern A. Zeeb 		    band == RTW89_BAND_5G ? "5G" : "6G",
74348e93258fSBjoern A. Zeeb 		    !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
74358e93258fSBjoern A. Zeeb 		    type,
74368e93258fSBjoern A. Zeeb 		    FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
74378e93258fSBjoern A. Zeeb 		    state == BTC_WRFK_STOP ? "RFK_STOP" :
74388e93258fSBjoern A. Zeeb 		    state == BTC_WRFK_START ? "RFK_START" :
74398e93258fSBjoern A. Zeeb 		    state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
74408e93258fSBjoern A. Zeeb 		    "ONE-SHOT_STOP");
74418e93258fSBjoern A. Zeeb 
74428e93258fSBjoern A. Zeeb 	if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
74438e93258fSBjoern A. Zeeb 		_ntfy_wl_rfk(rtwdev, phy_map, type, state);
74448e93258fSBjoern A. Zeeb 		return;
74458e93258fSBjoern A. Zeeb 	}
74468e93258fSBjoern A. Zeeb 
74478e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
74488e93258fSBjoern A. Zeeb 				rtwdev, phy_map, type, state);
74498e93258fSBjoern A. Zeeb 	if (ret) {
74508e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "RFK notify timeout\n");
74518e93258fSBjoern A. Zeeb 		rtwdev->is_bt_iqk_timeout = true;
74528e93258fSBjoern A. Zeeb 	}
74538e93258fSBjoern A. Zeeb }
74548e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
74558e93258fSBjoern A. Zeeb 
74568e93258fSBjoern A. Zeeb struct rtw89_btc_wl_sta_iter_data {
74578e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev;
74588e93258fSBjoern A. Zeeb 	u8 busy_all;
74598e93258fSBjoern A. Zeeb 	u8 dir_all;
74608e93258fSBjoern A. Zeeb 	u8 rssi_map_all;
74618e93258fSBjoern A. Zeeb 	bool is_sta_change;
74628e93258fSBjoern A. Zeeb 	bool is_traffic_change;
74638e93258fSBjoern A. Zeeb };
74648e93258fSBjoern A. Zeeb 
74658e93258fSBjoern A. Zeeb static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
74668e93258fSBjoern A. Zeeb {
74678e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_sta_iter_data *iter_data =
74688e93258fSBjoern A. Zeeb 				(struct rtw89_btc_wl_sta_iter_data *)data;
74698e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
74708e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
7471e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
7472e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
74738e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
74748e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *link_info = NULL;
74758e93258fSBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
74768e93258fSBjoern A. Zeeb 	struct rtw89_traffic_stats *link_info_t = NULL;
74778e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
74788e93258fSBjoern A. Zeeb 	struct rtw89_traffic_stats *stats = &rtwvif->stats;
74798e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
7480e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *r;
7481e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *r1;
74828e93258fSBjoern A. Zeeb 	u32 last_tx_rate, last_rx_rate;
74838e93258fSBjoern A. Zeeb 	u16 last_tx_lvl, last_rx_lvl;
74848e93258fSBjoern A. Zeeb 	u8 port = rtwvif->port;
74858e93258fSBjoern A. Zeeb 	u8 rssi;
74868e93258fSBjoern A. Zeeb 	u8 busy = 0;
74878e93258fSBjoern A. Zeeb 	u8 dir = 0;
74888e93258fSBjoern A. Zeeb 	u8 rssi_map = 0;
74898e93258fSBjoern A. Zeeb 	u8 i = 0;
74908e93258fSBjoern A. Zeeb 	bool is_sta_change = false, is_traffic_change = false;
74918e93258fSBjoern A. Zeeb 
74928e93258fSBjoern A. Zeeb 	rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
74938e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
74948e93258fSBjoern A. Zeeb 
74958e93258fSBjoern A. Zeeb 	link_info = &wl->link_info[port];
74968e93258fSBjoern A. Zeeb 	link_info->stat.traffic = rtwvif->stats;
74978e93258fSBjoern A. Zeeb 	link_info_t = &link_info->stat.traffic;
74988e93258fSBjoern A. Zeeb 
74998e93258fSBjoern A. Zeeb 	if (link_info->connected == MLME_NO_LINK) {
75008e93258fSBjoern A. Zeeb 		link_info->rx_rate_drop_cnt = 0;
75018e93258fSBjoern A. Zeeb 		return;
75028e93258fSBjoern A. Zeeb 	}
75038e93258fSBjoern A. Zeeb 
75048e93258fSBjoern A. Zeeb 	link_info->stat.rssi = rssi;
75058e93258fSBjoern A. Zeeb 	for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
75068e93258fSBjoern A. Zeeb 		link_info->rssi_state[i] =
75078e93258fSBjoern A. Zeeb 			_update_rssi_state(rtwdev,
75088e93258fSBjoern A. Zeeb 					   link_info->rssi_state[i],
75098e93258fSBjoern A. Zeeb 					   link_info->stat.rssi,
75108e93258fSBjoern A. Zeeb 					   chip->wl_rssi_thres[i]);
75118e93258fSBjoern A. Zeeb 		if (BTC_RSSI_LOW(link_info->rssi_state[i]))
75128e93258fSBjoern A. Zeeb 			rssi_map |= BIT(i);
75138e93258fSBjoern A. Zeeb 
7514*6d67aabdSBjoern A. Zeeb 		if (btc->ant_type == BTC_ANT_DEDICATED &&
75158e93258fSBjoern A. Zeeb 		    BTC_RSSI_CHANGE(link_info->rssi_state[i]))
75168e93258fSBjoern A. Zeeb 			is_sta_change = true;
75178e93258fSBjoern A. Zeeb 	}
75188e93258fSBjoern A. Zeeb 	iter_data->rssi_map_all |= rssi_map;
75198e93258fSBjoern A. Zeeb 
75208e93258fSBjoern A. Zeeb 	last_tx_rate = link_info_t->tx_rate;
75218e93258fSBjoern A. Zeeb 	last_rx_rate = link_info_t->rx_rate;
75228e93258fSBjoern A. Zeeb 	last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
75238e93258fSBjoern A. Zeeb 	last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
75248e93258fSBjoern A. Zeeb 
75258e93258fSBjoern A. Zeeb 	if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
75268e93258fSBjoern A. Zeeb 	    stats->rx_tfc_lv != RTW89_TFC_IDLE)
75278e93258fSBjoern A. Zeeb 		busy = 1;
75288e93258fSBjoern A. Zeeb 
75298e93258fSBjoern A. Zeeb 	if (stats->tx_tfc_lv > stats->rx_tfc_lv)
75308e93258fSBjoern A. Zeeb 		dir = RTW89_TFC_UL;
75318e93258fSBjoern A. Zeeb 	else
75328e93258fSBjoern A. Zeeb 		dir = RTW89_TFC_DL;
75338e93258fSBjoern A. Zeeb 
75348e93258fSBjoern A. Zeeb 	link_info = &wl->link_info[port];
75358e93258fSBjoern A. Zeeb 	if (link_info->busy != busy || link_info->dir != dir) {
75368e93258fSBjoern A. Zeeb 		is_sta_change = true;
75378e93258fSBjoern A. Zeeb 		link_info->busy = busy;
75388e93258fSBjoern A. Zeeb 		link_info->dir = dir;
75398e93258fSBjoern A. Zeeb 	}
75408e93258fSBjoern A. Zeeb 
75418e93258fSBjoern A. Zeeb 	iter_data->busy_all |= busy;
75428e93258fSBjoern A. Zeeb 	iter_data->dir_all |= BIT(dir);
75438e93258fSBjoern A. Zeeb 
75448e93258fSBjoern A. Zeeb 	if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
75458e93258fSBjoern A. Zeeb 	    last_rx_rate > RTW89_HW_RATE_CCK2 &&
75468e93258fSBjoern A. Zeeb 	    link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
75478e93258fSBjoern A. Zeeb 		link_info->rx_rate_drop_cnt++;
75488e93258fSBjoern A. Zeeb 
75498e93258fSBjoern A. Zeeb 	if (last_tx_rate != rtwsta->ra_report.hw_rate ||
75508e93258fSBjoern A. Zeeb 	    last_rx_rate != rtwsta->rx_hw_rate ||
75518e93258fSBjoern A. Zeeb 	    last_tx_lvl != link_info_t->tx_tfc_lv ||
75528e93258fSBjoern A. Zeeb 	    last_rx_lvl != link_info_t->rx_tfc_lv)
75538e93258fSBjoern A. Zeeb 		is_traffic_change = true;
75548e93258fSBjoern A. Zeeb 
75558e93258fSBjoern A. Zeeb 	link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
75568e93258fSBjoern A. Zeeb 	link_info_t->rx_rate = rtwsta->rx_hw_rate;
75578e93258fSBjoern A. Zeeb 
7558e2340276SBjoern A. Zeeb 	if (link_info->role == RTW89_WIFI_ROLE_STATION ||
7559e2340276SBjoern A. Zeeb 	    link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
7560e2340276SBjoern A. Zeeb 		dm->trx_info.tx_rate = link_info_t->tx_rate;
7561e2340276SBjoern A. Zeeb 		dm->trx_info.rx_rate = link_info_t->rx_rate;
7562e2340276SBjoern A. Zeeb 	}
7563e2340276SBjoern A. Zeeb 
7564e2340276SBjoern A. Zeeb 	if (ver->fwlrole == 0) {
7565e2340276SBjoern A. Zeeb 		r = &wl->role_info;
7566e2340276SBjoern A. Zeeb 		r->active_role[port].tx_lvl = stats->tx_tfc_lv;
7567e2340276SBjoern A. Zeeb 		r->active_role[port].rx_lvl = stats->rx_tfc_lv;
7568e2340276SBjoern A. Zeeb 		r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
7569e2340276SBjoern A. Zeeb 		r->active_role[port].rx_rate = rtwsta->rx_hw_rate;
7570e2340276SBjoern A. Zeeb 	} else if (ver->fwlrole == 1) {
7571e2340276SBjoern A. Zeeb 		r1 = &wl->role_info_v1;
7572e2340276SBjoern A. Zeeb 		r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
7573e2340276SBjoern A. Zeeb 		r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
7574e2340276SBjoern A. Zeeb 		r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate;
7575e2340276SBjoern A. Zeeb 		r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate;
7576e2340276SBjoern A. Zeeb 	} else if (ver->fwlrole == 2) {
7577e2340276SBjoern A. Zeeb 		dm->trx_info.tx_lvl = stats->tx_tfc_lv;
7578e2340276SBjoern A. Zeeb 		dm->trx_info.rx_lvl = stats->rx_tfc_lv;
7579e2340276SBjoern A. Zeeb 		dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate;
7580e2340276SBjoern A. Zeeb 		dm->trx_info.rx_rate = rtwsta->rx_hw_rate;
7581e2340276SBjoern A. Zeeb 	}
7582e2340276SBjoern A. Zeeb 
7583e2340276SBjoern A. Zeeb 	dm->trx_info.tx_tp = link_info_t->tx_throughput;
7584e2340276SBjoern A. Zeeb 	dm->trx_info.rx_tp = link_info_t->rx_throughput;
75858e93258fSBjoern A. Zeeb 
7586*6d67aabdSBjoern A. Zeeb 	/* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
7587*6d67aabdSBjoern A. Zeeb 	if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
7588*6d67aabdSBjoern A. Zeeb 	     dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
7589*6d67aabdSBjoern A. Zeeb 	     (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
7590*6d67aabdSBjoern A. Zeeb 	      dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
7591*6d67aabdSBjoern A. Zeeb 		iter_data->is_sta_change = true;
7592*6d67aabdSBjoern A. Zeeb 
75938e93258fSBjoern A. Zeeb 	if (is_sta_change)
75948e93258fSBjoern A. Zeeb 		iter_data->is_sta_change = true;
75958e93258fSBjoern A. Zeeb 
75968e93258fSBjoern A. Zeeb 	if (is_traffic_change)
75978e93258fSBjoern A. Zeeb 		iter_data->is_traffic_change = true;
75988e93258fSBjoern A. Zeeb }
75998e93258fSBjoern A. Zeeb 
76008e93258fSBjoern A. Zeeb #define BTC_NHM_CHK_INTVL 20
76018e93258fSBjoern A. Zeeb 
76028e93258fSBjoern A. Zeeb void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
76038e93258fSBjoern A. Zeeb {
76048e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
7605e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
76068e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
76078e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
76088e93258fSBjoern A. Zeeb 	u8 i;
76098e93258fSBjoern A. Zeeb 
76108e93258fSBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
76118e93258fSBjoern A. Zeeb 					  rtw89_btc_ntfy_wl_sta_iter,
76128e93258fSBjoern A. Zeeb 					  &data);
76138e93258fSBjoern A. Zeeb 
76148e93258fSBjoern A. Zeeb 	wl->rssi_level = 0;
76158e93258fSBjoern A. Zeeb 	btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
76168e93258fSBjoern A. Zeeb 	for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
76178e93258fSBjoern A. Zeeb 		/* set RSSI level 4 ~ 0 if rssi bit map match */
76188e93258fSBjoern A. Zeeb 		if (data.rssi_map_all & BIT(i - 1)) {
76198e93258fSBjoern A. Zeeb 			wl->rssi_level = i;
76208e93258fSBjoern A. Zeeb 			break;
76218e93258fSBjoern A. Zeeb 		}
76228e93258fSBjoern A. Zeeb 	}
76238e93258fSBjoern A. Zeeb 
7624e2340276SBjoern A. Zeeb 	if (dm->trx_info.wl_rssi != wl->rssi_level)
7625e2340276SBjoern A. Zeeb 		dm->trx_info.wl_rssi = wl->rssi_level;
7626e2340276SBjoern A. Zeeb 
76278e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
76288e93258fSBjoern A. Zeeb 		    __func__, !!wl->status.map.busy);
76298e93258fSBjoern A. Zeeb 
76308e93258fSBjoern A. Zeeb 	_write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
76318e93258fSBjoern A. Zeeb 
76328e93258fSBjoern A. Zeeb 	if (data.is_traffic_change)
76338e93258fSBjoern A. Zeeb 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
76348e93258fSBjoern A. Zeeb 	if (data.is_sta_change) {
76358e93258fSBjoern A. Zeeb 		wl->status.map.busy = data.busy_all;
76368e93258fSBjoern A. Zeeb 		wl->status.map.traffic_dir = data.dir_all;
76378e93258fSBjoern A. Zeeb 		_run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
76388e93258fSBjoern A. Zeeb 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
76398e93258fSBjoern A. Zeeb 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
76408e93258fSBjoern A. Zeeb 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
76418e93258fSBjoern A. Zeeb 			btc->dm.cnt_notify[BTC_NCNT_WL_STA];
76428e93258fSBjoern A. Zeeb 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
76438e93258fSBjoern A. Zeeb 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
76448e93258fSBjoern A. Zeeb 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
76458e93258fSBjoern A. Zeeb 		btc->dm.cnt_notify[BTC_NCNT_WL_STA];
76468e93258fSBjoern A. Zeeb 	}
76478e93258fSBjoern A. Zeeb }
76488e93258fSBjoern A. Zeeb 
76498e93258fSBjoern A. Zeeb void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
76508e93258fSBjoern A. Zeeb 			  u32 len, u8 class, u8 func)
76518e93258fSBjoern A. Zeeb {
76528e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
76538e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
76548e93258fSBjoern A. Zeeb 	u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
76558e93258fSBjoern A. Zeeb 
76568e93258fSBjoern A. Zeeb 	len -= RTW89_C2H_HEADER_LEN;
76578e93258fSBjoern A. Zeeb 
76588e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
76598e93258fSBjoern A. Zeeb 		    "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
76608e93258fSBjoern A. Zeeb 		    __func__, len, class, func);
76618e93258fSBjoern A. Zeeb 
76628e93258fSBjoern A. Zeeb 	if (class != BTFC_FW_EVENT)
76638e93258fSBjoern A. Zeeb 		return;
76648e93258fSBjoern A. Zeeb 
76658e93258fSBjoern A. Zeeb 	switch (func) {
76668e93258fSBjoern A. Zeeb 	case BTF_EVNT_RPT:
76678e93258fSBjoern A. Zeeb 	case BTF_EVNT_BUF_OVERFLOW:
76688e93258fSBjoern A. Zeeb 		pfwinfo->event[func]++;
76698e93258fSBjoern A. Zeeb 		/* Don't need rtw89_leave_ps_mode() */
76708e93258fSBjoern A. Zeeb 		btc_fw_event(rtwdev, func, buf, len);
76718e93258fSBjoern A. Zeeb 		break;
76728e93258fSBjoern A. Zeeb 	case BTF_EVNT_BT_INFO:
76738e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
76748e93258fSBjoern A. Zeeb 			    "[BTC], handle C2H BT INFO with data %8ph\n", buf);
76758e93258fSBjoern A. Zeeb 		btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
76768e93258fSBjoern A. Zeeb 		_update_bt_info(rtwdev, buf, len);
76778e93258fSBjoern A. Zeeb 		break;
76788e93258fSBjoern A. Zeeb 	case BTF_EVNT_BT_SCBD:
76798e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
76808e93258fSBjoern A. Zeeb 			    "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
76818e93258fSBjoern A. Zeeb 		btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
76828e93258fSBjoern A. Zeeb 		_update_bt_scbd(rtwdev, false);
76838e93258fSBjoern A. Zeeb 		break;
76848e93258fSBjoern A. Zeeb 	case BTF_EVNT_BT_PSD:
76858e93258fSBjoern A. Zeeb 		break;
76868e93258fSBjoern A. Zeeb 	case BTF_EVNT_BT_REG:
76878e93258fSBjoern A. Zeeb 		btc->dbg.rb_done = true;
76888e93258fSBjoern A. Zeeb 		btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
76898e93258fSBjoern A. Zeeb 
76908e93258fSBjoern A. Zeeb 		break;
76918e93258fSBjoern A. Zeeb 	case BTF_EVNT_C2H_LOOPBACK:
76928e93258fSBjoern A. Zeeb 		btc->dbg.rb_done = true;
76938e93258fSBjoern A. Zeeb 		btc->dbg.rb_val = buf[0];
76948e93258fSBjoern A. Zeeb 		break;
76958e93258fSBjoern A. Zeeb 	case BTF_EVNT_CX_RUNINFO:
76968e93258fSBjoern A. Zeeb 		btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
76978e93258fSBjoern A. Zeeb 		break;
76988e93258fSBjoern A. Zeeb 	}
76998e93258fSBjoern A. Zeeb }
77008e93258fSBjoern A. Zeeb 
77018e93258fSBjoern A. Zeeb #define BTC_CX_FW_OFFLOAD 0
77028e93258fSBjoern A. Zeeb 
77038e93258fSBjoern A. Zeeb static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
77048e93258fSBjoern A. Zeeb {
7705*6d67aabdSBjoern A. Zeeb 	union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
77068e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
7707*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
77088e93258fSBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
77098e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
77108e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
77118e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
77128e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
77138e93258fSBjoern A. Zeeb 	u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
7714*6d67aabdSBjoern A. Zeeb 	u8 cv, rfe, iso, ant_num, ant_single_pos;
77158e93258fSBjoern A. Zeeb 
77168e93258fSBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
77178e93258fSBjoern A. Zeeb 		return;
77188e93258fSBjoern A. Zeeb 
77198e93258fSBjoern A. Zeeb 	dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
77208e93258fSBjoern A. Zeeb 
77218e93258fSBjoern A. Zeeb 	seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
77228e93258fSBjoern A. Zeeb 		   chip->chip_id);
77238e93258fSBjoern A. Zeeb 
7724e2340276SBjoern A. Zeeb 	ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
7725e2340276SBjoern A. Zeeb 	ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
7726e2340276SBjoern A. Zeeb 	ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
7727e2340276SBjoern A. Zeeb 	id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
77288e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
77298e93258fSBjoern A. Zeeb 		   "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
77308e93258fSBjoern A. Zeeb 
77318e93258fSBjoern A. Zeeb 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
77328e93258fSBjoern A. Zeeb 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
77338e93258fSBjoern A. Zeeb 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
77348e93258fSBjoern A. Zeeb 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
77358e93258fSBjoern A. Zeeb 	seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
77368e93258fSBjoern A. Zeeb 		   ver_main, ver_sub, ver_hotfix, id_branch);
77378e93258fSBjoern A. Zeeb 
77388e93258fSBjoern A. Zeeb 	ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
77398e93258fSBjoern A. Zeeb 	ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
77408e93258fSBjoern A. Zeeb 	ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
77418e93258fSBjoern A. Zeeb 	seq_printf(m, "(%s, desired:%d.%d.%d), ",
77428e93258fSBjoern A. Zeeb 		   (wl->ver_info.fw_coex >= chip->wlcx_desired ?
77438e93258fSBjoern A. Zeeb 		   "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
77448e93258fSBjoern A. Zeeb 
77458e93258fSBjoern A. Zeeb 	seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
77468e93258fSBjoern A. Zeeb 		   bt->ver_info.fw_coex,
77478e93258fSBjoern A. Zeeb 		   (bt->ver_info.fw_coex >= chip->btcx_desired ?
77488e93258fSBjoern A. Zeeb 		   "Match" : "Mismatch"), chip->btcx_desired);
77498e93258fSBjoern A. Zeeb 
77508e93258fSBjoern A. Zeeb 	if (bt->enable.now && bt->ver_info.fw == 0)
77518e93258fSBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
77528e93258fSBjoern A. Zeeb 	else
77538e93258fSBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
77548e93258fSBjoern A. Zeeb 
77558e93258fSBjoern A. Zeeb 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
77568e93258fSBjoern A. Zeeb 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
77578e93258fSBjoern A. Zeeb 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
77588e93258fSBjoern A. Zeeb 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
77598e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
77608e93258fSBjoern A. Zeeb 		   "[sub_module]",
77618e93258fSBjoern A. Zeeb 		   ver_main, ver_sub, ver_hotfix, id_branch,
77628e93258fSBjoern A. Zeeb 		   bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
77638e93258fSBjoern A. Zeeb 
7764*6d67aabdSBjoern A. Zeeb 	if (ver->fcxinit == 7) {
7765*6d67aabdSBjoern A. Zeeb 		cv = md->md_v7.kt_ver;
7766*6d67aabdSBjoern A. Zeeb 		rfe = md->md_v7.rfe_type;
7767*6d67aabdSBjoern A. Zeeb 		iso = md->md_v7.ant.isolation;
7768*6d67aabdSBjoern A. Zeeb 		ant_num = md->md_v7.ant.num;
7769*6d67aabdSBjoern A. Zeeb 		ant_single_pos = md->md_v7.ant.single_pos;
7770*6d67aabdSBjoern A. Zeeb 	} else {
7771*6d67aabdSBjoern A. Zeeb 		cv = md->md.cv;
7772*6d67aabdSBjoern A. Zeeb 		rfe = md->md.rfe_type;
7773*6d67aabdSBjoern A. Zeeb 		iso = md->md.ant.isolation;
7774*6d67aabdSBjoern A. Zeeb 		ant_num = md->md.ant.num;
7775*6d67aabdSBjoern A. Zeeb 		ant_single_pos = md->md.ant.single_pos;
7776*6d67aabdSBjoern A. Zeeb 	}
7777*6d67aabdSBjoern A. Zeeb 
77788e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
7779*6d67aabdSBjoern A. Zeeb 		   "[hw_info]", cv, rfe, iso, ant_num,
7780*6d67aabdSBjoern A. Zeeb 		   ant_num > 1 ? "" :
7781*6d67aabdSBjoern A. Zeeb 		   ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
77828e93258fSBjoern A. Zeeb 
77838e93258fSBjoern A. Zeeb 	seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
77848e93258fSBjoern A. Zeeb 		   btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
77858e93258fSBjoern A. Zeeb 		   hal->rx_nss);
77868e93258fSBjoern A. Zeeb }
77878e93258fSBjoern A. Zeeb 
77888e93258fSBjoern A. Zeeb static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
77898e93258fSBjoern A. Zeeb {
77908e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
77918e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_link_info *plink = NULL;
77928e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
77938e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
77948e93258fSBjoern A. Zeeb 	struct rtw89_traffic_stats *t;
77958e93258fSBjoern A. Zeeb 	u8 i;
77968e93258fSBjoern A. Zeeb 
77978e93258fSBjoern A. Zeeb 	if (rtwdev->dbcc_en) {
77988e93258fSBjoern A. Zeeb 		seq_printf(m,
77998e93258fSBjoern A. Zeeb 			   " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
78008e93258fSBjoern A. Zeeb 			   "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
78018e93258fSBjoern A. Zeeb 			   wl_dinfo->scan_band[RTW89_PHY_0],
78028e93258fSBjoern A. Zeeb 			   wl_dinfo->real_band[RTW89_PHY_0]);
78038e93258fSBjoern A. Zeeb 		seq_printf(m,
78048e93258fSBjoern A. Zeeb 			   "PHY1_band(op:%d/scan:%d/real:%d)\n",
78058e93258fSBjoern A. Zeeb 			   wl_dinfo->op_band[RTW89_PHY_1],
78068e93258fSBjoern A. Zeeb 			   wl_dinfo->scan_band[RTW89_PHY_1],
78078e93258fSBjoern A. Zeeb 			   wl_dinfo->real_band[RTW89_PHY_1]);
78088e93258fSBjoern A. Zeeb 	}
78098e93258fSBjoern A. Zeeb 
78108e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_PORT_NUM; i++) {
7811*6d67aabdSBjoern A. Zeeb 		if (btc->ver->fwlrole == 8)
7812*6d67aabdSBjoern A. Zeeb 			plink = &btc->cx.wl.rlink_info[i][0];
7813*6d67aabdSBjoern A. Zeeb 		else
78148e93258fSBjoern A. Zeeb 			plink = &btc->cx.wl.link_info[i];
78158e93258fSBjoern A. Zeeb 
78168e93258fSBjoern A. Zeeb 		if (!plink->active)
78178e93258fSBjoern A. Zeeb 			continue;
78188e93258fSBjoern A. Zeeb 
78198e93258fSBjoern A. Zeeb 		seq_printf(m,
78208e93258fSBjoern A. Zeeb 			   " [port_%d]        : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
78218e93258fSBjoern A. Zeeb 			   plink->pid, (u32)plink->role, plink->phy,
78228e93258fSBjoern A. Zeeb 			   (u32)plink->connected, plink->client_cnt - 1,
78238e93258fSBjoern A. Zeeb 			   (u32)plink->mode, plink->ch, (u32)plink->bw);
78248e93258fSBjoern A. Zeeb 
78258e93258fSBjoern A. Zeeb 		if (plink->connected == MLME_NO_LINK)
78268e93258fSBjoern A. Zeeb 			continue;
78278e93258fSBjoern A. Zeeb 
78288e93258fSBjoern A. Zeeb 		seq_printf(m,
78298e93258fSBjoern A. Zeeb 			   ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
78308e93258fSBjoern A. Zeeb 			   plink->mac_id, plink->tx_time, plink->tx_retry);
78318e93258fSBjoern A. Zeeb 
78328e93258fSBjoern A. Zeeb 		seq_printf(m,
78338e93258fSBjoern A. Zeeb 			   " [port_%d]        : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
78348e93258fSBjoern A. Zeeb 			   plink->pid, 110 - plink->stat.rssi,
78358e93258fSBjoern A. Zeeb 			   plink->stat.rssi, plink->busy,
78368e93258fSBjoern A. Zeeb 			   plink->dir == RTW89_TFC_UL ? "UL" : "DL");
78378e93258fSBjoern A. Zeeb 
78388e93258fSBjoern A. Zeeb 		t = &plink->stat.traffic;
78398e93258fSBjoern A. Zeeb 
78408e93258fSBjoern A. Zeeb 		seq_printf(m,
78418e93258fSBjoern A. Zeeb 			   "tx[rate:%d/busy_level:%d], ",
78428e93258fSBjoern A. Zeeb 			   (u32)t->tx_rate, t->tx_tfc_lv);
78438e93258fSBjoern A. Zeeb 
78448e93258fSBjoern A. Zeeb 		seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
78458e93258fSBjoern A. Zeeb 			   (u32)t->rx_rate,
78468e93258fSBjoern A. Zeeb 			   t->rx_tfc_lv, plink->rx_rate_drop_cnt);
78478e93258fSBjoern A. Zeeb 	}
78488e93258fSBjoern A. Zeeb }
78498e93258fSBjoern A. Zeeb 
78508e93258fSBjoern A. Zeeb static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
78518e93258fSBjoern A. Zeeb {
78528e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
7853e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
78548e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
78558e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
78568e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
78578e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
7858e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
7859*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
78608e93258fSBjoern A. Zeeb 	u8 mode;
78618e93258fSBjoern A. Zeeb 
78628e93258fSBjoern A. Zeeb 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
78638e93258fSBjoern A. Zeeb 		return;
78648e93258fSBjoern A. Zeeb 
78658e93258fSBjoern A. Zeeb 	seq_puts(m, "========== [WL Status] ==========\n");
78668e93258fSBjoern A. Zeeb 
7867e2340276SBjoern A. Zeeb 	if (ver->fwlrole == 0)
78688e93258fSBjoern A. Zeeb 		mode = wl_rinfo->link_mode;
7869e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 1)
78708e93258fSBjoern A. Zeeb 		mode = wl_rinfo_v1->link_mode;
7871e2340276SBjoern A. Zeeb 	else if (ver->fwlrole == 2)
7872e2340276SBjoern A. Zeeb 		mode = wl_rinfo_v2->link_mode;
7873*6d67aabdSBjoern A. Zeeb 	else if (ver->fwlrole == 8)
7874*6d67aabdSBjoern A. Zeeb 		mode = wl_rinfo_v8->link_mode;
7875e2340276SBjoern A. Zeeb 	else
7876e2340276SBjoern A. Zeeb 		return;
78778e93258fSBjoern A. Zeeb 
78788e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
78798e93258fSBjoern A. Zeeb 
78808e93258fSBjoern A. Zeeb 	seq_printf(m,
78818e93258fSBjoern A. Zeeb 		   "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
78828e93258fSBjoern A. Zeeb 		   wl->status.map.rf_off, wl->status.map.lps,
78838e93258fSBjoern A. Zeeb 		   wl->status.map.scan ? "Y" : "N",
78848e93258fSBjoern A. Zeeb 		   wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
78858e93258fSBjoern A. Zeeb 
78868e93258fSBjoern A. Zeeb 	seq_printf(m,
78878e93258fSBjoern A. Zeeb 		   "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
78888e93258fSBjoern A. Zeeb 		   wl->status.map.connecting ? "Y" : "N",
78898e93258fSBjoern A. Zeeb 		   wl->status.map.roaming ?  "Y" : "N",
78908e93258fSBjoern A. Zeeb 		   wl->status.map._4way ? "Y" : "N",
78918e93258fSBjoern A. Zeeb 		   wl->status.map.init_ok ? "Y" : "N");
78928e93258fSBjoern A. Zeeb 
78938e93258fSBjoern A. Zeeb 	_show_wl_role_info(rtwdev, m);
78948e93258fSBjoern A. Zeeb }
78958e93258fSBjoern A. Zeeb 
78968e93258fSBjoern A. Zeeb enum btc_bt_a2dp_type {
78978e93258fSBjoern A. Zeeb 	BTC_A2DP_LEGACY = 0,
78988e93258fSBjoern A. Zeeb 	BTC_A2DP_TWS_SNIFF = 1,
78998e93258fSBjoern A. Zeeb 	BTC_A2DP_TWS_RELAY = 2,
79008e93258fSBjoern A. Zeeb };
79018e93258fSBjoern A. Zeeb 
79028e93258fSBjoern A. Zeeb static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
79038e93258fSBjoern A. Zeeb {
79048e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
79058e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
79068e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
79078e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
79088e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
79098e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
79108e93258fSBjoern A. Zeeb 
79118e93258fSBjoern A. Zeeb 	if (hfp.exist) {
79128e93258fSBjoern A. Zeeb 		seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
79138e93258fSBjoern A. Zeeb 			   "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
79148e93258fSBjoern A. Zeeb 			   bt_linfo->sut_pwr_level[0],
79158e93258fSBjoern A. Zeeb 			   bt_linfo->golden_rx_shift[0]);
79168e93258fSBjoern A. Zeeb 	}
79178e93258fSBjoern A. Zeeb 
79188e93258fSBjoern A. Zeeb 	if (hid.exist) {
79198e93258fSBjoern A. Zeeb 		seq_printf(m,
79208e93258fSBjoern A. Zeeb 			   "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
79218e93258fSBjoern A. Zeeb 			   "[HID]",
79228e93258fSBjoern A. Zeeb 			   hid.type & BTC_HID_218 ? "2/18," : "",
79238e93258fSBjoern A. Zeeb 			   hid.type & BTC_HID_418 ? "4/18," : "",
79248e93258fSBjoern A. Zeeb 			   hid.type & BTC_HID_BLE ? "BLE," : "",
79258e93258fSBjoern A. Zeeb 			   hid.type & BTC_HID_RCU ? "RCU," : "",
79268e93258fSBjoern A. Zeeb 			   hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
79278e93258fSBjoern A. Zeeb 			   hid.pair_cnt, bt_linfo->sut_pwr_level[1],
79288e93258fSBjoern A. Zeeb 			   bt_linfo->golden_rx_shift[1]);
79298e93258fSBjoern A. Zeeb 	}
79308e93258fSBjoern A. Zeeb 
79318e93258fSBjoern A. Zeeb 	if (a2dp.exist) {
79328e93258fSBjoern A. Zeeb 		seq_printf(m,
79338e93258fSBjoern A. Zeeb 			   " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
79348e93258fSBjoern A. Zeeb 			   "[A2DP]",
79358e93258fSBjoern A. Zeeb 			   a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
79368e93258fSBjoern A. Zeeb 			    a2dp.bitpool, a2dp.flush_time);
79378e93258fSBjoern A. Zeeb 
79388e93258fSBjoern A. Zeeb 		seq_printf(m,
79398e93258fSBjoern A. Zeeb 			   "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
79408e93258fSBjoern A. Zeeb 			   a2dp.vendor_id, a2dp.device_name,
79418e93258fSBjoern A. Zeeb 			   bt_linfo->sut_pwr_level[2],
79428e93258fSBjoern A. Zeeb 			   bt_linfo->golden_rx_shift[2]);
79438e93258fSBjoern A. Zeeb 	}
79448e93258fSBjoern A. Zeeb 
79458e93258fSBjoern A. Zeeb 	if (pan.exist) {
79468e93258fSBjoern A. Zeeb 		seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
79478e93258fSBjoern A. Zeeb 			   "[PAN]",
79488e93258fSBjoern A. Zeeb 			   bt_linfo->sut_pwr_level[3],
79498e93258fSBjoern A. Zeeb 			   bt_linfo->golden_rx_shift[3]);
79508e93258fSBjoern A. Zeeb 	}
79518e93258fSBjoern A. Zeeb }
79528e93258fSBjoern A. Zeeb 
79538e93258fSBjoern A. Zeeb static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
79548e93258fSBjoern A. Zeeb {
79558e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
7956e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
79578e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
79588e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
79598e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
79608e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
7961*6d67aabdSBjoern A. Zeeb 	union rtw89_btc_module_info *md = &btc->mdinfo;
79628e93258fSBjoern A. Zeeb 	u8 *afh = bt_linfo->afh_map;
7963e2340276SBjoern A. Zeeb 	u8 *afh_le = bt_linfo->afh_map_le;
7964*6d67aabdSBjoern A. Zeeb 	u8 bt_pos;
79658e93258fSBjoern A. Zeeb 
79668e93258fSBjoern A. Zeeb 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
79678e93258fSBjoern A. Zeeb 		return;
79688e93258fSBjoern A. Zeeb 
7969*6d67aabdSBjoern A. Zeeb 	if (ver->fcxinit == 7)
7970*6d67aabdSBjoern A. Zeeb 		bt_pos = md->md_v7.bt_pos;
7971*6d67aabdSBjoern A. Zeeb 	else
7972*6d67aabdSBjoern A. Zeeb 		bt_pos = md->md.bt_pos;
7973*6d67aabdSBjoern A. Zeeb 
79748e93258fSBjoern A. Zeeb 	seq_puts(m, "========== [BT Status] ==========\n");
79758e93258fSBjoern A. Zeeb 
79768e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
79778e93258fSBjoern A. Zeeb 		   "[status]", bt->enable.now ? "Y" : "N",
79788e93258fSBjoern A. Zeeb 		   bt->btg_type ? "Y" : "N",
7979*6d67aabdSBjoern A. Zeeb 		   (bt->enable.now && (bt->btg_type != bt_pos) ?
79808e93258fSBjoern A. Zeeb 		   "(efuse-mismatch!!)" : ""),
79818e93258fSBjoern A. Zeeb 		   (bt_linfo->status.map.connect ? "Y" : "N"));
79828e93258fSBjoern A. Zeeb 
79838e93258fSBjoern A. Zeeb 	seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
79848e93258fSBjoern A. Zeeb 		   bt->igno_wl ? "Y" : "N",
79858e93258fSBjoern A. Zeeb 		   bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
79868e93258fSBjoern A. Zeeb 
79878e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
79888e93258fSBjoern A. Zeeb 		   "[profile]",
79898e93258fSBjoern A. Zeeb 		   (bt_linfo->profile_cnt.now == 0) ? "None," : "",
79908e93258fSBjoern A. Zeeb 		   bt_linfo->hfp_desc.exist ? "HFP," : "",
79918e93258fSBjoern A. Zeeb 		   bt_linfo->hid_desc.exist ? "HID," : "",
79928e93258fSBjoern A. Zeeb 		   bt_linfo->a2dp_desc.exist ?
79938e93258fSBjoern A. Zeeb 		   (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
79948e93258fSBjoern A. Zeeb 		   bt_linfo->pan_desc.exist ? "PAN," : "");
79958e93258fSBjoern A. Zeeb 
79968e93258fSBjoern A. Zeeb 	seq_printf(m,
79978e93258fSBjoern A. Zeeb 		   "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
79988e93258fSBjoern A. Zeeb 		   bt_linfo->multi_link.now ? "Y" : "N",
79998e93258fSBjoern A. Zeeb 		   bt_linfo->slave_role ? "Slave" : "Master",
80008e93258fSBjoern A. Zeeb 		   bt_linfo->status.map.ble_connect ? "Y" : "N",
80018e93258fSBjoern A. Zeeb 		   bt_linfo->cqddr ? "Y" : "N",
80028e93258fSBjoern A. Zeeb 		   bt_linfo->a2dp_desc.active ? "Y" : "N",
80038e93258fSBjoern A. Zeeb 		   bt_linfo->pan_desc.active ? "Y" : "N");
80048e93258fSBjoern A. Zeeb 
80058e93258fSBjoern A. Zeeb 	seq_printf(m,
8006*6d67aabdSBjoern A. Zeeb 		   " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
80078e93258fSBjoern A. Zeeb 		   "[link]", bt_linfo->rssi - 100,
8008*6d67aabdSBjoern A. Zeeb 		   bt->rssi_level,
80098e93258fSBjoern A. Zeeb 		   bt_linfo->tx_3m ? 3 : 2,
80108e93258fSBjoern A. Zeeb 		   bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
80118e93258fSBjoern A. Zeeb 		   bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
80128e93258fSBjoern A. Zeeb 		   bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
80138e93258fSBjoern A. Zeeb 
80148e93258fSBjoern A. Zeeb 	seq_printf(m,
80158e93258fSBjoern A. Zeeb 		   "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
80168e93258fSBjoern A. Zeeb 		   bt_linfo->relink.now ? " ReLink!!" : "",
80178e93258fSBjoern A. Zeeb 		   afh[0], afh[1], afh[2], afh[3], afh[4],
80188e93258fSBjoern A. Zeeb 		   afh[5], afh[6], afh[7], afh[8], afh[9]);
80198e93258fSBjoern A. Zeeb 
8020e2340276SBjoern A. Zeeb 	if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
8021e2340276SBjoern A. Zeeb 		seq_printf(m,
8022e2340276SBjoern A. Zeeb 			   "LE[%02x%02x_%02x_%02x%02x]",
8023e2340276SBjoern A. Zeeb 			   afh_le[0], afh_le[1], afh_le[2],
8024e2340276SBjoern A. Zeeb 			   afh_le[3], afh_le[4]);
8025e2340276SBjoern A. Zeeb 
80268e93258fSBjoern A. Zeeb 	seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
80278e93258fSBjoern A. Zeeb 		   wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
80288e93258fSBjoern A. Zeeb 
80298e93258fSBjoern A. Zeeb 	seq_printf(m,
80308e93258fSBjoern A. Zeeb 		   " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
80318e93258fSBjoern A. Zeeb 		   "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
80328e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
80338e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
80348e93258fSBjoern A. Zeeb 
80358e93258fSBjoern A. Zeeb 	seq_printf(m,
80368e93258fSBjoern A. Zeeb 		   "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
80378e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
80388e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
80398e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
80408e93258fSBjoern A. Zeeb 
80418e93258fSBjoern A. Zeeb 	_show_bt_profile_info(rtwdev, m);
80428e93258fSBjoern A. Zeeb 
80438e93258fSBjoern A. Zeeb 	seq_printf(m,
80448e93258fSBjoern A. Zeeb 		   " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
80458e93258fSBjoern A. Zeeb 		   "[bt_info]", bt->raw_info[2], bt->raw_info[3],
80468e93258fSBjoern A. Zeeb 		   bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
80478e93258fSBjoern A. Zeeb 		   bt->raw_info[7],
80488e93258fSBjoern A. Zeeb 		   bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
80498e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_INFOUPDATE],
80508e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_INFOSAME]);
80518e93258fSBjoern A. Zeeb 
80528e93258fSBjoern A. Zeeb 	seq_printf(m,
8053e2340276SBjoern A. Zeeb 		   " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
80548e93258fSBjoern A. Zeeb 		   "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
80558e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
80568e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
8057e2340276SBjoern A. Zeeb 
8058e2340276SBjoern A. Zeeb 	if (!bt->scan_info_update) {
8059e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true);
8060e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
8061e2340276SBjoern A. Zeeb 	} else {
8062e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false);
8063e2340276SBjoern A. Zeeb 		if (ver->fcxbtscan == 1) {
8064e2340276SBjoern A. Zeeb 			seq_printf(m,
8065e2340276SBjoern A. Zeeb 				   "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
8066e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
8067e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
8068e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
8069e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
8070e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
8071e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
8072e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
8073e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
8074e2340276SBjoern A. Zeeb 		} else if (ver->fcxbtscan == 2) {
8075e2340276SBjoern A. Zeeb 			seq_printf(m,
8076e2340276SBjoern A. Zeeb 				   "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
8077e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
8078e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
8079e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
8080e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
8081e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
8082e2340276SBjoern A. Zeeb 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
8083e2340276SBjoern A. Zeeb 		}
8084e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
8085e2340276SBjoern A. Zeeb 	}
8086e2340276SBjoern A. Zeeb 
8087e2340276SBjoern A. Zeeb 	if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect)
8088e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true);
8089e2340276SBjoern A. Zeeb 	else
8090e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false);
8091e2340276SBjoern A. Zeeb 
8092e2340276SBjoern A. Zeeb 	if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
8093e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true);
8094e2340276SBjoern A. Zeeb 	else
8095e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false);
8096e2340276SBjoern A. Zeeb 
8097e2340276SBjoern A. Zeeb 	if (bt_linfo->a2dp_desc.exist &&
8098e2340276SBjoern A. Zeeb 	    (bt_linfo->a2dp_desc.flush_time == 0 ||
8099e2340276SBjoern A. Zeeb 	     bt_linfo->a2dp_desc.vendor_id == 0 ||
8100e2340276SBjoern A. Zeeb 	     bt_linfo->a2dp_desc.play_latency == 1))
8101e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true);
8102e2340276SBjoern A. Zeeb 	else
8103e2340276SBjoern A. Zeeb 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false);
81048e93258fSBjoern A. Zeeb }
81058e93258fSBjoern A. Zeeb 
81068e93258fSBjoern A. Zeeb #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
81078e93258fSBjoern A. Zeeb #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
81088e93258fSBjoern A. Zeeb #define CASE_BTC_POLICY_STR(e) \
81098e93258fSBjoern A. Zeeb 	case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
8110e2340276SBjoern A. Zeeb #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
8111e2340276SBjoern A. Zeeb #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
8112*6d67aabdSBjoern A. Zeeb #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
8113*6d67aabdSBjoern A. Zeeb #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
8114*6d67aabdSBjoern A. Zeeb #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
8115*6d67aabdSBjoern A. Zeeb #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
8116*6d67aabdSBjoern A. Zeeb #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
8117*6d67aabdSBjoern A. Zeeb 
8118*6d67aabdSBjoern A. Zeeb static const char *id_to_polut(u32 id)
8119*6d67aabdSBjoern A. Zeeb {
8120*6d67aabdSBjoern A. Zeeb 	switch (id) {
8121*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLUT_STR(NONE);
8122*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLUT_STR(GNT_BT_TX);
8123*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLUT_STR(GNT_BT_RX);
8124*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLUT_STR(GNT_WL);
8125*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLUT_STR(BT);
8126*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLUT_STR(ALL);
8127*6d67aabdSBjoern A. Zeeb 	default:
8128*6d67aabdSBjoern A. Zeeb 		return "unknown";
8129*6d67aabdSBjoern A. Zeeb 	}
8130*6d67aabdSBjoern A. Zeeb }
8131*6d67aabdSBjoern A. Zeeb 
8132*6d67aabdSBjoern A. Zeeb static const char *id_to_regtype(u32 id)
8133*6d67aabdSBjoern A. Zeeb {
8134*6d67aabdSBjoern A. Zeeb 	switch (id) {
8135*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(MAC);
8136*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(BB);
8137*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(RF);
8138*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(BT_RF);
8139*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(BT_MODEM);
8140*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
8141*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(BT_VENDOR);
8142*6d67aabdSBjoern A. Zeeb 	CASE_BTC_REGTYPE_STR(BT_LE);
8143*6d67aabdSBjoern A. Zeeb 	default:
8144*6d67aabdSBjoern A. Zeeb 		return "unknown";
8145*6d67aabdSBjoern A. Zeeb 	}
8146*6d67aabdSBjoern A. Zeeb }
8147*6d67aabdSBjoern A. Zeeb 
8148*6d67aabdSBjoern A. Zeeb static const char *id_to_gdbg(u32 id)
8149*6d67aabdSBjoern A. Zeeb {
8150*6d67aabdSBjoern A. Zeeb 	switch (id) {
8151*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(GNT_BT);
8152*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(GNT_WL);
8153*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(BCN_EARLY);
8154*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(WL_NULL0);
8155*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(WL_NULL1);
8156*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(WL_RXISR);
8157*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(TDMA_ENTRY);
8158*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(A2DP_EMPTY);
8159*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(BT_RETRY);
8160*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(BT_RELINK);
8161*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_WL);
8162*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_BT);
8163*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(WL_ERR);
8164*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(WL_OK);
8165*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_B2W);
8166*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_W1);
8167*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_W2);
8168*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_W2B);
8169*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_B1);
8170*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_B2);
8171*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_B3);
8172*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_B4);
8173*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_LK);
8174*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_E2G);
8175*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_E5G);
8176*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_EBT);
8177*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_WLK);
8178*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(SLOT_B1FDD);
8179*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(BT_CHANGE);
8180*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(WL_CCA);
8181*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(BT_LEAUDIO);
8182*6d67aabdSBjoern A. Zeeb 	CASE_BTC_GDBG_STR(USER_DEF);
8183*6d67aabdSBjoern A. Zeeb 	default:
8184*6d67aabdSBjoern A. Zeeb 		return "unknown";
8185*6d67aabdSBjoern A. Zeeb 	}
8186*6d67aabdSBjoern A. Zeeb }
81878e93258fSBjoern A. Zeeb 
81888e93258fSBjoern A. Zeeb static const char *steps_to_str(u16 step)
81898e93258fSBjoern A. Zeeb {
81908e93258fSBjoern A. Zeeb 	switch (step) {
81918e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NONE);
81928e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_INIT);
81938e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_SWBAND);
81948e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_WL_STA);
81958e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
81968e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
81978e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_WL_RFK);
81988e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(UPDATE_BT_INFO);
81998e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_SCAN_START);
82008e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
82018e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
82028e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_POWEROFF);
82038e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
82048e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(CMD_SET_COEX);
82058e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(ACT1_WORK);
82068e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
82078e93258fSBjoern A. Zeeb 	CASE_BTC_RSN_STR(RFK_CHK_WORK);
82088e93258fSBjoern A. Zeeb 
82098e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(NONE);
82108e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_ONLY);
82118e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_5G);
82128e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_OTHER);
82138e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_IDLE);
82148e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_NC);
82158e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_RFK);
82168e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_INIT);
82178e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_OFF);
82188e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(FREERUN);
82198e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_WHQL);
82208e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_RFK);
82218e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_OFF);
82228e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_IDLE);
82238e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_HFP);
82248e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_HID);
82258e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_A2DP);
82268e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_A2DPSINK);
82278e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_PAN);
82288e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_A2DP_HID);
82298e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_A2DP_PAN);
82308e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_PAN_HID);
82318e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
82328e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_25G_MCC);
82338e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_2G_MCC);
82348e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_2G_SCC);
82358e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_2G_AP);
82368e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_2G_GO);
82378e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_2G_GC);
82388e93258fSBjoern A. Zeeb 	CASE_BTC_ACT_STR(WL_2G_NAN);
82398e93258fSBjoern A. Zeeb 
82408e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_BT);
82418e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_WL);
82428e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_EQ0);
82438e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_EQ1);
82448e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_EQ2);
82458e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_EQ3);
8246*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_EQ4);
8247*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_EQ5);
82488e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_BWB0);
82498e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_BWB1);
82508e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_BWB2);
8251e2340276SBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_BWB3);
8252*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFF_WL2);
82538e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFB_BWB0);
82548e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFE_DEF);
82558e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFE_DEF2);
82568e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
82578e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFE_2GISOB);
82588e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
82598e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFE_WL);
82608e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
82618e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD3030);
82628e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD5050);
82638e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD2030);
82648e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD4010);
82658e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD7010);
82668e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD2060);
82678e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD3060);
82688e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD2080);
82698e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TDW1B1);
82708e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD4010ISO);
8271*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
8272*6d67aabdSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
82738e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PFIX_TD3030);
82748e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PFIX_TD5050);
82758e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PFIX_TD2030);
82768e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PFIX_TD2060);
82778e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PFIX_TD3070);
82788e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PFIX_TD2080);
82798e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PFIX_TDW1B1);
82808e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO_TD50B1);
82818e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO_TD60B1);
82828e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO_TD20B1);
82838e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO_TDW1B1);
82848e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO_TD50B1);
82858e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO_TD60B1);
82868e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO_TD20B1);
82878e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
82888e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO2_TD3050);
82898e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO2_TD3070);
82908e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO2_TD5050);
82918e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO2_TD6060);
82928e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO2_TD2080);
82938e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
82948e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO2_TD3050);
82958e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO2_TD3070);
82968e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO2_TD5050);
82978e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO2_TD6060);
82988e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO2_TD2080);
82998e93258fSBjoern A. Zeeb 	CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
83008e93258fSBjoern A. Zeeb 	default:
83018e93258fSBjoern A. Zeeb 		return "unknown step";
83028e93258fSBjoern A. Zeeb 	}
83038e93258fSBjoern A. Zeeb }
83048e93258fSBjoern A. Zeeb 
8305e2340276SBjoern A. Zeeb static const char *id_to_slot(u32 id)
8306e2340276SBjoern A. Zeeb {
8307e2340276SBjoern A. Zeeb 	switch (id) {
8308e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(OFF);
8309e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(B2W);
8310e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(W1);
8311e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(W2);
8312e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(W2B);
8313e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(B1);
8314e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(B2);
8315e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(B3);
8316e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(B4);
8317e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(LK);
8318e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(BLK);
8319e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(E2G);
8320e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(E5G);
8321e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(EBT);
8322e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(ENULL);
8323e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(WLK);
8324e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(W1FDD);
8325e2340276SBjoern A. Zeeb 	CASE_BTC_SLOT_STR(B1FDD);
8326e2340276SBjoern A. Zeeb 	default:
8327e2340276SBjoern A. Zeeb 		return "unknown";
8328e2340276SBjoern A. Zeeb 	}
8329e2340276SBjoern A. Zeeb }
8330e2340276SBjoern A. Zeeb 
8331e2340276SBjoern A. Zeeb static const char *id_to_evt(u32 id)
8332e2340276SBjoern A. Zeeb {
8333e2340276SBjoern A. Zeeb 	switch (id) {
8334e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(TDMA_ENTRY);
8335e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(WL_TMR);
8336e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(B1_TMR);
8337e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(B2_TMR);
8338e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(B3_TMR);
8339e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(B4_TMR);
8340e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(W2B_TMR);
8341e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(B2W_TMR);
8342e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(BCN_EARLY);
8343e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(A2DP_EMPTY);
8344e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(LK_END);
8345e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(RX_ISR);
8346e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(RX_FC0);
8347e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(RX_FC1);
8348e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(BT_RELINK);
8349e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(BT_RETRY);
8350e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(E2G);
8351e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(E5G);
8352e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(EBT);
8353e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(ENULL);
8354e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(DRV_WLK);
8355e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(BCN_OK);
8356e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(BT_CHANGE);
8357e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(EBT_EXTEND);
8358e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(E2G_NULL1);
8359e2340276SBjoern A. Zeeb 	CASE_BTC_EVT_STR(B1FDD_TMR);
8360e2340276SBjoern A. Zeeb 	default:
8361e2340276SBjoern A. Zeeb 		return "unknown";
8362e2340276SBjoern A. Zeeb 	}
8363e2340276SBjoern A. Zeeb }
8364e2340276SBjoern A. Zeeb 
8365*6d67aabdSBjoern A. Zeeb static const char *id_to_mode(u8 id)
8366*6d67aabdSBjoern A. Zeeb {
8367*6d67aabdSBjoern A. Zeeb 	switch (id) {
8368*6d67aabdSBjoern A. Zeeb 	CASE_BTC_INIT(NORMAL);
8369*6d67aabdSBjoern A. Zeeb 	CASE_BTC_INIT(WL);
8370*6d67aabdSBjoern A. Zeeb 	CASE_BTC_INIT(BT);
8371*6d67aabdSBjoern A. Zeeb 	CASE_BTC_INIT(WLOFF);
8372*6d67aabdSBjoern A. Zeeb 	default:
8373*6d67aabdSBjoern A. Zeeb 		return "unknown";
8374*6d67aabdSBjoern A. Zeeb 	}
8375*6d67aabdSBjoern A. Zeeb }
8376*6d67aabdSBjoern A. Zeeb 
8377*6d67aabdSBjoern A. Zeeb static const char *id_to_ant(u32 id)
8378*6d67aabdSBjoern A. Zeeb {
8379*6d67aabdSBjoern A. Zeeb 	switch (id) {
8380*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(WPOWERON);
8381*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(WINIT);
8382*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(WONLY);
8383*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(WOFF);
8384*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(W2G);
8385*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(W5G);
8386*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(W25G);
8387*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(FREERUN);
8388*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(WRFK);
8389*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(BRFK);
8390*6d67aabdSBjoern A. Zeeb 	CASE_BTC_ANTPATH_STR(MAX);
8391*6d67aabdSBjoern A. Zeeb 	default:
8392*6d67aabdSBjoern A. Zeeb 		return "unknown";
8393*6d67aabdSBjoern A. Zeeb 	}
8394*6d67aabdSBjoern A. Zeeb }
8395*6d67aabdSBjoern A. Zeeb 
83968e93258fSBjoern A. Zeeb static
83978e93258fSBjoern A. Zeeb void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
83988e93258fSBjoern A. Zeeb 		       u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
83998e93258fSBjoern A. Zeeb {
84008e93258fSBjoern A. Zeeb 	u8 i;
84018e93258fSBjoern A. Zeeb 	u8 cur_index;
84028e93258fSBjoern A. Zeeb 
84038e93258fSBjoern A. Zeeb 	for (i = 0; i < len ; i++) {
84048e93258fSBjoern A. Zeeb 		if ((i % seg_len) == 0)
84058e93258fSBjoern A. Zeeb 			seq_printf(m, " %-15s : ", prefix);
84068e93258fSBjoern A. Zeeb 		cur_index = (start_idx + i) % ring_len;
84078e93258fSBjoern A. Zeeb 		if (i % 3 == 0)
84088e93258fSBjoern A. Zeeb 			seq_printf(m, "-> %-20s",
84098e93258fSBjoern A. Zeeb 				   steps_to_str(*(data + cur_index)));
84108e93258fSBjoern A. Zeeb 		else if (i % 3 == 1)
84118e93258fSBjoern A. Zeeb 			seq_printf(m, "-> %-15s",
84128e93258fSBjoern A. Zeeb 				   steps_to_str(*(data + cur_index)));
84138e93258fSBjoern A. Zeeb 		else
84148e93258fSBjoern A. Zeeb 			seq_printf(m, "-> %-13s",
84158e93258fSBjoern A. Zeeb 				   steps_to_str(*(data + cur_index)));
84168e93258fSBjoern A. Zeeb 		if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
84178e93258fSBjoern A. Zeeb 			seq_puts(m, "\n");
84188e93258fSBjoern A. Zeeb 	}
84198e93258fSBjoern A. Zeeb }
84208e93258fSBjoern A. Zeeb 
84218e93258fSBjoern A. Zeeb static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
84228e93258fSBjoern A. Zeeb {
84238e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
84248e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
84258e93258fSBjoern A. Zeeb 	u8 start_idx;
84268e93258fSBjoern A. Zeeb 	u8 len;
84278e93258fSBjoern A. Zeeb 
84288e93258fSBjoern A. Zeeb 	len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
84298e93258fSBjoern A. Zeeb 	start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
84308e93258fSBjoern A. Zeeb 
84318e93258fSBjoern A. Zeeb 	seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
84328e93258fSBjoern A. Zeeb 			  ARRAY_SIZE(dm->dm_step.step));
84338e93258fSBjoern A. Zeeb }
84348e93258fSBjoern A. Zeeb 
84358e93258fSBjoern A. Zeeb static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
84368e93258fSBjoern A. Zeeb {
84378e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
8438*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
84398e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
84408e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
84418e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8442*6d67aabdSBjoern A. Zeeb 	u8 igno_bt;
84438e93258fSBjoern A. Zeeb 
84448e93258fSBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
84458e93258fSBjoern A. Zeeb 		return;
84468e93258fSBjoern A. Zeeb 
84478e93258fSBjoern A. Zeeb 	seq_printf(m, "========== [Mechanism Status %s] ==========\n",
8448*6d67aabdSBjoern A. Zeeb 		   (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
84498e93258fSBjoern A. Zeeb 
84508e93258fSBjoern A. Zeeb 	seq_printf(m,
8451*6d67aabdSBjoern A. Zeeb 		   " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
84528e93258fSBjoern A. Zeeb 		   "[status]",
8453*6d67aabdSBjoern A. Zeeb 		   btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
84548e93258fSBjoern A. Zeeb 		   steps_to_str(dm->run_reason),
84558e93258fSBjoern A. Zeeb 		   steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
8456*6d67aabdSBjoern A. Zeeb 		   id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
8457*6d67aabdSBjoern A. Zeeb 		   id_to_mode(wl->coex_mode),
84588e93258fSBjoern A. Zeeb 		   dm->cnt_dm[BTC_DCNT_RUN]);
84598e93258fSBjoern A. Zeeb 
84608e93258fSBjoern A. Zeeb 	_show_dm_step(rtwdev, m);
84618e93258fSBjoern A. Zeeb 
8462*6d67aabdSBjoern A. Zeeb 	if (ver->fcxctrl == 7)
8463*6d67aabdSBjoern A. Zeeb 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
8464*6d67aabdSBjoern A. Zeeb 	else
8465*6d67aabdSBjoern A. Zeeb 		igno_bt = btc->ctrl.ctrl.igno_bt;
8466*6d67aabdSBjoern A. Zeeb 
84678e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
8468*6d67aabdSBjoern A. Zeeb 		   "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt,
84698e93258fSBjoern A. Zeeb 		   dm->freerun, btc->lps, dm->wl_mimo_ps);
84708e93258fSBjoern A. Zeeb 
84718e93258fSBjoern A. Zeeb 	seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
84728e93258fSBjoern A. Zeeb 		   (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
84738e93258fSBjoern A. Zeeb 		   (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
84748e93258fSBjoern A. Zeeb 		    "" : "(Mismatch!!)"));
84758e93258fSBjoern A. Zeeb 
84768e93258fSBjoern A. Zeeb 	if (dm->rf_trx_para.wl_tx_power == 0xff)
84778e93258fSBjoern A. Zeeb 		seq_printf(m,
84788e93258fSBjoern A. Zeeb 			   " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
84798e93258fSBjoern A. Zeeb 			   "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
84808e93258fSBjoern A. Zeeb 
84818e93258fSBjoern A. Zeeb 	else
84828e93258fSBjoern A. Zeeb 		seq_printf(m,
84838e93258fSBjoern A. Zeeb 			   " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
84848e93258fSBjoern A. Zeeb 			   "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
84858e93258fSBjoern A. Zeeb 			   dm->rf_trx_para.wl_tx_power);
84868e93258fSBjoern A. Zeeb 
84878e93258fSBjoern A. Zeeb 	seq_printf(m,
84888e93258fSBjoern A. Zeeb 		   "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
84898e93258fSBjoern A. Zeeb 		   dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
84908e93258fSBjoern A. Zeeb 		   dm->rf_trx_para.bt_rx_gain,
84918e93258fSBjoern A. Zeeb 		   (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
84928e93258fSBjoern A. Zeeb 
84938e93258fSBjoern A. Zeeb 	seq_printf(m,
8494e2340276SBjoern A. Zeeb 		   " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
84958e93258fSBjoern A. Zeeb 		   "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
8496e2340276SBjoern A. Zeeb 		   dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri);
84978e93258fSBjoern A. Zeeb }
84988e93258fSBjoern A. Zeeb 
84998e93258fSBjoern A. Zeeb static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
85008e93258fSBjoern A. Zeeb {
85018e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
8502e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
85038e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8504e2340276SBjoern A. Zeeb 	union rtw89_btc_fbtc_cysta_info *pcysta;
8505e2340276SBjoern A. Zeeb 	u32 except_cnt, exception_map;
85068e93258fSBjoern A. Zeeb 
85078e93258fSBjoern A. Zeeb 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
8508e2340276SBjoern A. Zeeb 	if (ver->fcxcysta == 2) {
8509e2340276SBjoern A. Zeeb 		pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
8510e2340276SBjoern A. Zeeb 		except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
8511e2340276SBjoern A. Zeeb 		exception_map = le32_to_cpu(pcysta->v2.exception);
8512e2340276SBjoern A. Zeeb 	} else if (ver->fcxcysta == 3) {
8513e2340276SBjoern A. Zeeb 		pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
8514e2340276SBjoern A. Zeeb 		except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
8515e2340276SBjoern A. Zeeb 		exception_map = le32_to_cpu(pcysta->v3.except_map);
8516e2340276SBjoern A. Zeeb 	} else if (ver->fcxcysta == 4) {
8517e2340276SBjoern A. Zeeb 		pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
8518e2340276SBjoern A. Zeeb 		except_cnt = pcysta->v4.except_cnt;
8519e2340276SBjoern A. Zeeb 		exception_map = le32_to_cpu(pcysta->v4.except_map);
8520e2340276SBjoern A. Zeeb 	} else if (ver->fcxcysta == 5) {
8521e2340276SBjoern A. Zeeb 		pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
8522e2340276SBjoern A. Zeeb 		except_cnt = pcysta->v5.except_cnt;
8523e2340276SBjoern A. Zeeb 		exception_map = le32_to_cpu(pcysta->v5.except_map);
8524*6d67aabdSBjoern A. Zeeb 	} else if (ver->fcxcysta == 7) {
8525*6d67aabdSBjoern A. Zeeb 		pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
8526*6d67aabdSBjoern A. Zeeb 		except_cnt = pcysta->v7.except_cnt;
8527*6d67aabdSBjoern A. Zeeb 		exception_map = le32_to_cpu(pcysta->v7.except_map);
8528e2340276SBjoern A. Zeeb 	} else {
8529e2340276SBjoern A. Zeeb 		return;
8530e2340276SBjoern A. Zeeb 	}
85318e93258fSBjoern A. Zeeb 
8532e2340276SBjoern A. Zeeb 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
85338e93258fSBjoern A. Zeeb 	    !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
85348e93258fSBjoern A. Zeeb 		return;
85358e93258fSBjoern A. Zeeb 
85368e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : ", "[error]");
85378e93258fSBjoern A. Zeeb 
85388e93258fSBjoern A. Zeeb 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
85398e93258fSBjoern A. Zeeb 		seq_printf(m,
85408e93258fSBjoern A. Zeeb 			   "overflow-cnt: %d, ",
85418e93258fSBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
85428e93258fSBjoern A. Zeeb 	}
85438e93258fSBjoern A. Zeeb 
85448e93258fSBjoern A. Zeeb 	if (pfwinfo->len_mismch) {
85458e93258fSBjoern A. Zeeb 		seq_printf(m,
85468e93258fSBjoern A. Zeeb 			   "len-mismatch: 0x%x, ",
85478e93258fSBjoern A. Zeeb 			   pfwinfo->len_mismch);
85488e93258fSBjoern A. Zeeb 	}
85498e93258fSBjoern A. Zeeb 
85508e93258fSBjoern A. Zeeb 	if (pfwinfo->fver_mismch) {
85518e93258fSBjoern A. Zeeb 		seq_printf(m,
85528e93258fSBjoern A. Zeeb 			   "fver-mismatch: 0x%x, ",
85538e93258fSBjoern A. Zeeb 			   pfwinfo->fver_mismch);
85548e93258fSBjoern A. Zeeb 	}
85558e93258fSBjoern A. Zeeb 
85568e93258fSBjoern A. Zeeb 	/* cycle statistics exceptions */
8557e2340276SBjoern A. Zeeb 	if (exception_map || except_cnt) {
85588e93258fSBjoern A. Zeeb 		seq_printf(m,
85598e93258fSBjoern A. Zeeb 			   "exception-type: 0x%x, exception-cnt = %d",
8560e2340276SBjoern A. Zeeb 			   exception_map, except_cnt);
85618e93258fSBjoern A. Zeeb 	}
85628e93258fSBjoern A. Zeeb 	seq_puts(m, "\n");
85638e93258fSBjoern A. Zeeb }
85648e93258fSBjoern A. Zeeb 
85658e93258fSBjoern A. Zeeb static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
85668e93258fSBjoern A. Zeeb {
85678e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
8568e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
85698e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
85708e93258fSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
85718e93258fSBjoern A. Zeeb 	struct rtw89_btc_fbtc_tdma *t = NULL;
85728e93258fSBjoern A. Zeeb 
85738e93258fSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
85748e93258fSBjoern A. Zeeb 	if (!pcinfo->valid)
85758e93258fSBjoern A. Zeeb 		return;
85768e93258fSBjoern A. Zeeb 
8577e2340276SBjoern A. Zeeb 	if (ver->fcxtdma == 1)
8578e2340276SBjoern A. Zeeb 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
8579e2340276SBjoern A. Zeeb 	else
8580e2340276SBjoern A. Zeeb 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
85818e93258fSBjoern A. Zeeb 
85828e93258fSBjoern A. Zeeb 	seq_printf(m,
85838e93258fSBjoern A. Zeeb 		   " %-15s : ", "[tdma_policy]");
85848e93258fSBjoern A. Zeeb 	seq_printf(m,
85858e93258fSBjoern A. Zeeb 		   "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
85868e93258fSBjoern A. Zeeb 		   (u32)t->type,
85878e93258fSBjoern A. Zeeb 		   t->rxflctrl, t->txpause);
85888e93258fSBjoern A. Zeeb 
85898e93258fSBjoern A. Zeeb 	seq_printf(m,
85908e93258fSBjoern A. Zeeb 		   "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
85918e93258fSBjoern A. Zeeb 		   t->wtgle_n, t->leak_n, t->ext_ctrl);
85928e93258fSBjoern A. Zeeb 
85938e93258fSBjoern A. Zeeb 	seq_printf(m,
85948e93258fSBjoern A. Zeeb 		   "policy_type:%d",
85958e93258fSBjoern A. Zeeb 		   (u32)btc->policy_type);
85968e93258fSBjoern A. Zeeb 
85978e93258fSBjoern A. Zeeb 	seq_puts(m, "\n");
85988e93258fSBjoern A. Zeeb }
85998e93258fSBjoern A. Zeeb 
86008e93258fSBjoern A. Zeeb static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
86018e93258fSBjoern A. Zeeb {
86028e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
8603e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
8604*6d67aabdSBjoern A. Zeeb 	u16 dur, cxtype;
8605*6d67aabdSBjoern A. Zeeb 	u32 tbl;
86068e93258fSBjoern A. Zeeb 	u8 i = 0;
86078e93258fSBjoern A. Zeeb 
86088e93258fSBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
8609*6d67aabdSBjoern A. Zeeb 		if (btc->ver->fcxslots == 1) {
8610*6d67aabdSBjoern A. Zeeb 			dur = le16_to_cpu(dm->slot_now.v1[i].dur);
8611*6d67aabdSBjoern A. Zeeb 			tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
8612*6d67aabdSBjoern A. Zeeb 			cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
8613*6d67aabdSBjoern A. Zeeb 		} else if (btc->ver->fcxslots == 7) {
8614*6d67aabdSBjoern A. Zeeb 			dur = le16_to_cpu(dm->slot_now.v7[i].dur);
8615*6d67aabdSBjoern A. Zeeb 			tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
8616*6d67aabdSBjoern A. Zeeb 			cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
8617*6d67aabdSBjoern A. Zeeb 		} else {
8618*6d67aabdSBjoern A. Zeeb 			return;
8619*6d67aabdSBjoern A. Zeeb 		}
8620*6d67aabdSBjoern A. Zeeb 
8621e2340276SBjoern A. Zeeb 		if (i % 5 == 0)
86228e93258fSBjoern A. Zeeb 			seq_printf(m,
8623e2340276SBjoern A. Zeeb 				   " %-15s : %5s[%03d/0x%x/%d]",
86248e93258fSBjoern A. Zeeb 				   "[slot_list]",
8625e2340276SBjoern A. Zeeb 				   id_to_slot((u32)i),
8626*6d67aabdSBjoern A. Zeeb 				   dur, tbl, cxtype);
86278e93258fSBjoern A. Zeeb 		else
86288e93258fSBjoern A. Zeeb 			seq_printf(m,
8629e2340276SBjoern A. Zeeb 				   ", %5s[%03d/0x%x/%d]",
8630e2340276SBjoern A. Zeeb 				   id_to_slot((u32)i),
8631*6d67aabdSBjoern A. Zeeb 				   dur, tbl, cxtype);
8632*6d67aabdSBjoern A. Zeeb 
8633e2340276SBjoern A. Zeeb 		if (i % 5 == 4)
86348e93258fSBjoern A. Zeeb 			seq_puts(m, "\n");
86358e93258fSBjoern A. Zeeb 	}
8636e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
86378e93258fSBjoern A. Zeeb }
86388e93258fSBjoern A. Zeeb 
8639e2340276SBjoern A. Zeeb static void _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
86408e93258fSBjoern A. Zeeb {
86418e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
86428e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
86438e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
86448e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
86458e93258fSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
8646e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
86478e93258fSBjoern A. Zeeb 	union rtw89_btc_fbtc_rxflct r;
86488e93258fSBjoern A. Zeeb 	u8 i, cnt = 0, slot_pair;
86498e93258fSBjoern A. Zeeb 	u16 cycle, c_begin, c_end, store_index;
86508e93258fSBjoern A. Zeeb 
86518e93258fSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
86528e93258fSBjoern A. Zeeb 	if (!pcinfo->valid)
86538e93258fSBjoern A. Zeeb 		return;
86548e93258fSBjoern A. Zeeb 
8655e2340276SBjoern A. Zeeb 	pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
86568e93258fSBjoern A. Zeeb 	seq_printf(m,
86578e93258fSBjoern A. Zeeb 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
8658e2340276SBjoern A. Zeeb 		   "[cycle_cnt]",
8659e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->cycles),
8660e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
8661e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
8662e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
8663e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
86648e93258fSBjoern A. Zeeb 
86658e93258fSBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
8666e2340276SBjoern A. Zeeb 		if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
86678e93258fSBjoern A. Zeeb 			continue;
8668e2340276SBjoern A. Zeeb 		seq_printf(m, ", %s:%d", id_to_slot((u32)i),
8669e2340276SBjoern A. Zeeb 			   le32_to_cpu(pcysta_le32->slot_cnt[i]));
86708e93258fSBjoern A. Zeeb 	}
86718e93258fSBjoern A. Zeeb 
86728e93258fSBjoern A. Zeeb 	if (dm->tdma_now.rxflctrl) {
8673e2340276SBjoern A. Zeeb 		seq_printf(m, ", leak_rx:%d",
8674e2340276SBjoern A. Zeeb 			   le32_to_cpu(pcysta_le32->leakrx_cnt));
86758e93258fSBjoern A. Zeeb 	}
86768e93258fSBjoern A. Zeeb 
8677e2340276SBjoern A. Zeeb 	if (le32_to_cpu(pcysta_le32->collision_cnt)) {
8678e2340276SBjoern A. Zeeb 		seq_printf(m, ", collision:%d",
8679e2340276SBjoern A. Zeeb 			   le32_to_cpu(pcysta_le32->collision_cnt));
86808e93258fSBjoern A. Zeeb 	}
86818e93258fSBjoern A. Zeeb 
8682e2340276SBjoern A. Zeeb 	if (le32_to_cpu(pcysta_le32->skip_cnt)) {
8683e2340276SBjoern A. Zeeb 		seq_printf(m, ", skip:%d",
8684e2340276SBjoern A. Zeeb 			   le32_to_cpu(pcysta_le32->skip_cnt));
86858e93258fSBjoern A. Zeeb 	}
86868e93258fSBjoern A. Zeeb 	seq_puts(m, "\n");
86878e93258fSBjoern A. Zeeb 
86888e93258fSBjoern A. Zeeb 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
86898e93258fSBjoern A. Zeeb 		   "[cycle_time]",
8690e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
8691e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
8692e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
8693e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
8694e2340276SBjoern A. Zeeb 	seq_printf(m, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
8695e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
8696e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
8697e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
8698e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
8699e2340276SBjoern A. Zeeb 	seq_printf(m, ", maxdiff_t[wl:%d/bt:%d]\n",
8700e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
8701e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
87028e93258fSBjoern A. Zeeb 
8703e2340276SBjoern A. Zeeb 	if (le16_to_cpu(pcysta_le32->cycles) <= 1)
87048e93258fSBjoern A. Zeeb 		return;
87058e93258fSBjoern A. Zeeb 
87068e93258fSBjoern A. Zeeb 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
87078e93258fSBjoern A. Zeeb 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
87088e93258fSBjoern A. Zeeb 
8709e2340276SBjoern A. Zeeb 	if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
87108e93258fSBjoern A. Zeeb 		c_begin = 1;
87118e93258fSBjoern A. Zeeb 	else
8712e2340276SBjoern A. Zeeb 		c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
87138e93258fSBjoern A. Zeeb 
8714e2340276SBjoern A. Zeeb 	c_end = le16_to_cpu(pcysta_le32->cycles);
87158e93258fSBjoern A. Zeeb 
87168e93258fSBjoern A. Zeeb 	for (cycle = c_begin; cycle <= c_end; cycle++) {
87178e93258fSBjoern A. Zeeb 		cnt++;
87188e93258fSBjoern A. Zeeb 		store_index = ((cycle - 1) % slot_pair) * 2;
87198e93258fSBjoern A. Zeeb 
87208e93258fSBjoern A. Zeeb 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
87218e93258fSBjoern A. Zeeb 			seq_printf(m,
87228e93258fSBjoern A. Zeeb 				   " %-15s : ->b%02d->w%02d", "[cycle_step]",
8723e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
8724e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
87258e93258fSBjoern A. Zeeb 		else
87268e93258fSBjoern A. Zeeb 			seq_printf(m,
87278e93258fSBjoern A. Zeeb 				   "->b%02d->w%02d",
8728e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
8729e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
87308e93258fSBjoern A. Zeeb 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
87318e93258fSBjoern A. Zeeb 			seq_puts(m, "\n");
87328e93258fSBjoern A. Zeeb 	}
87338e93258fSBjoern A. Zeeb 
87348e93258fSBjoern A. Zeeb 	if (a2dp->exist) {
87358e93258fSBjoern A. Zeeb 		seq_printf(m,
87368e93258fSBjoern A. Zeeb 			   " %-15s : a2dp_ept:%d, a2dp_late:%d",
87378e93258fSBjoern A. Zeeb 			   "[a2dp_t_sta]",
8738e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta_le32->a2dpept),
8739e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta_le32->a2dpeptto));
87408e93258fSBjoern A. Zeeb 
87418e93258fSBjoern A. Zeeb 		seq_printf(m,
87428e93258fSBjoern A. Zeeb 			   ", avg_t:%d, max_t:%d",
8743e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta_le32->tavg_a2dpept),
8744e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta_le32->tmax_a2dpept));
87458e93258fSBjoern A. Zeeb 		r.val = dm->tdma_now.rxflctrl;
87468e93258fSBjoern A. Zeeb 
87478e93258fSBjoern A. Zeeb 		if (r.type && r.tgln_n) {
87488e93258fSBjoern A. Zeeb 			seq_printf(m,
87498e93258fSBjoern A. Zeeb 				   ", cycle[PSTDMA:%d/TDMA:%d], ",
8750e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
8751e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
87528e93258fSBjoern A. Zeeb 
87538e93258fSBjoern A. Zeeb 			seq_printf(m,
87548e93258fSBjoern A. Zeeb 				   "avg_t[PSTDMA:%d/TDMA:%d], ",
8755e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
8756e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
87578e93258fSBjoern A. Zeeb 
87588e93258fSBjoern A. Zeeb 			seq_printf(m,
87598e93258fSBjoern A. Zeeb 				   "max_t[PSTDMA:%d/TDMA:%d]",
8760e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
8761e2340276SBjoern A. Zeeb 				   le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
87628e93258fSBjoern A. Zeeb 		}
87638e93258fSBjoern A. Zeeb 		seq_puts(m, "\n");
87648e93258fSBjoern A. Zeeb 	}
87658e93258fSBjoern A. Zeeb }
87668e93258fSBjoern A. Zeeb 
8767e2340276SBjoern A. Zeeb static void _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, struct seq_file *m)
8768e2340276SBjoern A. Zeeb {
8769e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
8770e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
8771e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8772e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
8773e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
8774e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_cysta_v3 *pcysta;
8775e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
8776e2340276SBjoern A. Zeeb 	u8 i, cnt = 0, slot_pair, divide_cnt;
8777e2340276SBjoern A. Zeeb 	u16 cycle, c_begin, c_end, store_index;
8778e2340276SBjoern A. Zeeb 
8779e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
8780e2340276SBjoern A. Zeeb 	if (!pcinfo->valid)
8781e2340276SBjoern A. Zeeb 		return;
8782e2340276SBjoern A. Zeeb 
8783e2340276SBjoern A. Zeeb 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
8784e2340276SBjoern A. Zeeb 	seq_printf(m,
8785e2340276SBjoern A. Zeeb 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
8786e2340276SBjoern A. Zeeb 		   "[cycle_cnt]",
8787e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycles),
8788e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
8789e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
8790e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
8791e2340276SBjoern A. Zeeb 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
8792e2340276SBjoern A. Zeeb 
8793e2340276SBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
8794e2340276SBjoern A. Zeeb 		if (!le32_to_cpu(pcysta->slot_cnt[i]))
8795e2340276SBjoern A. Zeeb 			continue;
8796e2340276SBjoern A. Zeeb 
8797e2340276SBjoern A. Zeeb 		seq_printf(m, ", %s:%d", id_to_slot(i),
8798e2340276SBjoern A. Zeeb 			   le32_to_cpu(pcysta->slot_cnt[i]));
8799e2340276SBjoern A. Zeeb 	}
8800e2340276SBjoern A. Zeeb 
8801e2340276SBjoern A. Zeeb 	if (dm->tdma_now.rxflctrl)
8802e2340276SBjoern A. Zeeb 		seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr));
8803e2340276SBjoern A. Zeeb 
8804e2340276SBjoern A. Zeeb 	if (le32_to_cpu(pcysta->collision_cnt))
8805e2340276SBjoern A. Zeeb 		seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt));
8806e2340276SBjoern A. Zeeb 
8807e2340276SBjoern A. Zeeb 	if (le32_to_cpu(pcysta->skip_cnt))
8808e2340276SBjoern A. Zeeb 		seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt));
8809e2340276SBjoern A. Zeeb 
8810e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
8811e2340276SBjoern A. Zeeb 
8812e2340276SBjoern A. Zeeb 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
8813e2340276SBjoern A. Zeeb 		   "[cycle_time]",
8814e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
8815e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
8816e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
8817e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
8818e2340276SBjoern A. Zeeb 	seq_printf(m,
8819e2340276SBjoern A. Zeeb 		   ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
8820e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
8821e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
8822e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
8823e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
8824e2340276SBjoern A. Zeeb 	seq_printf(m,
8825e2340276SBjoern A. Zeeb 		   ", maxdiff_t[wl:%d/bt:%d]\n",
8826e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
8827e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
8828e2340276SBjoern A. Zeeb 
8829e2340276SBjoern A. Zeeb 	cycle = le16_to_cpu(pcysta->cycles);
8830e2340276SBjoern A. Zeeb 	if (cycle <= 1)
8831e2340276SBjoern A. Zeeb 		return;
8832e2340276SBjoern A. Zeeb 
8833e2340276SBjoern A. Zeeb 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
8834e2340276SBjoern A. Zeeb 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
8835e2340276SBjoern A. Zeeb 
8836e2340276SBjoern A. Zeeb 	if (cycle <= slot_pair)
8837e2340276SBjoern A. Zeeb 		c_begin = 1;
8838e2340276SBjoern A. Zeeb 	else
8839e2340276SBjoern A. Zeeb 		c_begin = cycle - slot_pair + 1;
8840e2340276SBjoern A. Zeeb 
8841e2340276SBjoern A. Zeeb 	c_end = cycle;
8842e2340276SBjoern A. Zeeb 
8843e2340276SBjoern A. Zeeb 	if (a2dp->exist)
8844e2340276SBjoern A. Zeeb 		divide_cnt = 3;
8845e2340276SBjoern A. Zeeb 	else
8846e2340276SBjoern A. Zeeb 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
8847e2340276SBjoern A. Zeeb 
8848e2340276SBjoern A. Zeeb 	for (cycle = c_begin; cycle <= c_end; cycle++) {
8849e2340276SBjoern A. Zeeb 		cnt++;
8850e2340276SBjoern A. Zeeb 		store_index = ((cycle - 1) % slot_pair) * 2;
8851e2340276SBjoern A. Zeeb 
8852e2340276SBjoern A. Zeeb 		if (cnt % divide_cnt == 1)
8853e2340276SBjoern A. Zeeb 			seq_printf(m, " %-15s : ", "[cycle_step]");
8854e2340276SBjoern A. Zeeb 
8855e2340276SBjoern A. Zeeb 		seq_printf(m, "->b%02d",
8856e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_step_time[store_index]));
8857e2340276SBjoern A. Zeeb 		if (a2dp->exist) {
8858e2340276SBjoern A. Zeeb 			a2dp_trx = &pcysta->a2dp_trx[store_index];
8859e2340276SBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
8860e2340276SBjoern A. Zeeb 				   a2dp_trx->empty_cnt,
8861e2340276SBjoern A. Zeeb 				   a2dp_trx->retry_cnt,
8862e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_rate ? 3 : 2,
8863e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_cnt,
8864e2340276SBjoern A. Zeeb 				   a2dp_trx->ack_cnt,
8865e2340276SBjoern A. Zeeb 				   a2dp_trx->nack_cnt);
8866e2340276SBjoern A. Zeeb 		}
8867e2340276SBjoern A. Zeeb 		seq_printf(m, "->w%02d",
8868e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
8869e2340276SBjoern A. Zeeb 		if (a2dp->exist) {
8870e2340276SBjoern A. Zeeb 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
8871e2340276SBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
8872e2340276SBjoern A. Zeeb 				   a2dp_trx->empty_cnt,
8873e2340276SBjoern A. Zeeb 				   a2dp_trx->retry_cnt,
8874e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_rate ? 3 : 2,
8875e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_cnt,
8876e2340276SBjoern A. Zeeb 				   a2dp_trx->ack_cnt,
8877e2340276SBjoern A. Zeeb 				   a2dp_trx->nack_cnt);
8878e2340276SBjoern A. Zeeb 		}
8879e2340276SBjoern A. Zeeb 		if (cnt % divide_cnt == 0 || cnt == c_end)
8880e2340276SBjoern A. Zeeb 			seq_puts(m, "\n");
8881e2340276SBjoern A. Zeeb 	}
8882e2340276SBjoern A. Zeeb 
8883e2340276SBjoern A. Zeeb 	if (a2dp->exist) {
8884e2340276SBjoern A. Zeeb 		seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
8885e2340276SBjoern A. Zeeb 			   "[a2dp_t_sta]",
8886e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
8887e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
8888e2340276SBjoern A. Zeeb 
8889e2340276SBjoern A. Zeeb 		seq_printf(m, ", avg_t:%d, max_t:%d",
8890e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
8891e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
8892e2340276SBjoern A. Zeeb 
8893e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
8894e2340276SBjoern A. Zeeb 	}
8895e2340276SBjoern A. Zeeb }
8896e2340276SBjoern A. Zeeb 
8897e2340276SBjoern A. Zeeb static void _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, struct seq_file *m)
8898e2340276SBjoern A. Zeeb {
8899e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
8900e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
8901e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8902e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
8903e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
8904e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_cysta_v4 *pcysta;
8905e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
8906e2340276SBjoern A. Zeeb 	u8 i, cnt = 0, slot_pair, divide_cnt;
8907e2340276SBjoern A. Zeeb 	u16 cycle, c_begin, c_end, store_index;
8908e2340276SBjoern A. Zeeb 
8909e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
8910e2340276SBjoern A. Zeeb 	if (!pcinfo->valid)
8911e2340276SBjoern A. Zeeb 		return;
8912e2340276SBjoern A. Zeeb 
8913e2340276SBjoern A. Zeeb 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
8914e2340276SBjoern A. Zeeb 	seq_printf(m,
8915e2340276SBjoern A. Zeeb 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
8916e2340276SBjoern A. Zeeb 		   "[cycle_cnt]",
8917e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycles),
8918e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
8919e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
8920e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
8921e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
8922e2340276SBjoern A. Zeeb 
8923e2340276SBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
8924e2340276SBjoern A. Zeeb 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
8925e2340276SBjoern A. Zeeb 			continue;
8926e2340276SBjoern A. Zeeb 
8927e2340276SBjoern A. Zeeb 		seq_printf(m, ", %s:%d", id_to_slot(i),
8928e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_cnt[i]));
8929e2340276SBjoern A. Zeeb 	}
8930e2340276SBjoern A. Zeeb 
8931e2340276SBjoern A. Zeeb 	if (dm->tdma_now.rxflctrl)
8932e2340276SBjoern A. Zeeb 		seq_printf(m, ", leak_rx:%d",
8933e2340276SBjoern A. Zeeb 			   le32_to_cpu(pcysta->leak_slot.cnt_rximr));
8934e2340276SBjoern A. Zeeb 
8935e2340276SBjoern A. Zeeb 	if (pcysta->collision_cnt)
8936e2340276SBjoern A. Zeeb 		seq_printf(m, ", collision:%d", pcysta->collision_cnt);
8937e2340276SBjoern A. Zeeb 
8938e2340276SBjoern A. Zeeb 	if (le16_to_cpu(pcysta->skip_cnt))
8939e2340276SBjoern A. Zeeb 		seq_printf(m, ", skip:%d",
8940e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->skip_cnt));
8941e2340276SBjoern A. Zeeb 
8942e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
8943e2340276SBjoern A. Zeeb 
8944e2340276SBjoern A. Zeeb 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
8945e2340276SBjoern A. Zeeb 		   "[cycle_time]",
8946e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
8947e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
8948e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
8949e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
8950e2340276SBjoern A. Zeeb 	seq_printf(m,
8951e2340276SBjoern A. Zeeb 		   ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
8952e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
8953e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
8954e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
8955e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
8956e2340276SBjoern A. Zeeb 	seq_printf(m,
8957e2340276SBjoern A. Zeeb 		   ", maxdiff_t[wl:%d/bt:%d]\n",
8958e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
8959e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
8960e2340276SBjoern A. Zeeb 
8961e2340276SBjoern A. Zeeb 	cycle = le16_to_cpu(pcysta->cycles);
8962e2340276SBjoern A. Zeeb 	if (cycle <= 1)
8963e2340276SBjoern A. Zeeb 		return;
8964e2340276SBjoern A. Zeeb 
8965e2340276SBjoern A. Zeeb 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
8966e2340276SBjoern A. Zeeb 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
8967e2340276SBjoern A. Zeeb 
8968e2340276SBjoern A. Zeeb 	if (cycle <= slot_pair)
8969e2340276SBjoern A. Zeeb 		c_begin = 1;
8970e2340276SBjoern A. Zeeb 	else
8971e2340276SBjoern A. Zeeb 		c_begin = cycle - slot_pair + 1;
8972e2340276SBjoern A. Zeeb 
8973e2340276SBjoern A. Zeeb 	c_end = cycle;
8974e2340276SBjoern A. Zeeb 
8975e2340276SBjoern A. Zeeb 	if (a2dp->exist)
8976e2340276SBjoern A. Zeeb 		divide_cnt = 3;
8977e2340276SBjoern A. Zeeb 	else
8978e2340276SBjoern A. Zeeb 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
8979e2340276SBjoern A. Zeeb 
8980e2340276SBjoern A. Zeeb 	for (cycle = c_begin; cycle <= c_end; cycle++) {
8981e2340276SBjoern A. Zeeb 		cnt++;
8982e2340276SBjoern A. Zeeb 		store_index = ((cycle - 1) % slot_pair) * 2;
8983e2340276SBjoern A. Zeeb 
8984e2340276SBjoern A. Zeeb 		if (cnt % divide_cnt == 1)
8985e2340276SBjoern A. Zeeb 			seq_printf(m, " %-15s : ", "[cycle_step]");
8986e2340276SBjoern A. Zeeb 
8987e2340276SBjoern A. Zeeb 		seq_printf(m, "->b%02d",
8988e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_step_time[store_index]));
8989e2340276SBjoern A. Zeeb 		if (a2dp->exist) {
8990e2340276SBjoern A. Zeeb 			a2dp_trx = &pcysta->a2dp_trx[store_index];
8991e2340276SBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
8992e2340276SBjoern A. Zeeb 				   a2dp_trx->empty_cnt,
8993e2340276SBjoern A. Zeeb 				   a2dp_trx->retry_cnt,
8994e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_rate ? 3 : 2,
8995e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_cnt,
8996e2340276SBjoern A. Zeeb 				   a2dp_trx->ack_cnt,
8997e2340276SBjoern A. Zeeb 				   a2dp_trx->nack_cnt);
8998e2340276SBjoern A. Zeeb 		}
8999e2340276SBjoern A. Zeeb 		seq_printf(m, "->w%02d",
9000e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
9001e2340276SBjoern A. Zeeb 		if (a2dp->exist) {
9002e2340276SBjoern A. Zeeb 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
9003e2340276SBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9004e2340276SBjoern A. Zeeb 				   a2dp_trx->empty_cnt,
9005e2340276SBjoern A. Zeeb 				   a2dp_trx->retry_cnt,
9006e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_rate ? 3 : 2,
9007e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_cnt,
9008e2340276SBjoern A. Zeeb 				   a2dp_trx->ack_cnt,
9009e2340276SBjoern A. Zeeb 				   a2dp_trx->nack_cnt);
9010e2340276SBjoern A. Zeeb 		}
9011e2340276SBjoern A. Zeeb 		if (cnt % divide_cnt == 0 || cnt == c_end)
9012e2340276SBjoern A. Zeeb 			seq_puts(m, "\n");
9013e2340276SBjoern A. Zeeb 	}
9014e2340276SBjoern A. Zeeb 
9015e2340276SBjoern A. Zeeb 	if (a2dp->exist) {
9016e2340276SBjoern A. Zeeb 		seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
9017e2340276SBjoern A. Zeeb 			   "[a2dp_t_sta]",
9018e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
9019e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
9020e2340276SBjoern A. Zeeb 
9021e2340276SBjoern A. Zeeb 		seq_printf(m, ", avg_t:%d, max_t:%d",
9022e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
9023e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
9024e2340276SBjoern A. Zeeb 
9025e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
9026e2340276SBjoern A. Zeeb 	}
9027e2340276SBjoern A. Zeeb }
9028e2340276SBjoern A. Zeeb 
9029e2340276SBjoern A. Zeeb static void _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, struct seq_file *m)
9030e2340276SBjoern A. Zeeb {
9031e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9032e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9033e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9034e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
9035e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
9036e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_cysta_v5 *pcysta;
9037e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9038e2340276SBjoern A. Zeeb 	u8 i, cnt = 0, slot_pair, divide_cnt;
9039e2340276SBjoern A. Zeeb 	u16 cycle, c_begin, c_end, store_index;
9040e2340276SBjoern A. Zeeb 
9041e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9042e2340276SBjoern A. Zeeb 	if (!pcinfo->valid)
9043e2340276SBjoern A. Zeeb 		return;
9044e2340276SBjoern A. Zeeb 
9045e2340276SBjoern A. Zeeb 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
9046e2340276SBjoern A. Zeeb 	seq_printf(m,
9047e2340276SBjoern A. Zeeb 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9048e2340276SBjoern A. Zeeb 		   "[cycle_cnt]",
9049e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycles),
9050e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9051e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9052e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9053e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9054e2340276SBjoern A. Zeeb 
9055e2340276SBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
9056e2340276SBjoern A. Zeeb 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
9057e2340276SBjoern A. Zeeb 			continue;
9058e2340276SBjoern A. Zeeb 
9059e2340276SBjoern A. Zeeb 		seq_printf(m, ", %s:%d", id_to_slot(i),
9060e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_cnt[i]));
9061e2340276SBjoern A. Zeeb 	}
9062e2340276SBjoern A. Zeeb 
9063e2340276SBjoern A. Zeeb 	if (dm->tdma_now.rxflctrl)
9064e2340276SBjoern A. Zeeb 		seq_printf(m, ", leak_rx:%d",
9065e2340276SBjoern A. Zeeb 			   le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9066e2340276SBjoern A. Zeeb 
9067e2340276SBjoern A. Zeeb 	if (pcysta->collision_cnt)
9068e2340276SBjoern A. Zeeb 		seq_printf(m, ", collision:%d", pcysta->collision_cnt);
9069e2340276SBjoern A. Zeeb 
9070e2340276SBjoern A. Zeeb 	if (le16_to_cpu(pcysta->skip_cnt))
9071e2340276SBjoern A. Zeeb 		seq_printf(m, ", skip:%d",
9072e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->skip_cnt));
9073e2340276SBjoern A. Zeeb 
9074e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
9075e2340276SBjoern A. Zeeb 
9076e2340276SBjoern A. Zeeb 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9077e2340276SBjoern A. Zeeb 		   "[cycle_time]",
9078e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9079e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9080e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9081e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9082e2340276SBjoern A. Zeeb 	seq_printf(m,
9083e2340276SBjoern A. Zeeb 		   ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
9084e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9085e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9086e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
9087e2340276SBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
9088e2340276SBjoern A. Zeeb 
9089e2340276SBjoern A. Zeeb 	cycle = le16_to_cpu(pcysta->cycles);
9090e2340276SBjoern A. Zeeb 	if (cycle <= 1)
9091e2340276SBjoern A. Zeeb 		return;
9092e2340276SBjoern A. Zeeb 
9093e2340276SBjoern A. Zeeb 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
9094e2340276SBjoern A. Zeeb 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9095e2340276SBjoern A. Zeeb 
9096e2340276SBjoern A. Zeeb 	if (cycle <= slot_pair)
9097e2340276SBjoern A. Zeeb 		c_begin = 1;
9098e2340276SBjoern A. Zeeb 	else
9099e2340276SBjoern A. Zeeb 		c_begin = cycle - slot_pair + 1;
9100e2340276SBjoern A. Zeeb 
9101e2340276SBjoern A. Zeeb 	c_end = cycle;
9102e2340276SBjoern A. Zeeb 
9103e2340276SBjoern A. Zeeb 	if (a2dp->exist)
9104e2340276SBjoern A. Zeeb 		divide_cnt = 3;
9105e2340276SBjoern A. Zeeb 	else
9106e2340276SBjoern A. Zeeb 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
9107e2340276SBjoern A. Zeeb 
9108e2340276SBjoern A. Zeeb 	if (c_begin > c_end)
9109e2340276SBjoern A. Zeeb 		return;
9110e2340276SBjoern A. Zeeb 
9111e2340276SBjoern A. Zeeb 	for (cycle = c_begin; cycle <= c_end; cycle++) {
9112e2340276SBjoern A. Zeeb 		cnt++;
9113e2340276SBjoern A. Zeeb 		store_index = ((cycle - 1) % slot_pair) * 2;
9114e2340276SBjoern A. Zeeb 
9115e2340276SBjoern A. Zeeb 		if (cnt % divide_cnt == 1)
9116e2340276SBjoern A. Zeeb 			seq_printf(m, " %-15s : ", "[cycle_step]");
9117e2340276SBjoern A. Zeeb 
9118e2340276SBjoern A. Zeeb 		seq_printf(m, "->b%02d",
9119e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_step_time[store_index]));
9120e2340276SBjoern A. Zeeb 		if (a2dp->exist) {
9121e2340276SBjoern A. Zeeb 			a2dp_trx = &pcysta->a2dp_trx[store_index];
9122e2340276SBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9123e2340276SBjoern A. Zeeb 				   a2dp_trx->empty_cnt,
9124e2340276SBjoern A. Zeeb 				   a2dp_trx->retry_cnt,
9125e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_rate ? 3 : 2,
9126e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_cnt,
9127e2340276SBjoern A. Zeeb 				   a2dp_trx->ack_cnt,
9128e2340276SBjoern A. Zeeb 				   a2dp_trx->nack_cnt);
9129e2340276SBjoern A. Zeeb 		}
9130e2340276SBjoern A. Zeeb 		seq_printf(m, "->w%02d",
9131e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
9132e2340276SBjoern A. Zeeb 		if (a2dp->exist) {
9133e2340276SBjoern A. Zeeb 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
9134e2340276SBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9135e2340276SBjoern A. Zeeb 				   a2dp_trx->empty_cnt,
9136e2340276SBjoern A. Zeeb 				   a2dp_trx->retry_cnt,
9137e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_rate ? 3 : 2,
9138e2340276SBjoern A. Zeeb 				   a2dp_trx->tx_cnt,
9139e2340276SBjoern A. Zeeb 				   a2dp_trx->ack_cnt,
9140e2340276SBjoern A. Zeeb 				   a2dp_trx->nack_cnt);
9141e2340276SBjoern A. Zeeb 		}
9142e2340276SBjoern A. Zeeb 		if (cnt % divide_cnt == 0 || cnt == c_end)
9143e2340276SBjoern A. Zeeb 			seq_puts(m, "\n");
9144e2340276SBjoern A. Zeeb 	}
9145e2340276SBjoern A. Zeeb 
9146e2340276SBjoern A. Zeeb 	if (a2dp->exist) {
9147e2340276SBjoern A. Zeeb 		seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
9148e2340276SBjoern A. Zeeb 			   "[a2dp_t_sta]",
9149e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
9150e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
9151e2340276SBjoern A. Zeeb 
9152e2340276SBjoern A. Zeeb 		seq_printf(m, ", avg_t:%d, max_t:%d",
9153e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
9154e2340276SBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
9155e2340276SBjoern A. Zeeb 
9156e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
9157e2340276SBjoern A. Zeeb 	}
9158e2340276SBjoern A. Zeeb }
9159e2340276SBjoern A. Zeeb 
9160*6d67aabdSBjoern A. Zeeb static void _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, struct seq_file *m)
9161*6d67aabdSBjoern A. Zeeb {
9162*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
9163*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
9164*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
9165*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
9166*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
9167*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9168*6d67aabdSBjoern A. Zeeb 	u16 cycle, c_begin, c_end, s_id;
9169*6d67aabdSBjoern A. Zeeb 	u8 i, cnt = 0, divide_cnt;
9170*6d67aabdSBjoern A. Zeeb 	u8 slot_pair;
9171*6d67aabdSBjoern A. Zeeb 
9172*6d67aabdSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9173*6d67aabdSBjoern A. Zeeb 	if (!pcinfo->valid)
9174*6d67aabdSBjoern A. Zeeb 		return;
9175*6d67aabdSBjoern A. Zeeb 
9176*6d67aabdSBjoern A. Zeeb 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
9177*6d67aabdSBjoern A. Zeeb 	seq_printf(m, "\n\r %-15s : cycle:%d", "[slot_stat]",
9178*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycles));
9179*6d67aabdSBjoern A. Zeeb 
9180*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < CXST_MAX; i++) {
9181*6d67aabdSBjoern A. Zeeb 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
9182*6d67aabdSBjoern A. Zeeb 			continue;
9183*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", %s:%d",
9184*6d67aabdSBjoern A. Zeeb 			   id_to_slot(i), le16_to_cpu(pcysta->slot_cnt[i]));
9185*6d67aabdSBjoern A. Zeeb 	}
9186*6d67aabdSBjoern A. Zeeb 
9187*6d67aabdSBjoern A. Zeeb 	if (dm->tdma_now.rxflctrl)
9188*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", leak_rx:%d",
9189*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9190*6d67aabdSBjoern A. Zeeb 
9191*6d67aabdSBjoern A. Zeeb 	if (pcysta->collision_cnt)
9192*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", collision:%d", pcysta->collision_cnt);
9193*6d67aabdSBjoern A. Zeeb 
9194*6d67aabdSBjoern A. Zeeb 	if (pcysta->skip_cnt)
9195*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", skip:%d", le16_to_cpu(pcysta->skip_cnt));
9196*6d67aabdSBjoern A. Zeeb 
9197*6d67aabdSBjoern A. Zeeb 	seq_printf(m, "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9198*6d67aabdSBjoern A. Zeeb 		   "[cycle_stat]",
9199*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9200*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9201*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9202*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9203*6d67aabdSBjoern A. Zeeb 	seq_printf(m, ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
9204*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9205*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9206*6d67aabdSBjoern A. Zeeb 		   dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
9207*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
9208*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
9209*6d67aabdSBjoern A. Zeeb 	seq_printf(m, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
9210*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9211*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9212*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9213*6d67aabdSBjoern A. Zeeb 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9214*6d67aabdSBjoern A. Zeeb 
9215*6d67aabdSBjoern A. Zeeb 	if (a2dp->exist) {
9216*6d67aabdSBjoern A. Zeeb 		seq_printf(m,
9217*6d67aabdSBjoern A. Zeeb 			   "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
9218*6d67aabdSBjoern A. Zeeb 			   "[a2dp_stat]",
9219*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
9220*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
9221*6d67aabdSBjoern A. Zeeb 			   a2dp->no_empty_streak_2s, a2dp->no_empty_streak_max);
9222*6d67aabdSBjoern A. Zeeb 
9223*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", avg_t:%d, max_t:%d",
9224*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
9225*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
9226*6d67aabdSBjoern A. Zeeb 	}
9227*6d67aabdSBjoern A. Zeeb 
9228*6d67aabdSBjoern A. Zeeb 	if (le16_to_cpu(pcysta->cycles) <= 1)
9229*6d67aabdSBjoern A. Zeeb 		return;
9230*6d67aabdSBjoern A. Zeeb 
9231*6d67aabdSBjoern A. Zeeb 	/* 1 cycle = 1 wl-slot + 1 bt-slot */
9232*6d67aabdSBjoern A. Zeeb 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9233*6d67aabdSBjoern A. Zeeb 
9234*6d67aabdSBjoern A. Zeeb 	if (le16_to_cpu(pcysta->cycles) <= slot_pair)
9235*6d67aabdSBjoern A. Zeeb 		c_begin = 1;
9236*6d67aabdSBjoern A. Zeeb 	else
9237*6d67aabdSBjoern A. Zeeb 		c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
9238*6d67aabdSBjoern A. Zeeb 
9239*6d67aabdSBjoern A. Zeeb 	c_end = le16_to_cpu(pcysta->cycles);
9240*6d67aabdSBjoern A. Zeeb 
9241*6d67aabdSBjoern A. Zeeb 	if (a2dp->exist)
9242*6d67aabdSBjoern A. Zeeb 		divide_cnt = 2;
9243*6d67aabdSBjoern A. Zeeb 	else
9244*6d67aabdSBjoern A. Zeeb 		divide_cnt = 6;
9245*6d67aabdSBjoern A. Zeeb 
9246*6d67aabdSBjoern A. Zeeb 	if (c_begin > c_end)
9247*6d67aabdSBjoern A. Zeeb 		return;
9248*6d67aabdSBjoern A. Zeeb 
9249*6d67aabdSBjoern A. Zeeb 	for (cycle = c_begin; cycle <= c_end; cycle++) {
9250*6d67aabdSBjoern A. Zeeb 		cnt++;
9251*6d67aabdSBjoern A. Zeeb 		s_id = ((cycle - 1) % slot_pair) * 2;
9252*6d67aabdSBjoern A. Zeeb 
9253*6d67aabdSBjoern A. Zeeb 		if (cnt % divide_cnt == 1) {
9254*6d67aabdSBjoern A. Zeeb 			if (a2dp->exist)
9255*6d67aabdSBjoern A. Zeeb 				seq_printf(m, "\n\r %-15s : ", "[slotT_wermtan]");
9256*6d67aabdSBjoern A. Zeeb 			else
9257*6d67aabdSBjoern A. Zeeb 				seq_printf(m, "\n\r %-15s : ", "[slotT_rxerr]");
9258*6d67aabdSBjoern A. Zeeb 		}
9259*6d67aabdSBjoern A. Zeeb 
9260*6d67aabdSBjoern A. Zeeb 		seq_printf(m, "->b%d", le16_to_cpu(pcysta->slot_step_time[s_id]));
9261*6d67aabdSBjoern A. Zeeb 
9262*6d67aabdSBjoern A. Zeeb 		if (a2dp->exist)
9263*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%d/%dM/%d/%d/%d)",
9264*6d67aabdSBjoern A. Zeeb 				   pcysta->wl_rx_err_ratio[s_id],
9265*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id].empty_cnt,
9266*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id].retry_cnt,
9267*6d67aabdSBjoern A. Zeeb 				   (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
9268*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id].tx_cnt,
9269*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id].ack_cnt,
9270*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id].nack_cnt);
9271*6d67aabdSBjoern A. Zeeb 		else
9272*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "(%d)", pcysta->wl_rx_err_ratio[s_id]);
9273*6d67aabdSBjoern A. Zeeb 
9274*6d67aabdSBjoern A. Zeeb 		seq_printf(m, "->w%d", le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
9275*6d67aabdSBjoern A. Zeeb 
9276*6d67aabdSBjoern A. Zeeb 		if (a2dp->exist)
9277*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "(%d/%d/%d/%dM/%d/%d/%d)",
9278*6d67aabdSBjoern A. Zeeb 				   pcysta->wl_rx_err_ratio[s_id + 1],
9279*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id + 1].empty_cnt,
9280*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id + 1].retry_cnt,
9281*6d67aabdSBjoern A. Zeeb 				   (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
9282*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id + 1].tx_cnt,
9283*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id + 1].ack_cnt,
9284*6d67aabdSBjoern A. Zeeb 				   pcysta->a2dp_trx[s_id + 1].nack_cnt);
9285*6d67aabdSBjoern A. Zeeb 		else
9286*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "(%d)", pcysta->wl_rx_err_ratio[s_id + 1]);
9287*6d67aabdSBjoern A. Zeeb 	}
9288*6d67aabdSBjoern A. Zeeb }
9289*6d67aabdSBjoern A. Zeeb 
92908e93258fSBjoern A. Zeeb static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
92918e93258fSBjoern A. Zeeb {
92928e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9293e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
92948e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9295e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9296e2340276SBjoern A. Zeeb 	union rtw89_btc_fbtc_cynullsta_info *ns;
92978e93258fSBjoern A. Zeeb 	u8 i = 0;
92988e93258fSBjoern A. Zeeb 
92998e93258fSBjoern A. Zeeb 	if (!btc->dm.tdma_now.rxflctrl)
93008e93258fSBjoern A. Zeeb 		return;
93018e93258fSBjoern A. Zeeb 
93028e93258fSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
93038e93258fSBjoern A. Zeeb 	if (!pcinfo->valid)
93048e93258fSBjoern A. Zeeb 		return;
93058e93258fSBjoern A. Zeeb 
93068e93258fSBjoern A. Zeeb 	ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
9307e2340276SBjoern A. Zeeb 	if (ver->fcxnullsta == 1) {
93088e93258fSBjoern A. Zeeb 		for (i = 0; i < 2; i++) {
9309e2340276SBjoern A. Zeeb 			seq_printf(m, " %-15s : ", "[NULL-STA]");
93108e93258fSBjoern A. Zeeb 			seq_printf(m, "null-%d", i);
9311e2340276SBjoern A. Zeeb 			seq_printf(m, "[ok:%d/",
9312e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.result[i][1]));
9313e2340276SBjoern A. Zeeb 			seq_printf(m, "fail:%d/",
9314e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.result[i][0]));
9315e2340276SBjoern A. Zeeb 			seq_printf(m, "on_time:%d/",
9316e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.result[i][2]));
9317e2340276SBjoern A. Zeeb 			seq_printf(m, "retry:%d/",
9318e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.result[i][3]));
93198e93258fSBjoern A. Zeeb 			seq_printf(m, "avg_t:%d.%03d/",
9320e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.avg_t[i]) / 1000,
9321e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.avg_t[i]) % 1000);
9322e2340276SBjoern A. Zeeb 			seq_printf(m, "max_t:%d.%03d]\n",
9323e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.max_t[i]) / 1000,
9324e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v1.max_t[i]) % 1000);
93258e93258fSBjoern A. Zeeb 		}
9326*6d67aabdSBjoern A. Zeeb 	} else if (ver->fcxnullsta == 7) {
9327*6d67aabdSBjoern A. Zeeb 		for (i = 0; i < 2; i++) {
9328*6d67aabdSBjoern A. Zeeb 			seq_printf(m, " %-15s : ", "[NULL-STA]");
9329*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "null-%d", i);
9330*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "[Tx:%d/",
9331*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.result[i][4]));
9332*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "[ok:%d/",
9333*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.result[i][1]));
9334*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "fail:%d/",
9335*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.result[i][0]));
9336*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "on_time:%d/",
9337*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.result[i][2]));
9338*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "retry:%d/",
9339*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.result[i][3]));
9340*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "avg_t:%d.%03d/",
9341*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.tavg[i]) / 1000,
9342*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.tavg[i]) % 1000);
9343*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "max_t:%d.%03d]\n",
9344*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.tmax[i]) / 1000,
9345*6d67aabdSBjoern A. Zeeb 				   le32_to_cpu(ns->v7.tmax[i]) % 1000);
9346*6d67aabdSBjoern A. Zeeb 		}
9347e2340276SBjoern A. Zeeb 	} else {
9348e2340276SBjoern A. Zeeb 		for (i = 0; i < 2; i++) {
9349e2340276SBjoern A. Zeeb 			seq_printf(m, " %-15s : ", "[NULL-STA]");
9350e2340276SBjoern A. Zeeb 			seq_printf(m, "null-%d", i);
9351e2340276SBjoern A. Zeeb 			seq_printf(m, "[Tx:%d/",
9352e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.result[i][4]));
9353e2340276SBjoern A. Zeeb 			seq_printf(m, "[ok:%d/",
9354e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.result[i][1]));
9355e2340276SBjoern A. Zeeb 			seq_printf(m, "fail:%d/",
9356e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.result[i][0]));
9357e2340276SBjoern A. Zeeb 			seq_printf(m, "on_time:%d/",
9358e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.result[i][2]));
9359e2340276SBjoern A. Zeeb 			seq_printf(m, "retry:%d/",
9360e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.result[i][3]));
9361e2340276SBjoern A. Zeeb 			seq_printf(m, "avg_t:%d.%03d/",
9362e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.avg_t[i]) / 1000,
9363e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.avg_t[i]) % 1000);
9364e2340276SBjoern A. Zeeb 			seq_printf(m, "max_t:%d.%03d]\n",
9365e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.max_t[i]) / 1000,
9366e2340276SBjoern A. Zeeb 				   le32_to_cpu(ns->v2.max_t[i]) % 1000);
9367e2340276SBjoern A. Zeeb 		}
9368e2340276SBjoern A. Zeeb 	}
93698e93258fSBjoern A. Zeeb }
93708e93258fSBjoern A. Zeeb 
9371e2340276SBjoern A. Zeeb static void _show_fbtc_step_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
93728e93258fSBjoern A. Zeeb {
93738e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
93748e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
93758e93258fSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9376e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
9377*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
93788e93258fSBjoern A. Zeeb 	u8 type, val, cnt = 0, state = 0;
93798e93258fSBjoern A. Zeeb 	bool outloop = false;
93808e93258fSBjoern A. Zeeb 	u16 i, diff_t, n_start = 0, n_stop = 0;
9381*6d67aabdSBjoern A. Zeeb 	u16 pos_old, pos_new, trace_step;
93828e93258fSBjoern A. Zeeb 
93838e93258fSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
93848e93258fSBjoern A. Zeeb 	if (!pcinfo->valid)
93858e93258fSBjoern A. Zeeb 		return;
93868e93258fSBjoern A. Zeeb 
9387e2340276SBjoern A. Zeeb 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
93888e93258fSBjoern A. Zeeb 	pos_old = le16_to_cpu(pstep->pos_old);
93898e93258fSBjoern A. Zeeb 	pos_new = le16_to_cpu(pstep->pos_new);
93908e93258fSBjoern A. Zeeb 
93918e93258fSBjoern A. Zeeb 	if (pcinfo->req_fver != pstep->fver)
93928e93258fSBjoern A. Zeeb 		return;
93938e93258fSBjoern A. Zeeb 
93948e93258fSBjoern A. Zeeb 	/* store step info by using ring instead of FIFO*/
93958e93258fSBjoern A. Zeeb 	do {
93968e93258fSBjoern A. Zeeb 		switch (state) {
93978e93258fSBjoern A. Zeeb 		case 0:
9398*6d67aabdSBjoern A. Zeeb 			if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
9399*6d67aabdSBjoern A. Zeeb 				trace_step = 50;
9400*6d67aabdSBjoern A. Zeeb 			else
9401*6d67aabdSBjoern A. Zeeb 				trace_step = btc->ctrl.ctrl.trace_step;
9402*6d67aabdSBjoern A. Zeeb 
94038e93258fSBjoern A. Zeeb 			n_start = pos_old;
94048e93258fSBjoern A. Zeeb 			if (pos_new >=  pos_old)
94058e93258fSBjoern A. Zeeb 				n_stop = pos_new;
94068e93258fSBjoern A. Zeeb 			else
9407*6d67aabdSBjoern A. Zeeb 				n_stop = trace_step - 1;
94088e93258fSBjoern A. Zeeb 
94098e93258fSBjoern A. Zeeb 			state = 1;
94108e93258fSBjoern A. Zeeb 			break;
94118e93258fSBjoern A. Zeeb 		case 1:
94128e93258fSBjoern A. Zeeb 			for (i = n_start; i <= n_stop; i++) {
94138e93258fSBjoern A. Zeeb 				type = pstep->step[i].type;
94148e93258fSBjoern A. Zeeb 				val = pstep->step[i].val;
94158e93258fSBjoern A. Zeeb 				diff_t = le16_to_cpu(pstep->step[i].difft);
94168e93258fSBjoern A. Zeeb 
94178e93258fSBjoern A. Zeeb 				if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
94188e93258fSBjoern A. Zeeb 					continue;
94198e93258fSBjoern A. Zeeb 
94208e93258fSBjoern A. Zeeb 				if (cnt % 10 == 0)
94218e93258fSBjoern A. Zeeb 					seq_printf(m, " %-15s : ", "[steps]");
94228e93258fSBjoern A. Zeeb 
94238e93258fSBjoern A. Zeeb 				seq_printf(m, "-> %s(%02d)(%02d)",
94248e93258fSBjoern A. Zeeb 					   (type == CXSTEP_SLOT ? "SLT" :
94258e93258fSBjoern A. Zeeb 					    "EVT"), (u32)val, diff_t);
94268e93258fSBjoern A. Zeeb 				if (cnt % 10 == 9)
94278e93258fSBjoern A. Zeeb 					seq_puts(m, "\n");
94288e93258fSBjoern A. Zeeb 				cnt++;
94298e93258fSBjoern A. Zeeb 			}
94308e93258fSBjoern A. Zeeb 
94318e93258fSBjoern A. Zeeb 			state = 2;
94328e93258fSBjoern A. Zeeb 			break;
94338e93258fSBjoern A. Zeeb 		case 2:
94348e93258fSBjoern A. Zeeb 			if (pos_new <  pos_old && n_start != 0) {
94358e93258fSBjoern A. Zeeb 				n_start = 0;
94368e93258fSBjoern A. Zeeb 				n_stop = pos_new;
94378e93258fSBjoern A. Zeeb 				state = 1;
94388e93258fSBjoern A. Zeeb 			} else {
94398e93258fSBjoern A. Zeeb 				outloop = true;
94408e93258fSBjoern A. Zeeb 			}
94418e93258fSBjoern A. Zeeb 			break;
94428e93258fSBjoern A. Zeeb 		}
94438e93258fSBjoern A. Zeeb 	} while (!outloop);
94448e93258fSBjoern A. Zeeb }
94458e93258fSBjoern A. Zeeb 
9446e2340276SBjoern A. Zeeb static void _show_fbtc_step_v3(struct rtw89_dev *rtwdev, struct seq_file *m)
9447e2340276SBjoern A. Zeeb {
9448e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9449e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9450e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9451e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_steps_v3 *pstep;
9452e2340276SBjoern A. Zeeb 	u32 i, n_begin, n_end, array_idx, cnt = 0;
9453e2340276SBjoern A. Zeeb 	u8 type, val;
9454e2340276SBjoern A. Zeeb 	u16 diff_t;
9455e2340276SBjoern A. Zeeb 
9456e2340276SBjoern A. Zeeb 	if ((pfwinfo->rpt_en_map &
9457e2340276SBjoern A. Zeeb 	     rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
9458e2340276SBjoern A. Zeeb 		return;
9459e2340276SBjoern A. Zeeb 
9460e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
9461e2340276SBjoern A. Zeeb 	if (!pcinfo->valid)
9462e2340276SBjoern A. Zeeb 		return;
9463e2340276SBjoern A. Zeeb 
9464e2340276SBjoern A. Zeeb 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
9465e2340276SBjoern A. Zeeb 	if (pcinfo->req_fver != pstep->fver)
9466e2340276SBjoern A. Zeeb 		return;
9467e2340276SBjoern A. Zeeb 
9468e2340276SBjoern A. Zeeb 	if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
9469e2340276SBjoern A. Zeeb 		n_begin = 1;
9470e2340276SBjoern A. Zeeb 	else
9471e2340276SBjoern A. Zeeb 		n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
9472e2340276SBjoern A. Zeeb 
9473e2340276SBjoern A. Zeeb 	n_end = le32_to_cpu(pstep->cnt);
9474e2340276SBjoern A. Zeeb 
9475e2340276SBjoern A. Zeeb 	if (n_begin > n_end)
9476e2340276SBjoern A. Zeeb 		return;
9477e2340276SBjoern A. Zeeb 
9478e2340276SBjoern A. Zeeb 	/* restore step info by using ring instead of FIFO */
9479e2340276SBjoern A. Zeeb 	for (i = n_begin; i <= n_end; i++) {
9480e2340276SBjoern A. Zeeb 		array_idx = (i - 1) % FCXDEF_STEP;
9481e2340276SBjoern A. Zeeb 		type = pstep->step[array_idx].type;
9482e2340276SBjoern A. Zeeb 		val = pstep->step[array_idx].val;
9483e2340276SBjoern A. Zeeb 		diff_t = le16_to_cpu(pstep->step[array_idx].difft);
9484e2340276SBjoern A. Zeeb 
9485e2340276SBjoern A. Zeeb 		if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
9486e2340276SBjoern A. Zeeb 			continue;
9487e2340276SBjoern A. Zeeb 
9488e2340276SBjoern A. Zeeb 		if (cnt % 10 == 0)
9489e2340276SBjoern A. Zeeb 			seq_printf(m, " %-15s : ", "[steps]");
9490e2340276SBjoern A. Zeeb 
9491e2340276SBjoern A. Zeeb 		seq_printf(m, "-> %s(%02d)",
9492e2340276SBjoern A. Zeeb 			   (type == CXSTEP_SLOT ?
9493e2340276SBjoern A. Zeeb 			    id_to_slot((u32)val) :
9494e2340276SBjoern A. Zeeb 			    id_to_evt((u32)val)), diff_t);
9495e2340276SBjoern A. Zeeb 
9496e2340276SBjoern A. Zeeb 		if (cnt % 10 == 9)
9497e2340276SBjoern A. Zeeb 			seq_puts(m, "\n");
9498e2340276SBjoern A. Zeeb 
9499e2340276SBjoern A. Zeeb 		cnt++;
9500e2340276SBjoern A. Zeeb 	}
9501e2340276SBjoern A. Zeeb }
9502e2340276SBjoern A. Zeeb 
95038e93258fSBjoern A. Zeeb static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
95048e93258fSBjoern A. Zeeb {
95058e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9506e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
95078e93258fSBjoern A. Zeeb 
95088e93258fSBjoern A. Zeeb 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
95098e93258fSBjoern A. Zeeb 		return;
95108e93258fSBjoern A. Zeeb 
95118e93258fSBjoern A. Zeeb 	_show_error(rtwdev, m);
95128e93258fSBjoern A. Zeeb 	_show_fbtc_tdma(rtwdev, m);
95138e93258fSBjoern A. Zeeb 	_show_fbtc_slots(rtwdev, m);
9514e2340276SBjoern A. Zeeb 
9515e2340276SBjoern A. Zeeb 	if (ver->fcxcysta == 2)
9516e2340276SBjoern A. Zeeb 		_show_fbtc_cysta_v2(rtwdev, m);
9517e2340276SBjoern A. Zeeb 	else if (ver->fcxcysta == 3)
9518e2340276SBjoern A. Zeeb 		_show_fbtc_cysta_v3(rtwdev, m);
9519e2340276SBjoern A. Zeeb 	else if (ver->fcxcysta == 4)
9520e2340276SBjoern A. Zeeb 		_show_fbtc_cysta_v4(rtwdev, m);
9521e2340276SBjoern A. Zeeb 	else if (ver->fcxcysta == 5)
9522e2340276SBjoern A. Zeeb 		_show_fbtc_cysta_v5(rtwdev, m);
9523*6d67aabdSBjoern A. Zeeb 	else if (ver->fcxcysta == 7)
9524*6d67aabdSBjoern A. Zeeb 		_show_fbtc_cysta_v7(rtwdev, m);
9525e2340276SBjoern A. Zeeb 
95268e93258fSBjoern A. Zeeb 	_show_fbtc_nullsta(rtwdev, m);
9527e2340276SBjoern A. Zeeb 
9528e2340276SBjoern A. Zeeb 	if (ver->fcxstep == 2)
9529e2340276SBjoern A. Zeeb 		_show_fbtc_step_v2(rtwdev, m);
9530e2340276SBjoern A. Zeeb 	else if (ver->fcxstep == 3)
9531e2340276SBjoern A. Zeeb 		_show_fbtc_step_v3(rtwdev, m);
9532e2340276SBjoern A. Zeeb 
95338e93258fSBjoern A. Zeeb }
95348e93258fSBjoern A. Zeeb 
9535e2340276SBjoern A. Zeeb static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
9536e2340276SBjoern A. Zeeb {
9537e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
9538e2340276SBjoern A. Zeeb 	struct rtw89_mac_ax_gnt *gnt;
9539e2340276SBjoern A. Zeeb 	u32 val, status;
9540e2340276SBjoern A. Zeeb 
9541*6d67aabdSBjoern A. Zeeb 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
9542*6d67aabdSBjoern A. Zeeb 	    chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
9543e2340276SBjoern A. Zeeb 		rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
9544e2340276SBjoern A. Zeeb 		rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
9545e2340276SBjoern A. Zeeb 
9546e2340276SBjoern A. Zeeb 		gnt = &gnt_cfg->band[0];
9547e2340276SBjoern A. Zeeb 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
9548e2340276SBjoern A. Zeeb 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
9549e2340276SBjoern A. Zeeb 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
9550e2340276SBjoern A. Zeeb 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
9551e2340276SBjoern A. Zeeb 
9552e2340276SBjoern A. Zeeb 		gnt = &gnt_cfg->band[1];
9553e2340276SBjoern A. Zeeb 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
9554e2340276SBjoern A. Zeeb 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
9555e2340276SBjoern A. Zeeb 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
9556e2340276SBjoern A. Zeeb 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
9557e2340276SBjoern A. Zeeb 	} else if (chip->chip_id == RTL8852C) {
9558e2340276SBjoern A. Zeeb 		val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
9559e2340276SBjoern A. Zeeb 		status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
9560e2340276SBjoern A. Zeeb 
9561e2340276SBjoern A. Zeeb 		gnt = &gnt_cfg->band[0];
9562e2340276SBjoern A. Zeeb 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
9563e2340276SBjoern A. Zeeb 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
9564e2340276SBjoern A. Zeeb 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
9565e2340276SBjoern A. Zeeb 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
9566e2340276SBjoern A. Zeeb 
9567e2340276SBjoern A. Zeeb 		gnt = &gnt_cfg->band[1];
9568e2340276SBjoern A. Zeeb 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
9569e2340276SBjoern A. Zeeb 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
9570e2340276SBjoern A. Zeeb 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
9571e2340276SBjoern A. Zeeb 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
9572e2340276SBjoern A. Zeeb 	} else {
9573e2340276SBjoern A. Zeeb 		return;
9574e2340276SBjoern A. Zeeb 	}
9575e2340276SBjoern A. Zeeb }
9576e2340276SBjoern A. Zeeb 
9577*6d67aabdSBjoern A. Zeeb static void _show_gpio_dbg(struct rtw89_dev *rtwdev, struct seq_file *m)
9578*6d67aabdSBjoern A. Zeeb {
9579*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
9580*6d67aabdSBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
9581*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9582*6d67aabdSBjoern A. Zeeb 	union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
9583*6d67aabdSBjoern A. Zeeb 	u8 *gpio_map, i;
9584*6d67aabdSBjoern A. Zeeb 	u32 en_map;
9585*6d67aabdSBjoern A. Zeeb 
9586*6d67aabdSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
9587*6d67aabdSBjoern A. Zeeb 	gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
9588*6d67aabdSBjoern A. Zeeb 	if (!pcinfo->valid) {
9589*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9590*6d67aabdSBjoern A. Zeeb 			    "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
9591*6d67aabdSBjoern A. Zeeb 			    __func__);
9592*6d67aabdSBjoern A. Zeeb 		seq_puts(m, "\n");
9593*6d67aabdSBjoern A. Zeeb 		return;
9594*6d67aabdSBjoern A. Zeeb 	}
9595*6d67aabdSBjoern A. Zeeb 
9596*6d67aabdSBjoern A. Zeeb 	if (ver->fcxgpiodbg == 7) {
9597*6d67aabdSBjoern A. Zeeb 		en_map = le32_to_cpu(gdbg->v7.en_map);
9598*6d67aabdSBjoern A. Zeeb 		gpio_map = gdbg->v7.gpio_map;
9599*6d67aabdSBjoern A. Zeeb 	} else {
9600*6d67aabdSBjoern A. Zeeb 		en_map = le32_to_cpu(gdbg->v1.en_map);
9601*6d67aabdSBjoern A. Zeeb 		gpio_map = gdbg->v1.gpio_map;
9602*6d67aabdSBjoern A. Zeeb 	}
9603*6d67aabdSBjoern A. Zeeb 
9604*6d67aabdSBjoern A. Zeeb 	if (!en_map)
9605*6d67aabdSBjoern A. Zeeb 		return;
9606*6d67aabdSBjoern A. Zeeb 
9607*6d67aabdSBjoern A. Zeeb 	seq_printf(m, " %-15s : enable_map:0x%08x",
9608*6d67aabdSBjoern A. Zeeb 		   "[gpio_dbg]", en_map);
9609*6d67aabdSBjoern A. Zeeb 
9610*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < BTC_DBG_MAX1; i++) {
9611*6d67aabdSBjoern A. Zeeb 		if (!(en_map & BIT(i)))
9612*6d67aabdSBjoern A. Zeeb 			continue;
9613*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", %s->GPIO%d", id_to_gdbg(i), gpio_map[i]);
9614*6d67aabdSBjoern A. Zeeb 	}
9615*6d67aabdSBjoern A. Zeeb 	seq_puts(m, "\n");
9616*6d67aabdSBjoern A. Zeeb }
9617*6d67aabdSBjoern A. Zeeb 
9618e2340276SBjoern A. Zeeb static void _show_mreg_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
96198e93258fSBjoern A. Zeeb {
96208e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
96218e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
96228e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
96238e93258fSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9624e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
96258e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
96268e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
96278e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9628e2340276SBjoern A. Zeeb 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
9629e2340276SBjoern A. Zeeb 	struct rtw89_mac_ax_gnt gnt;
96308e93258fSBjoern A. Zeeb 	u8 i = 0, type = 0, cnt = 0;
96318e93258fSBjoern A. Zeeb 	u32 val, offset;
96328e93258fSBjoern A. Zeeb 
96338e93258fSBjoern A. Zeeb 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
96348e93258fSBjoern A. Zeeb 		return;
96358e93258fSBjoern A. Zeeb 
96368e93258fSBjoern A. Zeeb 	seq_puts(m, "========== [HW Status] ==========\n");
96378e93258fSBjoern A. Zeeb 
96388e93258fSBjoern A. Zeeb 	seq_printf(m,
96398e93258fSBjoern A. Zeeb 		   " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
96408e93258fSBjoern A. Zeeb 		   "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
96418e93258fSBjoern A. Zeeb 		   bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
96428e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
96438e93258fSBjoern A. Zeeb 
9644e2340276SBjoern A. Zeeb 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
9645e2340276SBjoern A. Zeeb 	_get_gnt(rtwdev, &gnt_cfg);
9646*6d67aabdSBjoern A. Zeeb 
9647e2340276SBjoern A. Zeeb 	gnt = gnt_cfg.band[0];
96488e93258fSBjoern A. Zeeb 	seq_printf(m,
96498e93258fSBjoern A. Zeeb 		   " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
96508e93258fSBjoern A. Zeeb 		   "[gnt_status]",
9651e2340276SBjoern A. Zeeb 		   chip->chip_id == RTL8852C ? "HW" :
9652e2340276SBjoern A. Zeeb 		   btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
9653e2340276SBjoern A. Zeeb 		   gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
9654e2340276SBjoern A. Zeeb 		   gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
96558e93258fSBjoern A. Zeeb 
9656e2340276SBjoern A. Zeeb 	gnt = gnt_cfg.band[1];
96578e93258fSBjoern A. Zeeb 	seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
9658e2340276SBjoern A. Zeeb 		   gnt.gnt_wl_sw_en ? "SW" : "HW",
9659e2340276SBjoern A. Zeeb 		   gnt.gnt_wl,
9660e2340276SBjoern A. Zeeb 		   gnt.gnt_bt_sw_en ? "SW" : "HW",
9661e2340276SBjoern A. Zeeb 		   gnt.gnt_bt);
9662*6d67aabdSBjoern A. Zeeb 
96638e93258fSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
96648e93258fSBjoern A. Zeeb 	if (!pcinfo->valid) {
96658e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
96668e93258fSBjoern A. Zeeb 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
96678e93258fSBjoern A. Zeeb 			    __func__);
96688e93258fSBjoern A. Zeeb 		return;
96698e93258fSBjoern A. Zeeb 	}
96708e93258fSBjoern A. Zeeb 
9671e2340276SBjoern A. Zeeb 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
96728e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
96738e93258fSBjoern A. Zeeb 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
96748e93258fSBjoern A. Zeeb 		    __func__, pmreg->reg_num);
96758e93258fSBjoern A. Zeeb 
96768e93258fSBjoern A. Zeeb 	for (i = 0; i < pmreg->reg_num; i++) {
96778e93258fSBjoern A. Zeeb 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
96788e93258fSBjoern A. Zeeb 		offset = le32_to_cpu(chip->mon_reg[i].offset);
96798e93258fSBjoern A. Zeeb 		val = le32_to_cpu(pmreg->mreg_val[i]);
96808e93258fSBjoern A. Zeeb 
96818e93258fSBjoern A. Zeeb 		if (cnt % 6 == 0)
96828e93258fSBjoern A. Zeeb 			seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
96838e93258fSBjoern A. Zeeb 				   "[reg]", (u32)type, offset, val);
96848e93258fSBjoern A. Zeeb 		else
96858e93258fSBjoern A. Zeeb 			seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
96868e93258fSBjoern A. Zeeb 				   offset, val);
96878e93258fSBjoern A. Zeeb 		if (cnt % 6 == 5)
96888e93258fSBjoern A. Zeeb 			seq_puts(m, "\n");
96898e93258fSBjoern A. Zeeb 		cnt++;
9690e2340276SBjoern A. Zeeb 
9691e2340276SBjoern A. Zeeb 		if (i >= pmreg->reg_num)
9692e2340276SBjoern A. Zeeb 			seq_puts(m, "\n");
96938e93258fSBjoern A. Zeeb 	}
96948e93258fSBjoern A. Zeeb }
96958e93258fSBjoern A. Zeeb 
9696e2340276SBjoern A. Zeeb static void _show_mreg_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
9697e2340276SBjoern A. Zeeb {
9698e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
9699e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9700e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9701e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9702e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
9703e2340276SBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
9704e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9705e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9706e2340276SBjoern A. Zeeb 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
9707e2340276SBjoern A. Zeeb 	struct rtw89_mac_ax_gnt gnt;
9708e2340276SBjoern A. Zeeb 	u8 i = 0, type = 0, cnt = 0;
9709e2340276SBjoern A. Zeeb 	u32 val, offset;
9710e2340276SBjoern A. Zeeb 
9711e2340276SBjoern A. Zeeb 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
9712e2340276SBjoern A. Zeeb 		return;
9713e2340276SBjoern A. Zeeb 
9714e2340276SBjoern A. Zeeb 	seq_puts(m, "========== [HW Status] ==========\n");
9715e2340276SBjoern A. Zeeb 
9716e2340276SBjoern A. Zeeb 	seq_printf(m,
9717e2340276SBjoern A. Zeeb 		   " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
9718e2340276SBjoern A. Zeeb 		   "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
9719e2340276SBjoern A. Zeeb 		   bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
9720e2340276SBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
9721e2340276SBjoern A. Zeeb 
9722e2340276SBjoern A. Zeeb 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
9723e2340276SBjoern A. Zeeb 	_get_gnt(rtwdev, &gnt_cfg);
9724*6d67aabdSBjoern A. Zeeb 
9725e2340276SBjoern A. Zeeb 	gnt = gnt_cfg.band[0];
9726e2340276SBjoern A. Zeeb 	seq_printf(m,
9727*6d67aabdSBjoern A. Zeeb 		   " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
9728e2340276SBjoern A. Zeeb 		   "[gnt_status]",
9729e2340276SBjoern A. Zeeb 		   chip->chip_id == RTL8852C ? "HW" :
9730e2340276SBjoern A. Zeeb 		   btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
9731e2340276SBjoern A. Zeeb 		   gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
9732*6d67aabdSBjoern A. Zeeb 		   gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
9733*6d67aabdSBjoern A. Zeeb 		   id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
9734e2340276SBjoern A. Zeeb 
9735e2340276SBjoern A. Zeeb 	gnt = gnt_cfg.band[1];
9736e2340276SBjoern A. Zeeb 	seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
9737e2340276SBjoern A. Zeeb 		   gnt.gnt_wl_sw_en ? "SW" : "HW",
9738e2340276SBjoern A. Zeeb 		   gnt.gnt_wl,
9739e2340276SBjoern A. Zeeb 		   gnt.gnt_bt_sw_en ? "SW" : "HW",
9740e2340276SBjoern A. Zeeb 		   gnt.gnt_bt);
9741*6d67aabdSBjoern A. Zeeb 
9742e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
9743e2340276SBjoern A. Zeeb 	if (!pcinfo->valid) {
9744e2340276SBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9745e2340276SBjoern A. Zeeb 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
9746e2340276SBjoern A. Zeeb 			    __func__);
9747e2340276SBjoern A. Zeeb 		return;
9748e2340276SBjoern A. Zeeb 	}
9749e2340276SBjoern A. Zeeb 
9750e2340276SBjoern A. Zeeb 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
9751e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9752e2340276SBjoern A. Zeeb 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
9753e2340276SBjoern A. Zeeb 		    __func__, pmreg->reg_num);
9754e2340276SBjoern A. Zeeb 
9755e2340276SBjoern A. Zeeb 	for (i = 0; i < pmreg->reg_num; i++) {
9756e2340276SBjoern A. Zeeb 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
9757e2340276SBjoern A. Zeeb 		offset = le32_to_cpu(chip->mon_reg[i].offset);
9758e2340276SBjoern A. Zeeb 		val = le32_to_cpu(pmreg->mreg_val[i]);
9759e2340276SBjoern A. Zeeb 
9760e2340276SBjoern A. Zeeb 		if (cnt % 6 == 0)
9761e2340276SBjoern A. Zeeb 			seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
9762e2340276SBjoern A. Zeeb 				   "[reg]", (u32)type, offset, val);
9763e2340276SBjoern A. Zeeb 		else
9764e2340276SBjoern A. Zeeb 			seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
9765e2340276SBjoern A. Zeeb 				   offset, val);
9766e2340276SBjoern A. Zeeb 		if (cnt % 6 == 5)
9767e2340276SBjoern A. Zeeb 			seq_puts(m, "\n");
9768e2340276SBjoern A. Zeeb 		cnt++;
9769e2340276SBjoern A. Zeeb 
9770e2340276SBjoern A. Zeeb 		if (i >= pmreg->reg_num)
9771e2340276SBjoern A. Zeeb 			seq_puts(m, "\n");
9772e2340276SBjoern A. Zeeb 	}
9773e2340276SBjoern A. Zeeb }
9774e2340276SBjoern A. Zeeb 
9775*6d67aabdSBjoern A. Zeeb static void _show_mreg_v7(struct rtw89_dev *rtwdev, struct seq_file *m)
9776*6d67aabdSBjoern A. Zeeb {
9777*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9778*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9779*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
9780*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9781*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
9782*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
9783*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
9784*6d67aabdSBjoern A. Zeeb 	struct rtw89_mac_ax_gnt *gnt = NULL;
9785*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
9786*6d67aabdSBjoern A. Zeeb 	u8 i, type, cnt = 0;
9787*6d67aabdSBjoern A. Zeeb 	u32 val, offset;
9788*6d67aabdSBjoern A. Zeeb 
9789*6d67aabdSBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
9790e2340276SBjoern A. Zeeb 		return;
9791e2340276SBjoern A. Zeeb 
9792*6d67aabdSBjoern A. Zeeb 	seq_puts(m, "\n\r========== [HW Status] ==========");
9793e2340276SBjoern A. Zeeb 
9794*6d67aabdSBjoern A. Zeeb 	seq_printf(m,
9795*6d67aabdSBjoern A. Zeeb 		   "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
9796*6d67aabdSBjoern A. Zeeb 		   "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
9797*6d67aabdSBjoern A. Zeeb 		   bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
9798*6d67aabdSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
9799*6d67aabdSBjoern A. Zeeb 
9800*6d67aabdSBjoern A. Zeeb 	/* To avoid I/O if WL LPS or power-off  */
9801*6d67aabdSBjoern A. Zeeb 	dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
9802*6d67aabdSBjoern A. Zeeb 
9803*6d67aabdSBjoern A. Zeeb 	seq_printf(m,
9804*6d67aabdSBjoern A. Zeeb 		   "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s",
9805*6d67aabdSBjoern A. Zeeb 		   "[gnt_status]",
9806*6d67aabdSBjoern A. Zeeb 		   rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
9807*6d67aabdSBjoern A. Zeeb 		   dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
9808*6d67aabdSBjoern A. Zeeb 		   wl->pta_req_mac, id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
9809*6d67aabdSBjoern A. Zeeb 
9810*6d67aabdSBjoern A. Zeeb 	gnt = &dm->gnt.band[RTW89_PHY_0];
9811*6d67aabdSBjoern A. Zeeb 
9812*6d67aabdSBjoern A. Zeeb 	seq_printf(m, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
9813*6d67aabdSBjoern A. Zeeb 		   gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
9814*6d67aabdSBjoern A. Zeeb 		   gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
9815*6d67aabdSBjoern A. Zeeb 
9816*6d67aabdSBjoern A. Zeeb 	if (rtwdev->dbcc_en) {
9817*6d67aabdSBjoern A. Zeeb 		gnt = &dm->gnt.band[RTW89_PHY_1];
9818*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
9819*6d67aabdSBjoern A. Zeeb 			   gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
9820*6d67aabdSBjoern A. Zeeb 			   gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
9821*6d67aabdSBjoern A. Zeeb 	}
9822*6d67aabdSBjoern A. Zeeb 
9823*6d67aabdSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
9824*6d67aabdSBjoern A. Zeeb 	if (!pcinfo->valid)
9825*6d67aabdSBjoern A. Zeeb 		return;
9826*6d67aabdSBjoern A. Zeeb 
9827*6d67aabdSBjoern A. Zeeb 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
9828*6d67aabdSBjoern A. Zeeb 
9829*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < pmreg->reg_num; i++) {
9830*6d67aabdSBjoern A. Zeeb 		type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
9831*6d67aabdSBjoern A. Zeeb 		offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
9832*6d67aabdSBjoern A. Zeeb 		val = le32_to_cpu(pmreg->mreg_val[i]);
9833*6d67aabdSBjoern A. Zeeb 
9834*6d67aabdSBjoern A. Zeeb 		if (cnt % 6 == 0)
9835*6d67aabdSBjoern A. Zeeb 			seq_printf(m, "\n\r %-15s : %s_0x%x=0x%x", "[reg]",
9836*6d67aabdSBjoern A. Zeeb 				   id_to_regtype(type), offset, val);
9837*6d67aabdSBjoern A. Zeeb 		else
9838*6d67aabdSBjoern A. Zeeb 			seq_printf(m, ", %s_0x%x=0x%x",
9839*6d67aabdSBjoern A. Zeeb 				   id_to_regtype(type), offset, val);
9840*6d67aabdSBjoern A. Zeeb 		cnt++;
9841e2340276SBjoern A. Zeeb 	}
9842e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
9843e2340276SBjoern A. Zeeb }
9844e2340276SBjoern A. Zeeb 
9845e2340276SBjoern A. Zeeb static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
98468e93258fSBjoern A. Zeeb {
98478e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
98488e93258fSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
98498e93258fSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9850e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
98518e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
98528e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
98538e93258fSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
98548e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
98558e93258fSBjoern A. Zeeb 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
98568e93258fSBjoern A. Zeeb 	u8 i;
98578e93258fSBjoern A. Zeeb 
98588e93258fSBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
98598e93258fSBjoern A. Zeeb 		return;
98608e93258fSBjoern A. Zeeb 
98618e93258fSBjoern A. Zeeb 	seq_puts(m, "========== [Statistics] ==========\n");
98628e93258fSBjoern A. Zeeb 
98638e93258fSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
98648e93258fSBjoern A. Zeeb 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
9865e2340276SBjoern A. Zeeb 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
98668e93258fSBjoern A. Zeeb 
98678e93258fSBjoern A. Zeeb 		seq_printf(m,
98688e93258fSBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
98698e93258fSBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c,
98708e93258fSBjoern A. Zeeb 			   pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
98718e93258fSBjoern A. Zeeb 			   pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
98728e93258fSBjoern A. Zeeb 
98738e93258fSBjoern A. Zeeb 		seq_printf(m,
98748e93258fSBjoern A. Zeeb 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
98758e93258fSBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
98768e93258fSBjoern A. Zeeb 			   prptctrl->rpt_enable, dm->error.val);
98778e93258fSBjoern A. Zeeb 
98788e93258fSBjoern A. Zeeb 		if (dm->error.map.wl_fw_hang)
98798e93258fSBjoern A. Zeeb 			seq_puts(m, " (WL FW Hang!!)");
98808e93258fSBjoern A. Zeeb 		seq_puts(m, "\n");
98818e93258fSBjoern A. Zeeb 		seq_printf(m,
98828e93258fSBjoern A. Zeeb 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d",
98838e93258fSBjoern A. Zeeb 			   "[mailbox]", prptctrl->mb_send_ok_cnt,
98848e93258fSBjoern A. Zeeb 			   prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
98858e93258fSBjoern A. Zeeb 
98868e93258fSBjoern A. Zeeb 		seq_printf(m,
98878e93258fSBjoern A. Zeeb 			   "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
98888e93258fSBjoern A. Zeeb 			   prptctrl->mb_a2dp_empty_cnt,
98898e93258fSBjoern A. Zeeb 			   prptctrl->mb_a2dp_flct_cnt,
98908e93258fSBjoern A. Zeeb 			   prptctrl->mb_a2dp_full_cnt);
98918e93258fSBjoern A. Zeeb 
98928e93258fSBjoern A. Zeeb 		seq_printf(m,
98938e93258fSBjoern A. Zeeb 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
98948e93258fSBjoern A. Zeeb 			   "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
98958e93258fSBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
98968e93258fSBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
98978e93258fSBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
98988e93258fSBjoern A. Zeeb 
98998e93258fSBjoern A. Zeeb 		seq_printf(m,
99008e93258fSBjoern A. Zeeb 			   ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
99018e93258fSBjoern A. Zeeb 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
99028e93258fSBjoern A. Zeeb 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
99038e93258fSBjoern A. Zeeb 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
99048e93258fSBjoern A. Zeeb 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
99058e93258fSBjoern A. Zeeb 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
99068e93258fSBjoern A. Zeeb 
99078e93258fSBjoern A. Zeeb 		if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
99088e93258fSBjoern A. Zeeb 			bt->rfk_info.map.timeout = 1;
99098e93258fSBjoern A. Zeeb 		else
99108e93258fSBjoern A. Zeeb 			bt->rfk_info.map.timeout = 0;
99118e93258fSBjoern A. Zeeb 
99128e93258fSBjoern A. Zeeb 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
99138e93258fSBjoern A. Zeeb 	} else {
99148e93258fSBjoern A. Zeeb 		seq_printf(m,
99158e93258fSBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
99168e93258fSBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c,
99178e93258fSBjoern A. Zeeb 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
99188e93258fSBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_RPT],
99198e93258fSBjoern A. Zeeb 			   btc->fwinfo.rpt_en_map);
99208e93258fSBjoern A. Zeeb 		seq_puts(m, " (WL FW report invalid!!)\n");
99218e93258fSBjoern A. Zeeb 	}
99228e93258fSBjoern A. Zeeb 
99238e93258fSBjoern A. Zeeb 	for (i = 0; i < BTC_NCNT_NUM; i++)
99248e93258fSBjoern A. Zeeb 		cnt_sum += dm->cnt_notify[i];
99258e93258fSBjoern A. Zeeb 
99268e93258fSBjoern A. Zeeb 	seq_printf(m,
99278e93258fSBjoern A. Zeeb 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
99288e93258fSBjoern A. Zeeb 		   "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
99298e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
99308e93258fSBjoern A. Zeeb 
99318e93258fSBjoern A. Zeeb 	seq_printf(m,
99328e93258fSBjoern A. Zeeb 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
99338e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
99348e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
99358e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_WL_STA]);
99368e93258fSBjoern A. Zeeb 
99378e93258fSBjoern A. Zeeb 	seq_printf(m,
99388e93258fSBjoern A. Zeeb 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
99398e93258fSBjoern A. Zeeb 		   "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
99408e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
99418e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_SPECIAL_PACKET]);
99428e93258fSBjoern A. Zeeb 
99438e93258fSBjoern A. Zeeb 	seq_printf(m,
99448e93258fSBjoern A. Zeeb 		   "timer=%d, control=%d, customerize=%d\n",
99458e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
99468e93258fSBjoern A. Zeeb 		   cnt[BTC_NCNT_CUSTOMERIZE]);
99478e93258fSBjoern A. Zeeb }
99488e93258fSBjoern A. Zeeb 
9949e2340276SBjoern A. Zeeb static void _show_summary_v4(struct rtw89_dev *rtwdev, struct seq_file *m)
9950e2340276SBjoern A. Zeeb {
9951e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
9952e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9953e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
9954e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9955e2340276SBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
9956e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
9957e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
9958e2340276SBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
9959e2340276SBjoern A. Zeeb 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
9960e2340276SBjoern A. Zeeb 	u8 i;
9961e2340276SBjoern A. Zeeb 
9962e2340276SBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
9963e2340276SBjoern A. Zeeb 		return;
9964e2340276SBjoern A. Zeeb 
9965e2340276SBjoern A. Zeeb 	seq_puts(m, "========== [Statistics] ==========\n");
9966e2340276SBjoern A. Zeeb 
9967e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
9968e2340276SBjoern A. Zeeb 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
9969e2340276SBjoern A. Zeeb 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
9970e2340276SBjoern A. Zeeb 
9971e2340276SBjoern A. Zeeb 		seq_printf(m,
9972e2340276SBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
9973e2340276SBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c,
9974e2340276SBjoern A. Zeeb 			   pfwinfo->cnt_h2c_fail,
9975e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
9976e2340276SBjoern A. Zeeb 			   pfwinfo->cnt_c2h,
9977e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
9978e2340276SBjoern A. Zeeb 
9979e2340276SBjoern A. Zeeb 		seq_printf(m,
9980e2340276SBjoern A. Zeeb 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
9981e2340276SBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_RPT],
9982e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->rpt_info.cnt),
9983e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->rpt_info.en),
9984e2340276SBjoern A. Zeeb 			   dm->error.val);
9985e2340276SBjoern A. Zeeb 
9986e2340276SBjoern A. Zeeb 		if (dm->error.map.wl_fw_hang)
9987e2340276SBjoern A. Zeeb 			seq_puts(m, " (WL FW Hang!!)");
9988e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
9989e2340276SBjoern A. Zeeb 		seq_printf(m,
9990e2340276SBjoern A. Zeeb 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
9991e2340276SBjoern A. Zeeb 			   "[mailbox]",
9992e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
9993e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
9994e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
9995e2340276SBjoern A. Zeeb 
9996e2340276SBjoern A. Zeeb 		seq_printf(m,
9997e2340276SBjoern A. Zeeb 			   "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
9998e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
9999e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10000e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10001e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10002e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10003e2340276SBjoern A. Zeeb 
10004e2340276SBjoern A. Zeeb 		seq_printf(m,
10005e2340276SBjoern A. Zeeb 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
10006e2340276SBjoern A. Zeeb 			   "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10007e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
10008e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10009e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10010e2340276SBjoern A. Zeeb 
10011e2340276SBjoern A. Zeeb 		seq_printf(m,
10012e2340276SBjoern A. Zeeb 			   ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
10013e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
10014e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
10015e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
10016e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
10017e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
10018e2340276SBjoern A. Zeeb 
10019e2340276SBjoern A. Zeeb 		if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
10020e2340276SBjoern A. Zeeb 			bt->rfk_info.map.timeout = 1;
10021e2340276SBjoern A. Zeeb 		else
10022e2340276SBjoern A. Zeeb 			bt->rfk_info.map.timeout = 0;
10023e2340276SBjoern A. Zeeb 
10024e2340276SBjoern A. Zeeb 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
10025e2340276SBjoern A. Zeeb 	} else {
10026e2340276SBjoern A. Zeeb 		seq_printf(m,
10027e2340276SBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
10028e2340276SBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c,
10029e2340276SBjoern A. Zeeb 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
10030e2340276SBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_RPT],
10031e2340276SBjoern A. Zeeb 			   btc->fwinfo.rpt_en_map);
10032e2340276SBjoern A. Zeeb 		seq_puts(m, " (WL FW report invalid!!)\n");
10033e2340276SBjoern A. Zeeb 	}
10034e2340276SBjoern A. Zeeb 
10035e2340276SBjoern A. Zeeb 	for (i = 0; i < BTC_NCNT_NUM; i++)
10036e2340276SBjoern A. Zeeb 		cnt_sum += dm->cnt_notify[i];
10037e2340276SBjoern A. Zeeb 
10038e2340276SBjoern A. Zeeb 	seq_printf(m,
10039e2340276SBjoern A. Zeeb 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10040e2340276SBjoern A. Zeeb 		   "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10041e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10042e2340276SBjoern A. Zeeb 
10043e2340276SBjoern A. Zeeb 	seq_printf(m,
10044e2340276SBjoern A. Zeeb 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
10045e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10046e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10047e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_WL_STA]);
10048e2340276SBjoern A. Zeeb 
10049e2340276SBjoern A. Zeeb 	seq_printf(m,
10050e2340276SBjoern A. Zeeb 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10051e2340276SBjoern A. Zeeb 		   "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
10052e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
10053e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_SPECIAL_PACKET]);
10054e2340276SBjoern A. Zeeb 
10055e2340276SBjoern A. Zeeb 	seq_printf(m,
10056e2340276SBjoern A. Zeeb 		   "timer=%d, control=%d, customerize=%d\n",
10057e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10058e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_CUSTOMERIZE]);
10059e2340276SBjoern A. Zeeb }
10060e2340276SBjoern A. Zeeb 
10061e2340276SBjoern A. Zeeb static void _show_summary_v5(struct rtw89_dev *rtwdev, struct seq_file *m)
10062e2340276SBjoern A. Zeeb {
10063e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
10064e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10065e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
10066e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10067e2340276SBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
10068e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
10069e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
10070e2340276SBjoern A. Zeeb 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10071e2340276SBjoern A. Zeeb 	u8 i;
10072e2340276SBjoern A. Zeeb 
10073e2340276SBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10074e2340276SBjoern A. Zeeb 		return;
10075e2340276SBjoern A. Zeeb 
10076e2340276SBjoern A. Zeeb 	seq_puts(m, "========== [Statistics] ==========\n");
10077e2340276SBjoern A. Zeeb 
10078e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10079e2340276SBjoern A. Zeeb 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10080e2340276SBjoern A. Zeeb 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
10081e2340276SBjoern A. Zeeb 
10082e2340276SBjoern A. Zeeb 		seq_printf(m,
10083e2340276SBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
10084e2340276SBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10085e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
10086e2340276SBjoern A. Zeeb 			   pfwinfo->cnt_c2h,
10087e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10088e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.len_c2h));
10089e2340276SBjoern A. Zeeb 
10090e2340276SBjoern A. Zeeb 		seq_printf(m,
10091e2340276SBjoern A. Zeeb 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10092e2340276SBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_RPT],
10093e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt),
10094e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->rpt_info.en));
10095e2340276SBjoern A. Zeeb 
10096e2340276SBjoern A. Zeeb 		if (dm->error.map.wl_fw_hang)
10097e2340276SBjoern A. Zeeb 			seq_puts(m, " (WL FW Hang!!)");
10098e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
10099e2340276SBjoern A. Zeeb 		seq_printf(m,
10100e2340276SBjoern A. Zeeb 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10101e2340276SBjoern A. Zeeb 			   "[mailbox]",
10102e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10103e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10104e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10105e2340276SBjoern A. Zeeb 
10106e2340276SBjoern A. Zeeb 		seq_printf(m,
10107e2340276SBjoern A. Zeeb 			   "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
10108e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10109e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10110e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10111e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10112e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10113e2340276SBjoern A. Zeeb 
10114e2340276SBjoern A. Zeeb 		seq_printf(m,
10115e2340276SBjoern A. Zeeb 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
10116e2340276SBjoern A. Zeeb 			   "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10117e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
10118e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10119e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10120e2340276SBjoern A. Zeeb 
10121e2340276SBjoern A. Zeeb 		seq_printf(m,
10122e2340276SBjoern A. Zeeb 			   ", bt_rfk[req:%d]",
10123e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10124e2340276SBjoern A. Zeeb 
10125e2340276SBjoern A. Zeeb 		seq_printf(m,
10126e2340276SBjoern A. Zeeb 			   ", AOAC[RF_on:%d/RF_off:%d]",
10127e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10128e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10129e2340276SBjoern A. Zeeb 	} else {
10130e2340276SBjoern A. Zeeb 		seq_printf(m,
10131e2340276SBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
10132e2340276SBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c,
10133e2340276SBjoern A. Zeeb 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
10134e2340276SBjoern A. Zeeb 	}
10135e2340276SBjoern A. Zeeb 
10136e2340276SBjoern A. Zeeb 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
10137e2340276SBjoern A. Zeeb 	    pfwinfo->err[BTFRE_EXCEPTION]) {
10138e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
10139e2340276SBjoern A. Zeeb 		seq_printf(m,
10140e2340276SBjoern A. Zeeb 			   " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
10141e2340276SBjoern A. Zeeb 			   "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
10142e2340276SBjoern A. Zeeb 			   "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
10143e2340276SBjoern A. Zeeb 			   pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION],
10144e2340276SBjoern A. Zeeb 			   wl->status.map.lps, wl->status.map.rf_off);
10145e2340276SBjoern A. Zeeb 	}
10146e2340276SBjoern A. Zeeb 
10147e2340276SBjoern A. Zeeb 	for (i = 0; i < BTC_NCNT_NUM; i++)
10148e2340276SBjoern A. Zeeb 		cnt_sum += dm->cnt_notify[i];
10149e2340276SBjoern A. Zeeb 
10150e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
10151e2340276SBjoern A. Zeeb 	seq_printf(m,
10152e2340276SBjoern A. Zeeb 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10153e2340276SBjoern A. Zeeb 		   "[notify_cnt]",
10154e2340276SBjoern A. Zeeb 		   cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10155e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10156e2340276SBjoern A. Zeeb 
10157e2340276SBjoern A. Zeeb 	seq_printf(m,
10158e2340276SBjoern A. Zeeb 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10159e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10160e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10161e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_WL_STA]);
10162e2340276SBjoern A. Zeeb 
10163e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
10164e2340276SBjoern A. Zeeb 	seq_printf(m,
10165e2340276SBjoern A. Zeeb 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10166e2340276SBjoern A. Zeeb 		   "[notify_cnt]",
10167e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10168e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]);
10169e2340276SBjoern A. Zeeb 
10170e2340276SBjoern A. Zeeb 	seq_printf(m,
10171e2340276SBjoern A. Zeeb 		   "timer=%d, control=%d, customerize=%d",
10172e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10173e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_CUSTOMERIZE]);
10174e2340276SBjoern A. Zeeb }
10175e2340276SBjoern A. Zeeb 
10176e2340276SBjoern A. Zeeb static void _show_summary_v105(struct rtw89_dev *rtwdev, struct seq_file *m)
10177e2340276SBjoern A. Zeeb {
10178e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
10179e2340276SBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10180e2340276SBjoern A. Zeeb 	struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
10181e2340276SBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10182e2340276SBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
10183e2340276SBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
10184e2340276SBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
10185e2340276SBjoern A. Zeeb 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10186e2340276SBjoern A. Zeeb 	u8 i;
10187e2340276SBjoern A. Zeeb 
10188e2340276SBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10189e2340276SBjoern A. Zeeb 		return;
10190e2340276SBjoern A. Zeeb 
10191e2340276SBjoern A. Zeeb 	seq_puts(m, "========== [Statistics] ==========\n");
10192e2340276SBjoern A. Zeeb 
10193e2340276SBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10194e2340276SBjoern A. Zeeb 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10195e2340276SBjoern A. Zeeb 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
10196e2340276SBjoern A. Zeeb 
10197e2340276SBjoern A. Zeeb 		seq_printf(m,
10198e2340276SBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
10199e2340276SBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10200e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
10201e2340276SBjoern A. Zeeb 			   pfwinfo->cnt_c2h,
10202e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10203e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.len_c2h));
10204e2340276SBjoern A. Zeeb 
10205e2340276SBjoern A. Zeeb 		seq_printf(m,
10206e2340276SBjoern A. Zeeb 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10207e2340276SBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_RPT],
10208e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt),
10209e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->rpt_info.en));
10210e2340276SBjoern A. Zeeb 
10211e2340276SBjoern A. Zeeb 		if (dm->error.map.wl_fw_hang)
10212e2340276SBjoern A. Zeeb 			seq_puts(m, " (WL FW Hang!!)");
10213e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
10214e2340276SBjoern A. Zeeb 		seq_printf(m,
10215e2340276SBjoern A. Zeeb 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10216e2340276SBjoern A. Zeeb 			   "[mailbox]",
10217e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10218e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10219e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10220e2340276SBjoern A. Zeeb 
10221e2340276SBjoern A. Zeeb 		seq_printf(m,
10222e2340276SBjoern A. Zeeb 			   "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
10223e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10224e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10225e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10226e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10227e2340276SBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10228e2340276SBjoern A. Zeeb 
10229e2340276SBjoern A. Zeeb 		seq_printf(m,
10230e2340276SBjoern A. Zeeb 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
10231e2340276SBjoern A. Zeeb 			   "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10232e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
10233e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10234e2340276SBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10235e2340276SBjoern A. Zeeb 
10236e2340276SBjoern A. Zeeb 		seq_printf(m,
10237e2340276SBjoern A. Zeeb 			   ", bt_rfk[req:%d]",
10238e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10239e2340276SBjoern A. Zeeb 
10240e2340276SBjoern A. Zeeb 		seq_printf(m,
10241e2340276SBjoern A. Zeeb 			   ", AOAC[RF_on:%d/RF_off:%d]",
10242e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10243e2340276SBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10244e2340276SBjoern A. Zeeb 	} else {
10245e2340276SBjoern A. Zeeb 		seq_printf(m,
10246e2340276SBjoern A. Zeeb 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
10247e2340276SBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c,
10248e2340276SBjoern A. Zeeb 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
10249e2340276SBjoern A. Zeeb 	}
10250e2340276SBjoern A. Zeeb 
10251e2340276SBjoern A. Zeeb 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
10252e2340276SBjoern A. Zeeb 	    pfwinfo->err[BTFRE_EXCEPTION]) {
10253e2340276SBjoern A. Zeeb 		seq_puts(m, "\n");
10254e2340276SBjoern A. Zeeb 		seq_printf(m,
10255e2340276SBjoern A. Zeeb 			   " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
10256e2340276SBjoern A. Zeeb 			   "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
10257e2340276SBjoern A. Zeeb 			   "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
10258e2340276SBjoern A. Zeeb 			   pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION],
10259e2340276SBjoern A. Zeeb 			   wl->status.map.lps, wl->status.map.rf_off);
10260e2340276SBjoern A. Zeeb 	}
10261e2340276SBjoern A. Zeeb 
10262e2340276SBjoern A. Zeeb 	for (i = 0; i < BTC_NCNT_NUM; i++)
10263e2340276SBjoern A. Zeeb 		cnt_sum += dm->cnt_notify[i];
10264e2340276SBjoern A. Zeeb 
10265e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
10266e2340276SBjoern A. Zeeb 	seq_printf(m,
10267e2340276SBjoern A. Zeeb 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10268e2340276SBjoern A. Zeeb 		   "[notify_cnt]",
10269e2340276SBjoern A. Zeeb 		   cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10270e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10271e2340276SBjoern A. Zeeb 
10272e2340276SBjoern A. Zeeb 	seq_printf(m,
10273e2340276SBjoern A. Zeeb 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10274e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10275e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10276e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_WL_STA]);
10277e2340276SBjoern A. Zeeb 
10278e2340276SBjoern A. Zeeb 	seq_puts(m, "\n");
10279e2340276SBjoern A. Zeeb 	seq_printf(m,
10280e2340276SBjoern A. Zeeb 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10281e2340276SBjoern A. Zeeb 		   "[notify_cnt]",
10282e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10283e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]);
10284e2340276SBjoern A. Zeeb 
10285e2340276SBjoern A. Zeeb 	seq_printf(m,
10286e2340276SBjoern A. Zeeb 		   "timer=%d, control=%d, customerize=%d",
10287e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10288e2340276SBjoern A. Zeeb 		   cnt[BTC_NCNT_CUSTOMERIZE]);
10289e2340276SBjoern A. Zeeb }
10290e2340276SBjoern A. Zeeb 
10291*6d67aabdSBjoern A. Zeeb static void _show_summary_v8(struct rtw89_dev *rtwdev, struct seq_file *m)
10292*6d67aabdSBjoern A. Zeeb {
10293*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10294*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10295*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
10296*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
10297*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10298*6d67aabdSBjoern A. Zeeb 	struct rtw89_btc_wl_info *wl = &cx->wl;
10299*6d67aabdSBjoern A. Zeeb 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
10300*6d67aabdSBjoern A. Zeeb 	u32 cnt_sum = 0;
10301*6d67aabdSBjoern A. Zeeb 	u8 i;
10302*6d67aabdSBjoern A. Zeeb 
10303*6d67aabdSBjoern A. Zeeb 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10304*6d67aabdSBjoern A. Zeeb 		return;
10305*6d67aabdSBjoern A. Zeeb 
10306*6d67aabdSBjoern A. Zeeb 	seq_printf(m, "%s", "\n\r========== [Statistics] ==========");
10307*6d67aabdSBjoern A. Zeeb 
10308*6d67aabdSBjoern A. Zeeb 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10309*6d67aabdSBjoern A. Zeeb 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
10310*6d67aabdSBjoern A. Zeeb 	    !wl->status.map.rf_off) {
10311*6d67aabdSBjoern A. Zeeb 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
10312*6d67aabdSBjoern A. Zeeb 
10313*6d67aabdSBjoern A. Zeeb 		seq_printf(m,
10314*6d67aabdSBjoern A. Zeeb 			   "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
10315*6d67aabdSBjoern A. Zeeb 			   "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10316*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_h2c), pfwinfo->cnt_c2h,
10317*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10318*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.len_c2h),
10319*6d67aabdSBjoern A. Zeeb 			   (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
10320*6d67aabdSBjoern A. Zeeb 			   rtwdev->btc.ver->info_buf);
10321*6d67aabdSBjoern A. Zeeb 
10322*6d67aabdSBjoern A. Zeeb 		seq_printf(m, "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10323*6d67aabdSBjoern A. Zeeb 			   pfwinfo->event[BTF_EVNT_RPT],
10324*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt),
10325*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->rpt_info.en));
10326*6d67aabdSBjoern A. Zeeb 
10327*6d67aabdSBjoern A. Zeeb 		if (dm->error.map.wl_fw_hang)
10328*6d67aabdSBjoern A. Zeeb 			seq_puts(m, " (WL FW Hang!!)");
10329*6d67aabdSBjoern A. Zeeb 
10330*6d67aabdSBjoern A. Zeeb 		seq_printf(m, "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10331*6d67aabdSBjoern A. Zeeb 			   "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10332*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10333*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10334*6d67aabdSBjoern A. Zeeb 
10335*6d67aabdSBjoern A. Zeeb 		seq_printf(m, "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
10336*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10337*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10338*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10339*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10340*6d67aabdSBjoern A. Zeeb 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10341*6d67aabdSBjoern A. Zeeb 
10342*6d67aabdSBjoern A. Zeeb 		seq_printf(m,
10343*6d67aabdSBjoern A. Zeeb 			   "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
10344*6d67aabdSBjoern A. Zeeb 			   "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10345*6d67aabdSBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
10346*6d67aabdSBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10347*6d67aabdSBjoern A. Zeeb 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
10348*6d67aabdSBjoern A. Zeeb 			   wl->rfk_info.proc_time);
10349*6d67aabdSBjoern A. Zeeb 
10350*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", bt_rfk[req:%d]",
10351*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10352*6d67aabdSBjoern A. Zeeb 
10353*6d67aabdSBjoern A. Zeeb 		seq_printf(m, ", AOAC[RF_on:%d/RF_off:%d]",
10354*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10355*6d67aabdSBjoern A. Zeeb 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10356*6d67aabdSBjoern A. Zeeb 	} else {
10357*6d67aabdSBjoern A. Zeeb 		seq_printf(m,
10358*6d67aabdSBjoern A. Zeeb 			   "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
10359*6d67aabdSBjoern A. Zeeb 			   "[summary]",
10360*6d67aabdSBjoern A. Zeeb 			   pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10361*6d67aabdSBjoern A. Zeeb 			   pfwinfo->cnt_c2h,
10362*6d67aabdSBjoern A. Zeeb 			   wl->status.map.lps, wl->status.map.rf_off);
10363*6d67aabdSBjoern A. Zeeb 	}
10364*6d67aabdSBjoern A. Zeeb 
10365*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < BTC_NCNT_NUM; i++)
10366*6d67aabdSBjoern A. Zeeb 		cnt_sum += dm->cnt_notify[i];
10367*6d67aabdSBjoern A. Zeeb 
10368*6d67aabdSBjoern A. Zeeb 	seq_printf(m,
10369*6d67aabdSBjoern A. Zeeb 		   "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10370*6d67aabdSBjoern A. Zeeb 		   "[notify_cnt]",
10371*6d67aabdSBjoern A. Zeeb 		   cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10372*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10373*6d67aabdSBjoern A. Zeeb 
10374*6d67aabdSBjoern A. Zeeb 	seq_printf(m,
10375*6d67aabdSBjoern A. Zeeb 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10376*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10377*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10378*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_WL_STA]);
10379*6d67aabdSBjoern A. Zeeb 
10380*6d67aabdSBjoern A. Zeeb 	seq_printf(m,
10381*6d67aabdSBjoern A. Zeeb 		   "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
10382*6d67aabdSBjoern A. Zeeb 		   "[notify_cnt]",
10383*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10384*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
10385*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_SPECIAL_PACKET]);
10386*6d67aabdSBjoern A. Zeeb 
10387*6d67aabdSBjoern A. Zeeb 	seq_printf(m, "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
10388*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
10389*6d67aabdSBjoern A. Zeeb 		   rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
10390*6d67aabdSBjoern A. Zeeb 		   cnt[BTC_NCNT_COUNTRYCODE]);
10391*6d67aabdSBjoern A. Zeeb }
10392*6d67aabdSBjoern A. Zeeb 
103938e93258fSBjoern A. Zeeb void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
103948e93258fSBjoern A. Zeeb {
103958e93258fSBjoern A. Zeeb 	struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
103968e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
10397e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *ver = btc->ver;
103988e93258fSBjoern A. Zeeb 	struct rtw89_btc_cx *cx = &btc->cx;
103998e93258fSBjoern A. Zeeb 	struct rtw89_btc_bt_info *bt = &cx->bt;
104008e93258fSBjoern A. Zeeb 
104018e93258fSBjoern A. Zeeb 	seq_puts(m, "=========================================\n");
104028e93258fSBjoern A. Zeeb 	seq_printf(m, "WL FW / BT FW		%d.%d.%d.%d / NA\n",
104038e93258fSBjoern A. Zeeb 		   fw_suit->major_ver, fw_suit->minor_ver,
104048e93258fSBjoern A. Zeeb 		   fw_suit->sub_ver, fw_suit->sub_idex);
10405*6d67aabdSBjoern A. Zeeb 	seq_printf(m, "manual			%d\n", btc->manual_ctrl);
104068e93258fSBjoern A. Zeeb 
104078e93258fSBjoern A. Zeeb 	seq_puts(m, "=========================================\n");
104088e93258fSBjoern A. Zeeb 
104098e93258fSBjoern A. Zeeb 	seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
104108e93258fSBjoern A. Zeeb 		   "[bt_info]",
104118e93258fSBjoern A. Zeeb 		   bt->raw_info[2], bt->raw_info[3],
104128e93258fSBjoern A. Zeeb 		   bt->raw_info[4], bt->raw_info[5],
104138e93258fSBjoern A. Zeeb 		   bt->raw_info[6], bt->raw_info[7],
104148e93258fSBjoern A. Zeeb 		   bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
104158e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_INFOUPDATE],
104168e93258fSBjoern A. Zeeb 		   cx->cnt_bt[BTC_BCNT_INFOSAME]);
104178e93258fSBjoern A. Zeeb 
104188e93258fSBjoern A. Zeeb 	seq_puts(m, "\n=========================================\n");
104198e93258fSBjoern A. Zeeb 
104208e93258fSBjoern A. Zeeb 	_show_cx_info(rtwdev, m);
104218e93258fSBjoern A. Zeeb 	_show_wl_info(rtwdev, m);
104228e93258fSBjoern A. Zeeb 	_show_bt_info(rtwdev, m);
104238e93258fSBjoern A. Zeeb 	_show_dm_info(rtwdev, m);
104248e93258fSBjoern A. Zeeb 	_show_fw_dm_msg(rtwdev, m);
10425e2340276SBjoern A. Zeeb 
10426e2340276SBjoern A. Zeeb 	if (ver->fcxmreg == 1)
10427e2340276SBjoern A. Zeeb 		_show_mreg_v1(rtwdev, m);
10428e2340276SBjoern A. Zeeb 	else if (ver->fcxmreg == 2)
10429e2340276SBjoern A. Zeeb 		_show_mreg_v2(rtwdev, m);
10430*6d67aabdSBjoern A. Zeeb 	else if (ver->fcxmreg == 7)
10431*6d67aabdSBjoern A. Zeeb 		_show_mreg_v7(rtwdev, m);
10432*6d67aabdSBjoern A. Zeeb 
10433*6d67aabdSBjoern A. Zeeb 	_show_gpio_dbg(rtwdev, m);
10434e2340276SBjoern A. Zeeb 
10435e2340276SBjoern A. Zeeb 	if (ver->fcxbtcrpt == 1)
10436e2340276SBjoern A. Zeeb 		_show_summary_v1(rtwdev, m);
10437e2340276SBjoern A. Zeeb 	else if (ver->fcxbtcrpt == 4)
10438e2340276SBjoern A. Zeeb 		_show_summary_v4(rtwdev, m);
10439e2340276SBjoern A. Zeeb 	else if (ver->fcxbtcrpt == 5)
10440e2340276SBjoern A. Zeeb 		_show_summary_v5(rtwdev, m);
10441e2340276SBjoern A. Zeeb 	else if (ver->fcxbtcrpt == 105)
10442e2340276SBjoern A. Zeeb 		_show_summary_v105(rtwdev, m);
10443*6d67aabdSBjoern A. Zeeb 	else if (ver->fcxbtcrpt == 8)
10444*6d67aabdSBjoern A. Zeeb 		_show_summary_v8(rtwdev, m);
10445e2340276SBjoern A. Zeeb }
10446e2340276SBjoern A. Zeeb 
10447e2340276SBjoern A. Zeeb void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
10448e2340276SBjoern A. Zeeb {
10449e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
10450e2340276SBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
10451e2340276SBjoern A. Zeeb 	const struct rtw89_btc_ver *btc_ver_def;
10452e2340276SBjoern A. Zeeb 	const struct rtw89_fw_suit *fw_suit;
10453e2340276SBjoern A. Zeeb 	u32 suit_ver_code;
10454e2340276SBjoern A. Zeeb 	int i;
10455e2340276SBjoern A. Zeeb 
10456e2340276SBjoern A. Zeeb 	fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
10457e2340276SBjoern A. Zeeb 	suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
10458e2340276SBjoern A. Zeeb 
10459e2340276SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
10460e2340276SBjoern A. Zeeb 		btc_ver_def = &rtw89_btc_ver_defs[i];
10461e2340276SBjoern A. Zeeb 
10462e2340276SBjoern A. Zeeb 		if (chip->chip_id != btc_ver_def->chip_id)
10463e2340276SBjoern A. Zeeb 			continue;
10464e2340276SBjoern A. Zeeb 
10465e2340276SBjoern A. Zeeb 		if (suit_ver_code >= btc_ver_def->fw_ver_code) {
10466e2340276SBjoern A. Zeeb 			btc->ver = btc_ver_def;
10467e2340276SBjoern A. Zeeb 			goto out;
10468e2340276SBjoern A. Zeeb 		}
10469e2340276SBjoern A. Zeeb 	}
10470e2340276SBjoern A. Zeeb 
10471e2340276SBjoern A. Zeeb 	btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
10472e2340276SBjoern A. Zeeb 
10473e2340276SBjoern A. Zeeb out:
10474e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
10475e2340276SBjoern A. Zeeb 		    (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
104768e93258fSBjoern A. Zeeb }
10477