xref: /linux/drivers/net/wireless/realtek/rtw89/coex.c (revision 416a445e)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020  Realtek Corporation
3  */
4 
5 #include "coex.h"
6 #include "debug.h"
7 #include "fw.h"
8 #include "mac.h"
9 #include "phy.h"
10 #include "ps.h"
11 #include "reg.h"
12 
13 #define RTW89_COEX_VERSION 0x07000113
14 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
15 #define BTC_E2G_LIMIT_DEF 80
16 
17 enum btc_fbtc_tdma_template {
18 	CXTD_OFF = 0x0,
19 	CXTD_OFF_B2,
20 	CXTD_OFF_EXT,
21 	CXTD_FIX,
22 	CXTD_PFIX,
23 	CXTD_AUTO,
24 	CXTD_PAUTO,
25 	CXTD_AUTO2,
26 	CXTD_PAUTO2,
27 	CXTD_MAX,
28 };
29 
30 enum btc_fbtc_tdma_type {
31 	CXTDMA_OFF = 0x0,
32 	CXTDMA_FIX = 0x1,
33 	CXTDMA_AUTO = 0x2,
34 	CXTDMA_AUTO2 = 0x3,
35 	CXTDMA_MAX
36 };
37 
38 enum btc_fbtc_tdma_rx_flow_ctrl {
39 	CXFLC_OFF = 0x0,
40 	CXFLC_NULLP = 0x1,
41 	CXFLC_QOSNULL = 0x2,
42 	CXFLC_CTS = 0x3,
43 	CXFLC_MAX
44 };
45 
46 enum btc_fbtc_tdma_wlan_tx_pause {
47 	CXTPS_OFF = 0x0,  /* no wl tx pause*/
48 	CXTPS_ON = 0x1,
49 	CXTPS_MAX
50 };
51 
52 enum btc_mlme_state {
53 	MLME_NO_LINK,
54 	MLME_LINKING,
55 	MLME_LINKED,
56 };
57 
58 struct btc_fbtc_1slot {
59 	u8 fver;
60 	u8 sid; /* slot id */
61 	struct rtw89_btc_fbtc_slot slot;
62 } __packed;
63 
64 static const struct rtw89_btc_fbtc_tdma t_def[] = {
65 	[CXTD_OFF]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
66 	[CXTD_OFF_B2]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
67 	[CXTD_OFF_EXT]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
68 	[CXTD_FIX]	= { CXTDMA_FIX,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
69 	[CXTD_PFIX]	= { CXTDMA_FIX,  CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
70 	[CXTD_AUTO]	= { CXTDMA_AUTO,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
71 	[CXTD_PAUTO]	= { CXTDMA_AUTO, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
72 	[CXTD_AUTO2]	= {CXTDMA_AUTO2,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
73 	[CXTD_PAUTO2]	= {CXTDMA_AUTO2, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0}
74 };
75 
76 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
77 	{ .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
78 	  .cxtype = cpu_to_le16(__cxtype),}
79 
80 static const struct rtw89_btc_fbtc_slot s_def[] = {
81 	[CXST_OFF]	= __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
82 	[CXST_B2W]	= __DEF_FBTC_SLOT(5,   0xea5a5a5a, SLOT_ISO),
83 	[CXST_W1]	= __DEF_FBTC_SLOT(70,  0xea5a5a5a, SLOT_ISO),
84 	[CXST_W2]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
85 	[CXST_W2B]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
86 	[CXST_B1]	= __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
87 	[CXST_B2]	= __DEF_FBTC_SLOT(7,   0xea5a5a5a, SLOT_MIX),
88 	[CXST_B3]	= __DEF_FBTC_SLOT(5,   0xe5555555, SLOT_MIX),
89 	[CXST_B4]	= __DEF_FBTC_SLOT(50,  0xe5555555, SLOT_MIX),
90 	[CXST_LK]	= __DEF_FBTC_SLOT(20,  0xea5a5a5a, SLOT_ISO),
91 	[CXST_BLK]	= __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
92 	[CXST_E2G]	= __DEF_FBTC_SLOT(0,   0xea5a5a5a, SLOT_MIX),
93 	[CXST_E5G]	= __DEF_FBTC_SLOT(0,   0xffffffff, SLOT_ISO),
94 	[CXST_EBT]	= __DEF_FBTC_SLOT(0,   0xe5555555, SLOT_MIX),
95 	[CXST_ENULL]	= __DEF_FBTC_SLOT(0,   0xaaaaaaaa, SLOT_ISO),
96 	[CXST_WLK]	= __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
97 	[CXST_W1FDD]	= __DEF_FBTC_SLOT(50,  0xffffffff, SLOT_ISO),
98 	[CXST_B1FDD]	= __DEF_FBTC_SLOT(50,  0xffffdfff, SLOT_ISO),
99 };
100 
101 static const u32 cxtbl[] = {
102 	0xffffffff, /* 0 */
103 	0xaaaaaaaa, /* 1 */
104 	0xe5555555, /* 2 */
105 	0xee555555, /* 3 */
106 	0xd5555555, /* 4 */
107 	0x5a5a5a5a, /* 5 */
108 	0xfa5a5a5a, /* 6 */
109 	0xda5a5a5a, /* 7 */
110 	0xea5a5a5a, /* 8 */
111 	0x6a5a5aaa, /* 9 */
112 	0x6a5a6a5a, /* 10 */
113 	0x6a5a6aaa, /* 11 */
114 	0x6afa5afa, /* 12 */
115 	0xaaaa5aaa, /* 13 */
116 	0xaaffffaa, /* 14 */
117 	0xaa5555aa, /* 15 */
118 	0xfafafafa, /* 16 */
119 	0xffffddff, /* 17 */
120 	0xdaffdaff, /* 18 */
121 	0xfafadafa, /* 19 */
122 	0xea6a6a6a, /* 20 */
123 	0xea55556a, /* 21 */
124 	0xaafafafa, /* 22 */
125 	0xfafaaafa, /* 23 */
126 	0xfafffaff, /* 24 */
127 	0xea6a5a5a, /* 25 */
128 };
129 
130 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
131 	/* firmware version must be in decreasing order for each chip */
132 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
133 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
134 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
135 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
136 	 .fwlrole = 8,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
137 	 .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6,
138 	},
139 	{RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
140 	 .fcxbtcrpt = 105, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 5,
141 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
142 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
143 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
144 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
145 	},
146 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
147 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
148 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
149 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
150 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
151 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
152 	},
153 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
154 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
155 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
156 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
157 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
158 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
159 	},
160 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
161 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
162 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
163 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
164 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
165 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
166 	},
167 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
168 	 .fcxbtcrpt = 105, .fcxtdma = 3,  .fcxslots = 1, .fcxcysta = 5,
169 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
170 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
171 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
172 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
173 	},
174 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
175 	 .fcxbtcrpt = 5, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 4,
176 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
177 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
178 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
179 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6,
180 	},
181 	{RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
182 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
183 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
184 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
185 	 .fwlrole = 1,   .frptmap = 1,    .fcxctrl = 1,  .fcxinit = 0,
186 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
187 	},
188 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
189 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
190 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
191 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
192 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
193 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5,
194 	},
195 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
196 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
197 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
198 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
199 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
200 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5,
201 	},
202 
203 	/* keep it to be the last as default entry */
204 	{0, RTW89_FW_VER_CODE(0, 0, 0, 0),
205 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
206 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
207 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
208 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
209 	 .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5,
210 	},
211 };
212 
213 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
214 
215 static const union rtw89_btc_wl_state_map btc_scanning_map = {
216 	.map = {
217 		.scan = 1,
218 		.connecting = 1,
219 		.roaming = 1,
220 		.transacting = 1,
221 		._4way = 1,
222 	},
223 };
224 
chip_id_to_bt_rom_code_id(u32 id)225 static u32 chip_id_to_bt_rom_code_id(u32 id)
226 {
227 	switch (id) {
228 	case RTL8852A:
229 	case RTL8852B:
230 	case RTL8852C:
231 		return 0x8852;
232 	case RTL8851B:
233 		return 0x8851;
234 	case RTL8922A:
235 		return 0x8922;
236 	default:
237 		return 0;
238 	}
239 }
240 
241 struct rtw89_btc_btf_tlv {
242 	u8 type;
243 	u8 len;
244 	u8 val[];
245 } __packed;
246 
247 struct rtw89_btc_btf_tlv_v7 {
248 	u8 type;
249 	u8 ver;
250 	u8 len;
251 	u8 val[];
252 } __packed;
253 
254 enum btc_btf_set_report_en {
255 	RPT_EN_TDMA,
256 	RPT_EN_CYCLE,
257 	RPT_EN_MREG,
258 	RPT_EN_BT_VER_INFO,
259 	RPT_EN_BT_SCAN_INFO,
260 	RPT_EN_BT_DEVICE_INFO,
261 	RPT_EN_BT_AFH_MAP,
262 	RPT_EN_BT_AFH_MAP_LE,
263 	RPT_EN_FW_STEP_INFO,
264 	RPT_EN_TEST,
265 	RPT_EN_WL_ALL,
266 	RPT_EN_BT_ALL,
267 	RPT_EN_ALL,
268 	RPT_EN_MONITER,
269 };
270 
271 struct rtw89_btc_btf_set_report_v1 {
272 	u8 fver;
273 	__le32 enable;
274 	__le32 para;
275 } __packed;
276 
277 struct rtw89_btc_btf_set_report_v8 {
278 	u8 type;
279 	u8 fver;
280 	u8 len;
281 	__le32 map;
282 } __packed;
283 
284 union rtw89_fbtc_rtp_ctrl {
285 	struct rtw89_btc_btf_set_report_v1 v1;
286 	struct rtw89_btc_btf_set_report_v8 v8;
287 };
288 
289 #define BTF_SET_SLOT_TABLE_VER 1
290 struct rtw89_btc_btf_set_slot_table {
291 	u8 fver;
292 	u8 tbl_num;
293 	struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
294 } __packed;
295 
296 struct rtw89_btc_btf_set_slot_table_v7 {
297 	u8 type;
298 	u8 ver;
299 	u8 len;
300 	struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
301 } __packed;
302 
303 struct rtw89_btc_btf_set_mon_reg_v1 {
304 	u8 fver;
305 	u8 reg_num;
306 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
307 } __packed;
308 
309 struct rtw89_btc_btf_set_mon_reg_v7 {
310 	u8 type;
311 	u8 fver;
312 	u8 len;
313 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
314 } __packed;
315 
316 union rtw89_fbtc_set_mon_reg {
317 	struct rtw89_btc_btf_set_mon_reg_v1 v1;
318 	struct rtw89_btc_btf_set_mon_reg_v7 v7;
319 } __packed;
320 
321 struct _wl_rinfo_now {
322 	u8 link_mode;
323 	u32 dbcc_2g_phy: 2;
324 };
325 
326 enum btc_btf_set_cx_policy {
327 	CXPOLICY_TDMA = 0x0,
328 	CXPOLICY_SLOT = 0x1,
329 	CXPOLICY_TYPE = 0x2,
330 	CXPOLICY_MAX,
331 };
332 
333 enum btc_b2w_scoreboard {
334 	BTC_BSCB_ACT = BIT(0),
335 	BTC_BSCB_ON = BIT(1),
336 	BTC_BSCB_WHQL = BIT(2),
337 	BTC_BSCB_BT_S1 = BIT(3),
338 	BTC_BSCB_A2DP_ACT = BIT(4),
339 	BTC_BSCB_RFK_RUN = BIT(5),
340 	BTC_BSCB_RFK_REQ = BIT(6),
341 	BTC_BSCB_LPS = BIT(7),
342 	BTC_BSCB_BT_LNAB0 = BIT(8),
343 	BTC_BSCB_BT_LNAB1 = BIT(10),
344 	BTC_BSCB_WLRFK = BIT(11),
345 	BTC_BSCB_BT_HILNA = BIT(13),
346 	BTC_BSCB_BT_CONNECT = BIT(16),
347 	BTC_BSCB_PATCH_CODE = BIT(30),
348 	BTC_BSCB_ALL = GENMASK(30, 0),
349 };
350 
351 enum btc_phymap {
352 	BTC_PHY_0 = BIT(0),
353 	BTC_PHY_1 = BIT(1),
354 	BTC_PHY_ALL = BIT(0) | BIT(1),
355 };
356 
357 enum btc_cx_state_map {
358 	BTC_WIDLE = 0,
359 	BTC_WBUSY_BNOSCAN,
360 	BTC_WBUSY_BSCAN,
361 	BTC_WSCAN_BNOSCAN,
362 	BTC_WSCAN_BSCAN,
363 	BTC_WLINKING
364 };
365 
366 enum btc_ant_phase {
367 	BTC_ANT_WPOWERON = 0,
368 	BTC_ANT_WINIT,
369 	BTC_ANT_WONLY,
370 	BTC_ANT_WOFF,
371 	BTC_ANT_W2G,
372 	BTC_ANT_W5G,
373 	BTC_ANT_W25G,
374 	BTC_ANT_FREERUN,
375 	BTC_ANT_WRFK,
376 	BTC_ANT_WRFK2,
377 	BTC_ANT_BRFK,
378 	BTC_ANT_MAX
379 };
380 
381 enum btc_plt {
382 	BTC_PLT_NONE = 0,
383 	BTC_PLT_LTE_RX = BIT(0),
384 	BTC_PLT_GNT_BT_TX = BIT(1),
385 	BTC_PLT_GNT_BT_RX = BIT(2),
386 	BTC_PLT_GNT_WL = BIT(3),
387 	BTC_PLT_BT = BIT(1) | BIT(2),
388 	BTC_PLT_ALL = 0xf
389 };
390 
391 enum btc_cx_poicy_main_type {
392 	BTC_CXP_OFF = 0,
393 	BTC_CXP_OFFB,
394 	BTC_CXP_OFFE,
395 	BTC_CXP_FIX,
396 	BTC_CXP_PFIX,
397 	BTC_CXP_AUTO,
398 	BTC_CXP_PAUTO,
399 	BTC_CXP_AUTO2,
400 	BTC_CXP_PAUTO2,
401 	BTC_CXP_MANUAL,
402 	BTC_CXP_USERDEF0,
403 	BTC_CXP_MAIN_MAX
404 };
405 
406 enum btc_cx_poicy_type {
407 	/* TDMA off + pri: BT > WL */
408 	BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
409 
410 	/* TDMA off + pri: WL > BT */
411 	BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
412 
413 	/* TDMA off + pri: BT = WL */
414 	BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
415 
416 	/* TDMA off + pri: BT = WL > BT_Lo */
417 	BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
418 
419 	/* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
420 	BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
421 
422 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
423 	BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
424 
425 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
426 	BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
427 
428 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
429 	BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
430 
431 	/* TDMA off + pri: BT_Hi > WL > BT_Lo */
432 	BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
433 
434 	/* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
435 	BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
436 
437 	/* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
438 	BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
439 
440 	/* TDMA off + pri: WL_Hi-Tx = BT */
441 	BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
442 
443 	/* TDMA off + pri: WL > BT, Block-BT*/
444 	BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
445 
446 	/* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
447 	BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
448 
449 	/* TDMA off + Ext-Ctrl + pri: default */
450 	BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
451 
452 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
453 	BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
454 
455 	/* TDMA off + Ext-Ctrl + pri: default */
456 	BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
457 
458 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
459 	BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
460 
461 	/* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
462 	BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
463 
464 	/* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
465 	BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
466 
467 	/* TDMA off + Ext-Ctrl + pri: default */
468 	BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
469 
470 	/* TDMA Fix slot-0: W1:B1 = 30:30 */
471 	BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
472 
473 	/* TDMA Fix slot-1: W1:B1 = 50:50 */
474 	BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
475 
476 	/* TDMA Fix slot-2: W1:B1 = 20:30 */
477 	BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
478 
479 	/* TDMA Fix slot-3: W1:B1 = 40:10 */
480 	BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
481 
482 	/* TDMA Fix slot-4: W1:B1 = 70:10 */
483 	BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
484 
485 	/* TDMA Fix slot-5: W1:B1 = 20:60 */
486 	BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
487 
488 	/* TDMA Fix slot-6: W1:B1 = 30:60 */
489 	BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
490 
491 	/* TDMA Fix slot-7: W1:B1 = 20:80 */
492 	BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
493 
494 	/* TDMA Fix slot-8: W1:B1 = user-define */
495 	BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
496 
497 	/* TDMA Fix slot-9: W1:B1 = 40:10 */
498 	BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
499 
500 	/* TDMA Fix slot-10: W1:B1 = 40:10 */
501 	BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
502 
503 	/* TDMA Fix slot-11: W1:B1 = 40:10 */
504 	BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
505 
506 	/* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
507 	BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
508 
509 	/* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
510 	BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
511 
512 	/* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
513 	BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
514 
515 	/* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
516 	BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
517 
518 	/* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
519 	BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
520 
521 	/* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
522 	BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
523 
524 	/* PS-TDMA Fix slot-6: W1:B1 = user-define */
525 	BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
526 
527 	/* TDMA Auto slot-0: W1:B1 = 50:200 */
528 	BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
529 
530 	/* TDMA Auto slot-1: W1:B1 = 60:200 */
531 	BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
532 
533 	/* TDMA Auto slot-2: W1:B1 = 20:200 */
534 	BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
535 
536 	/* TDMA Auto slot-3: W1:B1 = user-define */
537 	BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
538 
539 	/* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
540 	BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
541 
542 	/* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
543 	BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
544 
545 	/* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
546 	BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
547 
548 	/* PS-TDMA Auto slot-3: W1:B1 = user-define */
549 	BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
550 
551 	/* TDMA Auto slot2-0: W1:B4 = 30:50 */
552 	BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
553 
554 	/* TDMA Auto slot2-1: W1:B4 = 30:70 */
555 	BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
556 
557 	/* TDMA Auto slot2-2: W1:B4 = 50:50 */
558 	BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
559 
560 	/* TDMA Auto slot2-3: W1:B4 = 60:60 */
561 	BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
562 
563 	/* TDMA Auto slot2-4: W1:B4 = 20:80 */
564 	BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
565 
566 	/* TDMA Auto slot2-5: W1:B4 = user-define */
567 	BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
568 
569 	/* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
570 	BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
571 
572 	/* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
573 	BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
574 
575 	/* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
576 	BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
577 
578 	/* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
579 	BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
580 
581 	/* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
582 	BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
583 
584 	/* PS-TDMA Auto slot2-5: W1:B4 = user-define */
585 	BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
586 
587 	BTC_CXP_MAX = 0xffff
588 };
589 
590 enum btc_wl_rfk_result {
591 	BTC_WRFK_REJECT = 0,
592 	BTC_WRFK_ALLOW = 1,
593 };
594 
595 enum btc_coex_info_map_en {
596 	BTC_COEX_INFO_CX = BIT(0),
597 	BTC_COEX_INFO_WL = BIT(1),
598 	BTC_COEX_INFO_BT = BIT(2),
599 	BTC_COEX_INFO_DM = BIT(3),
600 	BTC_COEX_INFO_MREG = BIT(4),
601 	BTC_COEX_INFO_SUMMARY = BIT(5),
602 	BTC_COEX_INFO_ALL = GENMASK(7, 0),
603 };
604 
605 #define BTC_CXP_MASK GENMASK(15, 8)
606 
607 enum btc_w2b_scoreboard {
608 	BTC_WSCB_ACTIVE = BIT(0),
609 	BTC_WSCB_ON = BIT(1),
610 	BTC_WSCB_SCAN = BIT(2),
611 	BTC_WSCB_UNDERTEST = BIT(3),
612 	BTC_WSCB_RXGAIN = BIT(4),
613 	BTC_WSCB_WLBUSY = BIT(7),
614 	BTC_WSCB_EXTFEM = BIT(8),
615 	BTC_WSCB_TDMA = BIT(9),
616 	BTC_WSCB_FIX2M = BIT(10),
617 	BTC_WSCB_WLRFK = BIT(11),
618 	BTC_WSCB_RXSCAN_PRI = BIT(12),
619 	BTC_WSCB_BT_HILNA = BIT(13),
620 	BTC_WSCB_BTLOG = BIT(14),
621 	BTC_WSCB_ALL = GENMASK(23, 0),
622 };
623 
624 enum btc_wl_link_mode {
625 	BTC_WLINK_NOLINK = 0x0,
626 	BTC_WLINK_2G_STA,
627 	BTC_WLINK_2G_AP,
628 	BTC_WLINK_2G_GO,
629 	BTC_WLINK_2G_GC,
630 	BTC_WLINK_2G_SCC,
631 	BTC_WLINK_2G_MCC,
632 	BTC_WLINK_25G_MCC,
633 	BTC_WLINK_25G_DBCC,
634 	BTC_WLINK_5G,
635 	BTC_WLINK_2G_NAN,
636 	BTC_WLINK_OTHER,
637 	BTC_WLINK_MAX
638 };
639 
640 enum btc_wl_mrole_type {
641 	BTC_WLMROLE_NONE = 0x0,
642 	BTC_WLMROLE_STA_GC,
643 	BTC_WLMROLE_STA_GC_NOA,
644 	BTC_WLMROLE_STA_GO,
645 	BTC_WLMROLE_STA_GO_NOA,
646 	BTC_WLMROLE_STA_STA,
647 	BTC_WLMROLE_MAX
648 };
649 
650 enum btc_bt_hid_type {
651 	BTC_HID_218 = BIT(0),
652 	BTC_HID_418 = BIT(1),
653 	BTC_HID_BLE = BIT(2),
654 	BTC_HID_RCU = BIT(3),
655 	BTC_HID_RCU_VOICE = BIT(4),
656 	BTC_HID_OTHER_LEGACY = BIT(5)
657 };
658 
659 enum btc_reset_module {
660 	BTC_RESET_CX = BIT(0),
661 	BTC_RESET_DM = BIT(1),
662 	BTC_RESET_CTRL = BIT(2),
663 	BTC_RESET_CXDM = BIT(0) | BIT(1),
664 	BTC_RESET_BTINFO = BIT(3),
665 	BTC_RESET_MDINFO = BIT(4),
666 	BTC_RESET_ALL =  GENMASK(7, 0),
667 };
668 
669 enum btc_gnt_state {
670 	BTC_GNT_HW	= 0,
671 	BTC_GNT_SW_LO,
672 	BTC_GNT_SW_HI,
673 	BTC_GNT_MAX
674 };
675 
676 enum btc_ctr_path {
677 	BTC_CTRL_BY_BT = 0,
678 	BTC_CTRL_BY_WL
679 };
680 
681 enum btc_wlact_state {
682 	BTC_WLACT_HW = 0,
683 	BTC_WLACT_SW_LO,
684 	BTC_WLACT_SW_HI,
685 	BTC_WLACT_MAX,
686 };
687 
688 enum btc_wl_max_tx_time {
689 	BTC_MAX_TX_TIME_L1 = 500,
690 	BTC_MAX_TX_TIME_L2 = 1000,
691 	BTC_MAX_TX_TIME_L3 = 2000,
692 	BTC_MAX_TX_TIME_DEF = 5280
693 };
694 
695 enum btc_wl_max_tx_retry {
696 	BTC_MAX_TX_RETRY_L1 = 7,
697 	BTC_MAX_TX_RETRY_L2 = 15,
698 	BTC_MAX_TX_RETRY_DEF = 31,
699 };
700 
701 enum btc_reason_and_action {
702 	BTC_RSN_NONE,
703 	BTC_RSN_NTFY_INIT,
704 	BTC_RSN_NTFY_SWBAND,
705 	BTC_RSN_NTFY_WL_STA,
706 	BTC_RSN_NTFY_RADIO_STATE,
707 	BTC_RSN_UPDATE_BT_SCBD,
708 	BTC_RSN_NTFY_WL_RFK,
709 	BTC_RSN_UPDATE_BT_INFO,
710 	BTC_RSN_NTFY_SCAN_START,
711 	BTC_RSN_NTFY_SCAN_FINISH,
712 	BTC_RSN_NTFY_SPECIFIC_PACKET,
713 	BTC_RSN_NTFY_POWEROFF,
714 	BTC_RSN_NTFY_ROLE_INFO,
715 	BTC_RSN_CMD_SET_COEX,
716 	BTC_RSN_ACT1_WORK,
717 	BTC_RSN_BT_DEVINFO_WORK,
718 	BTC_RSN_RFK_CHK_WORK,
719 	BTC_RSN_NUM,
720 	BTC_ACT_NONE = 100,
721 	BTC_ACT_WL_ONLY,
722 	BTC_ACT_WL_5G,
723 	BTC_ACT_WL_OTHER,
724 	BTC_ACT_WL_IDLE,
725 	BTC_ACT_WL_NC,
726 	BTC_ACT_WL_RFK,
727 	BTC_ACT_WL_INIT,
728 	BTC_ACT_WL_OFF,
729 	BTC_ACT_FREERUN,
730 	BTC_ACT_BT_WHQL,
731 	BTC_ACT_BT_RFK,
732 	BTC_ACT_BT_OFF,
733 	BTC_ACT_BT_IDLE,
734 	BTC_ACT_BT_HFP,
735 	BTC_ACT_BT_HID,
736 	BTC_ACT_BT_A2DP,
737 	BTC_ACT_BT_A2DPSINK,
738 	BTC_ACT_BT_PAN,
739 	BTC_ACT_BT_A2DP_HID,
740 	BTC_ACT_BT_A2DP_PAN,
741 	BTC_ACT_BT_PAN_HID,
742 	BTC_ACT_BT_A2DP_PAN_HID,
743 	BTC_ACT_WL_25G_MCC,
744 	BTC_ACT_WL_2G_MCC,
745 	BTC_ACT_WL_2G_SCC,
746 	BTC_ACT_WL_2G_AP,
747 	BTC_ACT_WL_2G_GO,
748 	BTC_ACT_WL_2G_GC,
749 	BTC_ACT_WL_2G_NAN,
750 	BTC_ACT_LAST,
751 	BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
752 	BTC_ACT_EXT_BIT = BIT(14),
753 	BTC_POLICY_EXT_BIT = BIT(15),
754 };
755 
756 #define BTC_FREERUN_ANTISO_MIN 30
757 #define BTC_TDMA_BTHID_MAX 2
758 #define BTC_BLINK_NOCONNECT 0
759 #define BTC_B1_MAX 250 /* unit ms */
760 
761 static void _run_coex(struct rtw89_dev *rtwdev,
762 		      enum btc_reason_and_action reason);
763 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
764 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
765 
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)766 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
767 			void *param, u16 len)
768 {
769 	struct rtw89_btc *btc = &rtwdev->btc;
770 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
771 	struct rtw89_btc_cx *cx = &btc->cx;
772 	struct rtw89_btc_wl_info *wl = &cx->wl;
773 	struct rtw89_btc_dm *dm = &btc->dm;
774 	int ret;
775 
776 	if (len > BTC_H2C_MAXLEN || len == 0) {
777 		btc->fwinfo.cnt_h2c_fail++;
778 		dm->error.map.h2c_buffer_over = true;
779 		return -EINVAL;
780 	} else if (!wl->status.map.init_ok) {
781 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
782 			    "[BTC], %s(): return by btc not init!!\n", __func__);
783 		pfwinfo->cnt_h2c_fail++;
784 		return -EINVAL;
785 	} else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
786 		    wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
787 		   (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
788 		    wl->status.map.lps == BTC_LPS_RF_OFF)) {
789 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
790 			    "[BTC], %s(): return by wl off!!\n", __func__);
791 		pfwinfo->cnt_h2c_fail++;
792 		return -EINVAL;
793 	}
794 
795 	ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
796 					false, true);
797 	if (ret)
798 		pfwinfo->cnt_h2c_fail++;
799 	else
800 		pfwinfo->cnt_h2c++;
801 
802 	return ret;
803 }
804 
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)805 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
806 {
807 	struct rtw89_btc *btc = &rtwdev->btc;
808 	const struct rtw89_btc_ver *ver = btc->ver;
809 	struct rtw89_btc_cx *cx = &btc->cx;
810 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
811 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
812 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
813 	struct rtw89_btc_wl_link_info *wl_linfo;
814 	u8 i;
815 
816 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
817 
818 	if (type & BTC_RESET_CX)
819 		memset(cx, 0, sizeof(*cx));
820 
821 	if (type & BTC_RESET_BTINFO) /* only for BT enable */
822 		memset(bt, 0, sizeof(*bt));
823 
824 	if (type & BTC_RESET_CTRL) {
825 		memset(&btc->ctrl, 0, sizeof(btc->ctrl));
826 		btc->manual_ctrl = false;
827 		if (ver->fcxctrl != 7)
828 			btc->ctrl.ctrl.trace_step = FCXDEF_STEP;
829 	}
830 
831 	/* Init Coex variables that are not zero */
832 	if (type & BTC_RESET_DM) {
833 		memset(&btc->dm, 0, sizeof(btc->dm));
834 		memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
835 		for (i = 0; i < RTW89_PORT_NUM; i++) {
836 			if (btc->ver->fwlrole == 8)
837 				wl_linfo = &wl->rlink_info[i][0];
838 			else
839 				wl_linfo = &wl->link_info[i];
840 			memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state));
841 		}
842 
843 		/* set the slot_now table to original */
844 		btc->dm.tdma_now = t_def[CXTD_OFF];
845 		btc->dm.tdma = t_def[CXTD_OFF];
846 		if (ver->fcxslots >= 7) {
847 			for (i = 0; i < ARRAY_SIZE(s_def); i++) {
848 				btc->dm.slot.v7[i].dur = s_def[i].dur;
849 				btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
850 				btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
851 			}
852 			memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
853 			       sizeof(btc->dm.slot_now.v7));
854 		} else {
855 			memcpy(&btc->dm.slot_now.v1, s_def,
856 			       sizeof(btc->dm.slot_now.v1));
857 			memcpy(&btc->dm.slot.v1, s_def,
858 			       sizeof(btc->dm.slot.v1));
859 		}
860 
861 		btc->policy_len = 0;
862 		btc->bt_req_len = 0;
863 
864 		btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
865 		btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
866 		btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
867 		btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
868 		btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
869 	}
870 
871 	if (type & BTC_RESET_MDINFO)
872 		memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
873 }
874 
_search_reg_index(struct rtw89_dev * rtwdev,u8 mreg_num,u16 reg_type,u32 target)875 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
876 {
877 	const struct rtw89_chip_info *chip = rtwdev->chip;
878 	u8 i;
879 
880 	for (i = 0; i < mreg_num; i++)
881 		if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
882 		    le32_to_cpu(chip->mon_reg[i].offset) == target) {
883 			return i;
884 	}
885 	return BTC_REG_NOTFOUND;
886 }
887 
_get_reg_status(struct rtw89_dev * rtwdev,u8 type,u8 * val)888 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
889 {
890 	struct rtw89_btc *btc = &rtwdev->btc;
891 	const struct rtw89_btc_ver *ver = btc->ver;
892 	union rtw89_btc_module_info *md = &btc->mdinfo;
893 	union rtw89_btc_fbtc_mreg_val *pmreg;
894 	u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
895 	u32 reg_val;
896 	u8 idx, switch_type;
897 
898 	if (ver->fcxinit == 7)
899 		switch_type = md->md_v7.switch_type;
900 	else
901 		switch_type = md->md.switch_type;
902 
903 	if (btc->btg_pos == RF_PATH_A)
904 		pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
905 
906 	switch (type) {
907 	case BTC_CSTATUS_TXDIV_POS:
908 		if (switch_type == BTC_SWITCH_INTERNAL)
909 			*val = BTC_ANT_DIV_MAIN;
910 		break;
911 	case BTC_CSTATUS_RXDIV_POS:
912 		if (switch_type == BTC_SWITCH_INTERNAL)
913 			*val = BTC_ANT_DIV_MAIN;
914 		break;
915 	case BTC_CSTATUS_BB_GNT_MUX:
916 		reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
917 		*val = !(reg_val & B_BTC_BB_GNT_MUX);
918 		break;
919 	case BTC_CSTATUS_BB_GNT_MUX_MON:
920 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
921 			return;
922 
923 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
924 		if (ver->fcxmreg == 1) {
925 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
926 						REG_BB, R_BTC_BB_BTG_RX);
927 			if (idx == BTC_REG_NOTFOUND) {
928 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
929 			} else {
930 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
931 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
932 			}
933 		} else if (ver->fcxmreg == 2) {
934 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
935 						REG_BB, R_BTC_BB_BTG_RX);
936 			if (idx == BTC_REG_NOTFOUND) {
937 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
938 			} else {
939 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
940 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
941 			}
942 		}
943 		break;
944 	case BTC_CSTATUS_BB_PRE_AGC:
945 		reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
946 		reg_val &= B_BTC_BB_PRE_AGC_MASK;
947 		*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
948 		break;
949 	case BTC_CSTATUS_BB_PRE_AGC_MON:
950 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
951 			return;
952 
953 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
954 		if (ver->fcxmreg == 1) {
955 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
956 						REG_BB, pre_agc_addr);
957 			if (idx == BTC_REG_NOTFOUND) {
958 				*val = BTC_PREAGC_NOTFOUND;
959 			} else {
960 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
961 					  B_BTC_BB_PRE_AGC_MASK;
962 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
963 			}
964 		} else if (ver->fcxmreg == 2) {
965 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
966 						REG_BB, pre_agc_addr);
967 			if (idx == BTC_REG_NOTFOUND) {
968 				*val = BTC_PREAGC_NOTFOUND;
969 			} else {
970 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
971 					  B_BTC_BB_PRE_AGC_MASK;
972 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
973 			}
974 		}
975 		break;
976 	default:
977 		break;
978 	}
979 }
980 
981 #define BTC_RPT_HDR_SIZE 3
982 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
983 #define BTC_CHK_BTSLOT_DRIFT_MAX 15
984 #define BTC_CHK_HANG_MAX 3
985 
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)986 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
987 {
988 	struct rtw89_btc *btc = &rtwdev->btc;
989 	struct rtw89_btc_cx *cx = &btc->cx;
990 	struct rtw89_btc_bt_info *bt = &cx->bt;
991 	struct rtw89_btc_wl_info *wl = &cx->wl;
992 	struct rtw89_btc_dm *dm = &btc->dm;
993 
994 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
995 		    "[BTC], %s(): type:%d cnt:%d\n",
996 		    __func__, type, cnt);
997 
998 	switch (type) {
999 	case BTC_DCNT_WL_FW_VER_MATCH:
1000 		if ((wl->ver_info.fw_coex & 0xffff0000) !=
1001 		     rtwdev->chip->wlcx_desired) {
1002 			wl->fw_ver_mismatch = true;
1003 			dm->error.map.wl_ver_mismatch = true;
1004 		} else {
1005 			wl->fw_ver_mismatch = false;
1006 			dm->error.map.wl_ver_mismatch = false;
1007 		}
1008 		break;
1009 	case BTC_DCNT_RPT_HANG:
1010 		if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1011 			dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
1012 		else
1013 			dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
1014 
1015 		if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
1016 			dm->error.map.wl_fw_hang = true;
1017 		else
1018 			dm->error.map.wl_fw_hang = false;
1019 
1020 		dm->cnt_dm[BTC_DCNT_RPT] = cnt;
1021 		break;
1022 	case BTC_DCNT_CYCLE_HANG:
1023 		if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
1024 		    (dm->tdma_now.type != CXTDMA_OFF ||
1025 		     dm->tdma_now.ext_ctrl == CXECTL_EXT))
1026 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
1027 		else
1028 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
1029 
1030 		if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
1031 			dm->error.map.cycle_hang = true;
1032 		else
1033 			dm->error.map.cycle_hang = false;
1034 
1035 		dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
1036 		break;
1037 	case BTC_DCNT_W1_HANG:
1038 		if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
1039 		    dm->tdma_now.type != CXTDMA_OFF)
1040 			dm->cnt_dm[BTC_DCNT_W1_HANG]++;
1041 		else
1042 			dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
1043 
1044 		if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
1045 			dm->error.map.w1_hang = true;
1046 		else
1047 			dm->error.map.w1_hang = false;
1048 
1049 		dm->cnt_dm[BTC_DCNT_W1] = cnt;
1050 		break;
1051 	case BTC_DCNT_B1_HANG:
1052 		if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
1053 		    dm->tdma_now.type != CXTDMA_OFF)
1054 			dm->cnt_dm[BTC_DCNT_B1_HANG]++;
1055 		else
1056 			dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
1057 
1058 		if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
1059 			dm->error.map.b1_hang = true;
1060 		else
1061 			dm->error.map.b1_hang = false;
1062 
1063 		dm->cnt_dm[BTC_DCNT_B1] = cnt;
1064 		break;
1065 	case BTC_DCNT_E2G_HANG:
1066 		if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1067 		    dm->tdma_now.ext_ctrl == CXECTL_EXT)
1068 			dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1069 		else
1070 			dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1071 
1072 		if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1073 			dm->error.map.wl_e2g_hang = true;
1074 		else
1075 			dm->error.map.wl_e2g_hang = false;
1076 
1077 		dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1078 		break;
1079 	case BTC_DCNT_TDMA_NONSYNC:
1080 		if (cnt != 0) /* if tdma not sync between drv/fw  */
1081 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
1082 		else
1083 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
1084 
1085 		if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
1086 			dm->error.map.tdma_no_sync = true;
1087 		else
1088 			dm->error.map.tdma_no_sync = false;
1089 		break;
1090 	case BTC_DCNT_SLOT_NONSYNC:
1091 		if (cnt != 0) /* if slot not sync between drv/fw  */
1092 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
1093 		else
1094 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
1095 
1096 		if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1097 			dm->error.map.slot_no_sync = true;
1098 		else
1099 			dm->error.map.slot_no_sync = false;
1100 		break;
1101 	case BTC_DCNT_BTTX_HANG:
1102 		cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1103 
1104 		if (cnt == 0 && bt->link_info.slave_role)
1105 			dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1106 		else
1107 			dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1108 
1109 		if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1110 			dm->error.map.bt_tx_hang = true;
1111 		else
1112 			dm->error.map.bt_tx_hang = false;
1113 		break;
1114 	case BTC_DCNT_BTCNT_HANG:
1115 		cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
1116 		      cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
1117 		      cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
1118 		      cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1119 
1120 		if (cnt == 0)
1121 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
1122 		else
1123 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
1124 
1125 		if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX &&
1126 		     bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] &&
1127 		     !bt->enable.now))
1128 			_update_bt_scbd(rtwdev, false);
1129 		break;
1130 	case BTC_DCNT_WL_SLOT_DRIFT:
1131 		if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
1132 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
1133 		else
1134 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
1135 
1136 		if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1137 			dm->error.map.wl_slot_drift = true;
1138 		else
1139 			dm->error.map.wl_slot_drift = false;
1140 		break;
1141 	case BTC_DCNT_BT_SLOT_DRIFT:
1142 		if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1143 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1144 		else
1145 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1146 
1147 		if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1148 			dm->error.map.bt_slot_drift = true;
1149 		else
1150 			dm->error.map.bt_slot_drift = false;
1151 
1152 		break;
1153 	}
1154 }
1155 
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)1156 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
1157 {
1158 	struct rtw89_btc *btc = &rtwdev->btc;
1159 	const struct rtw89_btc_ver *ver = btc->ver;
1160 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1161 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1162 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1163 	union  rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1164 	struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1165 	struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1166 	struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1167 	struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1168 	struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1169 	struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1170 	struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1171 	bool scan_update = true;
1172 	int i;
1173 
1174 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1175 		    "[BTC], %s(): rpt_type:%d\n",
1176 		    __func__, rpt_type);
1177 
1178 	switch (rpt_type) {
1179 	case BTC_RPT_TYPE_BT_VER:
1180 		if (ver->fcxbtver == 7) {
1181 			pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1182 			bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1183 			bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1184 							     GENMASK(7, 0));
1185 			bt->feature = le32_to_cpu(pver->v7.feature);
1186 		} else {
1187 			pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1188 			bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1189 			bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1190 							     GENMASK(7, 0));
1191 			bt->feature = le32_to_cpu(pver->v1.feature);
1192 		}
1193 		break;
1194 	case BTC_RPT_TYPE_BT_SCAN:
1195 		if (ver->fcxbtscan == 1) {
1196 			pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1197 			for (i = 0; i < BTC_SCAN_MAX1; i++) {
1198 				bt->scan_info_v1[i] = pscan_v1->scan[i];
1199 				if (bt->scan_info_v1[i].win == 0 &&
1200 				    bt->scan_info_v1[i].intvl == 0)
1201 					scan_update = false;
1202 			}
1203 		} else if (ver->fcxbtscan == 2) {
1204 			pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1205 			for (i = 0; i < CXSCAN_MAX; i++) {
1206 				bt->scan_info_v2[i] = pscan_v2->para[i];
1207 				if ((pscan_v2->type & BIT(i)) &&
1208 				    pscan_v2->para[i].win == 0 &&
1209 				    pscan_v2->para[i].intvl == 0)
1210 					scan_update = false;
1211 			}
1212 		} else if (ver->fcxbtscan == 7) {
1213 			pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1214 			for (i = 0; i < CXSCAN_MAX; i++) {
1215 				bt->scan_info_v2[i] = pscan_v7->para[i];
1216 				if ((pscan_v7->type & BIT(i)) &&
1217 				    pscan_v7->para[i].win == 0 &&
1218 				    pscan_v7->para[i].intvl == 0)
1219 					scan_update = false;
1220 			}
1221 		}
1222 		if (scan_update)
1223 			bt->scan_info_update = 1;
1224 		break;
1225 	case BTC_RPT_TYPE_BT_AFH:
1226 		if (ver->fcxbtafh == 2) {
1227 			pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1228 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1229 				memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1230 				memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1231 				memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1232 			}
1233 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1234 				memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1235 				memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1236 			}
1237 		} else if (ver->fcxbtafh == 7) {
1238 			pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1239 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1240 				memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1241 				memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1242 				memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1243 			}
1244 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1245 				memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1246 				memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1247 			}
1248 		} else if (ver->fcxbtafh == 1) {
1249 			pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1250 			memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1251 			memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1252 			memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1253 		}
1254 		break;
1255 	case BTC_RPT_TYPE_BT_DEVICE:
1256 		pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
1257 		a2dp->device_name = le32_to_cpu(pdev->dev_name);
1258 		a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
1259 		a2dp->flush_time = le32_to_cpu(pdev->flush_time);
1260 		break;
1261 	default:
1262 		break;
1263 	}
1264 }
1265 
rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev * rtwdev,u8 * index)1266 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1267 {
1268 	struct rtw89_btc *btc = &rtwdev->btc;
1269 	const struct rtw89_btc_ver *ver = btc->ver;
1270 
1271 	if (ver->fwevntrptl == 1)
1272 		return;
1273 
1274 	if (*index <= __BTC_RPT_TYPE_V0_SAME)
1275 		return;
1276 	else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1277 		(*index)++;
1278 	else
1279 		*index = BTC_RPT_TYPE_MAX;
1280 }
1281 
1282 #define BTC_LEAK_AP_TH 10
1283 #define BTC_CYSTA_CHK_PERIOD 100
1284 
1285 struct rtw89_btc_prpt {
1286 	u8 type;
1287 	__le16 len;
1288 	u8 content[];
1289 } __packed;
1290 
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)1291 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
1292 			   struct rtw89_btc_btf_fwinfo *pfwinfo,
1293 			   u8 *prptbuf, u32 index)
1294 {
1295 	struct rtw89_btc *btc = &rtwdev->btc;
1296 	const struct rtw89_btc_ver *ver = btc->ver;
1297 	struct rtw89_btc_dm *dm = &btc->dm;
1298 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
1299 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1300 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1301 	union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1302 	union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
1303 	struct rtw89_btc_prpt *btc_prpt = NULL;
1304 	void *rpt_content = NULL, *pfinfo = NULL;
1305 	u8 rpt_type = 0;
1306 	u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1307 	u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1308 	u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1309 	u8 i, val = 0, val1, val2;
1310 
1311 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1312 		    "[BTC], %s(): index:%d\n",
1313 		    __func__, index);
1314 
1315 	if (!prptbuf) {
1316 		pfwinfo->err[BTFRE_INVALID_INPUT]++;
1317 		return 0;
1318 	}
1319 
1320 	btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
1321 	rpt_type = btc_prpt->type;
1322 	rpt_len = le16_to_cpu(btc_prpt->len);
1323 	rpt_content = btc_prpt->content;
1324 
1325 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1326 		    "[BTC], %s(): rpt_type:%d\n",
1327 		    __func__, rpt_type);
1328 
1329 	rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1330 
1331 	switch (rpt_type) {
1332 	case BTC_RPT_TYPE_CTRL:
1333 		pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1334 		prpt = &pfwinfo->rpt_ctrl.finfo;
1335 		if (ver->fcxbtcrpt == 1) {
1336 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1337 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1338 		} else if (ver->fcxbtcrpt == 4) {
1339 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1340 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1341 		} else if (ver->fcxbtcrpt == 5) {
1342 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1343 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1344 		} else if (ver->fcxbtcrpt == 105) {
1345 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1346 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1347 			pcinfo->req_fver = 5;
1348 			break;
1349 		} else if (ver->fcxbtcrpt == 8) {
1350 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1351 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1352 			break;
1353 		} else {
1354 			goto err;
1355 		}
1356 		pcinfo->req_fver = ver->fcxbtcrpt;
1357 		break;
1358 	case BTC_RPT_TYPE_TDMA:
1359 		pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1360 		if (ver->fcxtdma == 1) {
1361 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1362 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1363 		} else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
1364 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1365 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
1366 		} else {
1367 			goto err;
1368 		}
1369 		pcinfo->req_fver = ver->fcxtdma;
1370 		break;
1371 	case BTC_RPT_TYPE_SLOT:
1372 		pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1373 		if (ver->fcxslots == 1) {
1374 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1375 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1376 		} else if (ver->fcxslots == 7) {
1377 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1378 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1379 		} else {
1380 			goto err;
1381 		}
1382 		pcinfo->req_fver = ver->fcxslots;
1383 		break;
1384 	case BTC_RPT_TYPE_CYSTA:
1385 		pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1386 		pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1387 		if (ver->fcxcysta == 2) {
1388 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1389 			pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1390 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1391 		} else if (ver->fcxcysta == 3) {
1392 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1393 			pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1394 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1395 		} else if (ver->fcxcysta == 4) {
1396 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1397 			pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1398 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1399 		} else if (ver->fcxcysta == 5) {
1400 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1401 			pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1402 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1403 		} else if (ver->fcxcysta == 7) {
1404 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1405 			pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1406 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
1407 		} else {
1408 			goto err;
1409 		}
1410 		pcinfo->req_fver = ver->fcxcysta;
1411 		break;
1412 	case BTC_RPT_TYPE_STEP:
1413 		pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1414 		if (ver->fcxctrl != 7)
1415 			trace_step = btc->ctrl.ctrl.trace_step;
1416 
1417 		if (ver->fcxstep == 2) {
1418 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1419 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1420 					  trace_step +
1421 					  offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1422 		} else if (ver->fcxstep == 3) {
1423 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1424 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1425 					  trace_step +
1426 					  offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1427 		} else {
1428 			goto err;
1429 		}
1430 		pcinfo->req_fver = ver->fcxstep;
1431 		break;
1432 	case BTC_RPT_TYPE_NULLSTA:
1433 		pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1434 		if (ver->fcxnullsta == 1) {
1435 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1436 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1437 		} else if (ver->fcxnullsta == 2) {
1438 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1439 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1440 		} else if (ver->fcxnullsta == 7) {
1441 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1442 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1443 		} else {
1444 			goto err;
1445 		}
1446 		pcinfo->req_fver = ver->fcxnullsta;
1447 		break;
1448 	case BTC_RPT_TYPE_MREG:
1449 		pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1450 		if (ver->fcxmreg == 1) {
1451 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1452 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1453 		} else if (ver->fcxmreg == 2) {
1454 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1455 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1456 		} else if (ver->fcxmreg == 7) {
1457 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1458 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1459 		} else {
1460 			goto err;
1461 		}
1462 		pcinfo->req_fver = ver->fcxmreg;
1463 		break;
1464 	case BTC_RPT_TYPE_GPIO_DBG:
1465 		pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1466 		if (ver->fcxgpiodbg == 7) {
1467 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1468 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1469 		} else {
1470 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1471 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1472 		}
1473 		pcinfo->req_fver = ver->fcxgpiodbg;
1474 		break;
1475 	case BTC_RPT_TYPE_BT_VER:
1476 		pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1477 		if (ver->fcxbtver == 1) {
1478 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1479 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1480 		} else if (ver->fcxbtver == 7) {
1481 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1482 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1483 		}
1484 		pcinfo->req_fver = ver->fcxbtver;
1485 		break;
1486 	case BTC_RPT_TYPE_BT_SCAN:
1487 		pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1488 		if (ver->fcxbtscan == 1) {
1489 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1490 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1491 		} else if (ver->fcxbtscan == 2) {
1492 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1493 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1494 		} else if (ver->fcxbtscan == 7) {
1495 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1496 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1497 		} else {
1498 			goto err;
1499 		}
1500 		pcinfo->req_fver = ver->fcxbtscan;
1501 		break;
1502 	case BTC_RPT_TYPE_BT_AFH:
1503 		pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1504 		if (ver->fcxbtafh == 1) {
1505 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1506 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1507 		} else if (ver->fcxbtafh == 2) {
1508 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1509 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1510 		} else {
1511 			goto err;
1512 		}
1513 		pcinfo->req_fver = ver->fcxbtafh;
1514 		break;
1515 	case BTC_RPT_TYPE_BT_DEVICE:
1516 		pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1517 		pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1518 		pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1519 		pcinfo->req_fver = ver->fcxbtdevinfo;
1520 		break;
1521 	default:
1522 		pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1523 		return 0;
1524 	}
1525 
1526 	pcinfo->rx_len = rpt_len;
1527 	pcinfo->rx_cnt++;
1528 
1529 	if (rpt_len != pcinfo->req_len) {
1530 		if (rpt_type < BTC_RPT_TYPE_MAX)
1531 			pfwinfo->len_mismch |= (0x1 << rpt_type);
1532 		else
1533 			pfwinfo->len_mismch |= BIT(31);
1534 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1535 			    "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
1536 			    __func__, rpt_type, rpt_len, pcinfo->req_len);
1537 
1538 		pcinfo->valid = 0;
1539 		return 0;
1540 	} else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
1541 		pfwinfo->err[BTFRE_EXCEPTION]++;
1542 		pcinfo->valid = 0;
1543 		return 0;
1544 	}
1545 
1546 	memcpy(pfinfo, rpt_content, pcinfo->req_len);
1547 	pcinfo->valid = 1;
1548 
1549 	switch (rpt_type) {
1550 	case BTC_RPT_TYPE_CTRL:
1551 		if (ver->fcxbtcrpt == 1) {
1552 			prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
1553 			btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
1554 			wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
1555 			wl->ver_info.fw = prpt->v1.wl_fw_ver;
1556 			dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
1557 
1558 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1559 				     pfwinfo->event[BTF_EVNT_RPT]);
1560 
1561 			/* To avoid I/O if WL LPS or power-off */
1562 			if (wl->status.map.lps != BTC_LPS_RF_OFF &&
1563 			    !wl->status.map.rf_off) {
1564 				rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1565 				_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1566 
1567 				btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1568 					rtw89_mac_get_plt_cnt(rtwdev,
1569 							      RTW89_MAC_0);
1570 			}
1571 		} else if (ver->fcxbtcrpt == 4) {
1572 			prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
1573 			btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
1574 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
1575 			wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
1576 			dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
1577 
1578 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1579 				memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i],
1580 				       sizeof(dm->gnt.band[i]));
1581 
1582 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1583 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
1584 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1585 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
1586 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1587 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
1588 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1589 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
1590 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1591 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
1592 
1593 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1594 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1595 				     pfwinfo->event[BTF_EVNT_RPT]);
1596 
1597 			if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1598 				bt->rfk_info.map.timeout = 1;
1599 			else
1600 				bt->rfk_info.map.timeout = 0;
1601 
1602 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1603 		} else if (ver->fcxbtcrpt == 5) {
1604 			prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
1605 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
1606 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
1607 			wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
1608 			dm->wl_fw_cx_offload = 0;
1609 
1610 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1611 				memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0],
1612 				       sizeof(dm->gnt.band[i]));
1613 
1614 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1615 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
1616 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1617 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
1618 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1619 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
1620 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1621 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
1622 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1623 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
1624 
1625 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1626 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1627 				     pfwinfo->event[BTF_EVNT_RPT]);
1628 
1629 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1630 		} else if (ver->fcxbtcrpt == 105) {
1631 			prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
1632 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
1633 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
1634 			wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
1635 			dm->wl_fw_cx_offload = 0;
1636 
1637 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1638 				memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0],
1639 				       sizeof(dm->gnt.band[i]));
1640 
1641 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1642 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
1643 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1644 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
1645 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1646 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
1647 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1648 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
1649 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1650 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1651 
1652 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1653 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1654 				     pfwinfo->event[BTF_EVNT_RPT]);
1655 
1656 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1657 		} else if (ver->fcxbtcrpt == 8) {
1658 			prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
1659 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
1660 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
1661 			wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
1662 
1663 			for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1664 				memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0],
1665 				       sizeof(dm->gnt.band[i]));
1666 
1667 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1668 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
1669 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1670 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
1671 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1672 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
1673 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1674 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
1675 
1676 			val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1677 			if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1678 				val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1679 
1680 			btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1681 			btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1682 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1683 
1684 			val1 = pfwinfo->event[BTF_EVNT_RPT];
1685 			if (((prpt->v8.rpt_len_max_h << 8) +
1686 			      prpt->v8.rpt_len_max_l) != ver->info_buf)
1687 				dm->error.map.h2c_c2h_buffer_mismatch = true;
1688 			else
1689 				dm->error.map.h2c_c2h_buffer_mismatch = false;
1690 
1691 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1692 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1693 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1694 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1695 		} else {
1696 			goto err;
1697 		}
1698 		break;
1699 	case BTC_RPT_TYPE_TDMA:
1700 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1701 			    "[BTC], %s(): check %d %zu\n", __func__,
1702 			    BTC_DCNT_TDMA_NONSYNC,
1703 			    sizeof(dm->tdma_now));
1704 		if (ver->fcxtdma == 1)
1705 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1706 				     memcmp(&dm->tdma_now,
1707 					    &pfwinfo->rpt_fbtc_tdma.finfo.v1,
1708 					    sizeof(dm->tdma_now)));
1709 		else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
1710 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1711 				     memcmp(&dm->tdma_now,
1712 					    &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
1713 					    sizeof(dm->tdma_now)));
1714 		else
1715 			goto err;
1716 		break;
1717 	case BTC_RPT_TYPE_SLOT:
1718 		if (ver->fcxslots == 7) {
1719 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1720 				    "[BTC], %s(): check %d %zu\n",
1721 				    __func__, BTC_DCNT_SLOT_NONSYNC,
1722 				    sizeof(dm->slot_now.v7));
1723 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1724 				     memcmp(dm->slot_now.v7,
1725 					    pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
1726 					    sizeof(dm->slot_now.v7)));
1727 		} else if (ver->fcxslots == 1) {
1728 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1729 				    "[BTC], %s(): check %d %zu\n",
1730 				    __func__, BTC_DCNT_SLOT_NONSYNC,
1731 				    sizeof(dm->slot_now.v1));
1732 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1733 				     memcmp(dm->slot_now.v1,
1734 					    pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
1735 					    sizeof(dm->slot_now.v1)));
1736 		}
1737 		break;
1738 	case BTC_RPT_TYPE_CYSTA:
1739 		if (ver->fcxcysta == 2) {
1740 			if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
1741 				break;
1742 			/* Check Leak-AP */
1743 			if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
1744 			    le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
1745 				if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
1746 				    BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
1747 					dm->leak_ap = 1;
1748 			}
1749 
1750 			/* Check diff time between WL slot and W1/E2G slot */
1751 			if (dm->tdma_now.type == CXTDMA_OFF &&
1752 			    dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1753 				if (ver->fcxslots == 1)
1754 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
1755 				else if (ver->fcxslots == 7)
1756 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
1757 			} else {
1758 				if (ver->fcxslots == 1)
1759 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1760 				else if (ver->fcxslots == 7)
1761 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1762 			}
1763 
1764 			if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
1765 				diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
1766 				_chk_btc_err(rtwdev,
1767 					     BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1768 			}
1769 
1770 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1771 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
1772 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1773 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
1774 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1775 				     le16_to_cpu(pcysta->v2.cycles));
1776 		} else if (ver->fcxcysta == 3) {
1777 			if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
1778 				break;
1779 
1780 			cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
1781 			cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
1782 
1783 			/* Check Leak-AP */
1784 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1785 			    dm->tdma_now.rxflctrl) {
1786 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1787 					dm->leak_ap = 1;
1788 			}
1789 
1790 			/* Check diff time between real WL slot and W1 slot */
1791 			if (dm->tdma_now.type == CXTDMA_OFF) {
1792 				if (ver->fcxslots == 1)
1793 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1794 				else if (ver->fcxslots == 7)
1795 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1796 				wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
1797 				if (wl_slot_real > wl_slot_set) {
1798 					diff_t = wl_slot_real - wl_slot_set;
1799 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1800 				}
1801 			}
1802 
1803 			/* Check diff time between real BT slot and EBT/E5G slot */
1804 			if (dm->tdma_now.type == CXTDMA_OFF &&
1805 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1806 			    btc->bt_req_len != 0) {
1807 				bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
1808 				if (btc->bt_req_len > bt_slot_real) {
1809 					diff_t = btc->bt_req_len - bt_slot_real;
1810 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1811 				}
1812 			}
1813 
1814 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1815 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
1816 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1817 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
1818 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1819 				     le16_to_cpu(pcysta->v3.cycles));
1820 		} else if (ver->fcxcysta == 4) {
1821 			if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
1822 				break;
1823 
1824 			cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
1825 			cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
1826 
1827 			/* Check Leak-AP */
1828 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1829 			    dm->tdma_now.rxflctrl) {
1830 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1831 					dm->leak_ap = 1;
1832 			}
1833 
1834 			/* Check diff time between real WL slot and W1 slot */
1835 			if (dm->tdma_now.type == CXTDMA_OFF) {
1836 				if (ver->fcxslots == 1)
1837 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1838 				else if (ver->fcxslots == 7)
1839 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1840 				wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
1841 				if (wl_slot_real > wl_slot_set) {
1842 					diff_t = wl_slot_real - wl_slot_set;
1843 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1844 				}
1845 			}
1846 
1847 			/* Check diff time between real BT slot and EBT/E5G slot */
1848 			if (dm->tdma_now.type == CXTDMA_OFF &&
1849 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1850 			    btc->bt_req_len != 0) {
1851 				bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
1852 
1853 				if (btc->bt_req_len > bt_slot_real) {
1854 					diff_t = btc->bt_req_len - bt_slot_real;
1855 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1856 				}
1857 			}
1858 
1859 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1860 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
1861 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1862 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
1863 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1864 				     le16_to_cpu(pcysta->v4.cycles));
1865 		} else if (ver->fcxcysta == 5) {
1866 			if (dm->fddt_train == BTC_FDDT_ENABLE)
1867 				break;
1868 			cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
1869 			cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
1870 
1871 			/* Check Leak-AP */
1872 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1873 			    dm->tdma_now.rxflctrl) {
1874 				if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
1875 				    cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1876 					dm->leak_ap = 1;
1877 			}
1878 
1879 			/* Check diff time between real WL slot and W1 slot */
1880 			if (dm->tdma_now.type == CXTDMA_OFF) {
1881 				if (ver->fcxslots == 1)
1882 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1883 				else if (ver->fcxslots == 7)
1884 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1885 				wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
1886 
1887 				if (wl_slot_real > wl_slot_set)
1888 					diff_t = wl_slot_real - wl_slot_set;
1889 				else
1890 					diff_t = wl_slot_set - wl_slot_real;
1891 			}
1892 			_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1893 
1894 			/* Check diff time between real BT slot and EBT/E5G slot */
1895 			bt_slot_set = btc->bt_req_len;
1896 			bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
1897 			diff_t = 0;
1898 			if (dm->tdma_now.type == CXTDMA_OFF &&
1899 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1900 			    bt_slot_set != 0) {
1901 				if (bt_slot_set > bt_slot_real)
1902 					diff_t = bt_slot_set - bt_slot_real;
1903 				else
1904 					diff_t = bt_slot_real - bt_slot_set;
1905 			}
1906 
1907 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1908 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
1909 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
1910 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1911 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
1912 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1913 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
1914 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1915 				     le16_to_cpu(pcysta->v5.cycles));
1916 		} else if (ver->fcxcysta == 7) {
1917 			if (dm->fddt_train == BTC_FDDT_ENABLE)
1918 				break;
1919 
1920 			pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1921 
1922 			if (dm->tdma_now.type != CXTDMA_OFF) {
1923 				/* Check diff time between real WL slot and W1 slot */
1924 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
1925 				_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
1926 
1927 				/* Check Leak-AP */
1928 				val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
1929 				       BTC_LEAK_AP_TH;
1930 				val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
1931 
1932 				val16 = le16_to_cpu(pcysta->v7.cycles);
1933 				if (dm->tdma_now.rxflctrl &&
1934 				    val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
1935 					dm->leak_ap = 1;
1936 			} else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1937 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
1938 				/* Check diff between real BT slot and EBT/E5G slot */
1939 				_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
1940 
1941 				/* Check bt slot length for P2P mode*/
1942 				val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
1943 				       BTC_SLOT_REQ_TH;
1944 				val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
1945 
1946 				val16 = le16_to_cpu(pcysta->v7.cycles);
1947 				if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
1948 					dm->slot_req_more = 1;
1949 				else if (bt->link_info.status.map.connect == 0)
1950 					dm->slot_req_more = 0;
1951 			}
1952 
1953 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
1954 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
1955 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1956 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
1957 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1958 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
1959 
1960 			/* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
1961 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
1962 				     le16_to_cpu(pcysta->v7.cycles));
1963 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1964 				     le16_to_cpu(pcysta->v7.cycles));
1965 		} else {
1966 			goto err;
1967 		}
1968 		break;
1969 	case BTC_RPT_TYPE_MREG:
1970 		if (ver->fcxmreg == 7)
1971 			break;
1972 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
1973 		if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
1974 			dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
1975 		else
1976 			dm->wl_btg_rx_rb = val;
1977 
1978 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
1979 		if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
1980 			dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
1981 		else
1982 			dm->wl_pre_agc_rb = val;
1983 		break;
1984 	case BTC_RPT_TYPE_BT_VER:
1985 	case BTC_RPT_TYPE_BT_SCAN:
1986 	case BTC_RPT_TYPE_BT_AFH:
1987 	case BTC_RPT_TYPE_BT_DEVICE:
1988 		_update_bt_report(rtwdev, rpt_type, pfinfo);
1989 		break;
1990 	}
1991 	return (rpt_len + BTC_RPT_HDR_SIZE);
1992 
1993 err:
1994 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1995 		    "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
1996 	return 0;
1997 }
1998 
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)1999 static void _parse_btc_report(struct rtw89_dev *rtwdev,
2000 			      struct rtw89_btc_btf_fwinfo *pfwinfo,
2001 			      u8 *pbuf, u32 buf_len)
2002 {
2003 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2004 	struct rtw89_btc_prpt *btc_prpt = NULL;
2005 	u32 index = 0, rpt_len = 0;
2006 
2007 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2008 		    "[BTC], %s(): buf_len:%d\n",
2009 		    __func__, buf_len);
2010 
2011 	while (pbuf) {
2012 		btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2013 		if (index + 2 >= ver->info_buf)
2014 			break;
2015 		/* At least 3 bytes: type(1) & len(2) */
2016 		rpt_len = le16_to_cpu(btc_prpt->len);
2017 		if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
2018 			break;
2019 
2020 		rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
2021 		if (!rpt_len)
2022 			break;
2023 		index += rpt_len;
2024 	}
2025 }
2026 
2027 #define BTC_TLV_HDR_LEN 2
2028 #define BTC_TLV_HDR_LEN_V7 3
2029 
_append_tdma(struct rtw89_dev * rtwdev)2030 static void _append_tdma(struct rtw89_dev *rtwdev)
2031 {
2032 	struct rtw89_btc *btc = &rtwdev->btc;
2033 	const struct rtw89_btc_ver *ver = btc->ver;
2034 	struct rtw89_btc_dm *dm = &btc->dm;
2035 	struct rtw89_btc_btf_tlv *tlv;
2036 	struct rtw89_btc_btf_tlv_v7 *tlv_v7;
2037 	struct rtw89_btc_fbtc_tdma *v;
2038 	struct rtw89_btc_fbtc_tdma_v3 *v3;
2039 	u16 len = btc->policy_len;
2040 
2041 	if (!btc->update_policy_force &&
2042 	    !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
2043 		rtw89_debug(rtwdev,
2044 			    RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
2045 			    __func__);
2046 		return;
2047 	}
2048 
2049 	tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2050 	tlv->type = CXPOLICY_TDMA;
2051 	if (ver->fcxtdma == 1) {
2052 		v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
2053 		tlv->len = sizeof(*v);
2054 		*v = dm->tdma;
2055 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2056 	} else if (ver->fcxtdma == 7) {
2057 		tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2058 		tlv_v7->len = sizeof(dm->tdma);
2059 		tlv_v7->ver = ver->fcxtdma;
2060 		tlv_v7->type = CXPOLICY_TDMA;
2061 		memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2062 		btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
2063 	} else {
2064 		tlv->len = sizeof(*v3);
2065 		v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2066 		v3->fver = ver->fcxtdma;
2067 		v3->tdma = dm->tdma;
2068 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
2069 	}
2070 
2071 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2072 		    "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
2073 		    __func__, dm->tdma.type, dm->tdma.rxflctrl,
2074 		    dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
2075 		    dm->tdma.ext_ctrl);
2076 }
2077 
_append_slot_v1(struct rtw89_dev * rtwdev)2078 static void _append_slot_v1(struct rtw89_dev *rtwdev)
2079 {
2080 	struct rtw89_btc *btc = &rtwdev->btc;
2081 	struct rtw89_btc_dm *dm = &btc->dm;
2082 	struct rtw89_btc_btf_tlv *tlv = NULL;
2083 	struct btc_fbtc_1slot *v = NULL;
2084 	u16 len = 0;
2085 	u8 i, cnt = 0;
2086 
2087 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2088 		    "[BTC], %s(): A:btc->policy_len = %d\n",
2089 		    __func__, btc->policy_len);
2090 
2091 	for (i = 0; i < CXST_MAX; i++) {
2092 		if (!btc->update_policy_force &&
2093 		    !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2094 			    sizeof(dm->slot.v1[i])))
2095 			continue;
2096 
2097 		len = btc->policy_len;
2098 
2099 		tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2100 		v = (struct btc_fbtc_1slot *)&tlv->val[0];
2101 		tlv->type = CXPOLICY_SLOT;
2102 		tlv->len = sizeof(*v);
2103 
2104 		v->fver = btc->ver->fcxslots;
2105 		v->sid = i;
2106 		v->slot = dm->slot.v1[i];
2107 
2108 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2109 			    "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2110 			    __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2111 			    dm->slot.v1[i].cxtype);
2112 		cnt++;
2113 
2114 		btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
2115 	}
2116 
2117 	if (cnt > 0)
2118 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2119 			    "[BTC], %s(): slot update (cnt=%d)!!\n",
2120 			    __func__, cnt);
2121 }
2122 
_append_slot_v7(struct rtw89_dev * rtwdev)2123 static void _append_slot_v7(struct rtw89_dev *rtwdev)
2124 {
2125 	struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2126 	struct rtw89_btc *btc = &rtwdev->btc;
2127 	struct rtw89_btc_dm *dm = &btc->dm;
2128 	u8 i, cnt = 0;
2129 	u16 len;
2130 
2131 	for (i = 0; i < CXST_MAX; i++) {
2132 		if (!btc->update_policy_force &&
2133 		    !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2134 			    sizeof(dm->slot.v7[i])))
2135 			continue;
2136 
2137 		len = btc->policy_len;
2138 
2139 		if (!tlv) {
2140 			if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2141 				rtw89_debug(rtwdev, RTW89_DBG_BTC,
2142 					    "[BTC], %s(): buff overflow!\n", __func__);
2143 				break;
2144 			}
2145 
2146 			tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2147 			tlv->type = CXPOLICY_SLOT;
2148 			tlv->ver = btc->ver->fcxslots;
2149 			tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2150 			len += BTC_TLV_HDR_LEN_V7;
2151 		}
2152 
2153 		if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2154 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
2155 				    "[BTC], %s(): buff overflow!\n", __func__);
2156 			break;
2157 		}
2158 
2159 		btc->policy[len] = i; /* slot-id */
2160 		memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2161 		       sizeof(dm->slot.v7[0]));
2162 		len += tlv->len;
2163 
2164 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2165 			    "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2166 			    __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2167 			    dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2168 		cnt++;
2169 		btc->policy_len = len; /* update total length */
2170 	}
2171 
2172 	if (cnt > 0)
2173 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2174 			    "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2175 			    __func__, cnt, btc->policy_len);
2176 }
2177 
_append_slot(struct rtw89_dev * rtwdev)2178 static void _append_slot(struct rtw89_dev *rtwdev)
2179 {
2180 	struct rtw89_btc *btc = &rtwdev->btc;
2181 
2182 	if (btc->ver->fcxslots == 7)
2183 		_append_slot_v7(rtwdev);
2184 	else
2185 		_append_slot_v1(rtwdev);
2186 }
2187 
rtw89_btc_fw_rpt_ver(struct rtw89_dev * rtwdev,u32 rpt_map)2188 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2189 {
2190 	struct rtw89_btc *btc = &rtwdev->btc;
2191 	const struct rtw89_btc_ver *ver = btc->ver;
2192 	u32 bit_map = 0;
2193 
2194 	switch (rpt_map) {
2195 	case RPT_EN_TDMA:
2196 		bit_map = BIT(0);
2197 		break;
2198 	case RPT_EN_CYCLE:
2199 		bit_map = BIT(1);
2200 		break;
2201 	case RPT_EN_MREG:
2202 		bit_map = BIT(2);
2203 		break;
2204 	case RPT_EN_BT_VER_INFO:
2205 		bit_map = BIT(3);
2206 		break;
2207 	case RPT_EN_BT_SCAN_INFO:
2208 		bit_map = BIT(4);
2209 		break;
2210 	case RPT_EN_BT_DEVICE_INFO:
2211 		switch (ver->frptmap) {
2212 		case 0:
2213 		case 1:
2214 		case 2:
2215 			bit_map = BIT(6);
2216 			break;
2217 		case 3:
2218 			bit_map = BIT(5);
2219 			break;
2220 		default:
2221 			break;
2222 		}
2223 		break;
2224 	case RPT_EN_BT_AFH_MAP:
2225 		switch (ver->frptmap) {
2226 		case 0:
2227 		case 1:
2228 		case 2:
2229 			bit_map = BIT(5);
2230 			break;
2231 		case 3:
2232 			bit_map = BIT(6);
2233 			break;
2234 		default:
2235 			break;
2236 		}
2237 		break;
2238 	case RPT_EN_BT_AFH_MAP_LE:
2239 		switch (ver->frptmap) {
2240 		case 2:
2241 			bit_map = BIT(8);
2242 			break;
2243 		case 3:
2244 			bit_map = BIT(7);
2245 			break;
2246 		default:
2247 			break;
2248 		}
2249 		break;
2250 	case RPT_EN_FW_STEP_INFO:
2251 		switch (ver->frptmap) {
2252 		case 1:
2253 		case 2:
2254 			bit_map = BIT(7);
2255 			break;
2256 		case 3:
2257 			bit_map = BIT(8);
2258 			break;
2259 		default:
2260 			break;
2261 		}
2262 		break;
2263 	case RPT_EN_TEST:
2264 		bit_map = BIT(31);
2265 		break;
2266 	case RPT_EN_WL_ALL:
2267 		switch (ver->frptmap) {
2268 		case 0:
2269 		case 1:
2270 		case 2:
2271 			bit_map = GENMASK(2, 0);
2272 			break;
2273 		case 3:
2274 			bit_map = GENMASK(2, 0) | BIT(8);
2275 			break;
2276 		default:
2277 			break;
2278 		}
2279 		break;
2280 	case RPT_EN_BT_ALL:
2281 		switch (ver->frptmap) {
2282 		case 0:
2283 		case 1:
2284 			bit_map = GENMASK(6, 3);
2285 			break;
2286 		case 2:
2287 			bit_map = GENMASK(6, 3) | BIT(8);
2288 			break;
2289 		case 3:
2290 			bit_map = GENMASK(7, 3);
2291 			break;
2292 		default:
2293 			break;
2294 		}
2295 		break;
2296 	case RPT_EN_ALL:
2297 		switch (ver->frptmap) {
2298 		case 0:
2299 			bit_map = GENMASK(6, 0);
2300 			break;
2301 		case 1:
2302 			bit_map = GENMASK(7, 0);
2303 			break;
2304 		case 2:
2305 		case 3:
2306 			bit_map = GENMASK(8, 0);
2307 			break;
2308 		default:
2309 			break;
2310 		}
2311 		break;
2312 	case RPT_EN_MONITER:
2313 		switch (ver->frptmap) {
2314 		case 0:
2315 		case 1:
2316 			bit_map = GENMASK(6, 2);
2317 			break;
2318 		case 2:
2319 			bit_map = GENMASK(6, 2) | BIT(8);
2320 			break;
2321 		case 3:
2322 			bit_map = GENMASK(8, 2);
2323 			break;
2324 		default:
2325 			break;
2326 		}
2327 		break;
2328 	}
2329 
2330 	return bit_map;
2331 }
2332 
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev)2333 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
2334 {
2335 	struct rtw89_btc *btc = &rtwdev->btc;
2336 	const struct rtw89_btc_ver *ver = btc->ver;
2337 	struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
2338 	struct rtw89_btc_btf_set_slot_table *tbl;
2339 	struct rtw89_btc_dm *dm = &btc->dm;
2340 	u16 n, len;
2341 
2342 	if (ver->fcxslots == 7) {
2343 		len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
2344 		tlv_v7 = kmalloc(len, GFP_KERNEL);
2345 		if (!tlv_v7)
2346 			return;
2347 
2348 		tlv_v7->type = SET_SLOT_TABLE;
2349 		tlv_v7->ver = ver->fcxslots;
2350 		tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
2351 		memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
2352 
2353 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
2354 
2355 		kfree(tlv_v7);
2356 	} else {
2357 		n = struct_size(tbl, tbls, CXST_MAX);
2358 		tbl = kmalloc(n, GFP_KERNEL);
2359 		if (!tbl)
2360 			return;
2361 
2362 		tbl->fver = BTF_SET_SLOT_TABLE_VER;
2363 		tbl->tbl_num = CXST_MAX;
2364 		memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
2365 
2366 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
2367 
2368 		kfree(tbl);
2369 	}
2370 }
2371 
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,u32 rpt_map,bool rpt_state)2372 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
2373 				u32 rpt_map, bool rpt_state)
2374 {
2375 	struct rtw89_btc *btc = &rtwdev->btc;
2376 	struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
2377 	struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
2378 	union rtw89_fbtc_rtp_ctrl r;
2379 	u32 val, bit_map;
2380 	int ret;
2381 
2382 	if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0)
2383 		return;
2384 
2385 	bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map);
2386 
2387 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2388 		    "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
2389 		    __func__, rpt_map, rpt_state);
2390 
2391 	if (rpt_state)
2392 		val = fwinfo->rpt_en_map | bit_map;
2393 	else
2394 		val = fwinfo->rpt_en_map & ~bit_map;
2395 
2396 	if (val == fwinfo->rpt_en_map)
2397 		return;
2398 
2399 	if (btc->ver->fcxbtcrpt == 8) {
2400 		r.v8.type = SET_REPORT_EN;
2401 		r.v8.fver = btc->ver->fcxbtcrpt;
2402 		r.v8.len = sizeof(r.v8.map);
2403 		r.v8.map = cpu_to_le32(val);
2404 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
2405 				   sizeof(r.v8));
2406 	} else {
2407 		if (btc->ver->fcxbtcrpt == 105)
2408 			r.v1.fver = 5;
2409 		else
2410 			r.v1.fver = btc->ver->fcxbtcrpt;
2411 		r.v1.enable = cpu_to_le32(val);
2412 		r.v1.para = cpu_to_le32(rpt_state);
2413 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v1,
2414 				   sizeof(r.v1));
2415 	}
2416 
2417 	if (!ret)
2418 		fwinfo->rpt_en_map = val;
2419 }
2420 
btc_fw_set_monreg(struct rtw89_dev * rtwdev)2421 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
2422 {
2423 	const struct rtw89_chip_info *chip = rtwdev->chip;
2424 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2425 	struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
2426 	struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
2427 	u8 i, n, ulen, cxmreg_max;
2428 	u16 sz = 0;
2429 
2430 	n = chip->mon_reg_num;
2431 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2432 		    "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
2433 
2434 	if (ver->fcxmreg == 1)
2435 		cxmreg_max = CXMREG_MAX;
2436 	else
2437 		cxmreg_max = CXMREG_MAX_V2;
2438 
2439 	if (n > cxmreg_max) {
2440 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2441 			    "[BTC], %s(): mon reg count %d > %d\n",
2442 			    __func__, n, cxmreg_max);
2443 		return;
2444 	}
2445 
2446 	ulen = sizeof(struct rtw89_btc_fbtc_mreg);
2447 
2448 	if (ver->fcxmreg == 7) {
2449 		sz = struct_size(v7, regs, n);
2450 		v7 = kmalloc(sz, GFP_KERNEL);
2451 		v7->type = RPT_EN_MREG;
2452 		v7->fver = ver->fcxmreg;
2453 		v7->len = n;
2454 		for (i = 0; i < n; i++) {
2455 			v7->regs[i].type = chip->mon_reg[i].type;
2456 			v7->regs[i].bytes = chip->mon_reg[i].bytes;
2457 			v7->regs[i].offset = chip->mon_reg[i].offset;
2458 		}
2459 
2460 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
2461 		kfree(v7);
2462 	} else {
2463 		sz = struct_size(v1, regs, n);
2464 		v1 = kmalloc(sz, GFP_KERNEL);
2465 		v1->fver = ver->fcxmreg;
2466 		v1->reg_num = n;
2467 		memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
2468 
2469 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
2470 		kfree(v1);
2471 	}
2472 
2473 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2474 		    "[BTC], %s(): sz=%d ulen=%d n=%d\n",
2475 		    __func__, sz, ulen, n);
2476 
2477 	rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
2478 }
2479 
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)2480 static void _update_dm_step(struct rtw89_dev *rtwdev,
2481 			    enum btc_reason_and_action reason_or_action)
2482 {
2483 	struct rtw89_btc *btc = &rtwdev->btc;
2484 	struct rtw89_btc_dm *dm = &btc->dm;
2485 
2486 	/* use ring-structure to store dm step */
2487 	dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
2488 	dm->dm_step.step_pos++;
2489 
2490 	if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
2491 		dm->dm_step.step_pos = 0;
2492 		dm->dm_step.step_ov = true;
2493 	}
2494 }
2495 
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)2496 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
2497 			   enum btc_reason_and_action action)
2498 {
2499 	struct rtw89_btc *btc = &rtwdev->btc;
2500 	struct rtw89_btc_dm *dm = &btc->dm;
2501 	int ret;
2502 
2503 	dm->run_action = action;
2504 
2505 	_update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
2506 	_update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
2507 
2508 	btc->policy_len = 0;
2509 	btc->policy_type = policy_type;
2510 
2511 	_append_tdma(rtwdev);
2512 	_append_slot(rtwdev);
2513 
2514 	if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
2515 		return;
2516 
2517 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2518 		    "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
2519 		    __func__, action, policy_type, btc->policy_len);
2520 
2521 	if (dm->tdma.rxflctrl == CXFLC_NULLP ||
2522 	    dm->tdma.rxflctrl == CXFLC_QOSNULL)
2523 		btc->lps = 1;
2524 	else
2525 		btc->lps = 0;
2526 
2527 	if (btc->lps == 1)
2528 		rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2529 
2530 	ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
2531 			   btc->policy, btc->policy_len);
2532 	if (!ret) {
2533 		memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
2534 		if (btc->ver->fcxslots == 7)
2535 			memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
2536 		else
2537 			memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
2538 	}
2539 
2540 	if (btc->update_policy_force)
2541 		btc->update_policy_force = false;
2542 
2543 	if (btc->lps == 0)
2544 		rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2545 }
2546 
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 type)2547 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
2548 {
2549 	struct rtw89_btc *btc = &rtwdev->btc;
2550 	const struct rtw89_btc_ver *ver = btc->ver;
2551 	struct rtw89_btc_dm *dm = &btc->dm;
2552 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2553 	struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para;
2554 
2555 	switch (type) {
2556 	case CXDRVINFO_INIT:
2557 		if (ver->fcxinit == 7)
2558 			rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type);
2559 		else
2560 			rtw89_fw_h2c_cxdrv_init(rtwdev, type);
2561 		break;
2562 	case CXDRVINFO_ROLE:
2563 		if (ver->fwlrole == 0)
2564 			rtw89_fw_h2c_cxdrv_role(rtwdev, type);
2565 		else if (ver->fwlrole == 1)
2566 			rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type);
2567 		else if (ver->fwlrole == 2)
2568 			rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type);
2569 		break;
2570 	case CXDRVINFO_CTRL:
2571 		if (ver->drvinfo_type == 1)
2572 			type = 2;
2573 
2574 		if (ver->fcxctrl == 7)
2575 			rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type);
2576 		else
2577 			rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type);
2578 		break;
2579 	case CXDRVINFO_TRX:
2580 		if (ver->drvinfo_type == 1)
2581 			type = 3;
2582 
2583 		dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power,
2584 						     RTW89_BTC_WL_DEF_TX_PWR);
2585 		dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain,
2586 						    RTW89_BTC_WL_DEF_TX_PWR);
2587 		dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power,
2588 							RTW89_BTC_WL_DEF_TX_PWR);
2589 		dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain,
2590 						       RTW89_BTC_WL_DEF_TX_PWR);
2591 		dm->trx_info.cn = wl->cn_report;
2592 		dm->trx_info.nhm = wl->nhm.pwr;
2593 		rtw89_fw_h2c_cxdrv_trx(rtwdev, type);
2594 		break;
2595 	case CXDRVINFO_RFK:
2596 		if (ver->drvinfo_type == 1)
2597 			return;
2598 
2599 		rtw89_fw_h2c_cxdrv_rfk(rtwdev, type);
2600 		break;
2601 	case CXDRVINFO_TXPWR:
2602 	case CXDRVINFO_FDDT:
2603 	case CXDRVINFO_MLO:
2604 	case CXDRVINFO_OSI:
2605 	default:
2606 		break;
2607 	}
2608 }
2609 
2610 static
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)2611 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
2612 {
2613 	struct rtw89_btc *btc = &rtwdev->btc;
2614 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
2615 
2616 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2617 		    "[BTC], %s(): evt_id:%d len:%d\n",
2618 		    __func__, evt_id, len);
2619 
2620 	if (!len || !data)
2621 		return;
2622 
2623 	switch (evt_id) {
2624 	case BTF_EVNT_RPT:
2625 		_parse_btc_report(rtwdev, pfwinfo, data, len);
2626 		break;
2627 	default:
2628 		break;
2629 	}
2630 }
2631 
_set_gnt(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state)2632 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
2633 {
2634 	struct rtw89_btc *btc = &rtwdev->btc;
2635 	struct rtw89_btc_dm *dm = &btc->dm;
2636 	struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2637 	u8 i;
2638 
2639 	if (phy_map > BTC_PHY_ALL)
2640 		return;
2641 
2642 	for (i = 0; i < RTW89_PHY_MAX; i++) {
2643 		if (!(phy_map & BIT(i)))
2644 			continue;
2645 
2646 		switch (wl_state) {
2647 		case BTC_GNT_HW:
2648 			g[i].gnt_wl_sw_en = 0;
2649 			g[i].gnt_wl = 0;
2650 			break;
2651 		case BTC_GNT_SW_LO:
2652 			g[i].gnt_wl_sw_en = 1;
2653 			g[i].gnt_wl = 0;
2654 			break;
2655 		case BTC_GNT_SW_HI:
2656 			g[i].gnt_wl_sw_en = 1;
2657 			g[i].gnt_wl = 1;
2658 			break;
2659 		}
2660 
2661 		switch (bt_state) {
2662 		case BTC_GNT_HW:
2663 			g[i].gnt_bt_sw_en = 0;
2664 			g[i].gnt_bt = 0;
2665 			break;
2666 		case BTC_GNT_SW_LO:
2667 			g[i].gnt_bt_sw_en = 1;
2668 			g[i].gnt_bt = 0;
2669 			break;
2670 		case BTC_GNT_SW_HI:
2671 			g[i].gnt_bt_sw_en = 1;
2672 			g[i].gnt_bt = 1;
2673 			break;
2674 		}
2675 	}
2676 
2677 	rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
2678 }
2679 
_set_gnt_v1(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state,u8 wlact_state)2680 static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map,
2681 			u8 wl_state, u8 bt_state, u8 wlact_state)
2682 {
2683 	struct rtw89_btc *btc = &rtwdev->btc;
2684 	struct rtw89_btc_dm *dm = &btc->dm;
2685 	struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2686 	u8 i, bt_idx = dm->bt_select + 1;
2687 
2688 	if (phy_map > BTC_PHY_ALL)
2689 		return;
2690 
2691 	for (i = 0; i < RTW89_PHY_MAX; i++) {
2692 		if (!(phy_map & BIT(i)))
2693 			continue;
2694 
2695 		switch (wl_state) {
2696 		case BTC_GNT_HW:
2697 			g[i].gnt_wl_sw_en = 0;
2698 			g[i].gnt_wl = 0;
2699 			break;
2700 		case BTC_GNT_SW_LO:
2701 			g[i].gnt_wl_sw_en = 1;
2702 			g[i].gnt_wl = 0;
2703 			break;
2704 		case BTC_GNT_SW_HI:
2705 			g[i].gnt_wl_sw_en = 1;
2706 			g[i].gnt_wl = 1;
2707 			break;
2708 		}
2709 
2710 		switch (bt_state) {
2711 		case BTC_GNT_HW:
2712 			g[i].gnt_bt_sw_en = 0;
2713 			g[i].gnt_bt = 0;
2714 			break;
2715 		case BTC_GNT_SW_LO:
2716 			g[i].gnt_bt_sw_en = 1;
2717 			g[i].gnt_bt = 0;
2718 			break;
2719 		case BTC_GNT_SW_HI:
2720 			g[i].gnt_bt_sw_en = 1;
2721 			g[i].gnt_bt = 1;
2722 			break;
2723 		}
2724 	}
2725 
2726 	if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) {
2727 		for (i = 0; i < 2; i++) {
2728 			if (!(bt_idx & BIT(i)))
2729 				continue;
2730 
2731 			switch (wlact_state) {
2732 			case BTC_WLACT_HW:
2733 				dm->gnt.bt[i].wlan_act_en = 0;
2734 				dm->gnt.bt[i].wlan_act = 0;
2735 				break;
2736 			case BTC_WLACT_SW_LO:
2737 				dm->gnt.bt[i].wlan_act_en = 1;
2738 				dm->gnt.bt[i].wlan_act = 0;
2739 				break;
2740 			case BTC_WLACT_SW_HI:
2741 				dm->gnt.bt[i].wlan_act_en = 1;
2742 				dm->gnt.bt[i].wlan_act = 1;
2743 				break;
2744 			}
2745 		}
2746 	}
2747 	rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
2748 }
2749 
2750 #define BTC_TDMA_WLROLE_MAX 2
2751 
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)2752 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
2753 {
2754 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2755 		    "[BTC], %s(): set bt %s wlan_act\n", __func__,
2756 		    enable ? "ignore" : "do not ignore");
2757 
2758 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
2759 }
2760 
2761 #define WL_TX_POWER_NO_BTC_CTRL	GENMASK(31, 0)
2762 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
2763 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
2764 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
2765 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
2766 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
2767 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
2768 
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level)2769 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
2770 {
2771 	const struct rtw89_chip_info *chip = rtwdev->chip;
2772 	struct rtw89_btc *btc = &rtwdev->btc;
2773 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2774 	u32 pwr_val;
2775 
2776 	if (wl->rf_para.tx_pwr_freerun == level)
2777 		return;
2778 
2779 	wl->rf_para.tx_pwr_freerun = level;
2780 	btc->dm.rf_trx_para.wl_tx_power = level;
2781 
2782 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2783 		    "[BTC], %s(): level = %d\n",
2784 		    __func__, level);
2785 
2786 	if (level == RTW89_BTC_WL_DEF_TX_PWR) {
2787 		pwr_val = WL_TX_POWER_NO_BTC_CTRL;
2788 	} else { /* only apply "force tx power" */
2789 		pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
2790 		if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
2791 			pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
2792 
2793 		if (level & B_BTC_WL_TX_POWER_SIGN)
2794 			pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
2795 		pwr_val |= WL_TX_POWER_WITH_BT;
2796 	}
2797 
2798 	chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
2799 }
2800 
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level)2801 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
2802 {
2803 	const struct rtw89_chip_info *chip = rtwdev->chip;
2804 	struct rtw89_btc *btc = &rtwdev->btc;
2805 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2806 
2807 	if (wl->rf_para.rx_gain_freerun == level)
2808 		return;
2809 
2810 	wl->rf_para.rx_gain_freerun = level;
2811 	btc->dm.rf_trx_para.wl_rx_gain = level;
2812 
2813 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2814 		    "[BTC], %s(): level = %d\n",
2815 		    __func__, level);
2816 
2817 	chip->ops->btc_set_wl_rx_gain(rtwdev, level);
2818 }
2819 
_set_bt_tx_power(struct rtw89_dev * rtwdev,u8 level)2820 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
2821 {
2822 	struct rtw89_btc *btc = &rtwdev->btc;
2823 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2824 	int ret;
2825 	u8 buf;
2826 
2827 	if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
2828 		return;
2829 
2830 	if (bt->rf_para.tx_pwr_freerun == level)
2831 		return;
2832 
2833 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2834 		    "[BTC], %s(): level = %d\n",
2835 		    __func__, level);
2836 
2837 	buf = (s8)(-level);
2838 	ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
2839 	if (!ret) {
2840 		bt->rf_para.tx_pwr_freerun = level;
2841 		btc->dm.rf_trx_para.bt_tx_power = level;
2842 	}
2843 }
2844 
2845 #define BTC_BT_RX_NORMAL_LVL 7
2846 
_set_bt_rx_gain(struct rtw89_dev * rtwdev,u8 level)2847 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
2848 {
2849 	struct rtw89_btc *btc = &rtwdev->btc;
2850 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2851 
2852 	if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
2853 		return;
2854 
2855 	if ((bt->rf_para.rx_gain_freerun == level ||
2856 	     level > BTC_BT_RX_NORMAL_LVL) &&
2857 	    (!rtwdev->chip->scbd || bt->lna_constrain == level))
2858 		return;
2859 
2860 	bt->rf_para.rx_gain_freerun = level;
2861 	btc->dm.rf_trx_para.bt_rx_gain = level;
2862 
2863 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2864 		    "[BTC], %s(): level = %d\n",
2865 		    __func__, level);
2866 
2867 	if (level == BTC_BT_RX_NORMAL_LVL)
2868 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
2869 	else
2870 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
2871 
2872 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level));
2873 }
2874 
_set_rf_trx_para(struct rtw89_dev * rtwdev)2875 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
2876 {
2877 	const struct rtw89_chip_info *chip = rtwdev->chip;
2878 	struct rtw89_btc *btc = &rtwdev->btc;
2879 	const struct rtw89_btc_ver *ver = btc->ver;
2880 	struct rtw89_btc_dm *dm = &btc->dm;
2881 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2882 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2883 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
2884 	struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
2885 	struct rtw89_btc_rf_trx_para para;
2886 	u32 wl_stb_chg = 0;
2887 	u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0;
2888 
2889 	if (ver->fwlrole == 0) {
2890 		link_mode = wl->role_info.link_mode;
2891 		for (i = 0; i < RTW89_PHY_MAX; i++) {
2892 			if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G)
2893 				dbcc_2g_phy = i;
2894 		}
2895 	} else if (ver->fwlrole == 1) {
2896 		link_mode = wl->role_info_v1.link_mode;
2897 		dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy;
2898 	} else if (ver->fwlrole == 2) {
2899 		link_mode = wl->role_info_v2.link_mode;
2900 		dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy;
2901 	}
2902 
2903 	/* decide trx_para_level */
2904 	if (btc->ant_type == BTC_ANT_SHARED) {
2905 		/* fix LNA2 + TIA gain not change by GNT_BT */
2906 		if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) ||
2907 		    dm->bt_only == 1)
2908 			dm->trx_para_level = 1; /* for better BT ACI issue */
2909 		else
2910 			dm->trx_para_level = 0;
2911 	} else { /* non-shared antenna  */
2912 		dm->trx_para_level = 5;
2913 		/* modify trx_para if WK 2.4G-STA-DL + bt link */
2914 		if (b->profile_cnt.now != 0 &&
2915 		    link_mode == BTC_WLINK_2G_STA &&
2916 		    wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
2917 			if (wl->rssi_level == 4 && bt->rssi_level > 2)
2918 				dm->trx_para_level = 6;
2919 			else if (wl->rssi_level == 3 && bt->rssi_level > 3)
2920 				dm->trx_para_level = 7;
2921 		}
2922 	}
2923 
2924 	level_id = dm->trx_para_level;
2925 	if (level_id >= chip->rf_para_dlink_num ||
2926 	    level_id >= chip->rf_para_ulink_num) {
2927 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2928 			    "[BTC], %s(): invalid level_id: %d\n",
2929 			    __func__, level_id);
2930 		return;
2931 	}
2932 
2933 	if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
2934 		para = chip->rf_para_ulink[level_id];
2935 	else
2936 		para = chip->rf_para_dlink[level_id];
2937 
2938 	if (dm->fddt_train) {
2939 		_set_wl_rx_gain(rtwdev, 1);
2940 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
2941 	} else {
2942 		_set_wl_tx_power(rtwdev, para.wl_tx_power);
2943 		_set_wl_rx_gain(rtwdev, para.wl_rx_gain);
2944 		_set_bt_tx_power(rtwdev, para.bt_tx_power);
2945 		_set_bt_rx_gain(rtwdev, para.bt_rx_gain);
2946 	}
2947 
2948 	if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
2949 	    wl_smap->lps == BTC_LPS_RF_OFF ||
2950 	    link_mode == BTC_WLINK_5G ||
2951 	    link_mode == BTC_WLINK_NOLINK ||
2952 	    (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1))
2953 		wl_stb_chg = 0;
2954 	else
2955 		wl_stb_chg = 1;
2956 
2957 	if (wl_stb_chg != dm->wl_stb_chg) {
2958 		dm->wl_stb_chg = wl_stb_chg;
2959 		chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
2960 	}
2961 }
2962 
_update_btc_state_map(struct rtw89_dev * rtwdev)2963 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
2964 {
2965 	struct rtw89_btc *btc = &rtwdev->btc;
2966 	struct rtw89_btc_cx *cx = &btc->cx;
2967 	struct rtw89_btc_wl_info *wl = &cx->wl;
2968 	struct rtw89_btc_bt_info *bt = &cx->bt;
2969 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
2970 
2971 	if (wl->status.map.connecting || wl->status.map._4way ||
2972 	    wl->status.map.roaming) {
2973 		cx->state_map = BTC_WLINKING;
2974 	} else if (wl->status.map.scan) { /* wl scan */
2975 		if (bt_linfo->status.map.inq_pag)
2976 			cx->state_map = BTC_WSCAN_BSCAN;
2977 		else
2978 			cx->state_map = BTC_WSCAN_BNOSCAN;
2979 	} else if (wl->status.map.busy) { /* only busy */
2980 		if (bt_linfo->status.map.inq_pag)
2981 			cx->state_map = BTC_WBUSY_BSCAN;
2982 		else
2983 			cx->state_map = BTC_WBUSY_BNOSCAN;
2984 	} else { /* wl idle */
2985 		cx->state_map = BTC_WIDLE;
2986 	}
2987 }
2988 
_set_bt_afh_info(struct rtw89_dev * rtwdev)2989 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
2990 {
2991 	const struct rtw89_chip_info *chip = rtwdev->chip;
2992 	struct rtw89_btc *btc = &rtwdev->btc;
2993 	const struct rtw89_btc_ver *ver = btc->ver;
2994 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2995 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2996 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
2997 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
2998 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
2999 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3000 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3001 	struct rtw89_btc_wl_active_role *r;
3002 	struct rtw89_btc_wl_active_role_v1 *r1;
3003 	struct rtw89_btc_wl_active_role_v2 *r2;
3004 	struct rtw89_btc_wl_rlink *rlink;
3005 	u8 en = 0, i, ch = 0, bw = 0;
3006 	u8 mode, connect_cnt;
3007 
3008 	if (btc->manual_ctrl || wl->status.map.scan)
3009 		return;
3010 
3011 	if (ver->fwlrole == 0) {
3012 		mode = wl_rinfo->link_mode;
3013 		connect_cnt = wl_rinfo->connect_cnt;
3014 	} else if (ver->fwlrole == 1) {
3015 		mode = wl_rinfo_v1->link_mode;
3016 		connect_cnt = wl_rinfo_v1->connect_cnt;
3017 	} else if (ver->fwlrole == 2) {
3018 		mode = wl_rinfo_v2->link_mode;
3019 		connect_cnt = wl_rinfo_v2->connect_cnt;
3020 	} else if (ver->fwlrole == 8) {
3021 		mode = wl_rinfo_v8->link_mode;
3022 		connect_cnt = wl_rinfo_v8->connect_cnt;
3023 	} else {
3024 		return;
3025 	}
3026 
3027 	if (wl->status.map.rf_off || bt->whql_test ||
3028 	    mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
3029 	    connect_cnt > BTC_TDMA_WLROLE_MAX) {
3030 		en = false;
3031 	} else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
3032 		en = true;
3033 		/* get p2p channel */
3034 		for (i = 0; i < RTW89_PORT_NUM; i++) {
3035 			r = &wl_rinfo->active_role[i];
3036 			r1 = &wl_rinfo_v1->active_role_v1[i];
3037 			r2 = &wl_rinfo_v2->active_role_v2[i];
3038 			rlink = &wl_rinfo_v8->rlink[i][0];
3039 
3040 			if (ver->fwlrole == 0 &&
3041 			    (r->role == RTW89_WIFI_ROLE_P2P_GO ||
3042 			     r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3043 				ch = r->ch;
3044 				bw = r->bw;
3045 				break;
3046 			} else if (ver->fwlrole == 1 &&
3047 				   (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
3048 				    r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3049 				ch = r1->ch;
3050 				bw = r1->bw;
3051 				break;
3052 			} else if (ver->fwlrole == 2 &&
3053 				   (r2->role == RTW89_WIFI_ROLE_P2P_GO ||
3054 				    r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3055 				ch = r2->ch;
3056 				bw = r2->bw;
3057 				break;
3058 			} else if (ver->fwlrole == 8 &&
3059 				   (rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3060 				    rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3061 				ch = rlink->ch;
3062 				bw = rlink->bw;
3063 				break;
3064 			}
3065 		}
3066 	} else {
3067 		en = true;
3068 		/* get 2g channel  */
3069 		for (i = 0; i < RTW89_PORT_NUM; i++) {
3070 			r = &wl_rinfo->active_role[i];
3071 			r1 = &wl_rinfo_v1->active_role_v1[i];
3072 			r2 = &wl_rinfo_v2->active_role_v2[i];
3073 			rlink = &wl_rinfo_v8->rlink[i][0];
3074 
3075 			if (ver->fwlrole == 0 &&
3076 			    r->connected && r->band == RTW89_BAND_2G) {
3077 				ch = r->ch;
3078 				bw = r->bw;
3079 				break;
3080 			} else if (ver->fwlrole == 1 &&
3081 				   r1->connected && r1->band == RTW89_BAND_2G) {
3082 				ch = r1->ch;
3083 				bw = r1->bw;
3084 				break;
3085 			} else if (ver->fwlrole == 2 &&
3086 				   r2->connected && r2->band == RTW89_BAND_2G) {
3087 				ch = r2->ch;
3088 				bw = r2->bw;
3089 				break;
3090 			} else if (ver->fwlrole == 8 &&
3091 				   rlink->connected && rlink->rf_band == RTW89_BAND_2G) {
3092 				ch = rlink->ch;
3093 				bw = rlink->bw;
3094 				break;
3095 			}
3096 		}
3097 	}
3098 
3099 	switch (bw) {
3100 	case RTW89_CHANNEL_WIDTH_20:
3101 		bw = 20 + chip->afh_guard_ch * 2;
3102 		break;
3103 	case RTW89_CHANNEL_WIDTH_40:
3104 		bw = 40 + chip->afh_guard_ch * 2;
3105 		break;
3106 	case RTW89_CHANNEL_WIDTH_5:
3107 		bw = 5 + chip->afh_guard_ch * 2;
3108 		break;
3109 	case RTW89_CHANNEL_WIDTH_10:
3110 		bw = 10 + chip->afh_guard_ch * 2;
3111 		break;
3112 	default:
3113 		bw = 0;
3114 		en = false; /* turn off AFH info if BW > 40 */
3115 		break;
3116 	}
3117 
3118 	if (wl->afh_info.en == en &&
3119 	    wl->afh_info.ch == ch &&
3120 	    wl->afh_info.bw == bw &&
3121 	    b->profile_cnt.last == b->profile_cnt.now) {
3122 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
3123 			    "[BTC], %s(): return because no change!\n",
3124 			    __func__);
3125 		return;
3126 	}
3127 
3128 	wl->afh_info.en = en;
3129 	wl->afh_info.ch = ch;
3130 	wl->afh_info.bw = bw;
3131 
3132 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
3133 
3134 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3135 		    "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3136 		    __func__, en, ch, bw);
3137 	btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3138 }
3139 
_check_freerun(struct rtw89_dev * rtwdev)3140 static bool _check_freerun(struct rtw89_dev *rtwdev)
3141 {
3142 	struct rtw89_btc *btc = &rtwdev->btc;
3143 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3144 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3145 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3146 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3147 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3148 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3149 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3150 	struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
3151 	union rtw89_btc_module_info *md = &btc->mdinfo;
3152 	const struct rtw89_btc_ver *ver = btc->ver;
3153 	u8 isolation, connect_cnt = 0;
3154 
3155 	if (ver->fcxinit == 7)
3156 		isolation = md->md_v7.ant.isolation;
3157 	else
3158 		isolation = md->md.ant.isolation;
3159 
3160 	if (ver->fwlrole == 0)
3161 		connect_cnt = wl_rinfo->connect_cnt;
3162 	else if (ver->fwlrole == 1)
3163 		connect_cnt = wl_rinfo_v1->connect_cnt;
3164 	else if (ver->fwlrole == 2)
3165 		connect_cnt = wl_rinfo_v2->connect_cnt;
3166 	else if (ver->fwlrole == 8)
3167 		connect_cnt = wl_rinfo_v8->connect_cnt;
3168 
3169 	if (btc->ant_type == BTC_ANT_SHARED) {
3170 		btc->dm.trx_para_level = 0;
3171 		return false;
3172 	}
3173 
3174 	/* The below is dedicated antenna case */
3175 	if (connect_cnt > BTC_TDMA_WLROLE_MAX) {
3176 		btc->dm.trx_para_level = 5;
3177 		return true;
3178 	}
3179 
3180 	if (bt_linfo->profile_cnt.now == 0) {
3181 		btc->dm.trx_para_level = 5;
3182 		return true;
3183 	}
3184 
3185 	if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
3186 		btc->dm.trx_para_level = 5;
3187 		return true;
3188 	}
3189 
3190 	/* TODO get isolation by BT psd */
3191 	if (isolation >= BTC_FREERUN_ANTISO_MIN) {
3192 		btc->dm.trx_para_level = 5;
3193 		return true;
3194 	}
3195 
3196 	if (!wl->status.map.busy) {/* wl idle -> freerun */
3197 		btc->dm.trx_para_level = 5;
3198 		return true;
3199 	} else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
3200 		btc->dm.trx_para_level = 0;
3201 		return false;
3202 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
3203 		if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
3204 			btc->dm.trx_para_level = 6;
3205 			return true;
3206 		} else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
3207 			btc->dm.trx_para_level = 7;
3208 			return true;
3209 		}
3210 		btc->dm.trx_para_level = 0;
3211 		return false;
3212 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
3213 		if (bt_linfo->rssi > 28) {
3214 			btc->dm.trx_para_level = 6;
3215 			return true;
3216 		}
3217 	}
3218 
3219 	btc->dm.trx_para_level = 0;
3220 	return false;
3221 }
3222 
3223 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
3224 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
3225 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
3226 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
3227 
3228 struct btc_btinfo_lb2 {
3229 	u8 connect: 1;
3230 	u8 sco_busy: 1;
3231 	u8 inq_pag: 1;
3232 	u8 acl_busy: 1;
3233 	u8 hfp: 1;
3234 	u8 hid: 1;
3235 	u8 a2dp: 1;
3236 	u8 pan: 1;
3237 };
3238 
3239 struct btc_btinfo_lb3 {
3240 	u8 retry: 4;
3241 	u8 cqddr: 1;
3242 	u8 inq: 1;
3243 	u8 mesh_busy: 1;
3244 	u8 pag: 1;
3245 };
3246 
3247 struct btc_btinfo_hb0 {
3248 	s8 rssi;
3249 };
3250 
3251 struct btc_btinfo_hb1 {
3252 	u8 ble_connect: 1;
3253 	u8 reinit: 1;
3254 	u8 relink: 1;
3255 	u8 igno_wl: 1;
3256 	u8 voice: 1;
3257 	u8 ble_scan: 1;
3258 	u8 role_sw: 1;
3259 	u8 multi_link: 1;
3260 };
3261 
3262 struct btc_btinfo_hb2 {
3263 	u8 pan_active: 1;
3264 	u8 afh_update: 1;
3265 	u8 a2dp_active: 1;
3266 	u8 slave: 1;
3267 	u8 hid_slot: 2;
3268 	u8 hid_cnt: 2;
3269 };
3270 
3271 struct btc_btinfo_hb3 {
3272 	u8 a2dp_bitpool: 6;
3273 	u8 tx_3m: 1;
3274 	u8 a2dp_sink: 1;
3275 };
3276 
3277 union btc_btinfo {
3278 	u8 val;
3279 	struct btc_btinfo_lb2 lb2;
3280 	struct btc_btinfo_lb3 lb3;
3281 	struct btc_btinfo_hb0 hb0;
3282 	struct btc_btinfo_hb1 hb1;
3283 	struct btc_btinfo_hb2 hb2;
3284 	struct btc_btinfo_hb3 hb3;
3285 };
3286 
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)3287 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
3288 			enum btc_reason_and_action action)
3289 {
3290 	const struct rtw89_chip_info *chip = rtwdev->chip;
3291 
3292 	chip->ops->btc_set_policy(rtwdev, policy_type);
3293 	_fw_set_policy(rtwdev, policy_type, action);
3294 }
3295 
3296 #define BTC_B1_MAX 250 /* unit ms */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)3297 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
3298 {
3299 	struct rtw89_btc *btc = &rtwdev->btc;
3300 	struct rtw89_btc_dm *dm = &btc->dm;
3301 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3302 	struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
3303 	u8 type;
3304 	u32 tbl_w1, tbl_b1, tbl_b4;
3305 
3306 	if (btc->ant_type == BTC_ANT_SHARED) {
3307 		if (btc->cx.wl.status.map._4way)
3308 			tbl_w1 = cxtbl[1];
3309 		else
3310 			tbl_w1 = cxtbl[8];
3311 		tbl_b1 = cxtbl[3];
3312 		tbl_b4 = cxtbl[3];
3313 	} else {
3314 		tbl_w1 = cxtbl[16];
3315 		tbl_b1 = cxtbl[17];
3316 		tbl_b4 = cxtbl[17];
3317 	}
3318 
3319 	type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
3320 	btc->bt_req_en = false;
3321 
3322 	switch (type) {
3323 	case BTC_CXP_USERDEF0:
3324 		*t = t_def[CXTD_OFF];
3325 		s[CXST_OFF] = s_def[CXST_OFF];
3326 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3327 		btc->update_policy_force = true;
3328 		break;
3329 	case BTC_CXP_OFF: /* TDMA off */
3330 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3331 		*t = t_def[CXTD_OFF];
3332 		s[CXST_OFF] = s_def[CXST_OFF];
3333 
3334 		switch (policy_type) {
3335 		case BTC_CXP_OFF_BT:
3336 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3337 			break;
3338 		case BTC_CXP_OFF_WL:
3339 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3340 			break;
3341 		case BTC_CXP_OFF_EQ0:
3342 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3343 			break;
3344 		case BTC_CXP_OFF_EQ1:
3345 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
3346 			break;
3347 		case BTC_CXP_OFF_EQ2:
3348 			_slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
3349 			break;
3350 		case BTC_CXP_OFF_EQ3:
3351 			_slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
3352 			break;
3353 		case BTC_CXP_OFF_BWB0:
3354 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
3355 			break;
3356 		case BTC_CXP_OFF_BWB1:
3357 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3358 			break;
3359 		case BTC_CXP_OFF_BWB3:
3360 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3361 			break;
3362 		}
3363 		break;
3364 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
3365 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3366 		*t = t_def[CXTD_OFF_B2];
3367 		s[CXST_OFF] = s_def[CXST_OFF];
3368 		switch (policy_type) {
3369 		case BTC_CXP_OFFB_BWB0:
3370 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3371 			break;
3372 		}
3373 		break;
3374 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
3375 		btc->bt_req_en = true;
3376 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3377 		*t = t_def[CXTD_OFF_EXT];
3378 		switch (policy_type) {
3379 		case BTC_CXP_OFFE_DEF:
3380 			s[CXST_E2G] = s_def[CXST_E2G];
3381 			s[CXST_E5G] = s_def[CXST_E5G];
3382 			s[CXST_EBT] = s_def[CXST_EBT];
3383 			s[CXST_ENULL] = s_def[CXST_ENULL];
3384 			break;
3385 		case BTC_CXP_OFFE_DEF2:
3386 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3387 			s[CXST_E5G] = s_def[CXST_E5G];
3388 			s[CXST_EBT] = s_def[CXST_EBT];
3389 			s[CXST_ENULL] = s_def[CXST_ENULL];
3390 			break;
3391 		}
3392 		break;
3393 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
3394 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3395 		*t = t_def[CXTD_FIX];
3396 		switch (policy_type) {
3397 		case BTC_CXP_FIX_TD3030:
3398 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3399 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3400 			break;
3401 		case BTC_CXP_FIX_TD5050:
3402 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3403 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3404 			break;
3405 		case BTC_CXP_FIX_TD2030:
3406 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3407 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3408 			break;
3409 		case BTC_CXP_FIX_TD4010:
3410 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
3411 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3412 			break;
3413 		case BTC_CXP_FIX_TD4010ISO:
3414 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3415 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3416 			break;
3417 		case BTC_CXP_FIX_TD4010ISO_DL:
3418 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3419 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3420 			break;
3421 		case BTC_CXP_FIX_TD4010ISO_UL:
3422 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3423 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3424 			break;
3425 		case BTC_CXP_FIX_TD7010:
3426 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
3427 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3428 			break;
3429 		case BTC_CXP_FIX_TD2060:
3430 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3431 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3432 			break;
3433 		case BTC_CXP_FIX_TD3060:
3434 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3435 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3436 			break;
3437 		case BTC_CXP_FIX_TD2080:
3438 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3439 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3440 			break;
3441 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
3442 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3443 				  tbl_w1, SLOT_ISO);
3444 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3445 				  tbl_b1, SLOT_MIX);
3446 			break;
3447 		}
3448 		break;
3449 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
3450 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3451 		*t = t_def[CXTD_PFIX];
3452 		if (btc->cx.wl.role_info.role_map.role.ap)
3453 			_tdma_set_flctrl(btc, CXFLC_QOSNULL);
3454 
3455 		switch (policy_type) {
3456 		case BTC_CXP_PFIX_TD3030:
3457 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3458 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3459 			break;
3460 		case BTC_CXP_PFIX_TD5050:
3461 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3462 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3463 			break;
3464 		case BTC_CXP_PFIX_TD2030:
3465 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3466 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3467 			break;
3468 		case BTC_CXP_PFIX_TD2060:
3469 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3470 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3471 			break;
3472 		case BTC_CXP_PFIX_TD3070:
3473 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3474 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3475 			break;
3476 		case BTC_CXP_PFIX_TD2080:
3477 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3478 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3479 			break;
3480 		}
3481 		break;
3482 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
3483 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3484 		*t = t_def[CXTD_AUTO];
3485 		switch (policy_type) {
3486 		case BTC_CXP_AUTO_TD50B1:
3487 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3488 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3489 			break;
3490 		case BTC_CXP_AUTO_TD60B1:
3491 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3492 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3493 			break;
3494 		case BTC_CXP_AUTO_TD20B1:
3495 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3496 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3497 			break;
3498 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
3499 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3500 				  tbl_w1, SLOT_ISO);
3501 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3502 				  tbl_b1, SLOT_MIX);
3503 			break;
3504 		}
3505 		break;
3506 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
3507 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3508 		*t = t_def[CXTD_PAUTO];
3509 		switch (policy_type) {
3510 		case BTC_CXP_PAUTO_TD50B1:
3511 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3512 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3513 			break;
3514 		case BTC_CXP_PAUTO_TD60B1:
3515 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3516 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3517 			break;
3518 		case BTC_CXP_PAUTO_TD20B1:
3519 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3520 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3521 			break;
3522 		case BTC_CXP_PAUTO_TDW1B1:
3523 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3524 				  tbl_w1, SLOT_ISO);
3525 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3526 				  tbl_b1, SLOT_MIX);
3527 			break;
3528 		}
3529 		break;
3530 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
3531 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3532 		*t = t_def[CXTD_AUTO2];
3533 		switch (policy_type) {
3534 		case BTC_CXP_AUTO2_TD3050:
3535 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3536 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3537 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3538 			break;
3539 		case BTC_CXP_AUTO2_TD3070:
3540 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3541 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3542 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3543 			break;
3544 		case BTC_CXP_AUTO2_TD5050:
3545 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3546 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3547 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3548 			break;
3549 		case BTC_CXP_AUTO2_TD6060:
3550 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3551 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3552 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3553 			break;
3554 		case BTC_CXP_AUTO2_TD2080:
3555 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3556 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3557 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3558 			break;
3559 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
3560 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3561 				  tbl_w1, SLOT_ISO);
3562 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3563 				  tbl_b4, SLOT_MIX);
3564 			break;
3565 		}
3566 		break;
3567 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
3568 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3569 		*t = t_def[CXTD_PAUTO2];
3570 		switch (policy_type) {
3571 		case BTC_CXP_PAUTO2_TD3050:
3572 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3573 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3574 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3575 			break;
3576 		case BTC_CXP_PAUTO2_TD3070:
3577 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3578 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3579 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3580 			break;
3581 		case BTC_CXP_PAUTO2_TD5050:
3582 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3583 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3584 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3585 			break;
3586 		case BTC_CXP_PAUTO2_TD6060:
3587 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3588 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3589 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3590 			break;
3591 		case BTC_CXP_PAUTO2_TD2080:
3592 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3593 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3594 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3595 			break;
3596 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
3597 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3598 				  tbl_w1, SLOT_ISO);
3599 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3600 				  tbl_b4, SLOT_MIX);
3601 			break;
3602 		}
3603 		break;
3604 	}
3605 }
3606 EXPORT_SYMBOL(rtw89_btc_set_policy);
3607 
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)3608 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
3609 {
3610 	struct rtw89_btc *btc = &rtwdev->btc;
3611 	struct rtw89_btc_dm *dm = &btc->dm;
3612 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3613 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
3614 	struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
3615 	struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
3616 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3617 	u8 type, null_role;
3618 	u32 tbl_w1, tbl_b1, tbl_b4;
3619 
3620 	type = FIELD_GET(BTC_CXP_MASK, policy_type);
3621 
3622 	if (btc->ant_type == BTC_ANT_SHARED) {
3623 		if (btc->cx.wl.status.map._4way)
3624 			tbl_w1 = cxtbl[1];
3625 		else if (hid->exist && hid->type == BTC_HID_218)
3626 			tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
3627 		else
3628 			tbl_w1 = cxtbl[8];
3629 
3630 		if (dm->leak_ap &&
3631 		    (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
3632 			tbl_b1 = cxtbl[3];
3633 			tbl_b4 = cxtbl[3];
3634 		} else if (hid->exist && hid->type == BTC_HID_218) {
3635 			tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
3636 			tbl_b4 = cxtbl[4];
3637 		} else {
3638 			tbl_b1 = cxtbl[2];
3639 			tbl_b4 = cxtbl[2];
3640 		}
3641 	} else {
3642 		tbl_b1 = cxtbl[17];
3643 		tbl_b4 = cxtbl[17];
3644 
3645 		if (wl->bg_mode)
3646 			tbl_w1 = cxtbl[8];
3647 		else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
3648 			 hid->exist)
3649 			tbl_w1 = cxtbl[19];
3650 		else
3651 			tbl_w1 = cxtbl[16];
3652 	}
3653 
3654 	btc->bt_req_en = false;
3655 
3656 	switch (type) {
3657 	case BTC_CXP_USERDEF0:
3658 		btc->update_policy_force = true;
3659 		*t = t_def[CXTD_OFF];
3660 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3661 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3662 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3663 		break;
3664 	case BTC_CXP_OFF: /* TDMA off */
3665 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3666 		*t = t_def[CXTD_OFF];
3667 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3668 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3669 
3670 		switch (policy_type) {
3671 		case BTC_CXP_OFF_BT:
3672 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3673 			break;
3674 		case BTC_CXP_OFF_WL:
3675 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3676 			break;
3677 		case BTC_CXP_OFF_EQ0:
3678 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3679 			_slot_set_type(btc, CXST_OFF, SLOT_ISO);
3680 			break;
3681 		case BTC_CXP_OFF_EQ1:
3682 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
3683 			break;
3684 		case BTC_CXP_OFF_EQ2:
3685 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3686 			break;
3687 		case BTC_CXP_OFF_EQ3:
3688 			_slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
3689 			break;
3690 		case BTC_CXP_OFF_BWB0:
3691 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
3692 			break;
3693 		case BTC_CXP_OFF_BWB1:
3694 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3695 			break;
3696 		case BTC_CXP_OFF_BWB2:
3697 			_slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
3698 			break;
3699 		case BTC_CXP_OFF_BWB3:
3700 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3701 			break;
3702 		default:
3703 			break;
3704 		}
3705 		break;
3706 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
3707 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3708 		*t = t_def[CXTD_OFF_B2];
3709 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3710 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3711 
3712 		switch (policy_type) {
3713 		case BTC_CXP_OFFB_BWB0:
3714 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3715 			break;
3716 		default:
3717 			break;
3718 		}
3719 		break;
3720 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
3721 		btc->bt_req_en = true;
3722 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3723 		*t = t_def[CXTD_OFF_EXT];
3724 
3725 		/* To avoid wl-s0 tx break by hid/hfp tx */
3726 		if (hid->exist || hfp->exist)
3727 			tbl_w1 = cxtbl[16];
3728 
3729 		switch (policy_type) {
3730 		case BTC_CXP_OFFE_DEF:
3731 			_slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
3732 				     s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
3733 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
3734 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
3735 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3736 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3737 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
3738 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
3739 			break;
3740 		case BTC_CXP_OFFE_DEF2:
3741 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3742 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
3743 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
3744 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3745 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3746 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
3747 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
3748 			break;
3749 		default:
3750 			break;
3751 		}
3752 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3753 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3754 		break;
3755 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
3756 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3757 		*t = t_def[CXTD_FIX];
3758 
3759 		switch (policy_type) {
3760 		case BTC_CXP_FIX_TD3030:
3761 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3762 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3763 			break;
3764 		case BTC_CXP_FIX_TD5050:
3765 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3766 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3767 			break;
3768 		case BTC_CXP_FIX_TD2030:
3769 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3770 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3771 			break;
3772 		case BTC_CXP_FIX_TD4010:
3773 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
3774 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3775 			break;
3776 		case BTC_CXP_FIX_TD4010ISO:
3777 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3778 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3779 			break;
3780 		case BTC_CXP_FIX_TD4010ISO_DL:
3781 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3782 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3783 			break;
3784 		case BTC_CXP_FIX_TD4010ISO_UL:
3785 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3786 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3787 			break;
3788 		case BTC_CXP_FIX_TD7010:
3789 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
3790 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3791 			break;
3792 		case BTC_CXP_FIX_TD2060:
3793 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3794 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3795 			break;
3796 		case BTC_CXP_FIX_TD3060:
3797 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3798 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3799 			break;
3800 		case BTC_CXP_FIX_TD2080:
3801 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3802 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3803 			break;
3804 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
3805 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3806 				  tbl_w1, SLOT_ISO);
3807 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3808 				  tbl_b1, SLOT_MIX);
3809 			break;
3810 		default:
3811 			break;
3812 		}
3813 		break;
3814 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
3815 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3816 		*t = t_def[CXTD_PFIX];
3817 
3818 		switch (policy_type) {
3819 		case BTC_CXP_PFIX_TD3030:
3820 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3821 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3822 			break;
3823 		case BTC_CXP_PFIX_TD5050:
3824 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3825 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3826 			break;
3827 		case BTC_CXP_PFIX_TD2030:
3828 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3829 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3830 			break;
3831 		case BTC_CXP_PFIX_TD2060:
3832 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3833 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3834 			break;
3835 		case BTC_CXP_PFIX_TD3070:
3836 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3837 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3838 			break;
3839 		case BTC_CXP_PFIX_TD2080:
3840 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3841 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3842 			break;
3843 		case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
3844 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3845 				  tbl_w1, SLOT_ISO);
3846 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3847 				  tbl_b1, SLOT_MIX);
3848 			break;
3849 		default:
3850 			break;
3851 		}
3852 		break;
3853 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
3854 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3855 		*t = t_def[CXTD_AUTO];
3856 
3857 		switch (policy_type) {
3858 		case BTC_CXP_AUTO_TD50B1:
3859 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
3860 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3861 			break;
3862 		case BTC_CXP_AUTO_TD60B1:
3863 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
3864 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3865 			break;
3866 		case BTC_CXP_AUTO_TD20B1:
3867 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
3868 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3869 			break;
3870 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
3871 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3872 				  tbl_w1, SLOT_ISO);
3873 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3874 				  tbl_b1, SLOT_MIX);
3875 			break;
3876 		default:
3877 			break;
3878 		}
3879 		break;
3880 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
3881 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3882 		*t = t_def[CXTD_PAUTO];
3883 
3884 		switch (policy_type) {
3885 		case BTC_CXP_PAUTO_TD50B1:
3886 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
3887 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3888 			break;
3889 		case BTC_CXP_PAUTO_TD60B1:
3890 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
3891 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3892 			break;
3893 		case BTC_CXP_PAUTO_TD20B1:
3894 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
3895 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3896 			break;
3897 		case BTC_CXP_PAUTO_TDW1B1:
3898 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3899 				  tbl_w1, SLOT_ISO);
3900 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3901 				  tbl_b1, SLOT_MIX);
3902 			break;
3903 		default:
3904 			break;
3905 		}
3906 		break;
3907 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
3908 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3909 		*t = t_def[CXTD_AUTO2];
3910 
3911 		switch (policy_type) {
3912 		case BTC_CXP_AUTO2_TD3050:
3913 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
3914 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3915 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
3916 			break;
3917 		case BTC_CXP_AUTO2_TD3070:
3918 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
3919 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3920 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
3921 			break;
3922 		case BTC_CXP_AUTO2_TD5050:
3923 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
3924 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3925 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
3926 			break;
3927 		case BTC_CXP_AUTO2_TD6060:
3928 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
3929 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3930 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
3931 			break;
3932 		case BTC_CXP_AUTO2_TD2080:
3933 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
3934 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3935 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
3936 			break;
3937 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
3938 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3939 				  tbl_w1, SLOT_ISO);
3940 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3941 				  tbl_b1, SLOT_MIX);
3942 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3943 				  tbl_b4, SLOT_MIX);
3944 			break;
3945 		default:
3946 			break;
3947 		}
3948 		break;
3949 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
3950 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3951 		*t = t_def[CXTD_PAUTO2];
3952 
3953 		switch (policy_type) {
3954 		case BTC_CXP_PAUTO2_TD3050:
3955 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
3956 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3957 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
3958 			break;
3959 		case BTC_CXP_PAUTO2_TD3070:
3960 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
3961 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3962 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
3963 			break;
3964 		case BTC_CXP_PAUTO2_TD5050:
3965 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
3966 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3967 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
3968 			break;
3969 		case BTC_CXP_PAUTO2_TD6060:
3970 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
3971 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3972 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
3973 			break;
3974 		case BTC_CXP_PAUTO2_TD2080:
3975 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
3976 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3977 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
3978 			break;
3979 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
3980 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3981 				  tbl_w1, SLOT_ISO);
3982 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3983 				  tbl_b1, SLOT_MIX);
3984 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3985 				  tbl_b4, SLOT_MIX);
3986 			break;
3987 		default:
3988 			break;
3989 		}
3990 		break;
3991 	}
3992 
3993 	if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
3994 		null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
3995 			    FIELD_PREP(0xf0, dm->wl_scc.null_role2);
3996 		_tdma_set_flctrl_role(btc, null_role);
3997 	}
3998 
3999 	/* enter leak_slot after each null-1 */
4000 	if (dm->leak_ap && dm->tdma.leak_n > 1)
4001 		_tdma_set_lek(btc, 1);
4002 
4003 	if (dm->tdma_instant_excute) {
4004 		btc->dm.tdma.option_ctrl |= BIT(0);
4005 		btc->update_policy_force = true;
4006 	}
4007 }
4008 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
4009 
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)4010 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
4011 			 u8 tx_val, u8 rx_val)
4012 {
4013 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
4014 	struct rtw89_mac_ax_plt plt;
4015 
4016 	plt.tx = tx_val;
4017 	plt.rx = rx_val;
4018 
4019 	if (rtwdev->btc.ver->fwlrole == 8) {
4020 		plt.band = wl->pta_req_mac;
4021 		if (wl->bt_polut_type[plt.band] == tx_val)
4022 			return;
4023 
4024 		wl->bt_polut_type[plt.band] = tx_val;
4025 		rtw89_mac_cfg_plt(rtwdev, &plt);
4026 	} else {
4027 		plt.band = RTW89_MAC_0;
4028 
4029 		if (phy_map & BTC_PHY_0)
4030 			rtw89_mac_cfg_plt(rtwdev, &plt);
4031 
4032 		if (!rtwdev->dbcc_en)
4033 			return;
4034 
4035 		plt.band = RTW89_MAC_1;
4036 		if (phy_map & BTC_PHY_1)
4037 			rtw89_mac_cfg_plt(rtwdev, &plt);
4038 	}
4039 }
4040 
_set_ant_v0(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4041 static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
4042 			u8 phy_map, u8 type)
4043 {
4044 	struct rtw89_btc *btc = &rtwdev->btc;
4045 	struct rtw89_btc_dm *dm = &btc->dm;
4046 	struct rtw89_btc_cx *cx = &btc->cx;
4047 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4048 	struct rtw89_btc_bt_info *bt = &cx->bt;
4049 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4050 	u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
4051 	bool dbcc_chg = false;
4052 	u32 ant_path_type;
4053 
4054 	ant_path_type = ((phy_map << 8) + type);
4055 
4056 	if (btc->ver->fwlrole == 1)
4057 		dbcc_chg = wl->role_info_v1.dbcc_chg;
4058 	else if (btc->ver->fwlrole == 2)
4059 		dbcc_chg = wl->role_info_v2.dbcc_chg;
4060 	else if (btc->ver->fwlrole == 8)
4061 		dbcc_chg = wl->role_info_v8.dbcc_chg;
4062 
4063 	if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4064 	    btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4065 	    btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
4066 		force_exec = FC_EXEC;
4067 
4068 	if (!force_exec && ant_path_type == dm->set_ant_path) {
4069 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4070 			    "[BTC], %s(): return by no change!!\n",
4071 			     __func__);
4072 		return;
4073 	} else if (bt->rfk_info.map.run) {
4074 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4075 			    "[BTC], %s(): return by bt rfk!!\n", __func__);
4076 		return;
4077 	} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4078 		   wl->rfk_info.state != BTC_WRFK_STOP) {
4079 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4080 			    "[BTC], %s(): return by wl rfk!!\n", __func__);
4081 		return;
4082 	}
4083 
4084 	dm->set_ant_path = ant_path_type;
4085 
4086 	rtw89_debug(rtwdev,
4087 		    RTW89_DBG_BTC,
4088 		    "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4089 		    __func__, phy_map, dm->set_ant_path & 0xff);
4090 
4091 	switch (type) {
4092 	case BTC_ANT_WPOWERON:
4093 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4094 		break;
4095 	case BTC_ANT_WINIT:
4096 		if (bt->enable.now)
4097 			_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4098 		else
4099 			_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4100 
4101 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4102 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
4103 		break;
4104 	case BTC_ANT_WONLY:
4105 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4106 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4107 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4108 		break;
4109 	case BTC_ANT_WOFF:
4110 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4111 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4112 		break;
4113 	case BTC_ANT_W2G:
4114 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4115 		if (rtwdev->dbcc_en) {
4116 			for (i = 0; i < RTW89_PHY_MAX; i++) {
4117 				b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
4118 
4119 				gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4120 				gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4121 				/* BT should control by GNT_BT if WL_2G at S0 */
4122 				if (i == 1 &&
4123 				    wl_dinfo->real_band[0] == RTW89_BAND_2G &&
4124 				    wl_dinfo->real_band[1] == RTW89_BAND_5G)
4125 					gnt_bt_ctrl = BTC_GNT_HW;
4126 				_set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
4127 				plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
4128 				_set_bt_plut(rtwdev, BIT(i),
4129 					     plt_ctrl, plt_ctrl);
4130 			}
4131 		} else {
4132 			_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4133 			_set_bt_plut(rtwdev, BTC_PHY_ALL,
4134 				     BTC_PLT_BT, BTC_PLT_BT);
4135 		}
4136 		break;
4137 	case BTC_ANT_W5G:
4138 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4139 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
4140 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4141 		break;
4142 	case BTC_ANT_W25G:
4143 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4144 		_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4145 		_set_bt_plut(rtwdev, BTC_PHY_ALL,
4146 			     BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4147 		break;
4148 	case BTC_ANT_FREERUN:
4149 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4150 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
4151 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4152 		break;
4153 	case BTC_ANT_WRFK:
4154 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4155 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4156 		_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4157 		break;
4158 	case BTC_ANT_BRFK:
4159 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4160 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4161 		_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4162 		break;
4163 	default:
4164 		break;
4165 	}
4166 }
4167 
_set_ant_v1(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4168 static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
4169 			u8 phy_map, u8 type)
4170 {
4171 	struct rtw89_btc *btc = &rtwdev->btc;
4172 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4173 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4174 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
4175 	u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
4176 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4177 	struct rtw89_btc_dm *dm = &btc->dm;
4178 	u8 gwl = BTC_GNT_HW;
4179 
4180 	if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4181 	    btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4182 	    btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
4183 		force_exec = FC_EXEC;
4184 
4185 	if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
4186 	    btc->dm.wl_btg_rx == 2)
4187 		force_exec = FC_EXEC;
4188 
4189 	if (!force_exec && ant_path_type == dm->set_ant_path) {
4190 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4191 			    "[BTC], %s(): return by no change!!\n",
4192 			     __func__);
4193 		return;
4194 	} else if (bt->rfk_info.map.run) {
4195 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4196 			    "[BTC], %s(): return by bt rfk!!\n", __func__);
4197 		return;
4198 	} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4199 		   wl->rfk_info.state != BTC_WRFK_STOP) {
4200 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4201 			    "[BTC], %s(): return by wl rfk!!\n", __func__);
4202 		return;
4203 	}
4204 
4205 	dm->set_ant_path = ant_path_type;
4206 
4207 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
4208 		    "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4209 		    __func__, phy_map, dm->set_ant_path & 0xff);
4210 
4211 	switch (type) {
4212 	case BTC_ANT_WINIT:
4213 		/* To avoid BT MP driver case (bt_enable but no mailbox) */
4214 		if (bt->enable.now && bt->run_patch_code)
4215 			_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4216 				    BTC_WLACT_SW_LO);
4217 		else
4218 			_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4219 				    BTC_WLACT_SW_HI);
4220 		break;
4221 	case BTC_ANT_WONLY:
4222 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4223 			    BTC_WLACT_SW_HI);
4224 		break;
4225 	case BTC_ANT_WOFF:
4226 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4227 			    BTC_WLACT_SW_LO);
4228 		break;
4229 	case BTC_ANT_W2G:
4230 	case BTC_ANT_W25G:
4231 		if (wl_rinfo->dbcc_en) {
4232 			if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
4233 				gwl = BTC_GNT_HW;
4234 			else
4235 				gwl = BTC_GNT_SW_HI;
4236 			_set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4237 
4238 			if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
4239 				gwl = BTC_GNT_HW;
4240 			else
4241 				gwl = BTC_GNT_SW_HI;
4242 			_set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4243 		} else {
4244 			gwl = BTC_GNT_HW;
4245 			_set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4246 		}
4247 		break;
4248 	case BTC_ANT_W5G:
4249 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
4250 		break;
4251 	case BTC_ANT_FREERUN:
4252 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
4253 			    BTC_WLACT_SW_LO);
4254 		break;
4255 	case BTC_ANT_WRFK:
4256 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4257 			    BTC_WLACT_HW);
4258 		break;
4259 	case BTC_ANT_WRFK2:
4260 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4261 			    BTC_WLACT_SW_HI); /* no BT-Tx */
4262 		break;
4263 	default:
4264 		return;
4265 	}
4266 
4267 	_set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4268 }
4269 
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4270 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
4271 		     u8 phy_map, u8 type)
4272 {
4273 	if (rtwdev->chip->chip_id == RTL8922A)
4274 		_set_ant_v1(rtwdev, force_exec, phy_map, type);
4275 	else
4276 		_set_ant_v0(rtwdev, force_exec, phy_map, type);
4277 }
4278 
_action_wl_only(struct rtw89_dev * rtwdev)4279 static void _action_wl_only(struct rtw89_dev *rtwdev)
4280 {
4281 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4282 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
4283 }
4284 
_action_wl_init(struct rtw89_dev * rtwdev)4285 static void _action_wl_init(struct rtw89_dev *rtwdev)
4286 {
4287 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4288 
4289 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
4290 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
4291 }
4292 
_action_wl_off(struct rtw89_dev * rtwdev,u8 mode)4293 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
4294 {
4295 	struct rtw89_btc *btc = &rtwdev->btc;
4296 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4297 
4298 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4299 
4300 	if (wl->status.map.rf_off || btc->dm.bt_only) {
4301 		_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
4302 	} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4303 		if (mode == BTC_WLINK_5G)
4304 			_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4305 		else
4306 			_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4307 	}
4308 
4309 	if (mode == BTC_WLINK_5G) {
4310 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
4311 	} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4312 		if (btc->cx.bt.link_info.a2dp_desc.active)
4313 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4314 		else
4315 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF);
4316 	} else {
4317 		_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4318 	}
4319 }
4320 
_action_freerun(struct rtw89_dev * rtwdev)4321 static void _action_freerun(struct rtw89_dev *rtwdev)
4322 {
4323 	struct rtw89_btc *btc = &rtwdev->btc;
4324 
4325 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4326 
4327 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
4328 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
4329 
4330 	btc->dm.freerun = true;
4331 }
4332 
_action_bt_whql(struct rtw89_dev * rtwdev)4333 static void _action_bt_whql(struct rtw89_dev *rtwdev)
4334 {
4335 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4336 
4337 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4338 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
4339 }
4340 
_action_bt_off(struct rtw89_dev * rtwdev)4341 static void _action_bt_off(struct rtw89_dev *rtwdev)
4342 {
4343 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4344 
4345 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4346 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
4347 }
4348 
_action_bt_idle(struct rtw89_dev * rtwdev)4349 static void _action_bt_idle(struct rtw89_dev *rtwdev)
4350 {
4351 	struct rtw89_btc *btc = &rtwdev->btc;
4352 	struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
4353 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4354 
4355 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4356 
4357 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4358 		switch (btc->cx.state_map) {
4359 		case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
4360 		case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
4361 			if (b->status.map.connect)
4362 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
4363 			else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
4364 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
4365 			else
4366 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
4367 			break;
4368 		case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
4369 			_set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
4370 				    BTC_ACT_BT_IDLE);
4371 			break;
4372 		case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
4373 			_set_policy(rtwdev, BTC_CXP_FIX_TD5050,
4374 				    BTC_ACT_BT_IDLE);
4375 			break;
4376 		case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
4377 			_set_policy(rtwdev, BTC_CXP_FIX_TD7010,
4378 				    BTC_ACT_BT_IDLE);
4379 			break;
4380 		case BTC_WIDLE:  /* wl-idle + bt-idle */
4381 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
4382 			break;
4383 		}
4384 	} else { /* dedicated-antenna */
4385 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
4386 	}
4387 }
4388 
_action_bt_hfp(struct rtw89_dev * rtwdev)4389 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
4390 {
4391 	struct rtw89_btc *btc = &rtwdev->btc;
4392 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4393 
4394 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4395 
4396 	if (btc->ant_type == BTC_ANT_SHARED) {
4397 		if (btc->cx.wl.status.map._4way) {
4398 			_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
4399 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4400 			btc->cx.bt.scan_rx_low_pri = true;
4401 			_set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
4402 		} else {
4403 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4404 		}
4405 	} else {
4406 		if (wl->bg_mode)
4407 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4408 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4409 			_set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
4410 		else
4411 			_set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
4412 	}
4413 }
4414 
_action_bt_hid(struct rtw89_dev * rtwdev)4415 static void _action_bt_hid(struct rtw89_dev *rtwdev)
4416 {
4417 	const struct rtw89_chip_info *chip = rtwdev->chip;
4418 	struct rtw89_btc *btc = &rtwdev->btc;
4419 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4420 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4421 	struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
4422 	u16 policy_type = BTC_CXP_OFF_BT;
4423 
4424 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4425 
4426 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4427 		if (wl->status.map._4way) {
4428 			policy_type = BTC_CXP_OFF_WL;
4429 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4430 			btc->cx.bt.scan_rx_low_pri = true;
4431 			if (hid->type & BTC_HID_BLE)
4432 				policy_type = BTC_CXP_OFF_BWB0;
4433 			else
4434 				policy_type = BTC_CXP_OFF_BWB2;
4435 		} else if (hid->type == BTC_HID_218) {
4436 			bt->scan_rx_low_pri = true;
4437 			policy_type = BTC_CXP_OFF_BWB2;
4438 		} else if (chip->para_ver == 0x1) {
4439 			policy_type = BTC_CXP_OFF_BWB3;
4440 		} else {
4441 			policy_type = BTC_CXP_OFF_BWB1;
4442 		}
4443 	} else { /* dedicated-antenna */
4444 		if (wl->bg_mode)
4445 			policy_type = BTC_CXP_OFF_BWB1;
4446 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4447 			policy_type = BTC_CXP_OFF_EQ4;
4448 		else
4449 			policy_type = BTC_CXP_OFF_EQ3;
4450 	}
4451 
4452 	_set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
4453 }
4454 
_action_bt_a2dp(struct rtw89_dev * rtwdev)4455 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
4456 {
4457 	struct rtw89_btc *btc = &rtwdev->btc;
4458 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4459 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4460 	struct rtw89_btc_dm *dm = &btc->dm;
4461 
4462 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4463 
4464 	switch (btc->cx.state_map) {
4465 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
4466 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4467 			dm->slot_dur[CXST_W1] = 40;
4468 			dm->slot_dur[CXST_B1] = 200;
4469 			_set_policy(rtwdev,
4470 				    BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
4471 		} else {
4472 			_set_policy(rtwdev,
4473 				    BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
4474 		}
4475 		break;
4476 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
4477 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
4478 		break;
4479 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
4480 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
4481 		break;
4482 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
4483 	case BTC_WLINKING: /* wl-connecting + bt-A2DP */
4484 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4485 			dm->slot_dur[CXST_W1] = 40;
4486 			dm->slot_dur[CXST_B1] = 200;
4487 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
4488 				    BTC_ACT_BT_A2DP);
4489 		} else {
4490 			_set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
4491 				    BTC_ACT_BT_A2DP);
4492 		}
4493 		break;
4494 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
4495 		_set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
4496 		break;
4497 	}
4498 }
4499 
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)4500 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
4501 {
4502 	struct rtw89_btc *btc = &rtwdev->btc;
4503 
4504 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4505 
4506 	switch (btc->cx.state_map) {
4507 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
4508 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
4509 		break;
4510 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
4511 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
4512 		break;
4513 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
4514 		_set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
4515 		break;
4516 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
4517 		_set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
4518 		break;
4519 	case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
4520 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
4521 		break;
4522 	case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
4523 		_set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
4524 		break;
4525 	}
4526 }
4527 
_action_bt_pan(struct rtw89_dev * rtwdev)4528 static void _action_bt_pan(struct rtw89_dev *rtwdev)
4529 {
4530 	struct rtw89_btc *btc = &rtwdev->btc;
4531 
4532 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4533 
4534 	switch (btc->cx.state_map) {
4535 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
4536 		_set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
4537 		break;
4538 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
4539 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
4540 		break;
4541 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
4542 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
4543 		break;
4544 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
4545 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
4546 		break;
4547 	case BTC_WLINKING: /* wl-connecting + bt-PAN */
4548 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
4549 		break;
4550 	case BTC_WIDLE: /* wl-idle + bt-pan */
4551 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
4552 		break;
4553 	}
4554 }
4555 
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)4556 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
4557 {
4558 	struct rtw89_btc *btc = &rtwdev->btc;
4559 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4560 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4561 	struct rtw89_btc_dm *dm = &btc->dm;
4562 
4563 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4564 
4565 	switch (btc->cx.state_map) {
4566 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
4567 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
4568 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4569 			dm->slot_dur[CXST_W1] = 40;
4570 			dm->slot_dur[CXST_B1] = 200;
4571 			_set_policy(rtwdev,
4572 				    BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
4573 		} else {
4574 			_set_policy(rtwdev,
4575 				    BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
4576 		}
4577 		break;
4578 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
4579 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
4580 		break;
4581 
4582 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
4583 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
4584 		break;
4585 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
4586 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
4587 		if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4588 			dm->slot_dur[CXST_W1] = 40;
4589 			dm->slot_dur[CXST_B1] = 200;
4590 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
4591 				    BTC_ACT_BT_A2DP_HID);
4592 		} else {
4593 			_set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
4594 				    BTC_ACT_BT_A2DP_HID);
4595 		}
4596 		break;
4597 	}
4598 }
4599 
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)4600 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
4601 {
4602 	struct rtw89_btc *btc = &rtwdev->btc;
4603 
4604 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4605 
4606 	switch (btc->cx.state_map) {
4607 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
4608 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
4609 		break;
4610 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
4611 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
4612 		break;
4613 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
4614 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
4615 		break;
4616 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
4617 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
4618 		break;
4619 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
4620 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
4621 		break;
4622 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN */
4623 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
4624 		break;
4625 	}
4626 }
4627 
_action_bt_pan_hid(struct rtw89_dev * rtwdev)4628 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
4629 {
4630 	struct rtw89_btc *btc = &rtwdev->btc;
4631 
4632 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4633 
4634 	switch (btc->cx.state_map) {
4635 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
4636 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
4637 		break;
4638 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
4639 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
4640 		break;
4641 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
4642 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
4643 		break;
4644 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
4645 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
4646 		break;
4647 	case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
4648 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
4649 		break;
4650 	case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
4651 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
4652 		break;
4653 	}
4654 }
4655 
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)4656 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
4657 {
4658 	struct rtw89_btc *btc = &rtwdev->btc;
4659 
4660 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4661 
4662 	switch (btc->cx.state_map) {
4663 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
4664 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
4665 			    BTC_ACT_BT_A2DP_PAN_HID);
4666 		break;
4667 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
4668 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
4669 			    BTC_ACT_BT_A2DP_PAN_HID);
4670 		break;
4671 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
4672 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
4673 			    BTC_ACT_BT_A2DP_PAN_HID);
4674 		break;
4675 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
4676 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
4677 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
4678 			    BTC_ACT_BT_A2DP_PAN_HID);
4679 		break;
4680 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN+HID */
4681 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
4682 			    BTC_ACT_BT_A2DP_PAN_HID);
4683 		break;
4684 	}
4685 }
4686 
_action_wl_5g(struct rtw89_dev * rtwdev)4687 static void _action_wl_5g(struct rtw89_dev *rtwdev)
4688 {
4689 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4690 	_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
4691 }
4692 
_action_wl_other(struct rtw89_dev * rtwdev)4693 static void _action_wl_other(struct rtw89_dev *rtwdev)
4694 {
4695 	struct rtw89_btc *btc = &rtwdev->btc;
4696 
4697 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4698 
4699 	if (btc->ant_type == BTC_ANT_SHARED)
4700 		_set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
4701 	else
4702 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
4703 }
4704 
_action_wl_nc(struct rtw89_dev * rtwdev)4705 static void _action_wl_nc(struct rtw89_dev *rtwdev)
4706 {
4707 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4708 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
4709 }
4710 
_action_wl_rfk(struct rtw89_dev * rtwdev)4711 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
4712 {
4713 	struct rtw89_btc *btc = &rtwdev->btc;
4714 	struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
4715 
4716 	if (rfk.state != BTC_WRFK_START)
4717 		return;
4718 
4719 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
4720 		    __func__, rfk.band);
4721 
4722 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
4723 	_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
4724 }
4725 
_set_btg_ctrl(struct rtw89_dev * rtwdev)4726 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
4727 {
4728 	struct rtw89_btc *btc = &rtwdev->btc;
4729 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4730 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4731 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
4732 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
4733 	struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info;
4734 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4735 	const struct rtw89_chip_info *chip = rtwdev->chip;
4736 	const struct rtw89_btc_ver *ver = btc->ver;
4737 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4738 	struct rtw89_btc_dm *dm = &btc->dm;
4739 	struct _wl_rinfo_now wl_rinfo;
4740 	u32 run_reason = btc->dm.run_reason;
4741 	u32 is_btg;
4742 	u8 i, val;
4743 
4744 	if (btc->manual_ctrl)
4745 		return;
4746 
4747 	if (ver->fwlrole == 0)
4748 		wl_rinfo.link_mode = wl_rinfo_v0->link_mode;
4749 	else if (ver->fwlrole == 1)
4750 		wl_rinfo.link_mode = wl_rinfo_v1->link_mode;
4751 	else if (ver->fwlrole == 2)
4752 		wl_rinfo.link_mode = wl_rinfo_v2->link_mode;
4753 	else if (ver->fwlrole == 8)
4754 		wl_rinfo.link_mode = wl_rinfo_v8->link_mode;
4755 	else
4756 		return;
4757 
4758 	if (rtwdev->dbcc_en) {
4759 		if (ver->fwlrole == 0) {
4760 			for (i = 0; i < RTW89_PHY_MAX; i++) {
4761 				if (wl_dinfo->real_band[i] == RTW89_BAND_2G)
4762 					wl_rinfo.dbcc_2g_phy = i;
4763 			}
4764 		} else if (ver->fwlrole == 1) {
4765 			wl_rinfo.dbcc_2g_phy = wl_rinfo_v1->dbcc_2g_phy;
4766 		} else if (ver->fwlrole == 2) {
4767 			wl_rinfo.dbcc_2g_phy = wl_rinfo_v2->dbcc_2g_phy;
4768 		} else if (ver->fwlrole == 8) {
4769 			wl_rinfo.dbcc_2g_phy = wl_rinfo_v8->dbcc_2g_phy;
4770 		} else {
4771 			return;
4772 		}
4773 	}
4774 
4775 	if (wl_rinfo.link_mode == BTC_WLINK_25G_MCC)
4776 		is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
4777 	else if (!(bt->run_patch_code && bt->enable.now))
4778 		is_btg = BTC_BTGCTRL_DISABLE;
4779 	else if (wl_rinfo.link_mode == BTC_WLINK_5G)
4780 		is_btg = BTC_BTGCTRL_DISABLE;
4781 	else if (dm->freerun)
4782 		is_btg = BTC_BTGCTRL_DISABLE;
4783 	else if (rtwdev->dbcc_en && wl_rinfo.dbcc_2g_phy != RTW89_PHY_1)
4784 		is_btg = BTC_BTGCTRL_DISABLE;
4785 	else
4786 		is_btg = BTC_BTGCTRL_ENABLE;
4787 
4788 	if (dm->wl_btg_rx_rb != dm->wl_btg_rx &&
4789 	    dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) {
4790 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX, &val);
4791 		dm->wl_btg_rx_rb = val;
4792 	}
4793 
4794 	if (run_reason == BTC_RSN_NTFY_INIT ||
4795 	    run_reason == BTC_RSN_NTFY_SWBAND ||
4796 	    dm->wl_btg_rx_rb != dm->wl_btg_rx ||
4797 	    is_btg != dm->wl_btg_rx) {
4798 
4799 		dm->wl_btg_rx = is_btg;
4800 
4801 		if (is_btg > BTC_BTGCTRL_ENABLE)
4802 			return;
4803 
4804 		chip->ops->ctrl_btg_bt_rx(rtwdev, is_btg, RTW89_PHY_0);
4805 	}
4806 }
4807 
_set_wl_preagc_ctrl(struct rtw89_dev * rtwdev)4808 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
4809 {
4810 	struct rtw89_btc *btc = &rtwdev->btc;
4811 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4812 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4813 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
4814 	const struct rtw89_chip_info *chip = rtwdev->chip;
4815 	const struct rtw89_btc_ver *ver = btc->ver;
4816 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4817 	struct rtw89_btc_dm *dm = &btc->dm;
4818 	u8 is_preagc, val;
4819 
4820 	if (btc->manual_ctrl)
4821 		return;
4822 
4823 	if (wl_rinfo->link_mode == BTC_WLINK_25G_MCC)
4824 		is_preagc = BTC_PREAGC_BB_FWCTRL;
4825 	else if (!(bt->run_patch_code && bt->enable.now))
4826 		is_preagc = BTC_PREAGC_DISABLE;
4827 	else if (wl_rinfo->link_mode == BTC_WLINK_5G)
4828 		is_preagc = BTC_PREAGC_DISABLE;
4829 	else if (wl_rinfo->link_mode == BTC_WLINK_NOLINK ||
4830 		 btc->cx.bt.link_info.profile_cnt.now == 0)
4831 		is_preagc = BTC_PREAGC_DISABLE;
4832 	else if (dm->tdma_now.type != CXTDMA_OFF &&
4833 		 !bt_linfo->hfp_desc.exist &&
4834 		 !bt_linfo->hid_desc.exist &&
4835 		 dm->fddt_train == BTC_FDDT_DISABLE)
4836 		is_preagc = BTC_PREAGC_DISABLE;
4837 	else if (ver->fwlrole == 2 && wl_rinfo->dbcc_en &&
4838 		 wl_rinfo->dbcc_2g_phy != RTW89_PHY_1)
4839 		is_preagc = BTC_PREAGC_DISABLE;
4840 	else if (btc->ant_type == BTC_ANT_SHARED)
4841 		is_preagc = BTC_PREAGC_DISABLE;
4842 	else
4843 		is_preagc = BTC_PREAGC_ENABLE;
4844 
4845 	if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
4846 	    dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
4847 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
4848 		dm->wl_pre_agc_rb = val;
4849 	}
4850 
4851 	if ((wl->coex_mode == BTC_MODE_NORMAL &&
4852 	     (dm->run_reason == BTC_RSN_NTFY_INIT ||
4853 	      dm->run_reason == BTC_RSN_NTFY_SWBAND ||
4854 	      dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
4855 	    is_preagc != dm->wl_pre_agc) {
4856 		dm->wl_pre_agc = is_preagc;
4857 
4858 		if (is_preagc > BTC_PREAGC_ENABLE)
4859 			return;
4860 		chip->ops->ctrl_nbtg_bt_tx(rtwdev, dm->wl_pre_agc, RTW89_PHY_0);
4861 	}
4862 }
4863 
4864 struct rtw89_txtime_data {
4865 	struct rtw89_dev *rtwdev;
4866 	int type;
4867 	u32 tx_time;
4868 	u8 tx_retry;
4869 	u16 enable;
4870 	bool reenable;
4871 };
4872 
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)4873 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
4874 {
4875 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
4876 	struct rtw89_txtime_data *iter_data =
4877 				(struct rtw89_txtime_data *)data;
4878 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
4879 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
4880 	struct rtw89_btc *btc = &rtwdev->btc;
4881 	struct rtw89_btc_cx *cx = &btc->cx;
4882 	struct rtw89_btc_wl_info *wl = &cx->wl;
4883 	struct rtw89_btc_wl_link_info *plink = NULL;
4884 	u8 port = rtwvif->port;
4885 	u32 tx_time = iter_data->tx_time;
4886 	u8 tx_retry = iter_data->tx_retry;
4887 	u16 enable = iter_data->enable;
4888 	bool reenable = iter_data->reenable;
4889 
4890 	if (btc->ver->fwlrole == 8)
4891 		plink = &wl->rlink_info[port][0];
4892 	else
4893 		plink = &wl->link_info[port];
4894 
4895 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
4896 		    "[BTC], %s(): port = %d\n", __func__, port);
4897 
4898 	if (!plink->connected) {
4899 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4900 			    "[BTC], %s(): connected = %d\n",
4901 			    __func__, plink->connected);
4902 		return;
4903 	}
4904 
4905 	/* backup the original tx time before tx-limit on */
4906 	if (reenable) {
4907 		rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time);
4908 		rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry);
4909 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4910 			    "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
4911 			    __func__, plink->tx_time, plink->tx_retry);
4912 	}
4913 
4914 	/* restore the original tx time if no tx-limit */
4915 	if (!enable) {
4916 		rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time);
4917 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true,
4918 					     plink->tx_retry);
4919 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4920 			    "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
4921 			    __func__, plink->tx_time, plink->tx_retry);
4922 
4923 	} else {
4924 		rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time);
4925 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry);
4926 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4927 			    "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
4928 			    __func__, tx_time, tx_retry);
4929 	}
4930 }
4931 
_set_wl_tx_limit(struct rtw89_dev * rtwdev)4932 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
4933 {
4934 	struct rtw89_btc *btc = &rtwdev->btc;
4935 	const struct rtw89_btc_ver *ver = btc->ver;
4936 	struct rtw89_btc_cx *cx = &btc->cx;
4937 	struct rtw89_btc_dm *dm = &btc->dm;
4938 	struct rtw89_btc_wl_info *wl = &cx->wl;
4939 	struct rtw89_btc_bt_info *bt = &cx->bt;
4940 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
4941 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4942 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4943 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4944 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4945 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
4946 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
4947 	struct rtw89_txtime_data data = {.rtwdev = rtwdev};
4948 	u8 mode, igno_bt, tx_retry;
4949 	u32 tx_time;
4950 	u16 enable;
4951 	bool reenable = false;
4952 
4953 	if (btc->manual_ctrl)
4954 		return;
4955 
4956 	if (ver->fwlrole == 0)
4957 		mode = wl_rinfo->link_mode;
4958 	else if (ver->fwlrole == 1)
4959 		mode = wl_rinfo_v1->link_mode;
4960 	else if (ver->fwlrole == 2)
4961 		mode = wl_rinfo_v2->link_mode;
4962 	else if (ver->fwlrole == 8)
4963 		mode = wl_rinfo_v8->link_mode;
4964 	else
4965 		return;
4966 
4967 	if (ver->fcxctrl == 7)
4968 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
4969 	else
4970 		igno_bt = btc->ctrl.ctrl.igno_bt;
4971 
4972 	if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 ||
4973 	    mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
4974 		enable = 0;
4975 		tx_time = BTC_MAX_TX_TIME_DEF;
4976 		tx_retry = BTC_MAX_TX_RETRY_DEF;
4977 	} else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
4978 		enable = 1;
4979 		tx_time = BTC_MAX_TX_TIME_L2;
4980 		tx_retry = BTC_MAX_TX_RETRY_L1;
4981 	} else if (hfp->exist || hid->exist) {
4982 		enable = 1;
4983 		tx_time = BTC_MAX_TX_TIME_L3;
4984 		tx_retry = BTC_MAX_TX_RETRY_L1;
4985 	} else {
4986 		enable = 0;
4987 		tx_time = BTC_MAX_TX_TIME_DEF;
4988 		tx_retry = BTC_MAX_TX_RETRY_DEF;
4989 	}
4990 
4991 	if (dm->wl_tx_limit.enable == enable &&
4992 	    dm->wl_tx_limit.tx_time == tx_time &&
4993 	    dm->wl_tx_limit.tx_retry == tx_retry)
4994 		return;
4995 
4996 	if (!dm->wl_tx_limit.enable && enable)
4997 		reenable = true;
4998 
4999 	dm->wl_tx_limit.enable = enable;
5000 	dm->wl_tx_limit.tx_time = tx_time;
5001 	dm->wl_tx_limit.tx_retry = tx_retry;
5002 
5003 	data.enable = enable;
5004 	data.tx_time = tx_time;
5005 	data.tx_retry = tx_retry;
5006 	data.reenable = reenable;
5007 
5008 	ieee80211_iterate_stations_atomic(rtwdev->hw,
5009 					  rtw89_tx_time_iter,
5010 					  &data);
5011 }
5012 
_set_bt_rx_agc(struct rtw89_dev * rtwdev)5013 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
5014 {
5015 	struct rtw89_btc *btc = &rtwdev->btc;
5016 	const struct rtw89_btc_ver *ver = btc->ver;
5017 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5018 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5019 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5020 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5021 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5022 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5023 	bool bt_hi_lna_rx = false;
5024 	u8 mode;
5025 
5026 	if (ver->fwlrole == 0)
5027 		mode = wl_rinfo->link_mode;
5028 	else if (ver->fwlrole == 1)
5029 		mode = wl_rinfo_v1->link_mode;
5030 	else if (ver->fwlrole == 2)
5031 		mode = wl_rinfo_v2->link_mode;
5032 	else if (ver->fwlrole == 8)
5033 		mode = wl_rinfo_v8->link_mode;
5034 	else
5035 		return;
5036 
5037 	if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
5038 		bt_hi_lna_rx = true;
5039 
5040 	if (bt_hi_lna_rx == bt->hi_lna_rx)
5041 		return;
5042 
5043 	_write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
5044 }
5045 
_set_bt_rx_scan_pri(struct rtw89_dev * rtwdev)5046 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
5047 {
5048 	struct rtw89_btc *btc = &rtwdev->btc;
5049 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5050 
5051 	_write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
5052 }
5053 
_action_common(struct rtw89_dev * rtwdev)5054 static void _action_common(struct rtw89_dev *rtwdev)
5055 {
5056 	struct rtw89_btc *btc = &rtwdev->btc;
5057 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5058 	struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
5059 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5060 	struct rtw89_btc_dm *dm = &btc->dm;
5061 	u32 bt_rom_code_id, bt_fw_ver;
5062 
5063 	_set_btg_ctrl(rtwdev);
5064 	_set_wl_preagc_ctrl(rtwdev);
5065 	_set_wl_tx_limit(rtwdev);
5066 	_set_bt_afh_info(rtwdev);
5067 	_set_bt_rx_agc(rtwdev);
5068 	_set_rf_trx_para(rtwdev);
5069 	_set_bt_rx_scan_pri(rtwdev);
5070 
5071 	bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
5072 	bt_fw_ver = bt->ver_info.fw & 0xffff;
5073 	if (bt->enable.now &&
5074 	    (bt_fw_ver == 0 ||
5075 	     (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd)))
5076 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1);
5077 	else
5078 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0);
5079 
5080 	if (dm->run_reason == BTC_RSN_NTFY_INIT ||
5081 	    dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5082 	    dm->run_reason == BTC_RSN_NTFY_POWEROFF) {
5083 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5084 
5085 		if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF)
5086 			rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
5087 		else
5088 			rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
5089 	}
5090 
5091 	if (wl->scbd_change) {
5092 		rtw89_mac_cfg_sb(rtwdev, wl->scbd);
5093 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
5094 			    wl->scbd);
5095 		wl->scbd_change = false;
5096 		btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
5097 	}
5098 	btc->dm.tdma_instant_excute = 0;
5099 }
5100 
_action_by_bt(struct rtw89_dev * rtwdev)5101 static void _action_by_bt(struct rtw89_dev *rtwdev)
5102 {
5103 	struct rtw89_btc *btc = &rtwdev->btc;
5104 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5105 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5106 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5107 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5108 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5109 	u8 profile_map = 0;
5110 
5111 	if (bt_linfo->hfp_desc.exist)
5112 		profile_map |= BTC_BT_HFP;
5113 
5114 	if (bt_linfo->hid_desc.exist)
5115 		profile_map |= BTC_BT_HID;
5116 
5117 	if (bt_linfo->a2dp_desc.exist)
5118 		profile_map |= BTC_BT_A2DP;
5119 
5120 	if (bt_linfo->pan_desc.exist)
5121 		profile_map |= BTC_BT_PAN;
5122 
5123 	switch (profile_map) {
5124 	case BTC_BT_NOPROFILE:
5125 		if (_check_freerun(rtwdev))
5126 			_action_freerun(rtwdev);
5127 		else if (pan.active)
5128 			_action_bt_pan(rtwdev);
5129 		else
5130 			_action_bt_idle(rtwdev);
5131 		break;
5132 	case BTC_BT_HFP:
5133 		if (_check_freerun(rtwdev))
5134 			_action_freerun(rtwdev);
5135 		else
5136 			_action_bt_hfp(rtwdev);
5137 		break;
5138 	case BTC_BT_HFP | BTC_BT_HID:
5139 	case BTC_BT_HID:
5140 		if (_check_freerun(rtwdev))
5141 			_action_freerun(rtwdev);
5142 		else
5143 			_action_bt_hid(rtwdev);
5144 		break;
5145 	case BTC_BT_A2DP:
5146 		if (_check_freerun(rtwdev))
5147 			_action_freerun(rtwdev);
5148 		else if (a2dp.sink)
5149 			_action_bt_a2dpsink(rtwdev);
5150 		else if (bt_linfo->multi_link.now && !hid.pair_cnt)
5151 			_action_bt_a2dp_pan(rtwdev);
5152 		else
5153 			_action_bt_a2dp(rtwdev);
5154 		break;
5155 	case BTC_BT_PAN:
5156 		_action_bt_pan(rtwdev);
5157 		break;
5158 	case BTC_BT_A2DP | BTC_BT_HFP:
5159 	case BTC_BT_A2DP | BTC_BT_HID:
5160 	case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
5161 		if (_check_freerun(rtwdev))
5162 			_action_freerun(rtwdev);
5163 		else
5164 			_action_bt_a2dp_hid(rtwdev);
5165 		break;
5166 	case BTC_BT_A2DP | BTC_BT_PAN:
5167 		_action_bt_a2dp_pan(rtwdev);
5168 		break;
5169 	case BTC_BT_PAN | BTC_BT_HFP:
5170 	case BTC_BT_PAN | BTC_BT_HID:
5171 	case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
5172 		_action_bt_pan_hid(rtwdev);
5173 		break;
5174 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
5175 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
5176 	default:
5177 		_action_bt_a2dp_pan_hid(rtwdev);
5178 		break;
5179 	}
5180 }
5181 
_action_wl_2g_sta(struct rtw89_dev * rtwdev)5182 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
5183 {
5184 	_action_by_bt(rtwdev);
5185 }
5186 
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)5187 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
5188 {
5189 	struct rtw89_btc *btc = &rtwdev->btc;
5190 	u16 policy_type = BTC_CXP_OFF_BT;
5191 
5192 	if (btc->ant_type == BTC_ANT_SHARED) {
5193 		if (btc->cx.wl.status.map._4way)
5194 			policy_type = BTC_CXP_OFFE_WL;
5195 		else if (btc->cx.wl.status.val & btc_scanning_map.val)
5196 			policy_type = BTC_CXP_OFFE_2GBWMIXB;
5197 		else if (btc->cx.bt.link_info.profile_cnt.now == 0)
5198 			policy_type = BTC_CXP_OFFE_2GISOB;
5199 		else
5200 			policy_type = BTC_CXP_OFFE_2GBWISOB;
5201 	} else { /* dedicated-antenna */
5202 		policy_type = BTC_CXP_OFF_EQ0;
5203 	}
5204 
5205 	btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5206 
5207 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
5208 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
5209 }
5210 
_action_wl_scan(struct rtw89_dev * rtwdev)5211 static void _action_wl_scan(struct rtw89_dev *rtwdev)
5212 {
5213 	struct rtw89_btc *btc = &rtwdev->btc;
5214 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5215 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5216 
5217 	if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
5218 		_action_wl_25g_mcc(rtwdev);
5219 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
5220 	} else if (rtwdev->dbcc_en) {
5221 		if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
5222 		    wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
5223 			_action_wl_5g(rtwdev);
5224 		else
5225 			_action_by_bt(rtwdev);
5226 	} else {
5227 		if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
5228 			_action_wl_5g(rtwdev);
5229 		else
5230 			_action_by_bt(rtwdev);
5231 	}
5232 }
5233 
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)5234 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
5235 {	struct rtw89_btc *btc = &rtwdev->btc;
5236 
5237 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5238 
5239 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5240 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5241 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5242 				    BTC_ACT_WL_2G_MCC);
5243 		else
5244 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF,
5245 				    BTC_ACT_WL_2G_MCC);
5246 	} else { /* dedicated-antenna */
5247 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
5248 	}
5249 }
5250 
_action_wl_2g_scc(struct rtw89_dev * rtwdev)5251 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
5252 {
5253 	struct rtw89_btc *btc = &rtwdev->btc;
5254 
5255 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5256 
5257 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5258 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5259 			_set_policy(rtwdev,
5260 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
5261 		else
5262 			_set_policy(rtwdev,
5263 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
5264 	} else { /* dedicated-antenna */
5265 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
5266 	}
5267 }
5268 
_action_wl_2g_scc_v1(struct rtw89_dev * rtwdev)5269 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
5270 {
5271 	struct rtw89_btc *btc = &rtwdev->btc;
5272 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5273 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5274 	struct rtw89_btc_dm *dm = &btc->dm;
5275 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5276 	u16 policy_type = BTC_CXP_OFF_BT;
5277 	u32 dur;
5278 
5279 	if (btc->ant_type == BTC_ANT_DEDICATED) {
5280 		policy_type = BTC_CXP_OFF_EQ0;
5281 	} else {
5282 		/* shared-antenna */
5283 		switch (wl_rinfo->mrole_type) {
5284 		case BTC_WLMROLE_STA_GC:
5285 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5286 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5287 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5288 			_action_by_bt(rtwdev);
5289 			return;
5290 		case BTC_WLMROLE_STA_STA:
5291 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5292 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5293 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5294 			_action_by_bt(rtwdev);
5295 			return;
5296 		case BTC_WLMROLE_STA_GC_NOA:
5297 		case BTC_WLMROLE_STA_GO:
5298 		case BTC_WLMROLE_STA_GO_NOA:
5299 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5300 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5301 			dur = wl_rinfo->mrole_noa_duration;
5302 
5303 			if (wl->status.map._4way) {
5304 				dm->wl_scc.ebt_null = 0;
5305 				policy_type = BTC_CXP_OFFE_WL;
5306 			} else if (bt->link_info.status.map.connect == 0) {
5307 				dm->wl_scc.ebt_null = 0;
5308 				policy_type = BTC_CXP_OFFE_2GISOB;
5309 			} else if (bt->link_info.a2dp_desc.exist &&
5310 				   dur < btc->bt_req_len) {
5311 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5312 				policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5313 			} else if (bt->link_info.a2dp_desc.exist ||
5314 				   bt->link_info.pan_desc.exist) {
5315 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5316 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5317 			} else {
5318 				dm->wl_scc.ebt_null = 0;
5319 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5320 			}
5321 			break;
5322 		default:
5323 			break;
5324 		}
5325 	}
5326 
5327 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5328 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5329 }
5330 
_action_wl_2g_scc_v2(struct rtw89_dev * rtwdev)5331 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
5332 {
5333 	struct rtw89_btc *btc = &rtwdev->btc;
5334 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5335 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5336 	struct rtw89_btc_dm *dm = &btc->dm;
5337 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
5338 	u16 policy_type = BTC_CXP_OFF_BT;
5339 	u32 dur;
5340 
5341 	if (btc->ant_type == BTC_ANT_DEDICATED) {
5342 		policy_type = BTC_CXP_OFF_EQ0;
5343 	} else {
5344 		/* shared-antenna */
5345 		switch (wl_rinfo->mrole_type) {
5346 		case BTC_WLMROLE_STA_GC:
5347 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5348 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5349 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5350 			_action_by_bt(rtwdev);
5351 			return;
5352 		case BTC_WLMROLE_STA_STA:
5353 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5354 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5355 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5356 			_action_by_bt(rtwdev);
5357 			return;
5358 		case BTC_WLMROLE_STA_GC_NOA:
5359 		case BTC_WLMROLE_STA_GO:
5360 		case BTC_WLMROLE_STA_GO_NOA:
5361 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5362 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5363 			dur = wl_rinfo->mrole_noa_duration;
5364 
5365 			if (wl->status.map._4way) {
5366 				dm->wl_scc.ebt_null = 0;
5367 				policy_type = BTC_CXP_OFFE_WL;
5368 			} else if (bt->link_info.status.map.connect == 0) {
5369 				dm->wl_scc.ebt_null = 0;
5370 				policy_type = BTC_CXP_OFFE_2GISOB;
5371 			} else if (bt->link_info.a2dp_desc.exist &&
5372 				   dur < btc->bt_req_len) {
5373 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5374 				policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5375 			} else if (bt->link_info.a2dp_desc.exist ||
5376 				   bt->link_info.pan_desc.exist) {
5377 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5378 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5379 			} else {
5380 				dm->wl_scc.ebt_null = 0;
5381 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5382 			}
5383 			break;
5384 		default:
5385 			break;
5386 		}
5387 	}
5388 
5389 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5390 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5391 }
5392 
_action_wl_2g_scc_v8(struct rtw89_dev * rtwdev)5393 static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
5394 {
5395 	struct rtw89_btc *btc = &rtwdev->btc;
5396 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5397 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5398 	struct rtw89_btc_dm *dm = &btc->dm;
5399 	u16 policy_type = BTC_CXP_OFF_BT;
5400 
5401 	if (btc->ant_type == BTC_ANT_SHARED) {
5402 		if (wl->status.map._4way)
5403 			policy_type = BTC_CXP_OFFE_WL;
5404 		else if (bt->link_info.status.map.connect == 0)
5405 			policy_type = BTC_CXP_OFFE_2GISOB;
5406 		else
5407 			policy_type = BTC_CXP_OFFE_2GBWISOB;
5408 	} else {
5409 		policy_type = BTC_CXP_OFF_EQ0;
5410 	}
5411 
5412 	dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5413 
5414 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5415 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5416 }
5417 
_action_wl_2g_ap(struct rtw89_dev * rtwdev)5418 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
5419 {
5420 	struct rtw89_btc *btc = &rtwdev->btc;
5421 
5422 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5423 
5424 	if (btc->ant_type == BTC_ANT_SHARED) {
5425 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5426 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5427 				    BTC_ACT_WL_2G_AP);
5428 		else
5429 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
5430 	} else {/* dedicated-antenna */
5431 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
5432 	}
5433 }
5434 
_action_wl_2g_go(struct rtw89_dev * rtwdev)5435 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
5436 {
5437 	struct rtw89_btc *btc = &rtwdev->btc;
5438 
5439 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5440 
5441 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5442 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5443 			_set_policy(rtwdev,
5444 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
5445 		else
5446 			_set_policy(rtwdev,
5447 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
5448 	} else { /* dedicated-antenna */
5449 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
5450 	}
5451 }
5452 
_action_wl_2g_gc(struct rtw89_dev * rtwdev)5453 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
5454 {
5455 	struct rtw89_btc *btc = &rtwdev->btc;
5456 
5457 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5458 
5459 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5460 		_action_by_bt(rtwdev);
5461 	} else {/* dedicated-antenna */
5462 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
5463 	}
5464 }
5465 
_action_wl_2g_nan(struct rtw89_dev * rtwdev)5466 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
5467 {
5468 	struct rtw89_btc *btc = &rtwdev->btc;
5469 
5470 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5471 
5472 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5473 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5474 			_set_policy(rtwdev,
5475 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
5476 		else
5477 			_set_policy(rtwdev,
5478 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
5479 	} else { /* dedicated-antenna */
5480 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
5481 	}
5482 }
5483 
_read_scbd(struct rtw89_dev * rtwdev)5484 static u32 _read_scbd(struct rtw89_dev *rtwdev)
5485 {
5486 	const struct rtw89_chip_info *chip = rtwdev->chip;
5487 	struct rtw89_btc *btc = &rtwdev->btc;
5488 	u32 scbd_val = 0;
5489 
5490 	if (!chip->scbd)
5491 		return 0;
5492 
5493 	scbd_val = rtw89_mac_get_sb(rtwdev);
5494 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
5495 		    scbd_val);
5496 
5497 	btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
5498 	return scbd_val;
5499 }
5500 
_write_scbd(struct rtw89_dev * rtwdev,u32 val,bool state)5501 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
5502 {
5503 	const struct rtw89_chip_info *chip = rtwdev->chip;
5504 	struct rtw89_btc *btc = &rtwdev->btc;
5505 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5506 	u32 scbd_val = 0;
5507 	u8 force_exec = false;
5508 
5509 	if (!chip->scbd)
5510 		return;
5511 
5512 	scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
5513 
5514 	if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
5515 		force_exec = true;
5516 
5517 	if (scbd_val != wl->scbd || force_exec) {
5518 		wl->scbd = scbd_val;
5519 		wl->scbd_change = true;
5520 	}
5521 }
5522 
5523 static u8
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)5524 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
5525 {
5526 	const struct rtw89_chip_info *chip = rtwdev->chip;
5527 	u8 next_state, tol = chip->rssi_tol;
5528 
5529 	if (pre_state == BTC_RSSI_ST_LOW ||
5530 	    pre_state == BTC_RSSI_ST_STAY_LOW) {
5531 		if (rssi >= (thresh + tol))
5532 			next_state = BTC_RSSI_ST_HIGH;
5533 		else
5534 			next_state = BTC_RSSI_ST_STAY_LOW;
5535 	} else {
5536 		if (rssi < thresh)
5537 			next_state = BTC_RSSI_ST_LOW;
5538 		else
5539 			next_state = BTC_RSSI_ST_STAY_HIGH;
5540 	}
5541 
5542 	return next_state;
5543 }
5544 
5545 static
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)5546 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
5547 {
5548 	struct rtw89_btc *btc = &rtwdev->btc;
5549 
5550 	btc->cx.wl.dbcc_info.real_band[phy_idx] =
5551 		btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
5552 		btc->cx.wl.dbcc_info.scan_band[phy_idx] :
5553 		btc->cx.wl.dbcc_info.op_band[phy_idx];
5554 }
5555 
_update_wl_info(struct rtw89_dev * rtwdev)5556 static void _update_wl_info(struct rtw89_dev *rtwdev)
5557 {
5558 	struct rtw89_btc *btc = &rtwdev->btc;
5559 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5560 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
5561 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5562 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5563 	u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
5564 	u8 cnt_2g = 0, cnt_5g = 0, phy;
5565 	u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
5566 	bool b2g = false, b5g = false, client_joined = false;
5567 
5568 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
5569 
5570 	for (i = 0; i < RTW89_PORT_NUM; i++) {
5571 		/* check if role active? */
5572 		if (!wl_linfo[i].active)
5573 			continue;
5574 
5575 		cnt_active++;
5576 		wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
5577 		wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
5578 		wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
5579 		wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
5580 		wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
5581 		wl_rinfo->active_role[cnt_active - 1].connected = 0;
5582 
5583 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
5584 
5585 		phy = wl_linfo[i].phy;
5586 
5587 		/* check dbcc role */
5588 		if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
5589 			wl_dinfo->role[phy] = wl_linfo[i].role;
5590 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
5591 			_update_dbcc_band(rtwdev, phy);
5592 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
5593 		}
5594 
5595 		if (wl_linfo[i].connected == MLME_NO_LINK) {
5596 			continue;
5597 		} else if (wl_linfo[i].connected == MLME_LINKING) {
5598 			cnt_connecting++;
5599 		} else {
5600 			cnt_connect++;
5601 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
5602 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
5603 			     wl_linfo[i].client_cnt > 1)
5604 				client_joined = true;
5605 		}
5606 
5607 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
5608 		wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
5609 		wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
5610 		wl_rinfo->active_role[cnt_active - 1].connected = 1;
5611 
5612 		/* only care 2 roles + BT coex */
5613 		if (wl_linfo[i].band != RTW89_BAND_2G) {
5614 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
5615 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
5616 			cnt_5g++;
5617 			b5g = true;
5618 		} else {
5619 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
5620 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
5621 			cnt_2g++;
5622 			b2g = true;
5623 		}
5624 	}
5625 
5626 	wl_rinfo->connect_cnt = cnt_connect;
5627 
5628 	/* Be careful to change the following sequence!! */
5629 	if (cnt_connect == 0) {
5630 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5631 		wl_rinfo->role_map.role.none = 1;
5632 	} else if (!b2g && b5g) {
5633 		wl_rinfo->link_mode = BTC_WLINK_5G;
5634 	} else if (wl_rinfo->role_map.role.nan) {
5635 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
5636 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
5637 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
5638 	} else  if (b2g && b5g && cnt_connect == 2) {
5639 		if (rtwdev->dbcc_en) {
5640 			switch (wl_dinfo->role[RTW89_PHY_0]) {
5641 			case RTW89_WIFI_ROLE_STATION:
5642 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5643 				break;
5644 			case RTW89_WIFI_ROLE_P2P_GO:
5645 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5646 				break;
5647 			case RTW89_WIFI_ROLE_P2P_CLIENT:
5648 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5649 				break;
5650 			case RTW89_WIFI_ROLE_AP:
5651 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5652 				break;
5653 			default:
5654 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
5655 				break;
5656 			}
5657 		} else {
5658 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
5659 		}
5660 	} else if (!b5g && cnt_connect == 2) {
5661 		if (wl_rinfo->role_map.role.station &&
5662 		    (wl_rinfo->role_map.role.p2p_go ||
5663 		    wl_rinfo->role_map.role.p2p_gc ||
5664 		    wl_rinfo->role_map.role.ap)) {
5665 			if (wl_2g_ch[0] == wl_2g_ch[1])
5666 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
5667 			else
5668 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5669 		} else {
5670 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5671 		}
5672 	} else if (!b5g && cnt_connect == 1) {
5673 		if (wl_rinfo->role_map.role.station)
5674 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5675 		else if (wl_rinfo->role_map.role.ap)
5676 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5677 		else if (wl_rinfo->role_map.role.p2p_go)
5678 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5679 		else if (wl_rinfo->role_map.role.p2p_gc)
5680 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5681 		else
5682 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
5683 	}
5684 
5685 	/* if no client_joined, don't care P2P-GO/AP role */
5686 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
5687 		if (!client_joined) {
5688 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
5689 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
5690 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5691 				wl_rinfo->connect_cnt = 1;
5692 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
5693 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
5694 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5695 				wl_rinfo->connect_cnt = 0;
5696 			}
5697 		}
5698 	}
5699 
5700 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
5701 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
5702 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
5703 
5704 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5705 }
5706 
_update_wl_info_v1(struct rtw89_dev * rtwdev)5707 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
5708 {
5709 	struct rtw89_btc *btc = &rtwdev->btc;
5710 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5711 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
5712 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5713 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5714 	u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
5715 	u8 cnt_2g = 0, cnt_5g = 0, phy;
5716 	u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
5717 	bool b2g = false, b5g = false, client_joined = false;
5718 	u8 i;
5719 
5720 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
5721 
5722 	for (i = 0; i < RTW89_PORT_NUM; i++) {
5723 		if (!wl_linfo[i].active)
5724 			continue;
5725 
5726 		cnt_active++;
5727 		wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
5728 		wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
5729 		wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
5730 		wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
5731 		wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
5732 		wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
5733 
5734 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
5735 
5736 		phy = wl_linfo[i].phy;
5737 
5738 		if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
5739 			wl_dinfo->role[phy] = wl_linfo[i].role;
5740 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
5741 			_update_dbcc_band(rtwdev, phy);
5742 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
5743 		}
5744 
5745 		if (wl_linfo[i].connected == MLME_NO_LINK) {
5746 			continue;
5747 		} else if (wl_linfo[i].connected == MLME_LINKING) {
5748 			cnt_connecting++;
5749 		} else {
5750 			cnt_connect++;
5751 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
5752 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
5753 			     wl_linfo[i].client_cnt > 1)
5754 				client_joined = true;
5755 		}
5756 
5757 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
5758 		wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
5759 		wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
5760 		wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
5761 
5762 		/* only care 2 roles + BT coex */
5763 		if (wl_linfo[i].band != RTW89_BAND_2G) {
5764 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
5765 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
5766 			cnt_5g++;
5767 			b5g = true;
5768 		} else {
5769 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
5770 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
5771 			cnt_2g++;
5772 			b2g = true;
5773 		}
5774 	}
5775 
5776 	wl_rinfo->connect_cnt = cnt_connect;
5777 
5778 	/* Be careful to change the following sequence!! */
5779 	if (cnt_connect == 0) {
5780 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5781 		wl_rinfo->role_map.role.none = 1;
5782 	} else if (!b2g && b5g) {
5783 		wl_rinfo->link_mode = BTC_WLINK_5G;
5784 	} else if (wl_rinfo->role_map.role.nan) {
5785 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
5786 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
5787 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
5788 	} else  if (b2g && b5g && cnt_connect == 2) {
5789 		if (rtwdev->dbcc_en) {
5790 			switch (wl_dinfo->role[RTW89_PHY_0]) {
5791 			case RTW89_WIFI_ROLE_STATION:
5792 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5793 				break;
5794 			case RTW89_WIFI_ROLE_P2P_GO:
5795 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5796 				break;
5797 			case RTW89_WIFI_ROLE_P2P_CLIENT:
5798 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5799 				break;
5800 			case RTW89_WIFI_ROLE_AP:
5801 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5802 				break;
5803 			default:
5804 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
5805 				break;
5806 			}
5807 		} else {
5808 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
5809 		}
5810 	} else if (!b5g && cnt_connect == 2) {
5811 		if (wl_rinfo->role_map.role.station &&
5812 		    (wl_rinfo->role_map.role.p2p_go ||
5813 		    wl_rinfo->role_map.role.p2p_gc ||
5814 		    wl_rinfo->role_map.role.ap)) {
5815 			if (wl_2g_ch[0] == wl_2g_ch[1])
5816 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
5817 			else
5818 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5819 		} else {
5820 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5821 		}
5822 	} else if (!b5g && cnt_connect == 1) {
5823 		if (wl_rinfo->role_map.role.station)
5824 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5825 		else if (wl_rinfo->role_map.role.ap)
5826 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5827 		else if (wl_rinfo->role_map.role.p2p_go)
5828 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5829 		else if (wl_rinfo->role_map.role.p2p_gc)
5830 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5831 		else
5832 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
5833 	}
5834 
5835 	/* if no client_joined, don't care P2P-GO/AP role */
5836 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
5837 		if (!client_joined) {
5838 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
5839 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
5840 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5841 				wl_rinfo->connect_cnt = 1;
5842 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
5843 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
5844 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5845 				wl_rinfo->connect_cnt = 0;
5846 			}
5847 		}
5848 	}
5849 
5850 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
5851 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
5852 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
5853 
5854 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5855 }
5856 
_update_wl_info_v2(struct rtw89_dev * rtwdev)5857 static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
5858 {
5859 	struct rtw89_btc *btc = &rtwdev->btc;
5860 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5861 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
5862 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
5863 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5864 	u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
5865 	u8 cnt_2g = 0, cnt_5g = 0, phy;
5866 	u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
5867 	bool b2g = false, b5g = false, client_joined = false;
5868 	u8 i;
5869 
5870 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
5871 
5872 	for (i = 0; i < RTW89_PORT_NUM; i++) {
5873 		if (!wl_linfo[i].active)
5874 			continue;
5875 
5876 		cnt_active++;
5877 		wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role;
5878 		wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid;
5879 		wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy;
5880 		wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band;
5881 		wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
5882 		wl_rinfo->active_role_v2[cnt_active - 1].connected = 0;
5883 
5884 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
5885 
5886 		phy = wl_linfo[i].phy;
5887 
5888 		if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
5889 			wl_dinfo->role[phy] = wl_linfo[i].role;
5890 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
5891 			_update_dbcc_band(rtwdev, phy);
5892 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
5893 		}
5894 
5895 		if (wl_linfo[i].connected == MLME_NO_LINK) {
5896 			continue;
5897 		} else if (wl_linfo[i].connected == MLME_LINKING) {
5898 			cnt_connecting++;
5899 		} else {
5900 			cnt_connect++;
5901 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
5902 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
5903 			     wl_linfo[i].client_cnt > 1)
5904 				client_joined = true;
5905 		}
5906 
5907 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
5908 		wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch;
5909 		wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw;
5910 		wl_rinfo->active_role_v2[cnt_active - 1].connected = 1;
5911 
5912 		/* only care 2 roles + BT coex */
5913 		if (wl_linfo[i].band != RTW89_BAND_2G) {
5914 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
5915 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
5916 			cnt_5g++;
5917 			b5g = true;
5918 		} else {
5919 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
5920 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
5921 			cnt_2g++;
5922 			b2g = true;
5923 		}
5924 	}
5925 
5926 	wl_rinfo->connect_cnt = cnt_connect;
5927 
5928 	/* Be careful to change the following sequence!! */
5929 	if (cnt_connect == 0) {
5930 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5931 		wl_rinfo->role_map.role.none = 1;
5932 	} else if (!b2g && b5g) {
5933 		wl_rinfo->link_mode = BTC_WLINK_5G;
5934 	} else if (wl_rinfo->role_map.role.nan) {
5935 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
5936 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
5937 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
5938 	} else  if (b2g && b5g && cnt_connect == 2) {
5939 		if (rtwdev->dbcc_en) {
5940 			switch (wl_dinfo->role[RTW89_PHY_0]) {
5941 			case RTW89_WIFI_ROLE_STATION:
5942 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5943 				break;
5944 			case RTW89_WIFI_ROLE_P2P_GO:
5945 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5946 				break;
5947 			case RTW89_WIFI_ROLE_P2P_CLIENT:
5948 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5949 				break;
5950 			case RTW89_WIFI_ROLE_AP:
5951 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5952 				break;
5953 			default:
5954 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
5955 				break;
5956 			}
5957 		} else {
5958 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
5959 		}
5960 	} else if (!b5g && cnt_connect == 2) {
5961 		if (wl_rinfo->role_map.role.station &&
5962 		    (wl_rinfo->role_map.role.p2p_go ||
5963 		    wl_rinfo->role_map.role.p2p_gc ||
5964 		    wl_rinfo->role_map.role.ap)) {
5965 			if (wl_2g_ch[0] == wl_2g_ch[1])
5966 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
5967 			else
5968 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5969 		} else {
5970 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5971 		}
5972 	} else if (!b5g && cnt_connect == 1) {
5973 		if (wl_rinfo->role_map.role.station)
5974 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5975 		else if (wl_rinfo->role_map.role.ap)
5976 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5977 		else if (wl_rinfo->role_map.role.p2p_go)
5978 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5979 		else if (wl_rinfo->role_map.role.p2p_gc)
5980 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5981 		else
5982 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
5983 	}
5984 
5985 	/* if no client_joined, don't care P2P-GO/AP role */
5986 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
5987 		if (!client_joined) {
5988 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
5989 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
5990 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5991 				wl_rinfo->connect_cnt = 1;
5992 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
5993 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
5994 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5995 				wl_rinfo->connect_cnt = 0;
5996 			}
5997 		}
5998 	}
5999 
6000 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6001 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6002 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6003 
6004 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6005 }
6006 
6007 #define BTC_CHK_HANG_MAX 3
6008 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
6009 
_get_role_link_mode(u8 role)6010 static u8 _get_role_link_mode(u8 role)
6011 {
6012 	switch (role) {
6013 	case RTW89_WIFI_ROLE_STATION:
6014 		return BTC_WLINK_2G_STA;
6015 	case RTW89_WIFI_ROLE_P2P_GO:
6016 		return BTC_WLINK_2G_GO;
6017 	case RTW89_WIFI_ROLE_P2P_CLIENT:
6018 		return BTC_WLINK_2G_GC;
6019 	case RTW89_WIFI_ROLE_AP:
6020 		return BTC_WLINK_2G_AP;
6021 	default:
6022 		return BTC_WLINK_OTHER;
6023 	}
6024 }
6025 
_chk_role_ch_group(const struct rtw89_btc_chdef * r1,const struct rtw89_btc_chdef * r2)6026 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
6027 			       const struct rtw89_btc_chdef *r2)
6028 {
6029 	if (r1->chan != r2->chan) { /* primary ch is different */
6030 		return false;
6031 	} else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
6032 		   r2->bw == RTW89_CHANNEL_WIDTH_40) {
6033 		if (r1->offset != r2->offset)
6034 			return false;
6035 	}
6036 	return true;
6037 }
6038 
_chk_dbcc(struct rtw89_dev * rtwdev,struct rtw89_btc_chdef * ch,u8 * phy,u8 * role,u8 * dbcc_2g_phy)6039 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
6040 		    u8 *phy, u8 *role, u8 *dbcc_2g_phy)
6041 {
6042 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6043 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6044 	bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
6045 	u8 j, k, dbcc_2g_cid, dbcc_2g_cid2;
6046 
6047 	/* find out the 2G-PHY by connect-id ->ch  */
6048 	for (j = 0; j < wl_rinfo->connect_cnt; j++) {
6049 		if (ch[j].center_ch <= 14) {
6050 			is_2g_ch_exist = true;
6051 			break;
6052 		}
6053 	}
6054 
6055 	/* If no any 2G-port exist, it's impossible because 5G-exclude */
6056 	if (!is_2g_ch_exist)
6057 		return BTC_WLINK_OTHER;
6058 
6059 	dbcc_2g_cid = j;
6060 	*dbcc_2g_phy = phy[dbcc_2g_cid];
6061 
6062 	/* connect_cnt <= 2 */
6063 	if (wl_rinfo->connect_cnt < BTC_TDMA_WLROLE_MAX)
6064 		return (_get_role_link_mode((role[dbcc_2g_cid])));
6065 
6066 	/* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
6067 	for (k = 0; k < wl_rinfo->connect_cnt; k++) {
6068 		if (k == dbcc_2g_cid)
6069 			continue;
6070 
6071 		if (phy[k] == *dbcc_2g_phy) {
6072 			is_multi_role_in_2g_phy = true;
6073 			dbcc_2g_cid2 = k;
6074 			break;
6075 		}
6076 	}
6077 
6078 	/* Single-role in 2G-PHY */
6079 	if (!is_multi_role_in_2g_phy)
6080 		return (_get_role_link_mode(role[dbcc_2g_cid]));
6081 
6082 	/* 2-role in 2G-PHY */
6083 	if (ch[dbcc_2g_cid2].center_ch > 14)
6084 		return BTC_WLINK_25G_MCC;
6085 	else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
6086 		return BTC_WLINK_2G_SCC;
6087 	else
6088 		return BTC_WLINK_2G_MCC;
6089 }
6090 
_update_role_link_mode(struct rtw89_dev * rtwdev,bool client_joined,u32 noa)6091 static void _update_role_link_mode(struct rtw89_dev *rtwdev,
6092 				   bool client_joined, u32 noa)
6093 {
6094 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &rtwdev->btc.cx.wl.role_info_v8;
6095 	u32 type = BTC_WLMROLE_NONE, dur = 0;
6096 	u32 wl_role = wl_rinfo->role_map;
6097 
6098 	/* if no client_joined, don't care P2P-GO/AP role */
6099 	if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6100 	     (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
6101 		if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC) {
6102 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6103 			wl_rinfo->connect_cnt--;
6104 		} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6105 			wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6106 			wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6107 			wl_rinfo->connect_cnt--;
6108 		}
6109 	}
6110 
6111 	/* Identify 2-Role type  */
6112 	if (wl_rinfo->connect_cnt >= 2 &&
6113 	    (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6114 	     wl_rinfo->link_mode == BTC_WLINK_2G_MCC ||
6115 	     wl_rinfo->link_mode == BTC_WLINK_25G_MCC ||
6116 	     wl_rinfo->link_mode == BTC_WLINK_5G)) {
6117 		if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6118 		    (wl_role & BIT(RTW89_WIFI_ROLE_AP)))
6119 			type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
6120 		else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
6121 			type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
6122 		else
6123 			type = BTC_WLMROLE_STA_STA;
6124 
6125 		dur = noa;
6126 	}
6127 
6128 	wl_rinfo->mrole_type = type;
6129 	wl_rinfo->mrole_noa_duration = dur;
6130 }
6131 
_update_wl_info_v8(struct rtw89_dev * rtwdev,u8 role_id,u8 rlink_id,enum btc_role_state state)6132 static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
6133 			       enum btc_role_state state)
6134 {
6135 	struct rtw89_btc *btc = &rtwdev->btc;
6136 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6137 	struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6138 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6139 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6140 	bool client_joined = false, b2g = false, b5g = false;
6141 	u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6142 	u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6143 	u8 dbcc_en = 0, pta_req_band = RTW89_MAC_0;
6144 	u8 i, j, cnt = 0, cnt_2g = 0, cnt_5g = 0;
6145 	struct rtw89_btc_wl_link_info *wl_linfo;
6146 	struct rtw89_btc_wl_rlink *rlink = NULL;
6147 	u8 dbcc_2g_phy = RTW89_PHY_0;
6148 	u8 mode = BTC_WLINK_NOLINK;
6149 	u32 noa_dur = 0;
6150 
6151 	if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id > RTW89_MAC_1)
6152 		return;
6153 
6154 	/* Extract wl->link_info[role_id][rlink_id] to wl->role_info
6155 	 * role_id: role index
6156 	 * rlink_id: rlink index (= HW-band index)
6157 	 * pid: port_index
6158 	 */
6159 
6160 	wl_linfo = &wl->rlink_info[role_id][rlink_id];
6161 	if (wl_linfo->connected == MLME_LINKING)
6162 		return;
6163 
6164 	rlink = &wl_rinfo->rlink[role_id][rlink_id];
6165 	rlink->role = wl_linfo->role;
6166 	rlink->active = wl_linfo->active; /* Doze or not */
6167 	rlink->pid = wl_linfo->pid;
6168 	rlink->phy = wl_linfo->phy;
6169 	rlink->rf_band = wl_linfo->band;
6170 	rlink->ch = wl_linfo->ch;
6171 	rlink->bw = wl_linfo->bw;
6172 	rlink->noa = wl_linfo->noa;
6173 	rlink->noa_dur = wl_linfo->noa_duration / 1000;
6174 	rlink->client_cnt = wl_linfo->client_cnt;
6175 	rlink->mode = wl_linfo->mode;
6176 
6177 	switch (wl_linfo->connected) {
6178 	case MLME_NO_LINK:
6179 		rlink->connected = 0;
6180 		if (rlink->role == RTW89_WIFI_ROLE_STATION)
6181 			btc->dm.leak_ap = 0;
6182 		break;
6183 	case MLME_LINKED:
6184 		rlink->connected = 1;
6185 		break;
6186 	default:
6187 		return;
6188 	}
6189 
6190 	wl->is_5g_hi_channel = false;
6191 	wl->bg_mode = false;
6192 	wl_rinfo->role_map = 0;
6193 	wl_rinfo->p2p_2g = 0;
6194 	memset(cid_ch, 0, sizeof(cid_ch));
6195 
6196 	for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
6197 		for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
6198 			rlink = &wl_rinfo->rlink[i][j];
6199 
6200 			if (!rlink->active || !rlink->connected)
6201 				continue;
6202 
6203 			cnt++;
6204 			wl_rinfo->role_map |= BIT(rlink->role);
6205 
6206 			/* only if client connect for p2p-Go/AP */
6207 			if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
6208 			     rlink->role == RTW89_WIFI_ROLE_AP) &&
6209 			     rlink->client_cnt > 1)
6210 				client_joined = true;
6211 
6212 			/* Identufy if P2P-Go (GO/GC/AP) exist at 2G band*/
6213 			if (rlink->rf_band == RTW89_BAND_2G &&
6214 			    (client_joined || rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT))
6215 				wl_rinfo->p2p_2g = 1;
6216 
6217 			/* only one noa-role exist */
6218 			if (rlink->noa && rlink->noa_dur > 0)
6219 				noa_dur = rlink->noa_dur;
6220 
6221 			/* for WL 5G-Rx interfered with BT issue */
6222 			if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100)
6223 				wl->is_5g_hi_channel = 1;
6224 
6225 			if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
6226 			    (rlink->mode & BIT(BTC_WL_MODE_11G)))
6227 				wl->bg_mode = 1;
6228 
6229 			if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT)
6230 				continue;
6231 
6232 			cid_ch[cnt - 1] = wl_linfo->chdef;
6233 			cid_phy[cnt - 1] = rlink->phy;
6234 			cid_role[cnt - 1] = rlink->role;
6235 
6236 			if (rlink->rf_band != RTW89_BAND_2G) {
6237 				cnt_5g++;
6238 				b5g = true;
6239 			} else {
6240 				cnt_2g++;
6241 				b2g = true;
6242 			}
6243 		}
6244 	}
6245 
6246 	if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
6247 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6248 			    "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6249 		rtw89_warn(rtwdev, "not support MLO feature yet");
6250 	} else {
6251 		dbcc_en = rtwdev->dbcc_en;
6252 
6253 		/* Be careful to change the following sequence!! */
6254 		if (cnt == 0) {
6255 			mode = BTC_WLINK_NOLINK;
6256 		} else if (!b2g && b5g) {
6257 			mode = BTC_WLINK_5G;
6258 		} else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6259 			mode = BTC_WLINK_2G_NAN;
6260 		} else if (cnt > BTC_TDMA_WLROLE_MAX) {
6261 			mode = BTC_WLINK_OTHER;
6262 		} else if (dbcc_en) {
6263 			mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role,
6264 					 &dbcc_2g_phy);
6265 		} else if (b2g && b5g && cnt == 2) {
6266 			mode = BTC_WLINK_25G_MCC;
6267 		} else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6268 			if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6269 				mode = BTC_WLINK_2G_SCC;
6270 			else
6271 				mode = BTC_WLINK_2G_MCC;
6272 		} else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6273 			mode = _get_role_link_mode(cid_role[0]);
6274 		}
6275 	}
6276 
6277 	wl_rinfo->link_mode = mode;
6278 	wl_rinfo->connect_cnt = cnt;
6279 	if (wl_rinfo->connect_cnt == 0)
6280 		wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6281 	_update_role_link_mode(rtwdev, client_joined, noa_dur);
6282 
6283 	wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6284 	if (wl_rinfo->dbcc_en != dbcc_en) {
6285 		wl_rinfo->dbcc_en = dbcc_en;
6286 		wl_rinfo->dbcc_chg = 1;
6287 		btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6288 	} else {
6289 		wl_rinfo->dbcc_chg = 0;
6290 	}
6291 
6292 	if (wl_rinfo->dbcc_en) {
6293 		memset(wl_dinfo, 0, sizeof(struct rtw89_btc_wl_dbcc_info));
6294 
6295 		if (mode == BTC_WLINK_5G) {
6296 			pta_req_band = RTW89_PHY_0;
6297 			wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
6298 			wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
6299 		} else if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_1) {
6300 			pta_req_band = RTW89_PHY_1;
6301 			wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
6302 			wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
6303 		} else {
6304 			pta_req_band = RTW89_PHY_0;
6305 			wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_2G;
6306 			wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_5G;
6307 		}
6308 		_update_dbcc_band(rtwdev, RTW89_PHY_0);
6309 		_update_dbcc_band(rtwdev, RTW89_PHY_1);
6310 	}
6311 
6312 	wl_rinfo->pta_req_band = pta_req_band;
6313 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6314 }
6315 
rtw89_coex_act1_work(struct work_struct * work)6316 void rtw89_coex_act1_work(struct work_struct *work)
6317 {
6318 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6319 						coex_act1_work.work);
6320 	struct rtw89_btc *btc = &rtwdev->btc;
6321 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6322 	struct rtw89_btc_cx *cx = &btc->cx;
6323 	struct rtw89_btc_wl_info *wl = &cx->wl;
6324 
6325 	mutex_lock(&rtwdev->mutex);
6326 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
6327 	dm->cnt_notify[BTC_NCNT_TIMER]++;
6328 	if (wl->status.map._4way)
6329 		wl->status.map._4way = false;
6330 	if (wl->status.map.connecting)
6331 		wl->status.map.connecting = false;
6332 
6333 	_run_coex(rtwdev, BTC_RSN_ACT1_WORK);
6334 	mutex_unlock(&rtwdev->mutex);
6335 }
6336 
rtw89_coex_bt_devinfo_work(struct work_struct * work)6337 void rtw89_coex_bt_devinfo_work(struct work_struct *work)
6338 {
6339 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6340 						coex_bt_devinfo_work.work);
6341 	struct rtw89_btc *btc = &rtwdev->btc;
6342 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6343 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
6344 
6345 	mutex_lock(&rtwdev->mutex);
6346 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
6347 	dm->cnt_notify[BTC_NCNT_TIMER]++;
6348 	a2dp->play_latency = 0;
6349 	_run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
6350 	mutex_unlock(&rtwdev->mutex);
6351 }
6352 
rtw89_coex_rfk_chk_work(struct work_struct * work)6353 void rtw89_coex_rfk_chk_work(struct work_struct *work)
6354 {
6355 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6356 						coex_rfk_chk_work.work);
6357 	struct rtw89_btc *btc = &rtwdev->btc;
6358 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6359 	struct rtw89_btc_cx *cx = &btc->cx;
6360 	struct rtw89_btc_wl_info *wl = &cx->wl;
6361 
6362 	mutex_lock(&rtwdev->mutex);
6363 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
6364 	dm->cnt_notify[BTC_NCNT_TIMER]++;
6365 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
6366 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6367 			    "[BTC], %s(): RFK timeout\n", __func__);
6368 		cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
6369 		dm->error.map.wl_rfk_timeout = true;
6370 		wl->rfk_info.state = BTC_WRFK_STOP;
6371 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
6372 		_run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
6373 	}
6374 	mutex_unlock(&rtwdev->mutex);
6375 }
6376 
_update_bt_scbd(struct rtw89_dev * rtwdev,bool only_update)6377 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
6378 {
6379 	const struct rtw89_chip_info *chip = rtwdev->chip;
6380 	struct rtw89_btc *btc = &rtwdev->btc;
6381 	struct rtw89_btc_cx *cx = &btc->cx;
6382 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6383 	u32 val;
6384 	bool status_change = false;
6385 
6386 	if (!chip->scbd)
6387 		return;
6388 
6389 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
6390 
6391 	val = _read_scbd(rtwdev);
6392 	if (val == BTC_SCB_INV_VALUE) {
6393 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6394 			    "[BTC], %s(): return by invalid scbd value\n",
6395 			    __func__);
6396 		return;
6397 	}
6398 
6399 	if (!(val & BTC_BSCB_ON))
6400 		bt->enable.now = 0;
6401 	else
6402 		bt->enable.now = 1;
6403 
6404 	if (bt->enable.now != bt->enable.last)
6405 		status_change = true;
6406 
6407 	/* reset bt info if bt re-enable */
6408 	if (bt->enable.now && !bt->enable.last) {
6409 		_reset_btc_var(rtwdev, BTC_RESET_BTINFO);
6410 		cx->cnt_bt[BTC_BCNT_REENABLE]++;
6411 		bt->enable.now = 1;
6412 	}
6413 
6414 	bt->enable.last = bt->enable.now;
6415 	bt->scbd = val;
6416 	bt->mbx_avl = !!(val & BTC_BSCB_ACT);
6417 
6418 	if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
6419 		status_change = true;
6420 
6421 	bt->whql_test = !!(val & BTC_BSCB_WHQL);
6422 	bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
6423 	bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
6424 
6425 	bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) +
6426 			    !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4;
6427 
6428 	/* if rfk run 1->0 */
6429 	if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
6430 		status_change = true;
6431 
6432 	bt->rfk_info.map.run  = !!(val & BTC_BSCB_RFK_RUN);
6433 	bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
6434 	bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
6435 	bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
6436 	bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
6437 
6438 	if (!only_update && status_change)
6439 		_run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
6440 }
6441 
_chk_wl_rfk_request(struct rtw89_dev * rtwdev)6442 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
6443 {
6444 	struct rtw89_btc *btc = &rtwdev->btc;
6445 	struct rtw89_btc_cx *cx = &btc->cx;
6446 	struct rtw89_btc_bt_info *bt = &cx->bt;
6447 
6448 	_update_bt_scbd(rtwdev, true);
6449 
6450 	cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
6451 
6452 	if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
6453 	    !bt->rfk_info.map.timeout) {
6454 		cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
6455 	} else {
6456 		cx->cnt_wl[BTC_WCNT_RFK_GO]++;
6457 		return true;
6458 	}
6459 	return false;
6460 }
6461 
6462 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)6463 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
6464 {
6465 	struct rtw89_btc *btc = &rtwdev->btc;
6466 	const struct rtw89_btc_ver *ver = btc->ver;
6467 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6468 	struct rtw89_btc_cx *cx = &btc->cx;
6469 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6470 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6471 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6472 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
6473 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
6474 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
6475 	u8 mode, igno_bt, always_freerun;
6476 
6477 	lockdep_assert_held(&rtwdev->mutex);
6478 
6479 	dm->run_reason = reason;
6480 	_update_dm_step(rtwdev, reason);
6481 	_update_btc_state_map(rtwdev);
6482 
6483 	if (ver->fwlrole == 0)
6484 		mode = wl_rinfo->link_mode;
6485 	else if (ver->fwlrole == 1)
6486 		mode = wl_rinfo_v1->link_mode;
6487 	else if (ver->fwlrole == 2)
6488 		mode = wl_rinfo_v2->link_mode;
6489 	else if (ver->fwlrole == 8)
6490 		mode = wl_rinfo_v8->link_mode;
6491 	else
6492 		return;
6493 
6494 	if (ver->fcxctrl == 7) {
6495 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
6496 		always_freerun = btc->ctrl.ctrl_v7.always_freerun;
6497 	} else {
6498 		igno_bt = btc->ctrl.ctrl.igno_bt;
6499 		always_freerun = btc->ctrl.ctrl.always_freerun;
6500 	}
6501 
6502 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
6503 		    __func__, reason, mode);
6504 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
6505 		    __func__, dm->wl_only, dm->bt_only);
6506 
6507 	/* Be careful to change the following function sequence!! */
6508 	if (btc->manual_ctrl) {
6509 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6510 			    "[BTC], %s(): return for Manual CTRL!!\n",
6511 			    __func__);
6512 		return;
6513 	}
6514 
6515 	if (igno_bt &&
6516 	    (reason == BTC_RSN_UPDATE_BT_INFO ||
6517 	     reason == BTC_RSN_UPDATE_BT_SCBD)) {
6518 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6519 			    "[BTC], %s(): return for Stop Coex DM!!\n",
6520 			    __func__);
6521 		return;
6522 	}
6523 
6524 	if (!wl->status.map.init_ok) {
6525 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6526 			    "[BTC], %s(): return for WL init fail!!\n",
6527 			    __func__);
6528 		return;
6529 	}
6530 
6531 	if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
6532 	    wl->status.map.lps_pre == wl->status.map.lps) {
6533 		if (reason == BTC_RSN_NTFY_POWEROFF ||
6534 		    reason == BTC_RSN_NTFY_RADIO_STATE) {
6535 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
6536 				    "[BTC], %s(): return for WL rf off state no change!!\n",
6537 				    __func__);
6538 			return;
6539 		}
6540 		if (wl->status.map.rf_off == 1 ||
6541 		    wl->status.map.lps == BTC_LPS_RF_OFF) {
6542 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
6543 				    "[BTC], %s(): return for WL rf off state!!\n",
6544 				    __func__);
6545 			return;
6546 		}
6547 	}
6548 
6549 	dm->freerun = false;
6550 	dm->cnt_dm[BTC_DCNT_RUN]++;
6551 	dm->fddt_train = BTC_FDDT_DISABLE;
6552 	bt->scan_rx_low_pri = false;
6553 	igno_bt = false;
6554 
6555 	if (always_freerun) {
6556 		_action_freerun(rtwdev);
6557 		igno_bt = true;
6558 		goto exit;
6559 	}
6560 
6561 	if (dm->wl_only) {
6562 		_action_wl_only(rtwdev);
6563 		igno_bt = true;
6564 		goto exit;
6565 	}
6566 
6567 	if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
6568 		_action_wl_off(rtwdev, mode);
6569 		igno_bt = true;
6570 		goto exit;
6571 	}
6572 
6573 	if (reason == BTC_RSN_NTFY_INIT) {
6574 		_action_wl_init(rtwdev);
6575 		goto exit;
6576 	}
6577 
6578 	if (!cx->bt.enable.now && !cx->other.type) {
6579 		_action_bt_off(rtwdev);
6580 		goto exit;
6581 	}
6582 
6583 	if (cx->bt.whql_test) {
6584 		_action_bt_whql(rtwdev);
6585 		goto exit;
6586 	}
6587 
6588 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
6589 		_action_wl_rfk(rtwdev);
6590 		goto exit;
6591 	}
6592 
6593 	if (cx->state_map == BTC_WLINKING) {
6594 		if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
6595 		    mode == BTC_WLINK_5G) {
6596 			_action_wl_scan(rtwdev);
6597 			bt->scan_rx_low_pri = false;
6598 			goto exit;
6599 		}
6600 	}
6601 
6602 	if (wl->status.map.scan) {
6603 		_action_wl_scan(rtwdev);
6604 		bt->scan_rx_low_pri = false;
6605 		goto exit;
6606 	}
6607 
6608 	switch (mode) {
6609 	case BTC_WLINK_NOLINK:
6610 		_action_wl_nc(rtwdev);
6611 		break;
6612 	case BTC_WLINK_2G_STA:
6613 		if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
6614 			bt->scan_rx_low_pri = true;
6615 		_action_wl_2g_sta(rtwdev);
6616 		break;
6617 	case BTC_WLINK_2G_AP:
6618 		bt->scan_rx_low_pri = true;
6619 		_action_wl_2g_ap(rtwdev);
6620 		break;
6621 	case BTC_WLINK_2G_GO:
6622 		bt->scan_rx_low_pri = true;
6623 		_action_wl_2g_go(rtwdev);
6624 		break;
6625 	case BTC_WLINK_2G_GC:
6626 		bt->scan_rx_low_pri = true;
6627 		_action_wl_2g_gc(rtwdev);
6628 		break;
6629 	case BTC_WLINK_2G_SCC:
6630 		bt->scan_rx_low_pri = true;
6631 		if (ver->fwlrole == 0)
6632 			_action_wl_2g_scc(rtwdev);
6633 		else if (ver->fwlrole == 1)
6634 			_action_wl_2g_scc_v1(rtwdev);
6635 		else if (ver->fwlrole == 2)
6636 			_action_wl_2g_scc_v2(rtwdev);
6637 		else if (ver->fwlrole == 8)
6638 			_action_wl_2g_scc_v8(rtwdev);
6639 		break;
6640 	case BTC_WLINK_2G_MCC:
6641 		bt->scan_rx_low_pri = true;
6642 		_action_wl_2g_mcc(rtwdev);
6643 		break;
6644 	case BTC_WLINK_25G_MCC:
6645 		bt->scan_rx_low_pri = true;
6646 		_action_wl_25g_mcc(rtwdev);
6647 		break;
6648 	case BTC_WLINK_5G:
6649 		_action_wl_5g(rtwdev);
6650 		break;
6651 	case BTC_WLINK_2G_NAN:
6652 		_action_wl_2g_nan(rtwdev);
6653 		break;
6654 	default:
6655 		_action_wl_other(rtwdev);
6656 		break;
6657 	}
6658 
6659 exit:
6660 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
6661 	if (ver->fcxctrl == 7)
6662 		btc->ctrl.ctrl_v7.igno_bt = igno_bt;
6663 	else
6664 		btc->ctrl.ctrl.igno_bt = igno_bt;
6665 	_action_common(rtwdev);
6666 }
6667 
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)6668 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
6669 {
6670 	struct rtw89_btc *btc = &rtwdev->btc;
6671 
6672 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
6673 	btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
6674 }
6675 
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)6676 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
6677 {
6678 	struct rtw89_btc *btc = &rtwdev->btc;
6679 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6680 
6681 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
6682 	btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
6683 
6684 	btc->cx.wl.status.map.rf_off = 1;
6685 	btc->cx.wl.status.map.busy = 0;
6686 	wl->status.map.lps = BTC_LPS_OFF;
6687 
6688 	_write_scbd(rtwdev, BTC_WSCB_ALL, false);
6689 	_run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
6690 
6691 	rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
6692 
6693 	btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
6694 }
6695 
_set_init_info(struct rtw89_dev * rtwdev)6696 static void _set_init_info(struct rtw89_dev *rtwdev)
6697 {
6698 	const struct rtw89_chip_info *chip = rtwdev->chip;
6699 	struct rtw89_btc *btc = &rtwdev->btc;
6700 	const struct rtw89_btc_ver *ver = btc->ver;
6701 	struct rtw89_btc_dm *dm = &btc->dm;
6702 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6703 
6704 	if (ver->fcxinit == 7) {
6705 		dm->init_info.init_v7.wl_only = (u8)dm->wl_only;
6706 		dm->init_info.init_v7.bt_only = (u8)dm->bt_only;
6707 		dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok;
6708 		dm->init_info.init_v7.cx_other = btc->cx.other.type;
6709 		dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch;
6710 		dm->init_info.init_v7.module = btc->mdinfo.md_v7;
6711 	} else {
6712 		dm->init_info.init.wl_only = (u8)dm->wl_only;
6713 		dm->init_info.init.bt_only = (u8)dm->bt_only;
6714 		dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok;
6715 		dm->init_info.init.dbcc_en = rtwdev->dbcc_en;
6716 		dm->init_info.init.cx_other = btc->cx.other.type;
6717 		dm->init_info.init.wl_guard_ch = chip->afh_guard_ch;
6718 		dm->init_info.init.module = btc->mdinfo.md;
6719 	}
6720 }
6721 
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)6722 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
6723 {
6724 	struct rtw89_btc *btc = &rtwdev->btc;
6725 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6726 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6727 	const struct rtw89_chip_info *chip = rtwdev->chip;
6728 	const struct rtw89_btc_ver *ver = btc->ver;
6729 
6730 	_reset_btc_var(rtwdev, BTC_RESET_ALL);
6731 	btc->dm.run_reason = BTC_RSN_NONE;
6732 	btc->dm.run_action = BTC_ACT_NONE;
6733 	if (ver->fcxctrl == 7)
6734 		btc->ctrl.ctrl_v7.igno_bt = true;
6735 	else
6736 		btc->ctrl.ctrl.igno_bt = true;
6737 
6738 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6739 		    "[BTC], %s(): mode=%d\n", __func__, mode);
6740 
6741 	wl->coex_mode = mode;
6742 	dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
6743 	dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
6744 	dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
6745 	wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
6746 
6747 	chip->ops->btc_set_rfe(rtwdev);
6748 	chip->ops->btc_init_cfg(rtwdev);
6749 
6750 	if (!wl->status.map.init_ok) {
6751 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6752 			    "[BTC], %s(): return for WL init fail!!\n",
6753 			    __func__);
6754 		dm->error.map.init = true;
6755 		return;
6756 	}
6757 
6758 	_write_scbd(rtwdev,
6759 		    BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
6760 	_update_bt_scbd(rtwdev, true);
6761 	if (rtw89_mac_get_ctrl_path(rtwdev)) {
6762 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6763 			    "[BTC], %s(): PTA owner warning!!\n",
6764 			    __func__);
6765 		dm->error.map.pta_owner = true;
6766 	}
6767 
6768 	_set_init_info(rtwdev);
6769 	_set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
6770 	btc_fw_set_monreg(rtwdev);
6771 	rtw89_btc_fw_set_slots(rtwdev);
6772 	_fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
6773 	_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
6774 
6775 	_run_coex(rtwdev, BTC_RSN_NTFY_INIT);
6776 }
6777 
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)6778 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
6779 {
6780 	struct rtw89_btc *btc = &rtwdev->btc;
6781 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6782 
6783 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6784 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
6785 		    __func__, phy_idx, band);
6786 
6787 	if (phy_idx >= RTW89_PHY_MAX)
6788 		return;
6789 
6790 	btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
6791 	wl->status.map.scan = true;
6792 	wl->scan_info.band[phy_idx] = band;
6793 	wl->scan_info.phy_map |= BIT(phy_idx);
6794 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
6795 
6796 	if (rtwdev->dbcc_en) {
6797 		wl->dbcc_info.scan_band[phy_idx] = band;
6798 		_update_dbcc_band(rtwdev, phy_idx);
6799 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6800 	}
6801 
6802 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
6803 }
6804 
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)6805 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
6806 {
6807 	struct rtw89_btc *btc = &rtwdev->btc;
6808 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6809 
6810 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6811 		    "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
6812 	btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
6813 
6814 	wl->status.map.scan = false;
6815 	wl->scan_info.phy_map &= ~BIT(phy_idx);
6816 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
6817 
6818 	if (rtwdev->dbcc_en) {
6819 		_update_dbcc_band(rtwdev, phy_idx);
6820 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6821 	}
6822 
6823 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
6824 }
6825 
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)6826 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
6827 {
6828 	struct rtw89_btc *btc = &rtwdev->btc;
6829 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6830 
6831 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6832 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
6833 		    __func__, phy_idx, band);
6834 
6835 	if (phy_idx >= RTW89_PHY_MAX)
6836 		return;
6837 
6838 	btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
6839 
6840 	wl->scan_info.band[phy_idx] = band;
6841 	wl->scan_info.phy_map |= BIT(phy_idx);
6842 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
6843 
6844 	if (rtwdev->dbcc_en) {
6845 		wl->dbcc_info.scan_band[phy_idx] = band;
6846 		_update_dbcc_band(rtwdev, phy_idx);
6847 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6848 	}
6849 	_run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
6850 }
6851 
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)6852 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
6853 				    enum btc_pkt_type pkt_type)
6854 {
6855 	struct rtw89_btc *btc = &rtwdev->btc;
6856 	struct rtw89_btc_cx *cx = &btc->cx;
6857 	struct rtw89_btc_wl_info *wl = &cx->wl;
6858 	struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
6859 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
6860 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
6861 	u32 cnt;
6862 	u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
6863 	bool delay_work = false;
6864 
6865 	switch (pkt_type) {
6866 	case PACKET_DHCP:
6867 		cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
6868 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6869 			    "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
6870 		wl->status.map.connecting = true;
6871 		delay_work = true;
6872 		break;
6873 	case PACKET_EAPOL:
6874 		cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
6875 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6876 			    "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
6877 		wl->status.map._4way = true;
6878 		delay_work = true;
6879 		if (hfp->exist || hid->exist)
6880 			delay /= 2;
6881 		break;
6882 	case PACKET_EAPOL_END:
6883 		cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
6884 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6885 			    "[BTC], %s(): EAPOL_End cnt=%d\n",
6886 			    __func__, cnt);
6887 		wl->status.map._4way = false;
6888 		cancel_delayed_work(&rtwdev->coex_act1_work);
6889 		break;
6890 	case PACKET_ARP:
6891 		cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
6892 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6893 			    "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
6894 		return;
6895 	case PACKET_ICMP:
6896 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6897 			    "[BTC], %s(): ICMP pkt\n", __func__);
6898 		return;
6899 	default:
6900 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6901 			    "[BTC], %s(): unknown packet type %d\n",
6902 			    __func__, pkt_type);
6903 		return;
6904 	}
6905 
6906 	if (delay_work) {
6907 		cancel_delayed_work(&rtwdev->coex_act1_work);
6908 		ieee80211_queue_delayed_work(rtwdev->hw,
6909 					     &rtwdev->coex_act1_work, delay);
6910 	}
6911 
6912 	btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
6913 	_run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
6914 }
6915 
rtw89_btc_ntfy_eapol_packet_work(struct work_struct * work)6916 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
6917 {
6918 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6919 						btc.eapol_notify_work);
6920 
6921 	mutex_lock(&rtwdev->mutex);
6922 	rtw89_leave_ps_mode(rtwdev);
6923 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
6924 	mutex_unlock(&rtwdev->mutex);
6925 }
6926 
rtw89_btc_ntfy_arp_packet_work(struct work_struct * work)6927 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
6928 {
6929 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6930 						btc.arp_notify_work);
6931 
6932 	mutex_lock(&rtwdev->mutex);
6933 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
6934 	mutex_unlock(&rtwdev->mutex);
6935 }
6936 
rtw89_btc_ntfy_dhcp_packet_work(struct work_struct * work)6937 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
6938 {
6939 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6940 						btc.dhcp_notify_work);
6941 
6942 	mutex_lock(&rtwdev->mutex);
6943 	rtw89_leave_ps_mode(rtwdev);
6944 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
6945 	mutex_unlock(&rtwdev->mutex);
6946 }
6947 
rtw89_btc_ntfy_icmp_packet_work(struct work_struct * work)6948 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
6949 {
6950 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6951 						btc.icmp_notify_work);
6952 
6953 	mutex_lock(&rtwdev->mutex);
6954 	rtw89_leave_ps_mode(rtwdev);
6955 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
6956 	mutex_unlock(&rtwdev->mutex);
6957 }
6958 
_update_bt_rssi_level(struct rtw89_dev * rtwdev,u8 rssi)6959 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
6960 {
6961 	const struct rtw89_chip_info *chip = rtwdev->chip;
6962 	struct rtw89_btc *btc = &rtwdev->btc;
6963 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6964 	u8 *rssi_st, rssi_th, rssi_level = 0;
6965 	u8 i;
6966 
6967 	/* for rssi locate in which {40, 36, 31, 28}
6968 	 * if rssi >= 40% (-60dBm) --> rssi_level = 4
6969 	 * if 36% <= rssi < 40%    --> rssi_level = 3
6970 	 * if 31% <= rssi < 36%    --> rssi_level = 2
6971 	 * if 28% <= rssi < 31%    --> rssi_level = 1
6972 	 * if rssi < 28%           --> rssi_level = 0
6973 	 */
6974 
6975 	/* check if rssi across bt_rssi_thres boundary */
6976 	for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
6977 		rssi_th = chip->bt_rssi_thres[i];
6978 		rssi_st = &bt->link_info.rssi_state[i];
6979 
6980 		*rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
6981 
6982 		if (BTC_RSSI_HIGH(*rssi_st)) {
6983 			rssi_level = BTC_BT_RSSI_THMAX - i;
6984 			break;
6985 		}
6986 	}
6987 	return rssi_level;
6988 }
6989 
_update_zb_coex_tbl(struct rtw89_dev * rtwdev)6990 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
6991 {
6992 	u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
6993 	u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
6994 
6995 	if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
6996 		zb_tbl0 = 0xffffffff;
6997 		zb_tbl1 = 0xffffffff;
6998 	} else if (mode == BTC_WLINK_25G_MCC) {
6999 		zb_tbl0 = 0xffffffff; /* for E5G slot */
7000 		zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
7001 	}
7002 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
7003 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
7004 }
7005 
7006 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
7007 
_update_bt_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)7008 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
7009 {
7010 	const struct rtw89_chip_info *chip = rtwdev->chip;
7011 	struct rtw89_btc *btc = &rtwdev->btc;
7012 	struct rtw89_btc_cx *cx = &btc->cx;
7013 	struct rtw89_btc_bt_info *bt = &cx->bt;
7014 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
7015 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7016 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7017 	struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
7018 	struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
7019 	union btc_btinfo btinfo;
7020 
7021 	if (buf[BTC_BTINFO_L1] != 6)
7022 		return;
7023 
7024 	if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
7025 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7026 			    "[BTC], %s(): return by bt-info duplicate!!\n",
7027 			    __func__);
7028 		cx->cnt_bt[BTC_BCNT_INFOSAME]++;
7029 		return;
7030 	}
7031 
7032 	memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
7033 
7034 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7035 		    "[BTC], %s(): bt_info[2]=0x%02x\n",
7036 		    __func__, bt->raw_info[2]);
7037 
7038 	/* reset to mo-connect before update */
7039 	b->status.val = BTC_BLINK_NOCONNECT;
7040 	b->profile_cnt.last = b->profile_cnt.now;
7041 	b->relink.last = b->relink.now;
7042 	a2dp->exist_last = a2dp->exist;
7043 	b->multi_link.last = b->multi_link.now;
7044 	bt->inq_pag.last = bt->inq_pag.now;
7045 	b->profile_cnt.now = 0;
7046 	hid->type = 0;
7047 
7048 	/* parse raw info low-Byte2 */
7049 	btinfo.val = bt->raw_info[BTC_BTINFO_L2];
7050 	b->status.map.connect = btinfo.lb2.connect;
7051 	b->status.map.sco_busy = btinfo.lb2.sco_busy;
7052 	b->status.map.acl_busy = btinfo.lb2.acl_busy;
7053 	b->status.map.inq_pag = btinfo.lb2.inq_pag;
7054 	bt->inq_pag.now = btinfo.lb2.inq_pag;
7055 	cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
7056 
7057 	hfp->exist = btinfo.lb2.hfp;
7058 	b->profile_cnt.now += (u8)hfp->exist;
7059 	hid->exist = btinfo.lb2.hid;
7060 	b->profile_cnt.now += (u8)hid->exist;
7061 	a2dp->exist = btinfo.lb2.a2dp;
7062 	b->profile_cnt.now += (u8)a2dp->exist;
7063 	pan->active = btinfo.lb2.pan;
7064 	btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
7065 
7066 	/* parse raw info low-Byte3 */
7067 	btinfo.val = bt->raw_info[BTC_BTINFO_L3];
7068 	if (btinfo.lb3.retry != 0)
7069 		cx->cnt_bt[BTC_BCNT_RETRY]++;
7070 	b->cqddr = btinfo.lb3.cqddr;
7071 	cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
7072 	bt->inq = btinfo.lb3.inq;
7073 	cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
7074 	bt->pag = btinfo.lb3.pag;
7075 
7076 	b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
7077 	/* parse raw info high-Byte0 */
7078 	btinfo.val = bt->raw_info[BTC_BTINFO_H0];
7079 	/* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
7080 	b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
7081 	bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
7082 	btc->dm.trx_info.bt_rssi = bt->rssi_level;
7083 
7084 	/* parse raw info high-Byte1 */
7085 	btinfo.val = bt->raw_info[BTC_BTINFO_H1];
7086 	b->status.map.ble_connect = btinfo.hb1.ble_connect;
7087 	if (btinfo.hb1.ble_connect)
7088 		hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
7089 
7090 	cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
7091 	bt->reinit = btinfo.hb1.reinit;
7092 	cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
7093 	b->relink.now = btinfo.hb1.relink;
7094 	cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
7095 	bt->igno_wl = btinfo.hb1.igno_wl;
7096 
7097 	if (bt->igno_wl && !cx->wl.status.map.rf_off)
7098 		_set_bt_ignore_wlan_act(rtwdev, false);
7099 
7100 	hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
7101 	bt->ble_scan_en = btinfo.hb1.ble_scan;
7102 
7103 	cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
7104 	b->role_sw = btinfo.hb1.role_sw;
7105 
7106 	b->multi_link.now = btinfo.hb1.multi_link;
7107 
7108 	/* parse raw info high-Byte2 */
7109 	btinfo.val = bt->raw_info[BTC_BTINFO_H2];
7110 	pan->exist = btinfo.hb2.pan_active;
7111 	b->profile_cnt.now += (u8)pan->exist;
7112 
7113 	cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
7114 	b->afh_update = btinfo.hb2.afh_update;
7115 	a2dp->active = btinfo.hb2.a2dp_active;
7116 	b->slave_role = btinfo.hb2.slave;
7117 	hid->slot_info = btinfo.hb2.hid_slot;
7118 	hid->pair_cnt = btinfo.hb2.hid_cnt;
7119 	hid->type |= (hid->slot_info == BTC_HID_218 ?
7120 		      BTC_HID_218 : BTC_HID_418);
7121 	/* parse raw info high-Byte3 */
7122 	btinfo.val = bt->raw_info[BTC_BTINFO_H3];
7123 	a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
7124 
7125 	if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
7126 		cx->cnt_bt[BTC_BCNT_RATECHG]++;
7127 	b->tx_3m = (u32)btinfo.hb3.tx_3m;
7128 
7129 	a2dp->sink = btinfo.hb3.a2dp_sink;
7130 
7131 	if (!a2dp->exist_last && a2dp->exist) {
7132 		a2dp->vendor_id = 0;
7133 		a2dp->flush_time = 0;
7134 		a2dp->play_latency = 1;
7135 		ieee80211_queue_delayed_work(rtwdev->hw,
7136 					     &rtwdev->coex_bt_devinfo_work,
7137 					     RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
7138 	}
7139 
7140 	_run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
7141 }
7142 
rtw89_btc_ntfy_role_info(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,struct rtw89_sta * rtwsta,enum btc_role_state state)7143 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
7144 			      struct rtw89_sta *rtwsta, enum btc_role_state state)
7145 {
7146 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
7147 						       rtwvif->sub_entity_idx);
7148 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
7149 	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
7150 	struct rtw89_btc *btc = &rtwdev->btc;
7151 	const struct rtw89_btc_ver *ver = btc->ver;
7152 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7153 	struct rtw89_btc_wl_link_info r = {0};
7154 	struct rtw89_btc_wl_link_info *wlinfo = NULL;
7155 	u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
7156 
7157 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
7158 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7159 		    "[BTC], role is STA=%d\n",
7160 		    vif->type == NL80211_IFTYPE_STATION);
7161 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
7162 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
7163 		    chan->band_type, chan->channel, chan->band_width);
7164 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
7165 		    state == BTC_ROLE_MSTS_STA_CONN_END);
7166 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7167 		    "[BTC], bcn_period=%d dtim_period=%d\n",
7168 		    vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
7169 
7170 	if (rtwsta) {
7171 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
7172 			    rtwsta->mac_id);
7173 
7174 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7175 			    "[BTC], STA support HE=%d VHT=%d HT=%d\n",
7176 			    sta->deflink.he_cap.has_he,
7177 			    sta->deflink.vht_cap.vht_supported,
7178 			    sta->deflink.ht_cap.ht_supported);
7179 		if (sta->deflink.he_cap.has_he)
7180 			mode |= BIT(BTC_WL_MODE_HE);
7181 		if (sta->deflink.vht_cap.vht_supported)
7182 			mode |= BIT(BTC_WL_MODE_VHT);
7183 		if (sta->deflink.ht_cap.ht_supported)
7184 			mode |= BIT(BTC_WL_MODE_HT);
7185 
7186 		r.mode = mode;
7187 	}
7188 
7189 	if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
7190 		return;
7191 
7192 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7193 		    "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
7194 
7195 	r.role = rtwvif->wifi_role;
7196 	r.phy = rtwvif->phy_idx;
7197 	r.pid = rtwvif->port;
7198 	r.active = true;
7199 	r.connected = MLME_LINKED;
7200 	r.bcn_period = vif->bss_conf.beacon_int;
7201 	r.dtim_period = vif->bss_conf.dtim_period;
7202 	r.band = chan->band_type;
7203 	r.ch = chan->channel;
7204 	r.bw = chan->band_width;
7205 	r.chdef.band = chan->band_type;
7206 	r.chdef.center_ch = chan->channel;
7207 	r.chdef.bw = chan->band_width;
7208 	r.chdef.chan = chan->primary_channel;
7209 	ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
7210 
7211 	if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
7212 		r.mac_id = rtwsta->mac_id;
7213 
7214 	btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
7215 
7216 	wlinfo = &wl->link_info[r.pid];
7217 
7218 	rlink_id = 0; /* to do */
7219 	if (ver->fwlrole == 0) {
7220 		*wlinfo = r;
7221 		_update_wl_info(rtwdev);
7222 	} else if (ver->fwlrole == 1) {
7223 		*wlinfo = r;
7224 		_update_wl_info_v1(rtwdev);
7225 	} else if (ver->fwlrole == 2) {
7226 		*wlinfo = r;
7227 		_update_wl_info_v2(rtwdev);
7228 	} else if (ver->fwlrole == 8) {
7229 		wlinfo = &wl->rlink_info[r.pid][rlink_id];
7230 		*wlinfo = r;
7231 		link_mode_ori = wl->role_info_v8.link_mode;
7232 		pta_req_mac_ori = wl->pta_req_mac;
7233 		_update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
7234 
7235 		if (wl->role_info_v8.link_mode != link_mode_ori) {
7236 			wl->role_info_v8.link_mode_chg = 1;
7237 			if (ver->fcxinit == 7)
7238 				wa_type = btc->mdinfo.md_v7.wa_type;
7239 			else
7240 				wa_type = btc->mdinfo.md.wa_type;
7241 
7242 			if (wa_type & BTC_WA_HFP_ZB)
7243 				_update_zb_coex_tbl(rtwdev);
7244 		}
7245 
7246 		if (wl->pta_req_mac != pta_req_mac_ori)
7247 			wl->pta_reg_mac_chg = 1;
7248 	}
7249 
7250 	if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
7251 	    wlinfo->connected == MLME_NO_LINK)
7252 		btc->dm.leak_ap = 0;
7253 
7254 	if (state == BTC_ROLE_MSTS_STA_CONN_START)
7255 		wl->status.map.connecting = 1;
7256 	else
7257 		wl->status.map.connecting = 0;
7258 
7259 	if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
7260 		wl->status.map._4way = false;
7261 
7262 	_run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
7263 }
7264 
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)7265 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
7266 {
7267 	const struct rtw89_chip_info *chip = rtwdev->chip;
7268 	struct rtw89_btc *btc = &rtwdev->btc;
7269 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7270 	u32 val;
7271 
7272 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
7273 		    __func__, rf_state);
7274 	btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
7275 
7276 	switch (rf_state) {
7277 	case BTC_RFCTRL_WL_OFF:
7278 		wl->status.map.rf_off = 1;
7279 		wl->status.map.lps = BTC_LPS_OFF;
7280 		wl->status.map.busy = 0;
7281 		break;
7282 	case BTC_RFCTRL_FW_CTRL:
7283 		wl->status.map.rf_off = 0;
7284 		wl->status.map.lps = BTC_LPS_RF_OFF;
7285 		wl->status.map.busy = 0;
7286 		break;
7287 	case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
7288 		wl->status.map.rf_off = 0;
7289 		wl->status.map.lps = BTC_LPS_RF_ON;
7290 		wl->status.map.busy = 0;
7291 		break;
7292 	case BTC_RFCTRL_WL_ON:
7293 	default:
7294 		wl->status.map.rf_off = 0;
7295 		wl->status.map.lps = BTC_LPS_OFF;
7296 		break;
7297 	}
7298 
7299 	if (rf_state == BTC_RFCTRL_WL_ON) {
7300 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true);
7301 		val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
7302 		_write_scbd(rtwdev, val, true);
7303 		_update_bt_scbd(rtwdev, true);
7304 		chip->ops->btc_init_cfg(rtwdev);
7305 	} else {
7306 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
7307 		if (rf_state == BTC_RFCTRL_FW_CTRL)
7308 			_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
7309 		else if (rf_state == BTC_RFCTRL_WL_OFF)
7310 			_write_scbd(rtwdev, BTC_WSCB_ALL, false);
7311 		else
7312 			_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
7313 
7314 		if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
7315 		    wl->status.map.lps_pre != BTC_LPS_OFF)
7316 			_update_bt_scbd(rtwdev, true);
7317 	}
7318 
7319 	btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
7320 	btc->dm.tdma_instant_excute = 1;
7321 
7322 	_run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
7323 	wl->status.map.rf_off_pre = wl->status.map.rf_off;
7324 	wl->status.map.lps_pre = wl->status.map.lps;
7325 }
7326 
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)7327 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
7328 			 enum btc_wl_rfk_type type,
7329 			 enum btc_wl_rfk_state state)
7330 {
7331 	struct rtw89_btc *btc = &rtwdev->btc;
7332 	struct rtw89_btc_cx *cx = &btc->cx;
7333 	struct rtw89_btc_wl_info *wl = &cx->wl;
7334 	bool result = BTC_WRFK_REJECT;
7335 
7336 	wl->rfk_info.type = type;
7337 	wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
7338 	wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
7339 	wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
7340 
7341 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7342 		    "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
7343 		    __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
7344 		    type, state);
7345 
7346 	switch (state) {
7347 	case BTC_WRFK_START:
7348 		result = _chk_wl_rfk_request(rtwdev);
7349 		wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
7350 
7351 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
7352 
7353 		btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
7354 		break;
7355 	case BTC_WRFK_ONESHOT_START:
7356 	case BTC_WRFK_ONESHOT_STOP:
7357 		if (wl->rfk_info.state == BTC_WRFK_STOP) {
7358 			result = BTC_WRFK_REJECT;
7359 		} else {
7360 			result = BTC_WRFK_ALLOW;
7361 			wl->rfk_info.state = state;
7362 		}
7363 		break;
7364 	case BTC_WRFK_STOP:
7365 		result = BTC_WRFK_ALLOW;
7366 		wl->rfk_info.state = BTC_WRFK_STOP;
7367 
7368 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
7369 		cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
7370 		break;
7371 	default:
7372 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7373 			    "[BTC], %s() warning state=%d\n", __func__, state);
7374 		break;
7375 	}
7376 
7377 	if (result == BTC_WRFK_ALLOW) {
7378 		if (wl->rfk_info.state == BTC_WRFK_START ||
7379 		    wl->rfk_info.state == BTC_WRFK_STOP)
7380 			_run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
7381 
7382 		if (wl->rfk_info.state == BTC_WRFK_START)
7383 			ieee80211_queue_delayed_work(rtwdev->hw,
7384 						     &rtwdev->coex_rfk_chk_work,
7385 						     RTW89_COEX_RFK_CHK_WORK_PERIOD);
7386 	}
7387 
7388 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7389 		    "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
7390 		    __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
7391 
7392 	return result == BTC_WRFK_ALLOW;
7393 }
7394 
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)7395 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
7396 			   enum btc_wl_rfk_type type,
7397 			   enum btc_wl_rfk_state state)
7398 {
7399 	u8 band;
7400 	bool allow;
7401 	int ret;
7402 
7403 	band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
7404 
7405 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
7406 		    "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
7407 		    band == RTW89_BAND_2G ? "2G" :
7408 		    band == RTW89_BAND_5G ? "5G" : "6G",
7409 		    !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
7410 		    type,
7411 		    FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
7412 		    state == BTC_WRFK_STOP ? "RFK_STOP" :
7413 		    state == BTC_WRFK_START ? "RFK_START" :
7414 		    state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
7415 		    "ONE-SHOT_STOP");
7416 
7417 	if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
7418 		_ntfy_wl_rfk(rtwdev, phy_map, type, state);
7419 		return;
7420 	}
7421 
7422 	ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
7423 				rtwdev, phy_map, type, state);
7424 	if (ret) {
7425 		rtw89_warn(rtwdev, "RFK notify timeout\n");
7426 		rtwdev->is_bt_iqk_timeout = true;
7427 	}
7428 }
7429 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
7430 
7431 struct rtw89_btc_wl_sta_iter_data {
7432 	struct rtw89_dev *rtwdev;
7433 	u8 busy_all;
7434 	u8 dir_all;
7435 	u8 rssi_map_all;
7436 	bool is_sta_change;
7437 	bool is_traffic_change;
7438 };
7439 
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)7440 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
7441 {
7442 	struct rtw89_btc_wl_sta_iter_data *iter_data =
7443 				(struct rtw89_btc_wl_sta_iter_data *)data;
7444 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
7445 	struct rtw89_btc *btc = &rtwdev->btc;
7446 	struct rtw89_btc_dm *dm = &btc->dm;
7447 	const struct rtw89_btc_ver *ver = btc->ver;
7448 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7449 	struct rtw89_btc_wl_link_info *link_info = NULL;
7450 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
7451 	struct rtw89_traffic_stats *link_info_t = NULL;
7452 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
7453 	struct rtw89_traffic_stats *stats = &rtwvif->stats;
7454 	const struct rtw89_chip_info *chip = rtwdev->chip;
7455 	struct rtw89_btc_wl_role_info *r;
7456 	struct rtw89_btc_wl_role_info_v1 *r1;
7457 	u32 last_tx_rate, last_rx_rate;
7458 	u16 last_tx_lvl, last_rx_lvl;
7459 	u8 port = rtwvif->port;
7460 	u8 rssi;
7461 	u8 busy = 0;
7462 	u8 dir = 0;
7463 	u8 rssi_map = 0;
7464 	u8 i = 0;
7465 	bool is_sta_change = false, is_traffic_change = false;
7466 
7467 	rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
7468 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
7469 
7470 	link_info = &wl->link_info[port];
7471 	link_info->stat.traffic = rtwvif->stats;
7472 	link_info_t = &link_info->stat.traffic;
7473 
7474 	if (link_info->connected == MLME_NO_LINK) {
7475 		link_info->rx_rate_drop_cnt = 0;
7476 		return;
7477 	}
7478 
7479 	link_info->stat.rssi = rssi;
7480 	for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
7481 		link_info->rssi_state[i] =
7482 			_update_rssi_state(rtwdev,
7483 					   link_info->rssi_state[i],
7484 					   link_info->stat.rssi,
7485 					   chip->wl_rssi_thres[i]);
7486 		if (BTC_RSSI_LOW(link_info->rssi_state[i]))
7487 			rssi_map |= BIT(i);
7488 
7489 		if (btc->ant_type == BTC_ANT_DEDICATED &&
7490 		    BTC_RSSI_CHANGE(link_info->rssi_state[i]))
7491 			is_sta_change = true;
7492 	}
7493 	iter_data->rssi_map_all |= rssi_map;
7494 
7495 	last_tx_rate = link_info_t->tx_rate;
7496 	last_rx_rate = link_info_t->rx_rate;
7497 	last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
7498 	last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
7499 
7500 	if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
7501 	    stats->rx_tfc_lv != RTW89_TFC_IDLE)
7502 		busy = 1;
7503 
7504 	if (stats->tx_tfc_lv > stats->rx_tfc_lv)
7505 		dir = RTW89_TFC_UL;
7506 	else
7507 		dir = RTW89_TFC_DL;
7508 
7509 	link_info = &wl->link_info[port];
7510 	if (link_info->busy != busy || link_info->dir != dir) {
7511 		is_sta_change = true;
7512 		link_info->busy = busy;
7513 		link_info->dir = dir;
7514 	}
7515 
7516 	iter_data->busy_all |= busy;
7517 	iter_data->dir_all |= BIT(dir);
7518 
7519 	if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
7520 	    last_rx_rate > RTW89_HW_RATE_CCK2 &&
7521 	    link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
7522 		link_info->rx_rate_drop_cnt++;
7523 
7524 	if (last_tx_rate != rtwsta->ra_report.hw_rate ||
7525 	    last_rx_rate != rtwsta->rx_hw_rate ||
7526 	    last_tx_lvl != link_info_t->tx_tfc_lv ||
7527 	    last_rx_lvl != link_info_t->rx_tfc_lv)
7528 		is_traffic_change = true;
7529 
7530 	link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
7531 	link_info_t->rx_rate = rtwsta->rx_hw_rate;
7532 
7533 	if (link_info->role == RTW89_WIFI_ROLE_STATION ||
7534 	    link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
7535 		dm->trx_info.tx_rate = link_info_t->tx_rate;
7536 		dm->trx_info.rx_rate = link_info_t->rx_rate;
7537 	}
7538 
7539 	if (ver->fwlrole == 0) {
7540 		r = &wl->role_info;
7541 		r->active_role[port].tx_lvl = stats->tx_tfc_lv;
7542 		r->active_role[port].rx_lvl = stats->rx_tfc_lv;
7543 		r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
7544 		r->active_role[port].rx_rate = rtwsta->rx_hw_rate;
7545 	} else if (ver->fwlrole == 1) {
7546 		r1 = &wl->role_info_v1;
7547 		r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
7548 		r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
7549 		r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate;
7550 		r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate;
7551 	} else if (ver->fwlrole == 2) {
7552 		dm->trx_info.tx_lvl = stats->tx_tfc_lv;
7553 		dm->trx_info.rx_lvl = stats->rx_tfc_lv;
7554 		dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate;
7555 		dm->trx_info.rx_rate = rtwsta->rx_hw_rate;
7556 	}
7557 
7558 	dm->trx_info.tx_tp = link_info_t->tx_throughput;
7559 	dm->trx_info.rx_tp = link_info_t->rx_throughput;
7560 
7561 	/* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
7562 	if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
7563 	     dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
7564 	     (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
7565 	      dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
7566 		iter_data->is_sta_change = true;
7567 
7568 	if (is_sta_change)
7569 		iter_data->is_sta_change = true;
7570 
7571 	if (is_traffic_change)
7572 		iter_data->is_traffic_change = true;
7573 }
7574 
7575 #define BTC_NHM_CHK_INTVL 20
7576 
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)7577 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
7578 {
7579 	struct rtw89_btc *btc = &rtwdev->btc;
7580 	struct rtw89_btc_dm *dm = &btc->dm;
7581 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7582 	struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
7583 	u8 i;
7584 
7585 	ieee80211_iterate_stations_atomic(rtwdev->hw,
7586 					  rtw89_btc_ntfy_wl_sta_iter,
7587 					  &data);
7588 
7589 	wl->rssi_level = 0;
7590 	btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
7591 	for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
7592 		/* set RSSI level 4 ~ 0 if rssi bit map match */
7593 		if (data.rssi_map_all & BIT(i - 1)) {
7594 			wl->rssi_level = i;
7595 			break;
7596 		}
7597 	}
7598 
7599 	if (dm->trx_info.wl_rssi != wl->rssi_level)
7600 		dm->trx_info.wl_rssi = wl->rssi_level;
7601 
7602 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
7603 		    __func__, !!wl->status.map.busy);
7604 
7605 	_write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
7606 
7607 	if (data.is_traffic_change)
7608 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
7609 	if (data.is_sta_change) {
7610 		wl->status.map.busy = data.busy_all;
7611 		wl->status.map.traffic_dir = data.dir_all;
7612 		_run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
7613 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
7614 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
7615 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
7616 			btc->dm.cnt_notify[BTC_NCNT_WL_STA];
7617 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
7618 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
7619 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
7620 		btc->dm.cnt_notify[BTC_NCNT_WL_STA];
7621 	}
7622 }
7623 
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)7624 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
7625 			  u32 len, u8 class, u8 func)
7626 {
7627 	struct rtw89_btc *btc = &rtwdev->btc;
7628 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
7629 	u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
7630 
7631 	len -= RTW89_C2H_HEADER_LEN;
7632 
7633 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7634 		    "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
7635 		    __func__, len, class, func);
7636 
7637 	if (class != BTFC_FW_EVENT)
7638 		return;
7639 
7640 	switch (func) {
7641 	case BTF_EVNT_RPT:
7642 	case BTF_EVNT_BUF_OVERFLOW:
7643 		pfwinfo->event[func]++;
7644 		/* Don't need rtw89_leave_ps_mode() */
7645 		btc_fw_event(rtwdev, func, buf, len);
7646 		break;
7647 	case BTF_EVNT_BT_INFO:
7648 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7649 			    "[BTC], handle C2H BT INFO with data %8ph\n", buf);
7650 		btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
7651 		_update_bt_info(rtwdev, buf, len);
7652 		break;
7653 	case BTF_EVNT_BT_SCBD:
7654 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7655 			    "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
7656 		btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
7657 		_update_bt_scbd(rtwdev, false);
7658 		break;
7659 	case BTF_EVNT_BT_PSD:
7660 		break;
7661 	case BTF_EVNT_BT_REG:
7662 		btc->dbg.rb_done = true;
7663 		btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
7664 
7665 		break;
7666 	case BTF_EVNT_C2H_LOOPBACK:
7667 		btc->dbg.rb_done = true;
7668 		btc->dbg.rb_val = buf[0];
7669 		break;
7670 	case BTF_EVNT_CX_RUNINFO:
7671 		btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
7672 		break;
7673 	}
7674 }
7675 
7676 #define BTC_CX_FW_OFFLOAD 0
7677 
_show_cx_info(struct rtw89_dev * rtwdev,struct seq_file * m)7678 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
7679 {
7680 	union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
7681 	const struct rtw89_chip_info *chip = rtwdev->chip;
7682 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
7683 	struct rtw89_hal *hal = &rtwdev->hal;
7684 	struct rtw89_btc *btc = &rtwdev->btc;
7685 	struct rtw89_btc_dm *dm = &btc->dm;
7686 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7687 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7688 	u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
7689 	u8 cv, rfe, iso, ant_num, ant_single_pos;
7690 
7691 	if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
7692 		return;
7693 
7694 	dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
7695 
7696 	seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
7697 		   chip->chip_id);
7698 
7699 	ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
7700 	ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
7701 	ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
7702 	id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
7703 	seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
7704 		   "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
7705 
7706 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
7707 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
7708 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
7709 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
7710 	seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
7711 		   ver_main, ver_sub, ver_hotfix, id_branch);
7712 
7713 	ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
7714 	ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
7715 	ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
7716 	seq_printf(m, "(%s, desired:%d.%d.%d), ",
7717 		   (wl->ver_info.fw_coex >= chip->wlcx_desired ?
7718 		   "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
7719 
7720 	seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
7721 		   bt->ver_info.fw_coex,
7722 		   (bt->ver_info.fw_coex >= chip->btcx_desired ?
7723 		   "Match" : "Mismatch"), chip->btcx_desired);
7724 
7725 	if (bt->enable.now && bt->ver_info.fw == 0)
7726 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
7727 	else
7728 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
7729 
7730 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
7731 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
7732 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
7733 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
7734 	seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
7735 		   "[sub_module]",
7736 		   ver_main, ver_sub, ver_hotfix, id_branch,
7737 		   bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
7738 
7739 	if (ver->fcxinit == 7) {
7740 		cv = md->md_v7.kt_ver;
7741 		rfe = md->md_v7.rfe_type;
7742 		iso = md->md_v7.ant.isolation;
7743 		ant_num = md->md_v7.ant.num;
7744 		ant_single_pos = md->md_v7.ant.single_pos;
7745 	} else {
7746 		cv = md->md.cv;
7747 		rfe = md->md.rfe_type;
7748 		iso = md->md.ant.isolation;
7749 		ant_num = md->md.ant.num;
7750 		ant_single_pos = md->md.ant.single_pos;
7751 	}
7752 
7753 	seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
7754 		   "[hw_info]", cv, rfe, iso, ant_num,
7755 		   ant_num > 1 ? "" :
7756 		   ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
7757 
7758 	seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
7759 		   btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
7760 		   hal->rx_nss);
7761 }
7762 
_show_wl_role_info(struct rtw89_dev * rtwdev,struct seq_file * m)7763 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
7764 {
7765 	struct rtw89_btc *btc = &rtwdev->btc;
7766 	struct rtw89_btc_wl_link_info *plink = NULL;
7767 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7768 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
7769 	struct rtw89_traffic_stats *t;
7770 	u8 i;
7771 
7772 	if (rtwdev->dbcc_en) {
7773 		seq_printf(m,
7774 			   " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
7775 			   "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
7776 			   wl_dinfo->scan_band[RTW89_PHY_0],
7777 			   wl_dinfo->real_band[RTW89_PHY_0]);
7778 		seq_printf(m,
7779 			   "PHY1_band(op:%d/scan:%d/real:%d)\n",
7780 			   wl_dinfo->op_band[RTW89_PHY_1],
7781 			   wl_dinfo->scan_band[RTW89_PHY_1],
7782 			   wl_dinfo->real_band[RTW89_PHY_1]);
7783 	}
7784 
7785 	for (i = 0; i < RTW89_PORT_NUM; i++) {
7786 		if (btc->ver->fwlrole == 8)
7787 			plink = &btc->cx.wl.rlink_info[i][0];
7788 		else
7789 			plink = &btc->cx.wl.link_info[i];
7790 
7791 		if (!plink->active)
7792 			continue;
7793 
7794 		seq_printf(m,
7795 			   " [port_%d]        : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
7796 			   plink->pid, (u32)plink->role, plink->phy,
7797 			   (u32)plink->connected, plink->client_cnt - 1,
7798 			   (u32)plink->mode, plink->ch, (u32)plink->bw);
7799 
7800 		if (plink->connected == MLME_NO_LINK)
7801 			continue;
7802 
7803 		seq_printf(m,
7804 			   ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
7805 			   plink->mac_id, plink->tx_time, plink->tx_retry);
7806 
7807 		seq_printf(m,
7808 			   " [port_%d]        : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
7809 			   plink->pid, 110 - plink->stat.rssi,
7810 			   plink->stat.rssi, plink->busy,
7811 			   plink->dir == RTW89_TFC_UL ? "UL" : "DL");
7812 
7813 		t = &plink->stat.traffic;
7814 
7815 		seq_printf(m,
7816 			   "tx[rate:%d/busy_level:%d], ",
7817 			   (u32)t->tx_rate, t->tx_tfc_lv);
7818 
7819 		seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
7820 			   (u32)t->rx_rate,
7821 			   t->rx_tfc_lv, plink->rx_rate_drop_cnt);
7822 	}
7823 }
7824 
_show_wl_info(struct rtw89_dev * rtwdev,struct seq_file * m)7825 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
7826 {
7827 	struct rtw89_btc *btc = &rtwdev->btc;
7828 	const struct rtw89_btc_ver *ver = btc->ver;
7829 	struct rtw89_btc_cx *cx = &btc->cx;
7830 	struct rtw89_btc_wl_info *wl = &cx->wl;
7831 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7832 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
7833 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
7834 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
7835 	u8 mode;
7836 
7837 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
7838 		return;
7839 
7840 	seq_puts(m, "========== [WL Status] ==========\n");
7841 
7842 	if (ver->fwlrole == 0)
7843 		mode = wl_rinfo->link_mode;
7844 	else if (ver->fwlrole == 1)
7845 		mode = wl_rinfo_v1->link_mode;
7846 	else if (ver->fwlrole == 2)
7847 		mode = wl_rinfo_v2->link_mode;
7848 	else if (ver->fwlrole == 8)
7849 		mode = wl_rinfo_v8->link_mode;
7850 	else
7851 		return;
7852 
7853 	seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
7854 
7855 	seq_printf(m,
7856 		   "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
7857 		   wl->status.map.rf_off, wl->status.map.lps,
7858 		   wl->status.map.scan ? "Y" : "N",
7859 		   wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
7860 
7861 	seq_printf(m,
7862 		   "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
7863 		   wl->status.map.connecting ? "Y" : "N",
7864 		   wl->status.map.roaming ?  "Y" : "N",
7865 		   wl->status.map._4way ? "Y" : "N",
7866 		   wl->status.map.init_ok ? "Y" : "N");
7867 
7868 	_show_wl_role_info(rtwdev, m);
7869 }
7870 
7871 enum btc_bt_a2dp_type {
7872 	BTC_A2DP_LEGACY = 0,
7873 	BTC_A2DP_TWS_SNIFF = 1,
7874 	BTC_A2DP_TWS_RELAY = 2,
7875 };
7876 
_show_bt_profile_info(struct rtw89_dev * rtwdev,struct seq_file * m)7877 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
7878 {
7879 	struct rtw89_btc *btc = &rtwdev->btc;
7880 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
7881 	struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
7882 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
7883 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
7884 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
7885 
7886 	if (hfp.exist) {
7887 		seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
7888 			   "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
7889 			   bt_linfo->sut_pwr_level[0],
7890 			   bt_linfo->golden_rx_shift[0]);
7891 	}
7892 
7893 	if (hid.exist) {
7894 		seq_printf(m,
7895 			   "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
7896 			   "[HID]",
7897 			   hid.type & BTC_HID_218 ? "2/18," : "",
7898 			   hid.type & BTC_HID_418 ? "4/18," : "",
7899 			   hid.type & BTC_HID_BLE ? "BLE," : "",
7900 			   hid.type & BTC_HID_RCU ? "RCU," : "",
7901 			   hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
7902 			   hid.pair_cnt, bt_linfo->sut_pwr_level[1],
7903 			   bt_linfo->golden_rx_shift[1]);
7904 	}
7905 
7906 	if (a2dp.exist) {
7907 		seq_printf(m,
7908 			   " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
7909 			   "[A2DP]",
7910 			   a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
7911 			    a2dp.bitpool, a2dp.flush_time);
7912 
7913 		seq_printf(m,
7914 			   "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
7915 			   a2dp.vendor_id, a2dp.device_name,
7916 			   bt_linfo->sut_pwr_level[2],
7917 			   bt_linfo->golden_rx_shift[2]);
7918 	}
7919 
7920 	if (pan.exist) {
7921 		seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
7922 			   "[PAN]",
7923 			   bt_linfo->sut_pwr_level[3],
7924 			   bt_linfo->golden_rx_shift[3]);
7925 	}
7926 }
7927 
_show_bt_info(struct rtw89_dev * rtwdev,struct seq_file * m)7928 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
7929 {
7930 	struct rtw89_btc *btc = &rtwdev->btc;
7931 	const struct rtw89_btc_ver *ver = btc->ver;
7932 	struct rtw89_btc_cx *cx = &btc->cx;
7933 	struct rtw89_btc_bt_info *bt = &cx->bt;
7934 	struct rtw89_btc_wl_info *wl = &cx->wl;
7935 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
7936 	union rtw89_btc_module_info *md = &btc->mdinfo;
7937 	u8 *afh = bt_linfo->afh_map;
7938 	u8 *afh_le = bt_linfo->afh_map_le;
7939 	u8 bt_pos;
7940 
7941 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
7942 		return;
7943 
7944 	if (ver->fcxinit == 7)
7945 		bt_pos = md->md_v7.bt_pos;
7946 	else
7947 		bt_pos = md->md.bt_pos;
7948 
7949 	seq_puts(m, "========== [BT Status] ==========\n");
7950 
7951 	seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
7952 		   "[status]", bt->enable.now ? "Y" : "N",
7953 		   bt->btg_type ? "Y" : "N",
7954 		   (bt->enable.now && (bt->btg_type != bt_pos) ?
7955 		   "(efuse-mismatch!!)" : ""),
7956 		   (bt_linfo->status.map.connect ? "Y" : "N"));
7957 
7958 	seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
7959 		   bt->igno_wl ? "Y" : "N",
7960 		   bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
7961 
7962 	seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
7963 		   "[profile]",
7964 		   (bt_linfo->profile_cnt.now == 0) ? "None," : "",
7965 		   bt_linfo->hfp_desc.exist ? "HFP," : "",
7966 		   bt_linfo->hid_desc.exist ? "HID," : "",
7967 		   bt_linfo->a2dp_desc.exist ?
7968 		   (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
7969 		   bt_linfo->pan_desc.exist ? "PAN," : "");
7970 
7971 	seq_printf(m,
7972 		   "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
7973 		   bt_linfo->multi_link.now ? "Y" : "N",
7974 		   bt_linfo->slave_role ? "Slave" : "Master",
7975 		   bt_linfo->status.map.ble_connect ? "Y" : "N",
7976 		   bt_linfo->cqddr ? "Y" : "N",
7977 		   bt_linfo->a2dp_desc.active ? "Y" : "N",
7978 		   bt_linfo->pan_desc.active ? "Y" : "N");
7979 
7980 	seq_printf(m,
7981 		   " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
7982 		   "[link]", bt_linfo->rssi - 100,
7983 		   bt->rssi_level,
7984 		   bt_linfo->tx_3m ? 3 : 2,
7985 		   bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
7986 		   bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
7987 		   bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
7988 
7989 	seq_printf(m,
7990 		   "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
7991 		   bt_linfo->relink.now ? " ReLink!!" : "",
7992 		   afh[0], afh[1], afh[2], afh[3], afh[4],
7993 		   afh[5], afh[6], afh[7], afh[8], afh[9]);
7994 
7995 	if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
7996 		seq_printf(m,
7997 			   "LE[%02x%02x_%02x_%02x%02x]",
7998 			   afh_le[0], afh_le[1], afh_le[2],
7999 			   afh_le[3], afh_le[4]);
8000 
8001 	seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
8002 		   wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
8003 
8004 	seq_printf(m,
8005 		   " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
8006 		   "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
8007 		   cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
8008 		   cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
8009 
8010 	seq_printf(m,
8011 		   "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
8012 		   cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
8013 		   cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
8014 		   cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
8015 
8016 	_show_bt_profile_info(rtwdev, m);
8017 
8018 	seq_printf(m,
8019 		   " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
8020 		   "[bt_info]", bt->raw_info[2], bt->raw_info[3],
8021 		   bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
8022 		   bt->raw_info[7],
8023 		   bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
8024 		   cx->cnt_bt[BTC_BCNT_INFOUPDATE],
8025 		   cx->cnt_bt[BTC_BCNT_INFOSAME]);
8026 
8027 	seq_printf(m,
8028 		   " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
8029 		   "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
8030 		   cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
8031 		   cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
8032 
8033 	if (!bt->scan_info_update) {
8034 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true);
8035 		seq_puts(m, "\n");
8036 	} else {
8037 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false);
8038 		if (ver->fcxbtscan == 1) {
8039 			seq_printf(m,
8040 				   "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
8041 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
8042 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
8043 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
8044 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
8045 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
8046 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
8047 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
8048 				   le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
8049 		} else if (ver->fcxbtscan == 2) {
8050 			seq_printf(m,
8051 				   "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
8052 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
8053 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
8054 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
8055 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
8056 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
8057 				   le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
8058 		}
8059 		seq_puts(m, "\n");
8060 	}
8061 
8062 	if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect)
8063 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true);
8064 	else
8065 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false);
8066 
8067 	if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
8068 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true);
8069 	else
8070 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false);
8071 
8072 	if (bt_linfo->a2dp_desc.exist &&
8073 	    (bt_linfo->a2dp_desc.flush_time == 0 ||
8074 	     bt_linfo->a2dp_desc.vendor_id == 0 ||
8075 	     bt_linfo->a2dp_desc.play_latency == 1))
8076 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true);
8077 	else
8078 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false);
8079 }
8080 
8081 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
8082 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
8083 #define CASE_BTC_POLICY_STR(e) \
8084 	case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
8085 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
8086 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
8087 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
8088 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
8089 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
8090 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
8091 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
8092 
id_to_polut(u32 id)8093 static const char *id_to_polut(u32 id)
8094 {
8095 	switch (id) {
8096 	CASE_BTC_POLUT_STR(NONE);
8097 	CASE_BTC_POLUT_STR(GNT_BT_TX);
8098 	CASE_BTC_POLUT_STR(GNT_BT_RX);
8099 	CASE_BTC_POLUT_STR(GNT_WL);
8100 	CASE_BTC_POLUT_STR(BT);
8101 	CASE_BTC_POLUT_STR(ALL);
8102 	default:
8103 		return "unknown";
8104 	}
8105 }
8106 
id_to_regtype(u32 id)8107 static const char *id_to_regtype(u32 id)
8108 {
8109 	switch (id) {
8110 	CASE_BTC_REGTYPE_STR(MAC);
8111 	CASE_BTC_REGTYPE_STR(BB);
8112 	CASE_BTC_REGTYPE_STR(RF);
8113 	CASE_BTC_REGTYPE_STR(BT_RF);
8114 	CASE_BTC_REGTYPE_STR(BT_MODEM);
8115 	CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
8116 	CASE_BTC_REGTYPE_STR(BT_VENDOR);
8117 	CASE_BTC_REGTYPE_STR(BT_LE);
8118 	default:
8119 		return "unknown";
8120 	}
8121 }
8122 
id_to_gdbg(u32 id)8123 static const char *id_to_gdbg(u32 id)
8124 {
8125 	switch (id) {
8126 	CASE_BTC_GDBG_STR(GNT_BT);
8127 	CASE_BTC_GDBG_STR(GNT_WL);
8128 	CASE_BTC_GDBG_STR(BCN_EARLY);
8129 	CASE_BTC_GDBG_STR(WL_NULL0);
8130 	CASE_BTC_GDBG_STR(WL_NULL1);
8131 	CASE_BTC_GDBG_STR(WL_RXISR);
8132 	CASE_BTC_GDBG_STR(TDMA_ENTRY);
8133 	CASE_BTC_GDBG_STR(A2DP_EMPTY);
8134 	CASE_BTC_GDBG_STR(BT_RETRY);
8135 	CASE_BTC_GDBG_STR(BT_RELINK);
8136 	CASE_BTC_GDBG_STR(SLOT_WL);
8137 	CASE_BTC_GDBG_STR(SLOT_BT);
8138 	CASE_BTC_GDBG_STR(WL_ERR);
8139 	CASE_BTC_GDBG_STR(WL_OK);
8140 	CASE_BTC_GDBG_STR(SLOT_B2W);
8141 	CASE_BTC_GDBG_STR(SLOT_W1);
8142 	CASE_BTC_GDBG_STR(SLOT_W2);
8143 	CASE_BTC_GDBG_STR(SLOT_W2B);
8144 	CASE_BTC_GDBG_STR(SLOT_B1);
8145 	CASE_BTC_GDBG_STR(SLOT_B2);
8146 	CASE_BTC_GDBG_STR(SLOT_B3);
8147 	CASE_BTC_GDBG_STR(SLOT_B4);
8148 	CASE_BTC_GDBG_STR(SLOT_LK);
8149 	CASE_BTC_GDBG_STR(SLOT_E2G);
8150 	CASE_BTC_GDBG_STR(SLOT_E5G);
8151 	CASE_BTC_GDBG_STR(SLOT_EBT);
8152 	CASE_BTC_GDBG_STR(SLOT_WLK);
8153 	CASE_BTC_GDBG_STR(SLOT_B1FDD);
8154 	CASE_BTC_GDBG_STR(BT_CHANGE);
8155 	CASE_BTC_GDBG_STR(WL_CCA);
8156 	CASE_BTC_GDBG_STR(BT_LEAUDIO);
8157 	CASE_BTC_GDBG_STR(USER_DEF);
8158 	default:
8159 		return "unknown";
8160 	}
8161 }
8162 
steps_to_str(u16 step)8163 static const char *steps_to_str(u16 step)
8164 {
8165 	switch (step) {
8166 	CASE_BTC_RSN_STR(NONE);
8167 	CASE_BTC_RSN_STR(NTFY_INIT);
8168 	CASE_BTC_RSN_STR(NTFY_SWBAND);
8169 	CASE_BTC_RSN_STR(NTFY_WL_STA);
8170 	CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
8171 	CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
8172 	CASE_BTC_RSN_STR(NTFY_WL_RFK);
8173 	CASE_BTC_RSN_STR(UPDATE_BT_INFO);
8174 	CASE_BTC_RSN_STR(NTFY_SCAN_START);
8175 	CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
8176 	CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
8177 	CASE_BTC_RSN_STR(NTFY_POWEROFF);
8178 	CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
8179 	CASE_BTC_RSN_STR(CMD_SET_COEX);
8180 	CASE_BTC_RSN_STR(ACT1_WORK);
8181 	CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
8182 	CASE_BTC_RSN_STR(RFK_CHK_WORK);
8183 
8184 	CASE_BTC_ACT_STR(NONE);
8185 	CASE_BTC_ACT_STR(WL_ONLY);
8186 	CASE_BTC_ACT_STR(WL_5G);
8187 	CASE_BTC_ACT_STR(WL_OTHER);
8188 	CASE_BTC_ACT_STR(WL_IDLE);
8189 	CASE_BTC_ACT_STR(WL_NC);
8190 	CASE_BTC_ACT_STR(WL_RFK);
8191 	CASE_BTC_ACT_STR(WL_INIT);
8192 	CASE_BTC_ACT_STR(WL_OFF);
8193 	CASE_BTC_ACT_STR(FREERUN);
8194 	CASE_BTC_ACT_STR(BT_WHQL);
8195 	CASE_BTC_ACT_STR(BT_RFK);
8196 	CASE_BTC_ACT_STR(BT_OFF);
8197 	CASE_BTC_ACT_STR(BT_IDLE);
8198 	CASE_BTC_ACT_STR(BT_HFP);
8199 	CASE_BTC_ACT_STR(BT_HID);
8200 	CASE_BTC_ACT_STR(BT_A2DP);
8201 	CASE_BTC_ACT_STR(BT_A2DPSINK);
8202 	CASE_BTC_ACT_STR(BT_PAN);
8203 	CASE_BTC_ACT_STR(BT_A2DP_HID);
8204 	CASE_BTC_ACT_STR(BT_A2DP_PAN);
8205 	CASE_BTC_ACT_STR(BT_PAN_HID);
8206 	CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
8207 	CASE_BTC_ACT_STR(WL_25G_MCC);
8208 	CASE_BTC_ACT_STR(WL_2G_MCC);
8209 	CASE_BTC_ACT_STR(WL_2G_SCC);
8210 	CASE_BTC_ACT_STR(WL_2G_AP);
8211 	CASE_BTC_ACT_STR(WL_2G_GO);
8212 	CASE_BTC_ACT_STR(WL_2G_GC);
8213 	CASE_BTC_ACT_STR(WL_2G_NAN);
8214 
8215 	CASE_BTC_POLICY_STR(OFF_BT);
8216 	CASE_BTC_POLICY_STR(OFF_WL);
8217 	CASE_BTC_POLICY_STR(OFF_EQ0);
8218 	CASE_BTC_POLICY_STR(OFF_EQ1);
8219 	CASE_BTC_POLICY_STR(OFF_EQ2);
8220 	CASE_BTC_POLICY_STR(OFF_EQ3);
8221 	CASE_BTC_POLICY_STR(OFF_EQ4);
8222 	CASE_BTC_POLICY_STR(OFF_EQ5);
8223 	CASE_BTC_POLICY_STR(OFF_BWB0);
8224 	CASE_BTC_POLICY_STR(OFF_BWB1);
8225 	CASE_BTC_POLICY_STR(OFF_BWB2);
8226 	CASE_BTC_POLICY_STR(OFF_BWB3);
8227 	CASE_BTC_POLICY_STR(OFF_WL2);
8228 	CASE_BTC_POLICY_STR(OFFB_BWB0);
8229 	CASE_BTC_POLICY_STR(OFFE_DEF);
8230 	CASE_BTC_POLICY_STR(OFFE_DEF2);
8231 	CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
8232 	CASE_BTC_POLICY_STR(OFFE_2GISOB);
8233 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
8234 	CASE_BTC_POLICY_STR(OFFE_WL);
8235 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
8236 	CASE_BTC_POLICY_STR(FIX_TD3030);
8237 	CASE_BTC_POLICY_STR(FIX_TD5050);
8238 	CASE_BTC_POLICY_STR(FIX_TD2030);
8239 	CASE_BTC_POLICY_STR(FIX_TD4010);
8240 	CASE_BTC_POLICY_STR(FIX_TD7010);
8241 	CASE_BTC_POLICY_STR(FIX_TD2060);
8242 	CASE_BTC_POLICY_STR(FIX_TD3060);
8243 	CASE_BTC_POLICY_STR(FIX_TD2080);
8244 	CASE_BTC_POLICY_STR(FIX_TDW1B1);
8245 	CASE_BTC_POLICY_STR(FIX_TD4010ISO);
8246 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
8247 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
8248 	CASE_BTC_POLICY_STR(PFIX_TD3030);
8249 	CASE_BTC_POLICY_STR(PFIX_TD5050);
8250 	CASE_BTC_POLICY_STR(PFIX_TD2030);
8251 	CASE_BTC_POLICY_STR(PFIX_TD2060);
8252 	CASE_BTC_POLICY_STR(PFIX_TD3070);
8253 	CASE_BTC_POLICY_STR(PFIX_TD2080);
8254 	CASE_BTC_POLICY_STR(PFIX_TDW1B1);
8255 	CASE_BTC_POLICY_STR(AUTO_TD50B1);
8256 	CASE_BTC_POLICY_STR(AUTO_TD60B1);
8257 	CASE_BTC_POLICY_STR(AUTO_TD20B1);
8258 	CASE_BTC_POLICY_STR(AUTO_TDW1B1);
8259 	CASE_BTC_POLICY_STR(PAUTO_TD50B1);
8260 	CASE_BTC_POLICY_STR(PAUTO_TD60B1);
8261 	CASE_BTC_POLICY_STR(PAUTO_TD20B1);
8262 	CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
8263 	CASE_BTC_POLICY_STR(AUTO2_TD3050);
8264 	CASE_BTC_POLICY_STR(AUTO2_TD3070);
8265 	CASE_BTC_POLICY_STR(AUTO2_TD5050);
8266 	CASE_BTC_POLICY_STR(AUTO2_TD6060);
8267 	CASE_BTC_POLICY_STR(AUTO2_TD2080);
8268 	CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
8269 	CASE_BTC_POLICY_STR(PAUTO2_TD3050);
8270 	CASE_BTC_POLICY_STR(PAUTO2_TD3070);
8271 	CASE_BTC_POLICY_STR(PAUTO2_TD5050);
8272 	CASE_BTC_POLICY_STR(PAUTO2_TD6060);
8273 	CASE_BTC_POLICY_STR(PAUTO2_TD2080);
8274 	CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
8275 	default:
8276 		return "unknown step";
8277 	}
8278 }
8279 
id_to_slot(u32 id)8280 static const char *id_to_slot(u32 id)
8281 {
8282 	switch (id) {
8283 	CASE_BTC_SLOT_STR(OFF);
8284 	CASE_BTC_SLOT_STR(B2W);
8285 	CASE_BTC_SLOT_STR(W1);
8286 	CASE_BTC_SLOT_STR(W2);
8287 	CASE_BTC_SLOT_STR(W2B);
8288 	CASE_BTC_SLOT_STR(B1);
8289 	CASE_BTC_SLOT_STR(B2);
8290 	CASE_BTC_SLOT_STR(B3);
8291 	CASE_BTC_SLOT_STR(B4);
8292 	CASE_BTC_SLOT_STR(LK);
8293 	CASE_BTC_SLOT_STR(BLK);
8294 	CASE_BTC_SLOT_STR(E2G);
8295 	CASE_BTC_SLOT_STR(E5G);
8296 	CASE_BTC_SLOT_STR(EBT);
8297 	CASE_BTC_SLOT_STR(ENULL);
8298 	CASE_BTC_SLOT_STR(WLK);
8299 	CASE_BTC_SLOT_STR(W1FDD);
8300 	CASE_BTC_SLOT_STR(B1FDD);
8301 	default:
8302 		return "unknown";
8303 	}
8304 }
8305 
id_to_evt(u32 id)8306 static const char *id_to_evt(u32 id)
8307 {
8308 	switch (id) {
8309 	CASE_BTC_EVT_STR(TDMA_ENTRY);
8310 	CASE_BTC_EVT_STR(WL_TMR);
8311 	CASE_BTC_EVT_STR(B1_TMR);
8312 	CASE_BTC_EVT_STR(B2_TMR);
8313 	CASE_BTC_EVT_STR(B3_TMR);
8314 	CASE_BTC_EVT_STR(B4_TMR);
8315 	CASE_BTC_EVT_STR(W2B_TMR);
8316 	CASE_BTC_EVT_STR(B2W_TMR);
8317 	CASE_BTC_EVT_STR(BCN_EARLY);
8318 	CASE_BTC_EVT_STR(A2DP_EMPTY);
8319 	CASE_BTC_EVT_STR(LK_END);
8320 	CASE_BTC_EVT_STR(RX_ISR);
8321 	CASE_BTC_EVT_STR(RX_FC0);
8322 	CASE_BTC_EVT_STR(RX_FC1);
8323 	CASE_BTC_EVT_STR(BT_RELINK);
8324 	CASE_BTC_EVT_STR(BT_RETRY);
8325 	CASE_BTC_EVT_STR(E2G);
8326 	CASE_BTC_EVT_STR(E5G);
8327 	CASE_BTC_EVT_STR(EBT);
8328 	CASE_BTC_EVT_STR(ENULL);
8329 	CASE_BTC_EVT_STR(DRV_WLK);
8330 	CASE_BTC_EVT_STR(BCN_OK);
8331 	CASE_BTC_EVT_STR(BT_CHANGE);
8332 	CASE_BTC_EVT_STR(EBT_EXTEND);
8333 	CASE_BTC_EVT_STR(E2G_NULL1);
8334 	CASE_BTC_EVT_STR(B1FDD_TMR);
8335 	default:
8336 		return "unknown";
8337 	}
8338 }
8339 
id_to_mode(u8 id)8340 static const char *id_to_mode(u8 id)
8341 {
8342 	switch (id) {
8343 	CASE_BTC_INIT(NORMAL);
8344 	CASE_BTC_INIT(WL);
8345 	CASE_BTC_INIT(BT);
8346 	CASE_BTC_INIT(WLOFF);
8347 	default:
8348 		return "unknown";
8349 	}
8350 }
8351 
id_to_ant(u32 id)8352 static const char *id_to_ant(u32 id)
8353 {
8354 	switch (id) {
8355 	CASE_BTC_ANTPATH_STR(WPOWERON);
8356 	CASE_BTC_ANTPATH_STR(WINIT);
8357 	CASE_BTC_ANTPATH_STR(WONLY);
8358 	CASE_BTC_ANTPATH_STR(WOFF);
8359 	CASE_BTC_ANTPATH_STR(W2G);
8360 	CASE_BTC_ANTPATH_STR(W5G);
8361 	CASE_BTC_ANTPATH_STR(W25G);
8362 	CASE_BTC_ANTPATH_STR(FREERUN);
8363 	CASE_BTC_ANTPATH_STR(WRFK);
8364 	CASE_BTC_ANTPATH_STR(BRFK);
8365 	CASE_BTC_ANTPATH_STR(MAX);
8366 	default:
8367 		return "unknown";
8368 	}
8369 }
8370 
8371 static
seq_print_segment(struct seq_file * m,const char * prefix,u16 * data,u8 len,u8 seg_len,u8 start_idx,u8 ring_len)8372 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
8373 		       u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
8374 {
8375 	u8 i;
8376 	u8 cur_index;
8377 
8378 	for (i = 0; i < len ; i++) {
8379 		if ((i % seg_len) == 0)
8380 			seq_printf(m, " %-15s : ", prefix);
8381 		cur_index = (start_idx + i) % ring_len;
8382 		if (i % 3 == 0)
8383 			seq_printf(m, "-> %-20s",
8384 				   steps_to_str(*(data + cur_index)));
8385 		else if (i % 3 == 1)
8386 			seq_printf(m, "-> %-15s",
8387 				   steps_to_str(*(data + cur_index)));
8388 		else
8389 			seq_printf(m, "-> %-13s",
8390 				   steps_to_str(*(data + cur_index)));
8391 		if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
8392 			seq_puts(m, "\n");
8393 	}
8394 }
8395 
_show_dm_step(struct rtw89_dev * rtwdev,struct seq_file * m)8396 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
8397 {
8398 	struct rtw89_btc *btc = &rtwdev->btc;
8399 	struct rtw89_btc_dm *dm = &btc->dm;
8400 	u8 start_idx;
8401 	u8 len;
8402 
8403 	len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
8404 	start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
8405 
8406 	seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
8407 			  ARRAY_SIZE(dm->dm_step.step));
8408 }
8409 
_show_dm_info(struct rtw89_dev * rtwdev,struct seq_file * m)8410 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
8411 {
8412 	struct rtw89_btc *btc = &rtwdev->btc;
8413 	const struct rtw89_btc_ver *ver = btc->ver;
8414 	struct rtw89_btc_dm *dm = &btc->dm;
8415 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8416 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8417 	u8 igno_bt;
8418 
8419 	if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
8420 		return;
8421 
8422 	seq_printf(m, "========== [Mechanism Status %s] ==========\n",
8423 		   (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
8424 
8425 	seq_printf(m,
8426 		   " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
8427 		   "[status]",
8428 		   btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
8429 		   steps_to_str(dm->run_reason),
8430 		   steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
8431 		   id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
8432 		   id_to_mode(wl->coex_mode),
8433 		   dm->cnt_dm[BTC_DCNT_RUN]);
8434 
8435 	_show_dm_step(rtwdev, m);
8436 
8437 	if (ver->fcxctrl == 7)
8438 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
8439 	else
8440 		igno_bt = btc->ctrl.ctrl.igno_bt;
8441 
8442 	seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
8443 		   "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt,
8444 		   dm->freerun, btc->lps, dm->wl_mimo_ps);
8445 
8446 	seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
8447 		   (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
8448 		   (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
8449 		    "" : "(Mismatch!!)"));
8450 
8451 	if (dm->rf_trx_para.wl_tx_power == 0xff)
8452 		seq_printf(m,
8453 			   " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
8454 			   "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
8455 
8456 	else
8457 		seq_printf(m,
8458 			   " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
8459 			   "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
8460 			   dm->rf_trx_para.wl_tx_power);
8461 
8462 	seq_printf(m,
8463 		   "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
8464 		   dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
8465 		   dm->rf_trx_para.bt_rx_gain,
8466 		   (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
8467 
8468 	seq_printf(m,
8469 		   " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
8470 		   "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
8471 		   dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri);
8472 }
8473 
_show_error(struct rtw89_dev * rtwdev,struct seq_file * m)8474 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
8475 {
8476 	struct rtw89_btc *btc = &rtwdev->btc;
8477 	const struct rtw89_btc_ver *ver = btc->ver;
8478 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8479 	union rtw89_btc_fbtc_cysta_info *pcysta;
8480 	u32 except_cnt, exception_map;
8481 
8482 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
8483 	if (ver->fcxcysta == 2) {
8484 		pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
8485 		except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
8486 		exception_map = le32_to_cpu(pcysta->v2.exception);
8487 	} else if (ver->fcxcysta == 3) {
8488 		pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
8489 		except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
8490 		exception_map = le32_to_cpu(pcysta->v3.except_map);
8491 	} else if (ver->fcxcysta == 4) {
8492 		pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
8493 		except_cnt = pcysta->v4.except_cnt;
8494 		exception_map = le32_to_cpu(pcysta->v4.except_map);
8495 	} else if (ver->fcxcysta == 5) {
8496 		pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
8497 		except_cnt = pcysta->v5.except_cnt;
8498 		exception_map = le32_to_cpu(pcysta->v5.except_map);
8499 	} else if (ver->fcxcysta == 7) {
8500 		pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
8501 		except_cnt = pcysta->v7.except_cnt;
8502 		exception_map = le32_to_cpu(pcysta->v7.except_map);
8503 	} else {
8504 		return;
8505 	}
8506 
8507 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
8508 	    !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
8509 		return;
8510 
8511 	seq_printf(m, " %-15s : ", "[error]");
8512 
8513 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
8514 		seq_printf(m,
8515 			   "overflow-cnt: %d, ",
8516 			   pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
8517 	}
8518 
8519 	if (pfwinfo->len_mismch) {
8520 		seq_printf(m,
8521 			   "len-mismatch: 0x%x, ",
8522 			   pfwinfo->len_mismch);
8523 	}
8524 
8525 	if (pfwinfo->fver_mismch) {
8526 		seq_printf(m,
8527 			   "fver-mismatch: 0x%x, ",
8528 			   pfwinfo->fver_mismch);
8529 	}
8530 
8531 	/* cycle statistics exceptions */
8532 	if (exception_map || except_cnt) {
8533 		seq_printf(m,
8534 			   "exception-type: 0x%x, exception-cnt = %d",
8535 			   exception_map, except_cnt);
8536 	}
8537 	seq_puts(m, "\n");
8538 }
8539 
_show_fbtc_tdma(struct rtw89_dev * rtwdev,struct seq_file * m)8540 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
8541 {
8542 	struct rtw89_btc *btc = &rtwdev->btc;
8543 	const struct rtw89_btc_ver *ver = btc->ver;
8544 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8545 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
8546 	struct rtw89_btc_fbtc_tdma *t = NULL;
8547 
8548 	pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
8549 	if (!pcinfo->valid)
8550 		return;
8551 
8552 	if (ver->fcxtdma == 1)
8553 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
8554 	else
8555 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
8556 
8557 	seq_printf(m,
8558 		   " %-15s : ", "[tdma_policy]");
8559 	seq_printf(m,
8560 		   "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
8561 		   (u32)t->type,
8562 		   t->rxflctrl, t->txpause);
8563 
8564 	seq_printf(m,
8565 		   "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
8566 		   t->wtgle_n, t->leak_n, t->ext_ctrl);
8567 
8568 	seq_printf(m,
8569 		   "policy_type:%d",
8570 		   (u32)btc->policy_type);
8571 
8572 	seq_puts(m, "\n");
8573 }
8574 
_show_fbtc_slots(struct rtw89_dev * rtwdev,struct seq_file * m)8575 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
8576 {
8577 	struct rtw89_btc *btc = &rtwdev->btc;
8578 	struct rtw89_btc_dm *dm = &btc->dm;
8579 	u16 dur, cxtype;
8580 	u32 tbl;
8581 	u8 i = 0;
8582 
8583 	for (i = 0; i < CXST_MAX; i++) {
8584 		if (btc->ver->fcxslots == 1) {
8585 			dur = le16_to_cpu(dm->slot_now.v1[i].dur);
8586 			tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
8587 			cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
8588 		} else if (btc->ver->fcxslots == 7) {
8589 			dur = le16_to_cpu(dm->slot_now.v7[i].dur);
8590 			tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
8591 			cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
8592 		} else {
8593 			return;
8594 		}
8595 
8596 		if (i % 5 == 0)
8597 			seq_printf(m,
8598 				   " %-15s : %5s[%03d/0x%x/%d]",
8599 				   "[slot_list]",
8600 				   id_to_slot((u32)i),
8601 				   dur, tbl, cxtype);
8602 		else
8603 			seq_printf(m,
8604 				   ", %5s[%03d/0x%x/%d]",
8605 				   id_to_slot((u32)i),
8606 				   dur, tbl, cxtype);
8607 
8608 		if (i % 5 == 4)
8609 			seq_puts(m, "\n");
8610 	}
8611 	seq_puts(m, "\n");
8612 }
8613 
_show_fbtc_cysta_v2(struct rtw89_dev * rtwdev,struct seq_file * m)8614 static void _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
8615 {
8616 	struct rtw89_btc *btc = &rtwdev->btc;
8617 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8618 	struct rtw89_btc_dm *dm = &btc->dm;
8619 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
8620 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
8621 	struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
8622 	union rtw89_btc_fbtc_rxflct r;
8623 	u8 i, cnt = 0, slot_pair;
8624 	u16 cycle, c_begin, c_end, store_index;
8625 
8626 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
8627 	if (!pcinfo->valid)
8628 		return;
8629 
8630 	pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
8631 	seq_printf(m,
8632 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
8633 		   "[cycle_cnt]",
8634 		   le16_to_cpu(pcysta_le32->cycles),
8635 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
8636 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
8637 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
8638 		   le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
8639 
8640 	for (i = 0; i < CXST_MAX; i++) {
8641 		if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
8642 			continue;
8643 		seq_printf(m, ", %s:%d", id_to_slot((u32)i),
8644 			   le32_to_cpu(pcysta_le32->slot_cnt[i]));
8645 	}
8646 
8647 	if (dm->tdma_now.rxflctrl) {
8648 		seq_printf(m, ", leak_rx:%d",
8649 			   le32_to_cpu(pcysta_le32->leakrx_cnt));
8650 	}
8651 
8652 	if (le32_to_cpu(pcysta_le32->collision_cnt)) {
8653 		seq_printf(m, ", collision:%d",
8654 			   le32_to_cpu(pcysta_le32->collision_cnt));
8655 	}
8656 
8657 	if (le32_to_cpu(pcysta_le32->skip_cnt)) {
8658 		seq_printf(m, ", skip:%d",
8659 			   le32_to_cpu(pcysta_le32->skip_cnt));
8660 	}
8661 	seq_puts(m, "\n");
8662 
8663 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
8664 		   "[cycle_time]",
8665 		   le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
8666 		   le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
8667 		   le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
8668 		   le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
8669 	seq_printf(m, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
8670 		   le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
8671 		   le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
8672 		   le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
8673 		   le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
8674 	seq_printf(m, ", maxdiff_t[wl:%d/bt:%d]\n",
8675 		   le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
8676 		   le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
8677 
8678 	if (le16_to_cpu(pcysta_le32->cycles) <= 1)
8679 		return;
8680 
8681 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
8682 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
8683 
8684 	if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
8685 		c_begin = 1;
8686 	else
8687 		c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
8688 
8689 	c_end = le16_to_cpu(pcysta_le32->cycles);
8690 
8691 	for (cycle = c_begin; cycle <= c_end; cycle++) {
8692 		cnt++;
8693 		store_index = ((cycle - 1) % slot_pair) * 2;
8694 
8695 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
8696 			seq_printf(m,
8697 				   " %-15s : ->b%02d->w%02d", "[cycle_step]",
8698 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
8699 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
8700 		else
8701 			seq_printf(m,
8702 				   "->b%02d->w%02d",
8703 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
8704 				   le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
8705 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
8706 			seq_puts(m, "\n");
8707 	}
8708 
8709 	if (a2dp->exist) {
8710 		seq_printf(m,
8711 			   " %-15s : a2dp_ept:%d, a2dp_late:%d",
8712 			   "[a2dp_t_sta]",
8713 			   le16_to_cpu(pcysta_le32->a2dpept),
8714 			   le16_to_cpu(pcysta_le32->a2dpeptto));
8715 
8716 		seq_printf(m,
8717 			   ", avg_t:%d, max_t:%d",
8718 			   le16_to_cpu(pcysta_le32->tavg_a2dpept),
8719 			   le16_to_cpu(pcysta_le32->tmax_a2dpept));
8720 		r.val = dm->tdma_now.rxflctrl;
8721 
8722 		if (r.type && r.tgln_n) {
8723 			seq_printf(m,
8724 				   ", cycle[PSTDMA:%d/TDMA:%d], ",
8725 				   le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
8726 				   le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
8727 
8728 			seq_printf(m,
8729 				   "avg_t[PSTDMA:%d/TDMA:%d], ",
8730 				   le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
8731 				   le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
8732 
8733 			seq_printf(m,
8734 				   "max_t[PSTDMA:%d/TDMA:%d]",
8735 				   le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
8736 				   le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
8737 		}
8738 		seq_puts(m, "\n");
8739 	}
8740 }
8741 
_show_fbtc_cysta_v3(struct rtw89_dev * rtwdev,struct seq_file * m)8742 static void _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, struct seq_file *m)
8743 {
8744 	struct rtw89_btc *btc = &rtwdev->btc;
8745 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
8746 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8747 	struct rtw89_btc_dm *dm = &btc->dm;
8748 	struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
8749 	struct rtw89_btc_fbtc_cysta_v3 *pcysta;
8750 	struct rtw89_btc_rpt_cmn_info *pcinfo;
8751 	u8 i, cnt = 0, slot_pair, divide_cnt;
8752 	u16 cycle, c_begin, c_end, store_index;
8753 
8754 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
8755 	if (!pcinfo->valid)
8756 		return;
8757 
8758 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
8759 	seq_printf(m,
8760 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
8761 		   "[cycle_cnt]",
8762 		   le16_to_cpu(pcysta->cycles),
8763 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
8764 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
8765 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
8766 		   le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
8767 
8768 	for (i = 0; i < CXST_MAX; i++) {
8769 		if (!le32_to_cpu(pcysta->slot_cnt[i]))
8770 			continue;
8771 
8772 		seq_printf(m, ", %s:%d", id_to_slot(i),
8773 			   le32_to_cpu(pcysta->slot_cnt[i]));
8774 	}
8775 
8776 	if (dm->tdma_now.rxflctrl)
8777 		seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr));
8778 
8779 	if (le32_to_cpu(pcysta->collision_cnt))
8780 		seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt));
8781 
8782 	if (le32_to_cpu(pcysta->skip_cnt))
8783 		seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt));
8784 
8785 	seq_puts(m, "\n");
8786 
8787 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
8788 		   "[cycle_time]",
8789 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
8790 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
8791 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
8792 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
8793 	seq_printf(m,
8794 		   ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
8795 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
8796 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
8797 		   le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
8798 		   le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
8799 	seq_printf(m,
8800 		   ", maxdiff_t[wl:%d/bt:%d]\n",
8801 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
8802 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
8803 
8804 	cycle = le16_to_cpu(pcysta->cycles);
8805 	if (cycle <= 1)
8806 		return;
8807 
8808 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
8809 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
8810 
8811 	if (cycle <= slot_pair)
8812 		c_begin = 1;
8813 	else
8814 		c_begin = cycle - slot_pair + 1;
8815 
8816 	c_end = cycle;
8817 
8818 	if (a2dp->exist)
8819 		divide_cnt = 3;
8820 	else
8821 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
8822 
8823 	for (cycle = c_begin; cycle <= c_end; cycle++) {
8824 		cnt++;
8825 		store_index = ((cycle - 1) % slot_pair) * 2;
8826 
8827 		if (cnt % divide_cnt == 1)
8828 			seq_printf(m, " %-15s : ", "[cycle_step]");
8829 
8830 		seq_printf(m, "->b%02d",
8831 			   le16_to_cpu(pcysta->slot_step_time[store_index]));
8832 		if (a2dp->exist) {
8833 			a2dp_trx = &pcysta->a2dp_trx[store_index];
8834 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
8835 				   a2dp_trx->empty_cnt,
8836 				   a2dp_trx->retry_cnt,
8837 				   a2dp_trx->tx_rate ? 3 : 2,
8838 				   a2dp_trx->tx_cnt,
8839 				   a2dp_trx->ack_cnt,
8840 				   a2dp_trx->nack_cnt);
8841 		}
8842 		seq_printf(m, "->w%02d",
8843 			   le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
8844 		if (a2dp->exist) {
8845 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
8846 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
8847 				   a2dp_trx->empty_cnt,
8848 				   a2dp_trx->retry_cnt,
8849 				   a2dp_trx->tx_rate ? 3 : 2,
8850 				   a2dp_trx->tx_cnt,
8851 				   a2dp_trx->ack_cnt,
8852 				   a2dp_trx->nack_cnt);
8853 		}
8854 		if (cnt % divide_cnt == 0 || cnt == c_end)
8855 			seq_puts(m, "\n");
8856 	}
8857 
8858 	if (a2dp->exist) {
8859 		seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
8860 			   "[a2dp_t_sta]",
8861 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
8862 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
8863 
8864 		seq_printf(m, ", avg_t:%d, max_t:%d",
8865 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
8866 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
8867 
8868 		seq_puts(m, "\n");
8869 	}
8870 }
8871 
_show_fbtc_cysta_v4(struct rtw89_dev * rtwdev,struct seq_file * m)8872 static void _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, struct seq_file *m)
8873 {
8874 	struct rtw89_btc *btc = &rtwdev->btc;
8875 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
8876 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8877 	struct rtw89_btc_dm *dm = &btc->dm;
8878 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
8879 	struct rtw89_btc_fbtc_cysta_v4 *pcysta;
8880 	struct rtw89_btc_rpt_cmn_info *pcinfo;
8881 	u8 i, cnt = 0, slot_pair, divide_cnt;
8882 	u16 cycle, c_begin, c_end, store_index;
8883 
8884 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
8885 	if (!pcinfo->valid)
8886 		return;
8887 
8888 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
8889 	seq_printf(m,
8890 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
8891 		   "[cycle_cnt]",
8892 		   le16_to_cpu(pcysta->cycles),
8893 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
8894 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
8895 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
8896 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
8897 
8898 	for (i = 0; i < CXST_MAX; i++) {
8899 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
8900 			continue;
8901 
8902 		seq_printf(m, ", %s:%d", id_to_slot(i),
8903 			   le16_to_cpu(pcysta->slot_cnt[i]));
8904 	}
8905 
8906 	if (dm->tdma_now.rxflctrl)
8907 		seq_printf(m, ", leak_rx:%d",
8908 			   le32_to_cpu(pcysta->leak_slot.cnt_rximr));
8909 
8910 	if (pcysta->collision_cnt)
8911 		seq_printf(m, ", collision:%d", pcysta->collision_cnt);
8912 
8913 	if (le16_to_cpu(pcysta->skip_cnt))
8914 		seq_printf(m, ", skip:%d",
8915 			   le16_to_cpu(pcysta->skip_cnt));
8916 
8917 	seq_puts(m, "\n");
8918 
8919 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
8920 		   "[cycle_time]",
8921 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
8922 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
8923 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
8924 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
8925 	seq_printf(m,
8926 		   ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
8927 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
8928 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
8929 		   le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
8930 		   le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
8931 	seq_printf(m,
8932 		   ", maxdiff_t[wl:%d/bt:%d]\n",
8933 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
8934 		   le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
8935 
8936 	cycle = le16_to_cpu(pcysta->cycles);
8937 	if (cycle <= 1)
8938 		return;
8939 
8940 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
8941 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
8942 
8943 	if (cycle <= slot_pair)
8944 		c_begin = 1;
8945 	else
8946 		c_begin = cycle - slot_pair + 1;
8947 
8948 	c_end = cycle;
8949 
8950 	if (a2dp->exist)
8951 		divide_cnt = 3;
8952 	else
8953 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
8954 
8955 	for (cycle = c_begin; cycle <= c_end; cycle++) {
8956 		cnt++;
8957 		store_index = ((cycle - 1) % slot_pair) * 2;
8958 
8959 		if (cnt % divide_cnt == 1)
8960 			seq_printf(m, " %-15s : ", "[cycle_step]");
8961 
8962 		seq_printf(m, "->b%02d",
8963 			   le16_to_cpu(pcysta->slot_step_time[store_index]));
8964 		if (a2dp->exist) {
8965 			a2dp_trx = &pcysta->a2dp_trx[store_index];
8966 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
8967 				   a2dp_trx->empty_cnt,
8968 				   a2dp_trx->retry_cnt,
8969 				   a2dp_trx->tx_rate ? 3 : 2,
8970 				   a2dp_trx->tx_cnt,
8971 				   a2dp_trx->ack_cnt,
8972 				   a2dp_trx->nack_cnt);
8973 		}
8974 		seq_printf(m, "->w%02d",
8975 			   le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
8976 		if (a2dp->exist) {
8977 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
8978 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
8979 				   a2dp_trx->empty_cnt,
8980 				   a2dp_trx->retry_cnt,
8981 				   a2dp_trx->tx_rate ? 3 : 2,
8982 				   a2dp_trx->tx_cnt,
8983 				   a2dp_trx->ack_cnt,
8984 				   a2dp_trx->nack_cnt);
8985 		}
8986 		if (cnt % divide_cnt == 0 || cnt == c_end)
8987 			seq_puts(m, "\n");
8988 	}
8989 
8990 	if (a2dp->exist) {
8991 		seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
8992 			   "[a2dp_t_sta]",
8993 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
8994 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
8995 
8996 		seq_printf(m, ", avg_t:%d, max_t:%d",
8997 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
8998 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
8999 
9000 		seq_puts(m, "\n");
9001 	}
9002 }
9003 
_show_fbtc_cysta_v5(struct rtw89_dev * rtwdev,struct seq_file * m)9004 static void _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, struct seq_file *m)
9005 {
9006 	struct rtw89_btc *btc = &rtwdev->btc;
9007 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9008 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9009 	struct rtw89_btc_dm *dm = &btc->dm;
9010 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
9011 	struct rtw89_btc_fbtc_cysta_v5 *pcysta;
9012 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9013 	u8 i, cnt = 0, slot_pair, divide_cnt;
9014 	u16 cycle, c_begin, c_end, store_index;
9015 
9016 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9017 	if (!pcinfo->valid)
9018 		return;
9019 
9020 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
9021 	seq_printf(m,
9022 		   " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9023 		   "[cycle_cnt]",
9024 		   le16_to_cpu(pcysta->cycles),
9025 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9026 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9027 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9028 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9029 
9030 	for (i = 0; i < CXST_MAX; i++) {
9031 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
9032 			continue;
9033 
9034 		seq_printf(m, ", %s:%d", id_to_slot(i),
9035 			   le16_to_cpu(pcysta->slot_cnt[i]));
9036 	}
9037 
9038 	if (dm->tdma_now.rxflctrl)
9039 		seq_printf(m, ", leak_rx:%d",
9040 			   le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9041 
9042 	if (pcysta->collision_cnt)
9043 		seq_printf(m, ", collision:%d", pcysta->collision_cnt);
9044 
9045 	if (le16_to_cpu(pcysta->skip_cnt))
9046 		seq_printf(m, ", skip:%d",
9047 			   le16_to_cpu(pcysta->skip_cnt));
9048 
9049 	seq_puts(m, "\n");
9050 
9051 	seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9052 		   "[cycle_time]",
9053 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9054 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9055 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9056 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9057 	seq_printf(m,
9058 		   ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
9059 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9060 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9061 		   le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
9062 		   le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
9063 
9064 	cycle = le16_to_cpu(pcysta->cycles);
9065 	if (cycle <= 1)
9066 		return;
9067 
9068 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
9069 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9070 
9071 	if (cycle <= slot_pair)
9072 		c_begin = 1;
9073 	else
9074 		c_begin = cycle - slot_pair + 1;
9075 
9076 	c_end = cycle;
9077 
9078 	if (a2dp->exist)
9079 		divide_cnt = 3;
9080 	else
9081 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
9082 
9083 	if (c_begin > c_end)
9084 		return;
9085 
9086 	for (cycle = c_begin; cycle <= c_end; cycle++) {
9087 		cnt++;
9088 		store_index = ((cycle - 1) % slot_pair) * 2;
9089 
9090 		if (cnt % divide_cnt == 1)
9091 			seq_printf(m, " %-15s : ", "[cycle_step]");
9092 
9093 		seq_printf(m, "->b%02d",
9094 			   le16_to_cpu(pcysta->slot_step_time[store_index]));
9095 		if (a2dp->exist) {
9096 			a2dp_trx = &pcysta->a2dp_trx[store_index];
9097 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9098 				   a2dp_trx->empty_cnt,
9099 				   a2dp_trx->retry_cnt,
9100 				   a2dp_trx->tx_rate ? 3 : 2,
9101 				   a2dp_trx->tx_cnt,
9102 				   a2dp_trx->ack_cnt,
9103 				   a2dp_trx->nack_cnt);
9104 		}
9105 		seq_printf(m, "->w%02d",
9106 			   le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
9107 		if (a2dp->exist) {
9108 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
9109 			seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9110 				   a2dp_trx->empty_cnt,
9111 				   a2dp_trx->retry_cnt,
9112 				   a2dp_trx->tx_rate ? 3 : 2,
9113 				   a2dp_trx->tx_cnt,
9114 				   a2dp_trx->ack_cnt,
9115 				   a2dp_trx->nack_cnt);
9116 		}
9117 		if (cnt % divide_cnt == 0 || cnt == c_end)
9118 			seq_puts(m, "\n");
9119 	}
9120 
9121 	if (a2dp->exist) {
9122 		seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
9123 			   "[a2dp_t_sta]",
9124 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
9125 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
9126 
9127 		seq_printf(m, ", avg_t:%d, max_t:%d",
9128 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
9129 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
9130 
9131 		seq_puts(m, "\n");
9132 	}
9133 }
9134 
_show_fbtc_cysta_v7(struct rtw89_dev * rtwdev,struct seq_file * m)9135 static void _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, struct seq_file *m)
9136 {
9137 	struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
9138 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
9139 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
9140 	struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
9141 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
9142 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9143 	u16 cycle, c_begin, c_end, s_id;
9144 	u8 i, cnt = 0, divide_cnt;
9145 	u8 slot_pair;
9146 
9147 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9148 	if (!pcinfo->valid)
9149 		return;
9150 
9151 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
9152 	seq_printf(m, "\n\r %-15s : cycle:%d", "[slot_stat]",
9153 		   le16_to_cpu(pcysta->cycles));
9154 
9155 	for (i = 0; i < CXST_MAX; i++) {
9156 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
9157 			continue;
9158 		seq_printf(m, ", %s:%d",
9159 			   id_to_slot(i), le16_to_cpu(pcysta->slot_cnt[i]));
9160 	}
9161 
9162 	if (dm->tdma_now.rxflctrl)
9163 		seq_printf(m, ", leak_rx:%d",
9164 			   le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9165 
9166 	if (pcysta->collision_cnt)
9167 		seq_printf(m, ", collision:%d", pcysta->collision_cnt);
9168 
9169 	if (pcysta->skip_cnt)
9170 		seq_printf(m, ", skip:%d", le16_to_cpu(pcysta->skip_cnt));
9171 
9172 	seq_printf(m, "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9173 		   "[cycle_stat]",
9174 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9175 		   le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9176 		   le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9177 		   le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9178 	seq_printf(m, ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
9179 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9180 		   le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9181 		   dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
9182 		   le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
9183 		   le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
9184 	seq_printf(m, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
9185 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9186 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9187 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9188 		   le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9189 
9190 	if (a2dp->exist) {
9191 		seq_printf(m,
9192 			   "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
9193 			   "[a2dp_stat]",
9194 			   le16_to_cpu(pcysta->a2dp_ept.cnt),
9195 			   le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
9196 			   a2dp->no_empty_streak_2s, a2dp->no_empty_streak_max);
9197 
9198 		seq_printf(m, ", avg_t:%d, max_t:%d",
9199 			   le16_to_cpu(pcysta->a2dp_ept.tavg),
9200 			   le16_to_cpu(pcysta->a2dp_ept.tmax));
9201 	}
9202 
9203 	if (le16_to_cpu(pcysta->cycles) <= 1)
9204 		return;
9205 
9206 	/* 1 cycle = 1 wl-slot + 1 bt-slot */
9207 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9208 
9209 	if (le16_to_cpu(pcysta->cycles) <= slot_pair)
9210 		c_begin = 1;
9211 	else
9212 		c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
9213 
9214 	c_end = le16_to_cpu(pcysta->cycles);
9215 
9216 	if (a2dp->exist)
9217 		divide_cnt = 2;
9218 	else
9219 		divide_cnt = 6;
9220 
9221 	if (c_begin > c_end)
9222 		return;
9223 
9224 	for (cycle = c_begin; cycle <= c_end; cycle++) {
9225 		cnt++;
9226 		s_id = ((cycle - 1) % slot_pair) * 2;
9227 
9228 		if (cnt % divide_cnt == 1) {
9229 			if (a2dp->exist)
9230 				seq_printf(m, "\n\r %-15s : ", "[slotT_wermtan]");
9231 			else
9232 				seq_printf(m, "\n\r %-15s : ", "[slotT_rxerr]");
9233 		}
9234 
9235 		seq_printf(m, "->b%d", le16_to_cpu(pcysta->slot_step_time[s_id]));
9236 
9237 		if (a2dp->exist)
9238 			seq_printf(m, "(%d/%d/%d/%dM/%d/%d/%d)",
9239 				   pcysta->wl_rx_err_ratio[s_id],
9240 				   pcysta->a2dp_trx[s_id].empty_cnt,
9241 				   pcysta->a2dp_trx[s_id].retry_cnt,
9242 				   (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
9243 				   pcysta->a2dp_trx[s_id].tx_cnt,
9244 				   pcysta->a2dp_trx[s_id].ack_cnt,
9245 				   pcysta->a2dp_trx[s_id].nack_cnt);
9246 		else
9247 			seq_printf(m, "(%d)", pcysta->wl_rx_err_ratio[s_id]);
9248 
9249 		seq_printf(m, "->w%d", le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
9250 
9251 		if (a2dp->exist)
9252 			seq_printf(m, "(%d/%d/%d/%dM/%d/%d/%d)",
9253 				   pcysta->wl_rx_err_ratio[s_id + 1],
9254 				   pcysta->a2dp_trx[s_id + 1].empty_cnt,
9255 				   pcysta->a2dp_trx[s_id + 1].retry_cnt,
9256 				   (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
9257 				   pcysta->a2dp_trx[s_id + 1].tx_cnt,
9258 				   pcysta->a2dp_trx[s_id + 1].ack_cnt,
9259 				   pcysta->a2dp_trx[s_id + 1].nack_cnt);
9260 		else
9261 			seq_printf(m, "(%d)", pcysta->wl_rx_err_ratio[s_id + 1]);
9262 	}
9263 }
9264 
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,struct seq_file * m)9265 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
9266 {
9267 	struct rtw89_btc *btc = &rtwdev->btc;
9268 	const struct rtw89_btc_ver *ver = btc->ver;
9269 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9270 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9271 	union rtw89_btc_fbtc_cynullsta_info *ns;
9272 	u8 i = 0;
9273 
9274 	if (!btc->dm.tdma_now.rxflctrl)
9275 		return;
9276 
9277 	pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
9278 	if (!pcinfo->valid)
9279 		return;
9280 
9281 	ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
9282 	if (ver->fcxnullsta == 1) {
9283 		for (i = 0; i < 2; i++) {
9284 			seq_printf(m, " %-15s : ", "[NULL-STA]");
9285 			seq_printf(m, "null-%d", i);
9286 			seq_printf(m, "[ok:%d/",
9287 				   le32_to_cpu(ns->v1.result[i][1]));
9288 			seq_printf(m, "fail:%d/",
9289 				   le32_to_cpu(ns->v1.result[i][0]));
9290 			seq_printf(m, "on_time:%d/",
9291 				   le32_to_cpu(ns->v1.result[i][2]));
9292 			seq_printf(m, "retry:%d/",
9293 				   le32_to_cpu(ns->v1.result[i][3]));
9294 			seq_printf(m, "avg_t:%d.%03d/",
9295 				   le32_to_cpu(ns->v1.avg_t[i]) / 1000,
9296 				   le32_to_cpu(ns->v1.avg_t[i]) % 1000);
9297 			seq_printf(m, "max_t:%d.%03d]\n",
9298 				   le32_to_cpu(ns->v1.max_t[i]) / 1000,
9299 				   le32_to_cpu(ns->v1.max_t[i]) % 1000);
9300 		}
9301 	} else if (ver->fcxnullsta == 7) {
9302 		for (i = 0; i < 2; i++) {
9303 			seq_printf(m, " %-15s : ", "[NULL-STA]");
9304 			seq_printf(m, "null-%d", i);
9305 			seq_printf(m, "[Tx:%d/",
9306 				   le32_to_cpu(ns->v7.result[i][4]));
9307 			seq_printf(m, "[ok:%d/",
9308 				   le32_to_cpu(ns->v7.result[i][1]));
9309 			seq_printf(m, "fail:%d/",
9310 				   le32_to_cpu(ns->v7.result[i][0]));
9311 			seq_printf(m, "on_time:%d/",
9312 				   le32_to_cpu(ns->v7.result[i][2]));
9313 			seq_printf(m, "retry:%d/",
9314 				   le32_to_cpu(ns->v7.result[i][3]));
9315 			seq_printf(m, "avg_t:%d.%03d/",
9316 				   le32_to_cpu(ns->v7.tavg[i]) / 1000,
9317 				   le32_to_cpu(ns->v7.tavg[i]) % 1000);
9318 			seq_printf(m, "max_t:%d.%03d]\n",
9319 				   le32_to_cpu(ns->v7.tmax[i]) / 1000,
9320 				   le32_to_cpu(ns->v7.tmax[i]) % 1000);
9321 		}
9322 	} else {
9323 		for (i = 0; i < 2; i++) {
9324 			seq_printf(m, " %-15s : ", "[NULL-STA]");
9325 			seq_printf(m, "null-%d", i);
9326 			seq_printf(m, "[Tx:%d/",
9327 				   le32_to_cpu(ns->v2.result[i][4]));
9328 			seq_printf(m, "[ok:%d/",
9329 				   le32_to_cpu(ns->v2.result[i][1]));
9330 			seq_printf(m, "fail:%d/",
9331 				   le32_to_cpu(ns->v2.result[i][0]));
9332 			seq_printf(m, "on_time:%d/",
9333 				   le32_to_cpu(ns->v2.result[i][2]));
9334 			seq_printf(m, "retry:%d/",
9335 				   le32_to_cpu(ns->v2.result[i][3]));
9336 			seq_printf(m, "avg_t:%d.%03d/",
9337 				   le32_to_cpu(ns->v2.avg_t[i]) / 1000,
9338 				   le32_to_cpu(ns->v2.avg_t[i]) % 1000);
9339 			seq_printf(m, "max_t:%d.%03d]\n",
9340 				   le32_to_cpu(ns->v2.max_t[i]) / 1000,
9341 				   le32_to_cpu(ns->v2.max_t[i]) % 1000);
9342 		}
9343 	}
9344 }
9345 
_show_fbtc_step_v2(struct rtw89_dev * rtwdev,struct seq_file * m)9346 static void _show_fbtc_step_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
9347 {
9348 	struct rtw89_btc *btc = &rtwdev->btc;
9349 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9350 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9351 	struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
9352 	const struct rtw89_btc_ver *ver = btc->ver;
9353 	u8 type, val, cnt = 0, state = 0;
9354 	bool outloop = false;
9355 	u16 i, diff_t, n_start = 0, n_stop = 0;
9356 	u16 pos_old, pos_new, trace_step;
9357 
9358 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
9359 	if (!pcinfo->valid)
9360 		return;
9361 
9362 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
9363 	pos_old = le16_to_cpu(pstep->pos_old);
9364 	pos_new = le16_to_cpu(pstep->pos_new);
9365 
9366 	if (pcinfo->req_fver != pstep->fver)
9367 		return;
9368 
9369 	/* store step info by using ring instead of FIFO*/
9370 	do {
9371 		switch (state) {
9372 		case 0:
9373 			if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
9374 				trace_step = 50;
9375 			else
9376 				trace_step = btc->ctrl.ctrl.trace_step;
9377 
9378 			n_start = pos_old;
9379 			if (pos_new >=  pos_old)
9380 				n_stop = pos_new;
9381 			else
9382 				n_stop = trace_step - 1;
9383 
9384 			state = 1;
9385 			break;
9386 		case 1:
9387 			for (i = n_start; i <= n_stop; i++) {
9388 				type = pstep->step[i].type;
9389 				val = pstep->step[i].val;
9390 				diff_t = le16_to_cpu(pstep->step[i].difft);
9391 
9392 				if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
9393 					continue;
9394 
9395 				if (cnt % 10 == 0)
9396 					seq_printf(m, " %-15s : ", "[steps]");
9397 
9398 				seq_printf(m, "-> %s(%02d)(%02d)",
9399 					   (type == CXSTEP_SLOT ? "SLT" :
9400 					    "EVT"), (u32)val, diff_t);
9401 				if (cnt % 10 == 9)
9402 					seq_puts(m, "\n");
9403 				cnt++;
9404 			}
9405 
9406 			state = 2;
9407 			break;
9408 		case 2:
9409 			if (pos_new <  pos_old && n_start != 0) {
9410 				n_start = 0;
9411 				n_stop = pos_new;
9412 				state = 1;
9413 			} else {
9414 				outloop = true;
9415 			}
9416 			break;
9417 		}
9418 	} while (!outloop);
9419 }
9420 
_show_fbtc_step_v3(struct rtw89_dev * rtwdev,struct seq_file * m)9421 static void _show_fbtc_step_v3(struct rtw89_dev *rtwdev, struct seq_file *m)
9422 {
9423 	struct rtw89_btc *btc = &rtwdev->btc;
9424 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9425 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9426 	struct rtw89_btc_fbtc_steps_v3 *pstep;
9427 	u32 i, n_begin, n_end, array_idx, cnt = 0;
9428 	u8 type, val;
9429 	u16 diff_t;
9430 
9431 	if ((pfwinfo->rpt_en_map &
9432 	     rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
9433 		return;
9434 
9435 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
9436 	if (!pcinfo->valid)
9437 		return;
9438 
9439 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
9440 	if (pcinfo->req_fver != pstep->fver)
9441 		return;
9442 
9443 	if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
9444 		n_begin = 1;
9445 	else
9446 		n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
9447 
9448 	n_end = le32_to_cpu(pstep->cnt);
9449 
9450 	if (n_begin > n_end)
9451 		return;
9452 
9453 	/* restore step info by using ring instead of FIFO */
9454 	for (i = n_begin; i <= n_end; i++) {
9455 		array_idx = (i - 1) % FCXDEF_STEP;
9456 		type = pstep->step[array_idx].type;
9457 		val = pstep->step[array_idx].val;
9458 		diff_t = le16_to_cpu(pstep->step[array_idx].difft);
9459 
9460 		if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
9461 			continue;
9462 
9463 		if (cnt % 10 == 0)
9464 			seq_printf(m, " %-15s : ", "[steps]");
9465 
9466 		seq_printf(m, "-> %s(%02d)",
9467 			   (type == CXSTEP_SLOT ?
9468 			    id_to_slot((u32)val) :
9469 			    id_to_evt((u32)val)), diff_t);
9470 
9471 		if (cnt % 10 == 9)
9472 			seq_puts(m, "\n");
9473 
9474 		cnt++;
9475 	}
9476 }
9477 
_show_fw_dm_msg(struct rtw89_dev * rtwdev,struct seq_file * m)9478 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
9479 {
9480 	struct rtw89_btc *btc = &rtwdev->btc;
9481 	const struct rtw89_btc_ver *ver = btc->ver;
9482 
9483 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
9484 		return;
9485 
9486 	_show_error(rtwdev, m);
9487 	_show_fbtc_tdma(rtwdev, m);
9488 	_show_fbtc_slots(rtwdev, m);
9489 
9490 	if (ver->fcxcysta == 2)
9491 		_show_fbtc_cysta_v2(rtwdev, m);
9492 	else if (ver->fcxcysta == 3)
9493 		_show_fbtc_cysta_v3(rtwdev, m);
9494 	else if (ver->fcxcysta == 4)
9495 		_show_fbtc_cysta_v4(rtwdev, m);
9496 	else if (ver->fcxcysta == 5)
9497 		_show_fbtc_cysta_v5(rtwdev, m);
9498 	else if (ver->fcxcysta == 7)
9499 		_show_fbtc_cysta_v7(rtwdev, m);
9500 
9501 	_show_fbtc_nullsta(rtwdev, m);
9502 
9503 	if (ver->fcxstep == 2)
9504 		_show_fbtc_step_v2(rtwdev, m);
9505 	else if (ver->fcxstep == 3)
9506 		_show_fbtc_step_v3(rtwdev, m);
9507 
9508 }
9509 
_get_gnt(struct rtw89_dev * rtwdev,struct rtw89_mac_ax_coex_gnt * gnt_cfg)9510 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
9511 {
9512 	const struct rtw89_chip_info *chip = rtwdev->chip;
9513 	struct rtw89_mac_ax_gnt *gnt;
9514 	u32 val, status;
9515 
9516 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
9517 	    chip->chip_id == RTL8851B) {
9518 		rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
9519 		rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
9520 
9521 		gnt = &gnt_cfg->band[0];
9522 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
9523 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
9524 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
9525 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
9526 
9527 		gnt = &gnt_cfg->band[1];
9528 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
9529 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
9530 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
9531 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
9532 	} else if (chip->chip_id == RTL8852C) {
9533 		val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
9534 		status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
9535 
9536 		gnt = &gnt_cfg->band[0];
9537 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
9538 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
9539 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
9540 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
9541 
9542 		gnt = &gnt_cfg->band[1];
9543 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
9544 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
9545 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
9546 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
9547 	} else {
9548 		return;
9549 	}
9550 }
9551 
_show_gpio_dbg(struct rtw89_dev * rtwdev,struct seq_file * m)9552 static void _show_gpio_dbg(struct rtw89_dev *rtwdev, struct seq_file *m)
9553 {
9554 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
9555 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
9556 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9557 	union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
9558 	u8 *gpio_map, i;
9559 	u32 en_map;
9560 
9561 	pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
9562 	gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
9563 	if (!pcinfo->valid) {
9564 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9565 			    "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
9566 			    __func__);
9567 		seq_puts(m, "\n");
9568 		return;
9569 	}
9570 
9571 	if (ver->fcxgpiodbg == 7) {
9572 		en_map = le32_to_cpu(gdbg->v7.en_map);
9573 		gpio_map = gdbg->v7.gpio_map;
9574 	} else {
9575 		en_map = le32_to_cpu(gdbg->v1.en_map);
9576 		gpio_map = gdbg->v1.gpio_map;
9577 	}
9578 
9579 	if (!en_map)
9580 		return;
9581 
9582 	seq_printf(m, " %-15s : enable_map:0x%08x",
9583 		   "[gpio_dbg]", en_map);
9584 
9585 	for (i = 0; i < BTC_DBG_MAX1; i++) {
9586 		if (!(en_map & BIT(i)))
9587 			continue;
9588 		seq_printf(m, ", %s->GPIO%d", id_to_gdbg(i), gpio_map[i]);
9589 	}
9590 	seq_puts(m, "\n");
9591 }
9592 
_show_mreg_v1(struct rtw89_dev * rtwdev,struct seq_file * m)9593 static void _show_mreg_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
9594 {
9595 	const struct rtw89_chip_info *chip = rtwdev->chip;
9596 	struct rtw89_btc *btc = &rtwdev->btc;
9597 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9598 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9599 	struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
9600 	struct rtw89_btc_cx *cx = &btc->cx;
9601 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9602 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9603 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
9604 	struct rtw89_mac_ax_gnt gnt;
9605 	u8 i = 0, type = 0, cnt = 0;
9606 	u32 val, offset;
9607 
9608 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
9609 		return;
9610 
9611 	seq_puts(m, "========== [HW Status] ==========\n");
9612 
9613 	seq_printf(m,
9614 		   " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
9615 		   "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
9616 		   bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
9617 		   cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
9618 
9619 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
9620 	_get_gnt(rtwdev, &gnt_cfg);
9621 
9622 	gnt = gnt_cfg.band[0];
9623 	seq_printf(m,
9624 		   " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
9625 		   "[gnt_status]",
9626 		   chip->chip_id == RTL8852C ? "HW" :
9627 		   btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
9628 		   gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
9629 		   gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
9630 
9631 	gnt = gnt_cfg.band[1];
9632 	seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
9633 		   gnt.gnt_wl_sw_en ? "SW" : "HW",
9634 		   gnt.gnt_wl,
9635 		   gnt.gnt_bt_sw_en ? "SW" : "HW",
9636 		   gnt.gnt_bt);
9637 
9638 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
9639 	if (!pcinfo->valid) {
9640 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9641 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
9642 			    __func__);
9643 		return;
9644 	}
9645 
9646 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
9647 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9648 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
9649 		    __func__, pmreg->reg_num);
9650 
9651 	for (i = 0; i < pmreg->reg_num; i++) {
9652 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
9653 		offset = le32_to_cpu(chip->mon_reg[i].offset);
9654 		val = le32_to_cpu(pmreg->mreg_val[i]);
9655 
9656 		if (cnt % 6 == 0)
9657 			seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
9658 				   "[reg]", (u32)type, offset, val);
9659 		else
9660 			seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
9661 				   offset, val);
9662 		if (cnt % 6 == 5)
9663 			seq_puts(m, "\n");
9664 		cnt++;
9665 
9666 		if (i >= pmreg->reg_num)
9667 			seq_puts(m, "\n");
9668 	}
9669 }
9670 
_show_mreg_v2(struct rtw89_dev * rtwdev,struct seq_file * m)9671 static void _show_mreg_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
9672 {
9673 	const struct rtw89_chip_info *chip = rtwdev->chip;
9674 	struct rtw89_btc *btc = &rtwdev->btc;
9675 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9676 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9677 	struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
9678 	struct rtw89_btc_cx *cx = &btc->cx;
9679 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9680 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9681 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
9682 	struct rtw89_mac_ax_gnt gnt;
9683 	u8 i = 0, type = 0, cnt = 0;
9684 	u32 val, offset;
9685 
9686 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
9687 		return;
9688 
9689 	seq_puts(m, "========== [HW Status] ==========\n");
9690 
9691 	seq_printf(m,
9692 		   " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
9693 		   "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
9694 		   bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
9695 		   cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
9696 
9697 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
9698 	_get_gnt(rtwdev, &gnt_cfg);
9699 
9700 	gnt = gnt_cfg.band[0];
9701 	seq_printf(m,
9702 		   " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
9703 		   "[gnt_status]",
9704 		   chip->chip_id == RTL8852C ? "HW" :
9705 		   btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
9706 		   gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
9707 		   gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
9708 		   id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
9709 
9710 	gnt = gnt_cfg.band[1];
9711 	seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
9712 		   gnt.gnt_wl_sw_en ? "SW" : "HW",
9713 		   gnt.gnt_wl,
9714 		   gnt.gnt_bt_sw_en ? "SW" : "HW",
9715 		   gnt.gnt_bt);
9716 
9717 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
9718 	if (!pcinfo->valid) {
9719 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9720 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
9721 			    __func__);
9722 		return;
9723 	}
9724 
9725 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
9726 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9727 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
9728 		    __func__, pmreg->reg_num);
9729 
9730 	for (i = 0; i < pmreg->reg_num; i++) {
9731 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
9732 		offset = le32_to_cpu(chip->mon_reg[i].offset);
9733 		val = le32_to_cpu(pmreg->mreg_val[i]);
9734 
9735 		if (cnt % 6 == 0)
9736 			seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
9737 				   "[reg]", (u32)type, offset, val);
9738 		else
9739 			seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
9740 				   offset, val);
9741 		if (cnt % 6 == 5)
9742 			seq_puts(m, "\n");
9743 		cnt++;
9744 
9745 		if (i >= pmreg->reg_num)
9746 			seq_puts(m, "\n");
9747 	}
9748 }
9749 
_show_mreg_v7(struct rtw89_dev * rtwdev,struct seq_file * m)9750 static void _show_mreg_v7(struct rtw89_dev *rtwdev, struct seq_file *m)
9751 {
9752 	struct rtw89_btc *btc = &rtwdev->btc;
9753 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9754 	struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
9755 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9756 	struct rtw89_btc_cx *cx = &btc->cx;
9757 	struct rtw89_btc_wl_info *wl = &cx->wl;
9758 	struct rtw89_btc_bt_info *bt = &cx->bt;
9759 	struct rtw89_mac_ax_gnt *gnt = NULL;
9760 	struct rtw89_btc_dm *dm = &btc->dm;
9761 	u8 i, type, cnt = 0;
9762 	u32 val, offset;
9763 
9764 	if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
9765 		return;
9766 
9767 	seq_puts(m, "\n\r========== [HW Status] ==========");
9768 
9769 	seq_printf(m,
9770 		   "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
9771 		   "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
9772 		   bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
9773 		   cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
9774 
9775 	/* To avoid I/O if WL LPS or power-off  */
9776 	dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
9777 
9778 	seq_printf(m,
9779 		   "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s",
9780 		   "[gnt_status]",
9781 		   rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
9782 		   dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
9783 		   wl->pta_req_mac, id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
9784 
9785 	gnt = &dm->gnt.band[RTW89_PHY_0];
9786 
9787 	seq_printf(m, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
9788 		   gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
9789 		   gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
9790 
9791 	if (rtwdev->dbcc_en) {
9792 		gnt = &dm->gnt.band[RTW89_PHY_1];
9793 		seq_printf(m, ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
9794 			   gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
9795 			   gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
9796 	}
9797 
9798 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
9799 	if (!pcinfo->valid)
9800 		return;
9801 
9802 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
9803 
9804 	for (i = 0; i < pmreg->reg_num; i++) {
9805 		type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
9806 		offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
9807 		val = le32_to_cpu(pmreg->mreg_val[i]);
9808 
9809 		if (cnt % 6 == 0)
9810 			seq_printf(m, "\n\r %-15s : %s_0x%x=0x%x", "[reg]",
9811 				   id_to_regtype(type), offset, val);
9812 		else
9813 			seq_printf(m, ", %s_0x%x=0x%x",
9814 				   id_to_regtype(type), offset, val);
9815 		cnt++;
9816 	}
9817 	seq_puts(m, "\n");
9818 }
9819 
_show_summary_v1(struct rtw89_dev * rtwdev,struct seq_file * m)9820 static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
9821 {
9822 	struct rtw89_btc *btc = &rtwdev->btc;
9823 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9824 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9825 	struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
9826 	struct rtw89_btc_cx *cx = &btc->cx;
9827 	struct rtw89_btc_dm *dm = &btc->dm;
9828 	struct rtw89_btc_wl_info *wl = &cx->wl;
9829 	struct rtw89_btc_bt_info *bt = &cx->bt;
9830 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
9831 	u8 i;
9832 
9833 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
9834 		return;
9835 
9836 	seq_puts(m, "========== [Statistics] ==========\n");
9837 
9838 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
9839 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
9840 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
9841 
9842 		seq_printf(m,
9843 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
9844 			   "[summary]", pfwinfo->cnt_h2c,
9845 			   pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
9846 			   pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
9847 
9848 		seq_printf(m,
9849 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
9850 			   pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
9851 			   prptctrl->rpt_enable, dm->error.val);
9852 
9853 		if (dm->error.map.wl_fw_hang)
9854 			seq_puts(m, " (WL FW Hang!!)");
9855 		seq_puts(m, "\n");
9856 		seq_printf(m,
9857 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d",
9858 			   "[mailbox]", prptctrl->mb_send_ok_cnt,
9859 			   prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
9860 
9861 		seq_printf(m,
9862 			   "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
9863 			   prptctrl->mb_a2dp_empty_cnt,
9864 			   prptctrl->mb_a2dp_flct_cnt,
9865 			   prptctrl->mb_a2dp_full_cnt);
9866 
9867 		seq_printf(m,
9868 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
9869 			   "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
9870 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
9871 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
9872 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
9873 
9874 		seq_printf(m,
9875 			   ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
9876 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
9877 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
9878 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
9879 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
9880 			   prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
9881 
9882 		if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
9883 			bt->rfk_info.map.timeout = 1;
9884 		else
9885 			bt->rfk_info.map.timeout = 0;
9886 
9887 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
9888 	} else {
9889 		seq_printf(m,
9890 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
9891 			   "[summary]", pfwinfo->cnt_h2c,
9892 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
9893 			   pfwinfo->event[BTF_EVNT_RPT],
9894 			   btc->fwinfo.rpt_en_map);
9895 		seq_puts(m, " (WL FW report invalid!!)\n");
9896 	}
9897 
9898 	for (i = 0; i < BTC_NCNT_NUM; i++)
9899 		cnt_sum += dm->cnt_notify[i];
9900 
9901 	seq_printf(m,
9902 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
9903 		   "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
9904 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
9905 
9906 	seq_printf(m,
9907 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
9908 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
9909 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
9910 		   cnt[BTC_NCNT_WL_STA]);
9911 
9912 	seq_printf(m,
9913 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
9914 		   "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
9915 		   cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
9916 		   cnt[BTC_NCNT_SPECIAL_PACKET]);
9917 
9918 	seq_printf(m,
9919 		   "timer=%d, control=%d, customerize=%d\n",
9920 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
9921 		   cnt[BTC_NCNT_CUSTOMERIZE]);
9922 }
9923 
_show_summary_v4(struct rtw89_dev * rtwdev,struct seq_file * m)9924 static void _show_summary_v4(struct rtw89_dev *rtwdev, struct seq_file *m)
9925 {
9926 	struct rtw89_btc *btc = &rtwdev->btc;
9927 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9928 	struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
9929 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9930 	struct rtw89_btc_cx *cx = &btc->cx;
9931 	struct rtw89_btc_dm *dm = &btc->dm;
9932 	struct rtw89_btc_wl_info *wl = &cx->wl;
9933 	struct rtw89_btc_bt_info *bt = &cx->bt;
9934 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
9935 	u8 i;
9936 
9937 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
9938 		return;
9939 
9940 	seq_puts(m, "========== [Statistics] ==========\n");
9941 
9942 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
9943 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
9944 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
9945 
9946 		seq_printf(m,
9947 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
9948 			   "[summary]", pfwinfo->cnt_h2c,
9949 			   pfwinfo->cnt_h2c_fail,
9950 			   le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
9951 			   pfwinfo->cnt_c2h,
9952 			   le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
9953 
9954 		seq_printf(m,
9955 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
9956 			   pfwinfo->event[BTF_EVNT_RPT],
9957 			   le32_to_cpu(prptctrl->rpt_info.cnt),
9958 			   le32_to_cpu(prptctrl->rpt_info.en),
9959 			   dm->error.val);
9960 
9961 		if (dm->error.map.wl_fw_hang)
9962 			seq_puts(m, " (WL FW Hang!!)");
9963 		seq_puts(m, "\n");
9964 		seq_printf(m,
9965 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
9966 			   "[mailbox]",
9967 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
9968 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
9969 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
9970 
9971 		seq_printf(m,
9972 			   "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
9973 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
9974 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
9975 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
9976 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
9977 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
9978 
9979 		seq_printf(m,
9980 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
9981 			   "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
9982 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
9983 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
9984 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
9985 
9986 		seq_printf(m,
9987 			   ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
9988 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
9989 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
9990 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
9991 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
9992 			   le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
9993 
9994 		if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
9995 			bt->rfk_info.map.timeout = 1;
9996 		else
9997 			bt->rfk_info.map.timeout = 0;
9998 
9999 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
10000 	} else {
10001 		seq_printf(m,
10002 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
10003 			   "[summary]", pfwinfo->cnt_h2c,
10004 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
10005 			   pfwinfo->event[BTF_EVNT_RPT],
10006 			   btc->fwinfo.rpt_en_map);
10007 		seq_puts(m, " (WL FW report invalid!!)\n");
10008 	}
10009 
10010 	for (i = 0; i < BTC_NCNT_NUM; i++)
10011 		cnt_sum += dm->cnt_notify[i];
10012 
10013 	seq_printf(m,
10014 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10015 		   "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10016 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10017 
10018 	seq_printf(m,
10019 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
10020 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10021 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10022 		   cnt[BTC_NCNT_WL_STA]);
10023 
10024 	seq_printf(m,
10025 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10026 		   "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
10027 		   cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
10028 		   cnt[BTC_NCNT_SPECIAL_PACKET]);
10029 
10030 	seq_printf(m,
10031 		   "timer=%d, control=%d, customerize=%d\n",
10032 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10033 		   cnt[BTC_NCNT_CUSTOMERIZE]);
10034 }
10035 
_show_summary_v5(struct rtw89_dev * rtwdev,struct seq_file * m)10036 static void _show_summary_v5(struct rtw89_dev *rtwdev, struct seq_file *m)
10037 {
10038 	struct rtw89_btc *btc = &rtwdev->btc;
10039 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10040 	struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
10041 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10042 	struct rtw89_btc_cx *cx = &btc->cx;
10043 	struct rtw89_btc_dm *dm = &btc->dm;
10044 	struct rtw89_btc_wl_info *wl = &cx->wl;
10045 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10046 	u8 i;
10047 
10048 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10049 		return;
10050 
10051 	seq_puts(m, "========== [Statistics] ==========\n");
10052 
10053 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10054 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10055 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
10056 
10057 		seq_printf(m,
10058 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
10059 			   "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10060 			   le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
10061 			   pfwinfo->cnt_c2h,
10062 			   le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10063 			   le16_to_cpu(prptctrl->rpt_info.len_c2h));
10064 
10065 		seq_printf(m,
10066 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10067 			   pfwinfo->event[BTF_EVNT_RPT],
10068 			   le16_to_cpu(prptctrl->rpt_info.cnt),
10069 			   le32_to_cpu(prptctrl->rpt_info.en));
10070 
10071 		if (dm->error.map.wl_fw_hang)
10072 			seq_puts(m, " (WL FW Hang!!)");
10073 		seq_puts(m, "\n");
10074 		seq_printf(m,
10075 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10076 			   "[mailbox]",
10077 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10078 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10079 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10080 
10081 		seq_printf(m,
10082 			   "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
10083 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10084 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10085 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10086 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10087 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10088 
10089 		seq_printf(m,
10090 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
10091 			   "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10092 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
10093 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10094 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10095 
10096 		seq_printf(m,
10097 			   ", bt_rfk[req:%d]",
10098 			   le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10099 
10100 		seq_printf(m,
10101 			   ", AOAC[RF_on:%d/RF_off:%d]",
10102 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10103 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10104 	} else {
10105 		seq_printf(m,
10106 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
10107 			   "[summary]", pfwinfo->cnt_h2c,
10108 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
10109 	}
10110 
10111 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
10112 	    pfwinfo->err[BTFRE_EXCEPTION]) {
10113 		seq_puts(m, "\n");
10114 		seq_printf(m,
10115 			   " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
10116 			   "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
10117 			   "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
10118 			   pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION],
10119 			   wl->status.map.lps, wl->status.map.rf_off);
10120 	}
10121 
10122 	for (i = 0; i < BTC_NCNT_NUM; i++)
10123 		cnt_sum += dm->cnt_notify[i];
10124 
10125 	seq_puts(m, "\n");
10126 	seq_printf(m,
10127 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10128 		   "[notify_cnt]",
10129 		   cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10130 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10131 
10132 	seq_printf(m,
10133 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10134 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10135 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10136 		   cnt[BTC_NCNT_WL_STA]);
10137 
10138 	seq_puts(m, "\n");
10139 	seq_printf(m,
10140 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10141 		   "[notify_cnt]",
10142 		   cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10143 		   cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]);
10144 
10145 	seq_printf(m,
10146 		   "timer=%d, control=%d, customerize=%d",
10147 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10148 		   cnt[BTC_NCNT_CUSTOMERIZE]);
10149 }
10150 
_show_summary_v105(struct rtw89_dev * rtwdev,struct seq_file * m)10151 static void _show_summary_v105(struct rtw89_dev *rtwdev, struct seq_file *m)
10152 {
10153 	struct rtw89_btc *btc = &rtwdev->btc;
10154 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10155 	struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
10156 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10157 	struct rtw89_btc_cx *cx = &btc->cx;
10158 	struct rtw89_btc_dm *dm = &btc->dm;
10159 	struct rtw89_btc_wl_info *wl = &cx->wl;
10160 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10161 	u8 i;
10162 
10163 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10164 		return;
10165 
10166 	seq_puts(m, "========== [Statistics] ==========\n");
10167 
10168 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10169 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10170 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
10171 
10172 		seq_printf(m,
10173 			   " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
10174 			   "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10175 			   le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
10176 			   pfwinfo->cnt_c2h,
10177 			   le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10178 			   le16_to_cpu(prptctrl->rpt_info.len_c2h));
10179 
10180 		seq_printf(m,
10181 			   "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10182 			   pfwinfo->event[BTF_EVNT_RPT],
10183 			   le16_to_cpu(prptctrl->rpt_info.cnt),
10184 			   le32_to_cpu(prptctrl->rpt_info.en));
10185 
10186 		if (dm->error.map.wl_fw_hang)
10187 			seq_puts(m, " (WL FW Hang!!)");
10188 		seq_puts(m, "\n");
10189 		seq_printf(m,
10190 			   " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10191 			   "[mailbox]",
10192 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10193 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10194 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10195 
10196 		seq_printf(m,
10197 			   "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
10198 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10199 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10200 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10201 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10202 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10203 
10204 		seq_printf(m,
10205 			   " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
10206 			   "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10207 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
10208 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10209 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10210 
10211 		seq_printf(m,
10212 			   ", bt_rfk[req:%d]",
10213 			   le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10214 
10215 		seq_printf(m,
10216 			   ", AOAC[RF_on:%d/RF_off:%d]",
10217 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10218 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10219 	} else {
10220 		seq_printf(m,
10221 			   " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
10222 			   "[summary]", pfwinfo->cnt_h2c,
10223 			   pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
10224 	}
10225 
10226 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
10227 	    pfwinfo->err[BTFRE_EXCEPTION]) {
10228 		seq_puts(m, "\n");
10229 		seq_printf(m,
10230 			   " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
10231 			   "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
10232 			   "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
10233 			   pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION],
10234 			   wl->status.map.lps, wl->status.map.rf_off);
10235 	}
10236 
10237 	for (i = 0; i < BTC_NCNT_NUM; i++)
10238 		cnt_sum += dm->cnt_notify[i];
10239 
10240 	seq_puts(m, "\n");
10241 	seq_printf(m,
10242 		   " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10243 		   "[notify_cnt]",
10244 		   cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10245 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10246 
10247 	seq_printf(m,
10248 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10249 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10250 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10251 		   cnt[BTC_NCNT_WL_STA]);
10252 
10253 	seq_puts(m, "\n");
10254 	seq_printf(m,
10255 		   " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10256 		   "[notify_cnt]",
10257 		   cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10258 		   cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]);
10259 
10260 	seq_printf(m,
10261 		   "timer=%d, control=%d, customerize=%d",
10262 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10263 		   cnt[BTC_NCNT_CUSTOMERIZE]);
10264 }
10265 
_show_summary_v8(struct rtw89_dev * rtwdev,struct seq_file * m)10266 static void _show_summary_v8(struct rtw89_dev *rtwdev, struct seq_file *m)
10267 {
10268 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10269 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10270 	struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
10271 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
10272 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10273 	struct rtw89_btc_wl_info *wl = &cx->wl;
10274 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
10275 	u32 cnt_sum = 0;
10276 	u8 i;
10277 
10278 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10279 		return;
10280 
10281 	seq_printf(m, "%s", "\n\r========== [Statistics] ==========");
10282 
10283 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10284 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
10285 	    !wl->status.map.rf_off) {
10286 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
10287 
10288 		seq_printf(m,
10289 			   "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
10290 			   "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10291 			   le16_to_cpu(prptctrl->rpt_info.cnt_h2c), pfwinfo->cnt_c2h,
10292 			   le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10293 			   le16_to_cpu(prptctrl->rpt_info.len_c2h),
10294 			   (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
10295 			   rtwdev->btc.ver->info_buf);
10296 
10297 		seq_printf(m, "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10298 			   pfwinfo->event[BTF_EVNT_RPT],
10299 			   le16_to_cpu(prptctrl->rpt_info.cnt),
10300 			   le32_to_cpu(prptctrl->rpt_info.en));
10301 
10302 		if (dm->error.map.wl_fw_hang)
10303 			seq_puts(m, " (WL FW Hang!!)");
10304 
10305 		seq_printf(m, "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10306 			   "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10307 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10308 			   le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10309 
10310 		seq_printf(m, "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
10311 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10312 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10313 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10314 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10315 			   le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10316 
10317 		seq_printf(m,
10318 			   "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
10319 			   "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10320 			   cx->cnt_wl[BTC_WCNT_RFK_GO],
10321 			   cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10322 			   cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
10323 			   wl->rfk_info.proc_time);
10324 
10325 		seq_printf(m, ", bt_rfk[req:%d]",
10326 			   le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10327 
10328 		seq_printf(m, ", AOAC[RF_on:%d/RF_off:%d]",
10329 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10330 			   le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10331 	} else {
10332 		seq_printf(m,
10333 			   "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
10334 			   "[summary]",
10335 			   pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10336 			   pfwinfo->cnt_c2h,
10337 			   wl->status.map.lps, wl->status.map.rf_off);
10338 	}
10339 
10340 	for (i = 0; i < BTC_NCNT_NUM; i++)
10341 		cnt_sum += dm->cnt_notify[i];
10342 
10343 	seq_printf(m,
10344 		   "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10345 		   "[notify_cnt]",
10346 		   cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10347 		   cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10348 
10349 	seq_printf(m,
10350 		   "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10351 		   cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10352 		   cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10353 		   cnt[BTC_NCNT_WL_STA]);
10354 
10355 	seq_printf(m,
10356 		   "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
10357 		   "[notify_cnt]",
10358 		   cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10359 		   cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
10360 		   cnt[BTC_NCNT_SPECIAL_PACKET]);
10361 
10362 	seq_printf(m, "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
10363 		   cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
10364 		   rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
10365 		   cnt[BTC_NCNT_COUNTRYCODE]);
10366 }
10367 
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,struct seq_file * m)10368 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
10369 {
10370 	struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
10371 	struct rtw89_btc *btc = &rtwdev->btc;
10372 	const struct rtw89_btc_ver *ver = btc->ver;
10373 	struct rtw89_btc_cx *cx = &btc->cx;
10374 	struct rtw89_btc_bt_info *bt = &cx->bt;
10375 
10376 	seq_puts(m, "=========================================\n");
10377 	seq_printf(m, "WL FW / BT FW		%d.%d.%d.%d / NA\n",
10378 		   fw_suit->major_ver, fw_suit->minor_ver,
10379 		   fw_suit->sub_ver, fw_suit->sub_idex);
10380 	seq_printf(m, "manual			%d\n", btc->manual_ctrl);
10381 
10382 	seq_puts(m, "=========================================\n");
10383 
10384 	seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
10385 		   "[bt_info]",
10386 		   bt->raw_info[2], bt->raw_info[3],
10387 		   bt->raw_info[4], bt->raw_info[5],
10388 		   bt->raw_info[6], bt->raw_info[7],
10389 		   bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
10390 		   cx->cnt_bt[BTC_BCNT_INFOUPDATE],
10391 		   cx->cnt_bt[BTC_BCNT_INFOSAME]);
10392 
10393 	seq_puts(m, "\n=========================================\n");
10394 
10395 	_show_cx_info(rtwdev, m);
10396 	_show_wl_info(rtwdev, m);
10397 	_show_bt_info(rtwdev, m);
10398 	_show_dm_info(rtwdev, m);
10399 	_show_fw_dm_msg(rtwdev, m);
10400 
10401 	if (ver->fcxmreg == 1)
10402 		_show_mreg_v1(rtwdev, m);
10403 	else if (ver->fcxmreg == 2)
10404 		_show_mreg_v2(rtwdev, m);
10405 	else if (ver->fcxmreg == 7)
10406 		_show_mreg_v7(rtwdev, m);
10407 
10408 	_show_gpio_dbg(rtwdev, m);
10409 
10410 	if (ver->fcxbtcrpt == 1)
10411 		_show_summary_v1(rtwdev, m);
10412 	else if (ver->fcxbtcrpt == 4)
10413 		_show_summary_v4(rtwdev, m);
10414 	else if (ver->fcxbtcrpt == 5)
10415 		_show_summary_v5(rtwdev, m);
10416 	else if (ver->fcxbtcrpt == 105)
10417 		_show_summary_v105(rtwdev, m);
10418 	else if (ver->fcxbtcrpt == 8)
10419 		_show_summary_v8(rtwdev, m);
10420 }
10421 
rtw89_coex_recognize_ver(struct rtw89_dev * rtwdev)10422 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
10423 {
10424 	const struct rtw89_chip_info *chip = rtwdev->chip;
10425 	struct rtw89_btc *btc = &rtwdev->btc;
10426 	const struct rtw89_btc_ver *btc_ver_def;
10427 	const struct rtw89_fw_suit *fw_suit;
10428 	u32 suit_ver_code;
10429 	int i;
10430 
10431 	fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
10432 	suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
10433 
10434 	for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
10435 		btc_ver_def = &rtw89_btc_ver_defs[i];
10436 
10437 		if (chip->chip_id != btc_ver_def->chip_id)
10438 			continue;
10439 
10440 		if (suit_ver_code >= btc_ver_def->fw_ver_code) {
10441 			btc->ver = btc_ver_def;
10442 			goto out;
10443 		}
10444 	}
10445 
10446 	btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
10447 
10448 out:
10449 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
10450 		    (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
10451 }
10452