Loading...
Note: File does not exist in v3.1.
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 "ps.h"
10#include "reg.h"
11
12#define RTW89_COEX_VERSION 0x06030013
13#define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
14
15enum btc_fbtc_tdma_template {
16 CXTD_OFF = 0x0,
17 CXTD_OFF_B2,
18 CXTD_OFF_EXT,
19 CXTD_FIX,
20 CXTD_PFIX,
21 CXTD_AUTO,
22 CXTD_PAUTO,
23 CXTD_AUTO2,
24 CXTD_PAUTO2,
25 CXTD_MAX,
26};
27
28enum btc_fbtc_tdma_type {
29 CXTDMA_OFF = 0x0,
30 CXTDMA_FIX = 0x1,
31 CXTDMA_AUTO = 0x2,
32 CXTDMA_AUTO2 = 0x3,
33 CXTDMA_MAX
34};
35
36enum btc_fbtc_tdma_rx_flow_ctrl {
37 CXFLC_OFF = 0x0,
38 CXFLC_NULLP = 0x1,
39 CXFLC_QOSNULL = 0x2,
40 CXFLC_CTS = 0x3,
41 CXFLC_MAX
42};
43
44enum btc_fbtc_tdma_wlan_tx_pause {
45 CXTPS_OFF = 0x0, /* no wl tx pause*/
46 CXTPS_ON = 0x1,
47 CXTPS_MAX
48};
49
50enum btc_mlme_state {
51 MLME_NO_LINK,
52 MLME_LINKING,
53 MLME_LINKED,
54};
55
56#define FCXONESLOT_VER 1
57struct btc_fbtc_1slot {
58 u8 fver;
59 u8 sid; /* slot id */
60 struct rtw89_btc_fbtc_slot slot;
61} __packed;
62
63static const struct rtw89_btc_fbtc_tdma t_def[] = {
64 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
65 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
66 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 3, 0, 0},
67 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
68 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
69 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
70 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
71 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
72 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}
73};
74
75#define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
76 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
77 .cxtype = cpu_to_le16(__cxtype),}
78
79static const struct rtw89_btc_fbtc_slot s_def[] = {
80 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
81 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO),
82 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO),
83 [CXST_W2] = __DEF_FBTC_SLOT(70, 0xea5a5aaa, SLOT_ISO),
84 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
85 [CXST_B1] = __DEF_FBTC_SLOT(100, 0xe5555555, SLOT_MIX),
86 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX),
87 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
88 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX),
89 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO),
90 [CXST_BLK] = __DEF_FBTC_SLOT(250, 0x55555555, SLOT_MIX),
91 [CXST_E2G] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_MIX),
92 [CXST_E5G] = __DEF_FBTC_SLOT(20, 0xffffffff, SLOT_MIX),
93 [CXST_EBT] = __DEF_FBTC_SLOT(20, 0xe5555555, SLOT_MIX),
94 [CXST_ENULL] = __DEF_FBTC_SLOT(7, 0xaaaaaaaa, SLOT_ISO),
95 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
96 [CXST_W1FDD] = __DEF_FBTC_SLOT(35, 0xfafafafa, SLOT_ISO),
97 [CXST_B1FDD] = __DEF_FBTC_SLOT(100, 0xffffffff, SLOT_MIX),
98};
99
100static const u32 cxtbl[] = {
101 0xffffffff, /* 0 */
102 0xaaaaaaaa, /* 1 */
103 0xe5555555, /* 2 */
104 0xee555555, /* 3 */
105 0xd5555555, /* 4 */
106 0x5a5a5a5a, /* 5 */
107 0xfa5a5a5a, /* 6 */
108 0xda5a5a5a, /* 7 */
109 0xea5a5a5a, /* 8 */
110 0x6a5a5aaa, /* 9 */
111 0x6a5a6a5a, /* 10 */
112 0x6a5a6aaa, /* 11 */
113 0x6afa5afa, /* 12 */
114 0xaaaa5aaa, /* 13 */
115 0xaaffffaa, /* 14 */
116 0xaa5555aa, /* 15 */
117 0xfafafafa, /* 16 */
118 0xffffddff, /* 17 */
119 0xdaffdaff, /* 18 */
120 0xfafadafa /* 19 */
121};
122
123struct rtw89_btc_btf_tlv {
124 u8 type;
125 u8 len;
126 u8 val[1];
127} __packed;
128
129enum btc_btf_set_report_en {
130 RPT_EN_TDMA = BIT(0),
131 RPT_EN_CYCLE = BIT(1),
132 RPT_EN_MREG = BIT(2),
133 RPT_EN_BT_VER_INFO = BIT(3),
134 RPT_EN_BT_SCAN_INFO = BIT(4),
135 RPT_EN_BT_AFH_MAP = BIT(5),
136 RPT_EN_BT_DEVICE_INFO = BIT(6),
137 RPT_EN_WL_ALL = GENMASK(2, 0),
138 RPT_EN_BT_ALL = GENMASK(6, 3),
139 RPT_EN_ALL = GENMASK(6, 0),
140};
141
142#define BTF_SET_REPORT_VER 1
143struct rtw89_btc_btf_set_report {
144 u8 fver;
145 __le32 enable;
146 __le32 para;
147} __packed;
148
149#define BTF_SET_SLOT_TABLE_VER 1
150struct rtw89_btc_btf_set_slot_table {
151 u8 fver;
152 u8 tbl_num;
153 u8 buf[];
154} __packed;
155
156#define BTF_SET_MON_REG_VER 1
157struct rtw89_btc_btf_set_mon_reg {
158 u8 fver;
159 u8 reg_num;
160 u8 buf[];
161} __packed;
162
163enum btc_btf_set_cx_policy {
164 CXPOLICY_TDMA = 0x0,
165 CXPOLICY_SLOT = 0x1,
166 CXPOLICY_TYPE = 0x2,
167 CXPOLICY_MAX,
168};
169
170enum btc_b2w_scoreboard {
171 BTC_BSCB_ACT = BIT(0),
172 BTC_BSCB_ON = BIT(1),
173 BTC_BSCB_WHQL = BIT(2),
174 BTC_BSCB_BT_S1 = BIT(3),
175 BTC_BSCB_A2DP_ACT = BIT(4),
176 BTC_BSCB_RFK_RUN = BIT(5),
177 BTC_BSCB_RFK_REQ = BIT(6),
178 BTC_BSCB_LPS = BIT(7),
179 BTC_BSCB_WLRFK = BIT(11),
180 BTC_BSCB_BT_HILNA = BIT(13),
181 BTC_BSCB_BT_CONNECT = BIT(16),
182 BTC_BSCB_PATCH_CODE = BIT(30),
183 BTC_BSCB_ALL = GENMASK(30, 0),
184};
185
186enum btc_phymap {
187 BTC_PHY_0 = BIT(0),
188 BTC_PHY_1 = BIT(1),
189 BTC_PHY_ALL = BIT(0) | BIT(1),
190};
191
192enum btc_cx_state_map {
193 BTC_WIDLE = 0,
194 BTC_WBUSY_BNOSCAN,
195 BTC_WBUSY_BSCAN,
196 BTC_WSCAN_BNOSCAN,
197 BTC_WSCAN_BSCAN,
198 BTC_WLINKING
199};
200
201enum btc_ant_phase {
202 BTC_ANT_WPOWERON = 0,
203 BTC_ANT_WINIT,
204 BTC_ANT_WONLY,
205 BTC_ANT_WOFF,
206 BTC_ANT_W2G,
207 BTC_ANT_W5G,
208 BTC_ANT_W25G,
209 BTC_ANT_FREERUN,
210 BTC_ANT_WRFK,
211 BTC_ANT_BRFK,
212 BTC_ANT_MAX
213};
214
215enum btc_plt {
216 BTC_PLT_NONE = 0,
217 BTC_PLT_LTE_RX = BIT(0),
218 BTC_PLT_GNT_BT_TX = BIT(1),
219 BTC_PLT_GNT_BT_RX = BIT(2),
220 BTC_PLT_GNT_WL = BIT(3),
221 BTC_PLT_BT = BIT(1) | BIT(2),
222 BTC_PLT_ALL = 0xf
223};
224
225enum btc_cx_poicy_main_type {
226 BTC_CXP_OFF = 0,
227 BTC_CXP_OFFB,
228 BTC_CXP_OFFE,
229 BTC_CXP_FIX,
230 BTC_CXP_PFIX,
231 BTC_CXP_AUTO,
232 BTC_CXP_PAUTO,
233 BTC_CXP_AUTO2,
234 BTC_CXP_PAUTO2,
235 BTC_CXP_MANUAL,
236 BTC_CXP_USERDEF0,
237 BTC_CXP_MAIN_MAX
238};
239
240enum btc_cx_poicy_type {
241 /* TDMA off + pri: BT > WL */
242 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
243
244 /* TDMA off + pri: WL > BT */
245 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
246
247 /* TDMA off + pri: BT = WL */
248 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
249
250 /* TDMA off + pri: BT = WL > BT_Lo */
251 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
252
253 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
254 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
255
256 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
257 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
258
259 /* TDMA off + pri: BT_Hi > WL > BT_Lo */
260 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 6,
261
262 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
263 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 7,
264
265 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
266 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 8,
267
268 /* TDMA off + pri: WL_Hi-Tx = BT */
269 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 9,
270
271 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
272 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
273
274 /* TDMA off + Ext-Ctrl + pri: default */
275 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
276
277 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
278 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
279
280 /* TDMA off + Ext-Ctrl + pri: default */
281 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
282
283 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
284 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
285
286 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
287 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
288
289 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
290 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
291
292 /* TDMA off + Ext-Ctrl + pri: default */
293 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
294
295 /* TDMA Fix slot-0: W1:B1 = 30:30 */
296 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
297
298 /* TDMA Fix slot-1: W1:B1 = 50:50 */
299 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
300
301 /* TDMA Fix slot-2: W1:B1 = 20:30 */
302 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
303
304 /* TDMA Fix slot-3: W1:B1 = 40:10 */
305 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
306
307 /* TDMA Fix slot-4: W1:B1 = 70:10 */
308 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
309
310 /* TDMA Fix slot-5: W1:B1 = 20:60 */
311 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
312
313 /* TDMA Fix slot-6: W1:B1 = 30:60 */
314 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
315
316 /* TDMA Fix slot-7: W1:B1 = 20:80 */
317 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
318
319 /* TDMA Fix slot-8: W1:B1 = user-define */
320 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
321
322 /* TDMA Fix slot-9: W1:B1 = 40:20 */
323 BTC_CXP_FIX_TD4020 = (BTC_CXP_FIX << 8) | 9,
324
325 /* TDMA Fix slot-9: W1:B1 = 40:10 */
326 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 10,
327
328 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
329 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
330
331 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
332 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
333
334 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
335 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
336
337 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
338 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
339
340 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
341 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
342
343 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
344 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
345
346 /* PS-TDMA Fix slot-6: W1:B1 = user-define */
347 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
348
349 /* TDMA Auto slot-0: W1:B1 = 50:200 */
350 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
351
352 /* TDMA Auto slot-1: W1:B1 = 60:200 */
353 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
354
355 /* TDMA Auto slot-2: W1:B1 = 20:200 */
356 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
357
358 /* TDMA Auto slot-3: W1:B1 = user-define */
359 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
360
361 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
362 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
363
364 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
365 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
366
367 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
368 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
369
370 /* PS-TDMA Auto slot-3: W1:B1 = user-define */
371 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
372
373 /* TDMA Auto slot2-0: W1:B4 = 30:50 */
374 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
375
376 /* TDMA Auto slot2-1: W1:B4 = 30:70 */
377 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
378
379 /* TDMA Auto slot2-2: W1:B4 = 50:50 */
380 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
381
382 /* TDMA Auto slot2-3: W1:B4 = 60:60 */
383 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
384
385 /* TDMA Auto slot2-4: W1:B4 = 20:80 */
386 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
387
388 /* TDMA Auto slot2-5: W1:B4 = user-define */
389 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
390
391 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
392 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
393
394 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
395 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
396
397 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
398 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
399
400 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
401 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
402
403 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
404 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
405
406 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */
407 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
408
409 BTC_CXP_MAX = 0xffff
410};
411
412enum btc_wl_rfk_result {
413 BTC_WRFK_REJECT = 0,
414 BTC_WRFK_ALLOW = 1,
415};
416
417enum btc_coex_info_map_en {
418 BTC_COEX_INFO_CX = BIT(0),
419 BTC_COEX_INFO_WL = BIT(1),
420 BTC_COEX_INFO_BT = BIT(2),
421 BTC_COEX_INFO_DM = BIT(3),
422 BTC_COEX_INFO_MREG = BIT(4),
423 BTC_COEX_INFO_SUMMARY = BIT(5),
424 BTC_COEX_INFO_ALL = GENMASK(7, 0),
425};
426
427#define BTC_CXP_MASK GENMASK(15, 8)
428
429enum btc_w2b_scoreboard {
430 BTC_WSCB_ACTIVE = BIT(0),
431 BTC_WSCB_ON = BIT(1),
432 BTC_WSCB_SCAN = BIT(2),
433 BTC_WSCB_UNDERTEST = BIT(3),
434 BTC_WSCB_RXGAIN = BIT(4),
435 BTC_WSCB_WLBUSY = BIT(7),
436 BTC_WSCB_EXTFEM = BIT(8),
437 BTC_WSCB_TDMA = BIT(9),
438 BTC_WSCB_FIX2M = BIT(10),
439 BTC_WSCB_WLRFK = BIT(11),
440 BTC_WSCB_RXSCAN_PRI = BIT(12),
441 BTC_WSCB_BT_HILNA = BIT(13),
442 BTC_WSCB_BTLOG = BIT(14),
443 BTC_WSCB_ALL = GENMASK(23, 0),
444};
445
446enum btc_wl_link_mode {
447 BTC_WLINK_NOLINK = 0x0,
448 BTC_WLINK_2G_STA,
449 BTC_WLINK_2G_AP,
450 BTC_WLINK_2G_GO,
451 BTC_WLINK_2G_GC,
452 BTC_WLINK_2G_SCC,
453 BTC_WLINK_2G_MCC,
454 BTC_WLINK_25G_MCC,
455 BTC_WLINK_25G_DBCC,
456 BTC_WLINK_5G,
457 BTC_WLINK_2G_NAN,
458 BTC_WLINK_OTHER,
459 BTC_WLINK_MAX
460};
461
462enum btc_wl_mrole_type {
463 BTC_WLMROLE_NONE = 0x0,
464 BTC_WLMROLE_STA_GC,
465 BTC_WLMROLE_STA_GC_NOA,
466 BTC_WLMROLE_STA_GO,
467 BTC_WLMROLE_STA_GO_NOA,
468 BTC_WLMROLE_STA_STA,
469 BTC_WLMROLE_MAX
470};
471
472enum btc_bt_hid_type {
473 BTC_HID_218 = BIT(0),
474 BTC_HID_418 = BIT(1),
475 BTC_HID_BLE = BIT(2),
476 BTC_HID_RCU = BIT(3),
477 BTC_HID_RCU_VOICE = BIT(4),
478 BTC_HID_OTHER_LEGACY = BIT(5)
479};
480
481enum btc_reset_module {
482 BTC_RESET_CX = BIT(0),
483 BTC_RESET_DM = BIT(1),
484 BTC_RESET_CTRL = BIT(2),
485 BTC_RESET_CXDM = BIT(0) | BIT(1),
486 BTC_RESET_BTINFO = BIT(3),
487 BTC_RESET_MDINFO = BIT(4),
488 BTC_RESET_ALL = GENMASK(7, 0),
489};
490
491enum btc_gnt_state {
492 BTC_GNT_HW = 0,
493 BTC_GNT_SW_LO,
494 BTC_GNT_SW_HI,
495 BTC_GNT_MAX
496};
497
498enum btc_ctr_path {
499 BTC_CTRL_BY_BT = 0,
500 BTC_CTRL_BY_WL
501};
502
503enum btc_wl_max_tx_time {
504 BTC_MAX_TX_TIME_L1 = 500,
505 BTC_MAX_TX_TIME_L2 = 1000,
506 BTC_MAX_TX_TIME_L3 = 2000,
507 BTC_MAX_TX_TIME_DEF = 5280
508};
509
510enum btc_wl_max_tx_retry {
511 BTC_MAX_TX_RETRY_L1 = 7,
512 BTC_MAX_TX_RETRY_L2 = 15,
513 BTC_MAX_TX_RETRY_DEF = 31,
514};
515
516enum btc_reason_and_action {
517 BTC_RSN_NONE,
518 BTC_RSN_NTFY_INIT,
519 BTC_RSN_NTFY_SWBAND,
520 BTC_RSN_NTFY_WL_STA,
521 BTC_RSN_NTFY_RADIO_STATE,
522 BTC_RSN_UPDATE_BT_SCBD,
523 BTC_RSN_NTFY_WL_RFK,
524 BTC_RSN_UPDATE_BT_INFO,
525 BTC_RSN_NTFY_SCAN_START,
526 BTC_RSN_NTFY_SCAN_FINISH,
527 BTC_RSN_NTFY_SPECIFIC_PACKET,
528 BTC_RSN_NTFY_POWEROFF,
529 BTC_RSN_NTFY_ROLE_INFO,
530 BTC_RSN_CMD_SET_COEX,
531 BTC_RSN_ACT1_WORK,
532 BTC_RSN_BT_DEVINFO_WORK,
533 BTC_RSN_RFK_CHK_WORK,
534 BTC_RSN_NUM,
535 BTC_ACT_NONE = 100,
536 BTC_ACT_WL_ONLY,
537 BTC_ACT_WL_5G,
538 BTC_ACT_WL_OTHER,
539 BTC_ACT_WL_IDLE,
540 BTC_ACT_WL_NC,
541 BTC_ACT_WL_RFK,
542 BTC_ACT_WL_INIT,
543 BTC_ACT_WL_OFF,
544 BTC_ACT_FREERUN,
545 BTC_ACT_BT_WHQL,
546 BTC_ACT_BT_RFK,
547 BTC_ACT_BT_OFF,
548 BTC_ACT_BT_IDLE,
549 BTC_ACT_BT_HFP,
550 BTC_ACT_BT_HID,
551 BTC_ACT_BT_A2DP,
552 BTC_ACT_BT_A2DPSINK,
553 BTC_ACT_BT_PAN,
554 BTC_ACT_BT_A2DP_HID,
555 BTC_ACT_BT_A2DP_PAN,
556 BTC_ACT_BT_PAN_HID,
557 BTC_ACT_BT_A2DP_PAN_HID,
558 BTC_ACT_WL_25G_MCC,
559 BTC_ACT_WL_2G_MCC,
560 BTC_ACT_WL_2G_SCC,
561 BTC_ACT_WL_2G_AP,
562 BTC_ACT_WL_2G_GO,
563 BTC_ACT_WL_2G_GC,
564 BTC_ACT_WL_2G_NAN,
565 BTC_ACT_LAST,
566 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
567 BTC_ACT_EXT_BIT = BIT(14),
568 BTC_POLICY_EXT_BIT = BIT(15),
569};
570
571#define BTC_FREERUN_ANTISO_MIN 30
572#define BTC_TDMA_BTHID_MAX 2
573#define BTC_BLINK_NOCONNECT 0
574#define BTC_B1_MAX 250 /* unit ms */
575
576static void _run_coex(struct rtw89_dev *rtwdev,
577 enum btc_reason_and_action reason);
578static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
579static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
580
581static void _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
582 void *param, u16 len)
583{
584 struct rtw89_btc *btc = &rtwdev->btc;
585 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
586 struct rtw89_btc_cx *cx = &btc->cx;
587 struct rtw89_btc_wl_info *wl = &cx->wl;
588 int ret;
589
590 if (!wl->status.map.init_ok) {
591 rtw89_debug(rtwdev, RTW89_DBG_BTC,
592 "[BTC], %s(): return by btc not init!!\n", __func__);
593 pfwinfo->cnt_h2c_fail++;
594 return;
595 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
596 wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
597 (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
598 wl->status.map.lps == BTC_LPS_RF_OFF)) {
599 rtw89_debug(rtwdev, RTW89_DBG_BTC,
600 "[BTC], %s(): return by wl off!!\n", __func__);
601 pfwinfo->cnt_h2c_fail++;
602 return;
603 }
604
605 pfwinfo->cnt_h2c++;
606
607 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
608 false, true);
609 if (ret != 0)
610 pfwinfo->cnt_h2c_fail++;
611}
612
613static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
614{
615 struct rtw89_btc *btc = &rtwdev->btc;
616 struct rtw89_btc_cx *cx = &btc->cx;
617 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
618 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
619 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
620 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
621 u8 i;
622
623 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
624
625 if (type & BTC_RESET_CX)
626 memset(cx, 0, sizeof(*cx));
627 else if (type & BTC_RESET_BTINFO) /* only for BT enable */
628 memset(bt, 0, sizeof(*bt));
629
630 if (type & BTC_RESET_CTRL) {
631 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
632 btc->ctrl.trace_step = FCXDEF_STEP;
633 }
634
635 /* Init Coex variables that are not zero */
636 if (type & BTC_RESET_DM) {
637 memset(&btc->dm, 0, sizeof(btc->dm));
638 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
639
640 for (i = 0; i < RTW89_PORT_NUM; i++)
641 memset(wl_linfo[i].rssi_state, 0,
642 sizeof(wl_linfo[i].rssi_state));
643
644 /* set the slot_now table to original */
645 btc->dm.tdma_now = t_def[CXTD_OFF];
646 btc->dm.tdma = t_def[CXTD_OFF];
647 memcpy(&btc->dm.slot_now, s_def, sizeof(btc->dm.slot_now));
648 memcpy(&btc->dm.slot, s_def, sizeof(btc->dm.slot));
649
650 btc->policy_len = 0;
651 btc->bt_req_len = 0;
652
653 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
654 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
655 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
656 }
657
658 if (type & BTC_RESET_MDINFO)
659 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
660}
661
662#define BTC_RPT_HDR_SIZE 3
663#define BTC_CHK_WLSLOT_DRIFT_MAX 15
664#define BTC_CHK_HANG_MAX 3
665
666static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
667{
668 struct rtw89_btc *btc = &rtwdev->btc;
669 struct rtw89_btc_cx *cx = &btc->cx;
670 struct rtw89_btc_dm *dm = &btc->dm;
671 struct rtw89_btc_bt_info *bt = &cx->bt;
672
673 rtw89_debug(rtwdev, RTW89_DBG_BTC,
674 "[BTC], %s(): type:%d cnt:%d\n",
675 __func__, type, cnt);
676
677 switch (type) {
678 case BTC_DCNT_RPT_FREEZE:
679 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
680 dm->cnt_dm[BTC_DCNT_RPT_FREEZE]++;
681 else
682 dm->cnt_dm[BTC_DCNT_RPT_FREEZE] = 0;
683
684 if (dm->cnt_dm[BTC_DCNT_RPT_FREEZE] >= BTC_CHK_HANG_MAX)
685 dm->error.map.wl_fw_hang = true;
686 else
687 dm->error.map.wl_fw_hang = false;
688
689 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
690 break;
691 case BTC_DCNT_CYCLE_FREEZE:
692 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
693 (dm->tdma_now.type != CXTDMA_OFF ||
694 dm->tdma_now.ext_ctrl == CXECTL_EXT))
695 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE]++;
696 else
697 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] = 0;
698
699 if (dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] >= BTC_CHK_HANG_MAX)
700 dm->error.map.cycle_hang = true;
701 else
702 dm->error.map.cycle_hang = false;
703
704 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
705 break;
706 case BTC_DCNT_W1_FREEZE:
707 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
708 dm->tdma_now.type != CXTDMA_OFF)
709 dm->cnt_dm[BTC_DCNT_W1_FREEZE]++;
710 else
711 dm->cnt_dm[BTC_DCNT_W1_FREEZE] = 0;
712
713 if (dm->cnt_dm[BTC_DCNT_W1_FREEZE] >= BTC_CHK_HANG_MAX)
714 dm->error.map.w1_hang = true;
715 else
716 dm->error.map.w1_hang = false;
717
718 dm->cnt_dm[BTC_DCNT_W1] = cnt;
719 break;
720 case BTC_DCNT_B1_FREEZE:
721 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
722 dm->tdma_now.type != CXTDMA_OFF)
723 dm->cnt_dm[BTC_DCNT_B1_FREEZE]++;
724 else
725 dm->cnt_dm[BTC_DCNT_B1_FREEZE] = 0;
726
727 if (dm->cnt_dm[BTC_DCNT_B1_FREEZE] >= BTC_CHK_HANG_MAX)
728 dm->error.map.b1_hang = true;
729 else
730 dm->error.map.b1_hang = false;
731
732 dm->cnt_dm[BTC_DCNT_B1] = cnt;
733 break;
734 case BTC_DCNT_TDMA_NONSYNC:
735 if (cnt != 0) /* if tdma not sync between drv/fw */
736 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
737 else
738 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
739
740 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
741 dm->error.map.tdma_no_sync = true;
742 else
743 dm->error.map.tdma_no_sync = false;
744 break;
745 case BTC_DCNT_SLOT_NONSYNC:
746 if (cnt != 0) /* if slot not sync between drv/fw */
747 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
748 else
749 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
750
751 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
752 dm->error.map.tdma_no_sync = true;
753 else
754 dm->error.map.tdma_no_sync = false;
755 break;
756 case BTC_DCNT_BTCNT_FREEZE:
757 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
758 cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
759 cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
760 cx->cnt_bt[BTC_BCNT_LOPRI_TX];
761
762 if (cnt == 0)
763 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE]++;
764 else
765 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
766
767 if ((dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX &&
768 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] &&
769 !bt->enable.now))
770 _update_bt_scbd(rtwdev, false);
771 break;
772 case BTC_DCNT_WL_SLOT_DRIFT:
773 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
774 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
775 else
776 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
777
778 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
779 dm->error.map.wl_slot_drift = true;
780 else
781 dm->error.map.wl_slot_drift = false;
782 break;
783 }
784}
785
786static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
787{
788 struct rtw89_btc *btc = &rtwdev->btc;
789 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
790 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
791 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
792 struct rtw89_btc_fbtc_btver *pver = NULL;
793 struct rtw89_btc_fbtc_btscan *pscan = NULL;
794 struct rtw89_btc_fbtc_btafh *pafh = NULL;
795 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
796
797 pver = (struct rtw89_btc_fbtc_btver *)pfinfo;
798 pscan = (struct rtw89_btc_fbtc_btscan *)pfinfo;
799 pafh = (struct rtw89_btc_fbtc_btafh *)pfinfo;
800 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
801
802 rtw89_debug(rtwdev, RTW89_DBG_BTC,
803 "[BTC], %s(): rpt_type:%d\n",
804 __func__, rpt_type);
805
806 switch (rpt_type) {
807 case BTC_RPT_TYPE_BT_VER:
808 bt->ver_info.fw = le32_to_cpu(pver->fw_ver);
809 bt->ver_info.fw_coex = le32_get_bits(pver->coex_ver, GENMASK(7, 0));
810 bt->feature = le32_to_cpu(pver->feature);
811 break;
812 case BTC_RPT_TYPE_BT_SCAN:
813 memcpy(bt->scan_info, pscan->scan, BTC_SCAN_MAX1);
814 break;
815 case BTC_RPT_TYPE_BT_AFH:
816 memcpy(&bt_linfo->afh_map[0], pafh->afh_l, 4);
817 memcpy(&bt_linfo->afh_map[4], pafh->afh_m, 4);
818 memcpy(&bt_linfo->afh_map[8], pafh->afh_h, 2);
819 break;
820 case BTC_RPT_TYPE_BT_DEVICE:
821 a2dp->device_name = le32_to_cpu(pdev->dev_name);
822 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
823 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
824 break;
825 default:
826 break;
827 }
828}
829
830struct rtw89_btc_fbtc_cysta_cpu {
831 u8 fver;
832 u8 rsvd;
833 u16 cycles;
834 u16 cycles_a2dp[CXT_FLCTRL_MAX];
835 u16 a2dpept;
836 u16 a2dpeptto;
837 u16 tavg_cycle[CXT_MAX];
838 u16 tmax_cycle[CXT_MAX];
839 u16 tmaxdiff_cycle[CXT_MAX];
840 u16 tavg_a2dp[CXT_FLCTRL_MAX];
841 u16 tmax_a2dp[CXT_FLCTRL_MAX];
842 u16 tavg_a2dpept;
843 u16 tmax_a2dpept;
844 u16 tavg_lk;
845 u16 tmax_lk;
846 u32 slot_cnt[CXST_MAX];
847 u32 bcn_cnt[CXBCN_MAX];
848 u32 leakrx_cnt;
849 u32 collision_cnt;
850 u32 skip_cnt;
851 u32 exception;
852 u32 except_cnt;
853 u16 tslot_cycle[BTC_CYCLE_SLOT_MAX];
854};
855
856static void rtw89_btc_fbtc_cysta_to_cpu(const struct rtw89_btc_fbtc_cysta *src,
857 struct rtw89_btc_fbtc_cysta_cpu *dst)
858{
859 static_assert(sizeof(*src) == sizeof(*dst));
860
861#define __CPY_U8(_x) ({dst->_x = src->_x; })
862#define __CPY_LE16(_x) ({dst->_x = le16_to_cpu(src->_x); })
863#define __CPY_LE16S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
864 dst->_x[_i] = le16_to_cpu(src->_x[_i]); })
865#define __CPY_LE32(_x) ({dst->_x = le32_to_cpu(src->_x); })
866#define __CPY_LE32S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
867 dst->_x[_i] = le32_to_cpu(src->_x[_i]); })
868
869 __CPY_U8(fver);
870 __CPY_U8(rsvd);
871 __CPY_LE16(cycles);
872 __CPY_LE16S(cycles_a2dp);
873 __CPY_LE16(a2dpept);
874 __CPY_LE16(a2dpeptto);
875 __CPY_LE16S(tavg_cycle);
876 __CPY_LE16S(tmax_cycle);
877 __CPY_LE16S(tmaxdiff_cycle);
878 __CPY_LE16S(tavg_a2dp);
879 __CPY_LE16S(tmax_a2dp);
880 __CPY_LE16(tavg_a2dpept);
881 __CPY_LE16(tmax_a2dpept);
882 __CPY_LE16(tavg_lk);
883 __CPY_LE16(tmax_lk);
884 __CPY_LE32S(slot_cnt);
885 __CPY_LE32S(bcn_cnt);
886 __CPY_LE32(leakrx_cnt);
887 __CPY_LE32(collision_cnt);
888 __CPY_LE32(skip_cnt);
889 __CPY_LE32(exception);
890 __CPY_LE32(except_cnt);
891 __CPY_LE16S(tslot_cycle);
892
893#undef __CPY_U8
894#undef __CPY_LE16
895#undef __CPY_LE16S
896#undef __CPY_LE32
897#undef __CPY_LE32S
898}
899
900#define BTC_LEAK_AP_TH 10
901#define BTC_CYSTA_CHK_PERIOD 100
902
903struct rtw89_btc_prpt {
904 u8 type;
905 __le16 len;
906 u8 content[];
907} __packed;
908
909static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
910 struct rtw89_btc_btf_fwinfo *pfwinfo,
911 u8 *prptbuf, u32 index)
912{
913 const struct rtw89_chip_info *chip = rtwdev->chip;
914 struct rtw89_btc *btc = &rtwdev->btc;
915 struct rtw89_btc_dm *dm = &btc->dm;
916 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
917 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
918 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
919 struct rtw89_btc_fbtc_rpt_ctrl *prpt;
920 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prpt_v1;
921 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
922 struct rtw89_btc_fbtc_cysta_v1 *pcysta_v1 = NULL;
923 struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
924 struct rtw89_btc_prpt *btc_prpt = NULL;
925 struct rtw89_btc_fbtc_slot *rtp_slot = NULL;
926 void *rpt_content = NULL, *pfinfo = NULL;
927 u8 rpt_type = 0;
928 u16 wl_slot_set = 0, wl_slot_real = 0;
929 u32 trace_step = btc->ctrl.trace_step, rpt_len = 0, diff_t;
930 u32 cnt_leak_slot = 0, bt_slot_real = 0, cnt_rx_imr = 0;
931 u8 i;
932
933 rtw89_debug(rtwdev, RTW89_DBG_BTC,
934 "[BTC], %s(): index:%d\n",
935 __func__, index);
936
937 if (!prptbuf) {
938 pfwinfo->err[BTFRE_INVALID_INPUT]++;
939 return 0;
940 }
941
942 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
943 rpt_type = btc_prpt->type;
944 rpt_len = le16_to_cpu(btc_prpt->len);
945 rpt_content = btc_prpt->content;
946
947 rtw89_debug(rtwdev, RTW89_DBG_BTC,
948 "[BTC], %s(): rpt_type:%d\n",
949 __func__, rpt_type);
950
951 switch (rpt_type) {
952 case BTC_RPT_TYPE_CTRL:
953 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
954 if (chip->chip_id == RTL8852A) {
955 pfinfo = &pfwinfo->rpt_ctrl.finfo;
956 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo);
957 } else {
958 pfinfo = &pfwinfo->rpt_ctrl.finfo_v1;
959 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo_v1);
960 }
961 pcinfo->req_fver = chip->fcxbtcrpt_ver;
962 pcinfo->rx_len = rpt_len;
963 pcinfo->rx_cnt++;
964 break;
965 case BTC_RPT_TYPE_TDMA:
966 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
967 if (chip->chip_id == RTL8852A) {
968 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo;
969 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo);
970 } else {
971 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo_v1;
972 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo_v1);
973 }
974 pcinfo->req_fver = chip->fcxtdma_ver;
975 pcinfo->rx_len = rpt_len;
976 pcinfo->rx_cnt++;
977 break;
978 case BTC_RPT_TYPE_SLOT:
979 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
980 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo;
981 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
982 pcinfo->req_fver = chip->fcxslots_ver;
983 pcinfo->rx_len = rpt_len;
984 pcinfo->rx_cnt++;
985 break;
986 case BTC_RPT_TYPE_CYSTA:
987 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
988 if (chip->chip_id == RTL8852A) {
989 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo;
990 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
991 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
992 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo);
993 } else {
994 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
995 pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
996 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo_v1);
997 }
998 pcinfo->req_fver = chip->fcxcysta_ver;
999 pcinfo->rx_len = rpt_len;
1000 pcinfo->rx_cnt++;
1001 break;
1002 case BTC_RPT_TYPE_STEP:
1003 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1004 if (chip->chip_id == RTL8852A) {
1005 pfinfo = &pfwinfo->rpt_fbtc_step.finfo;
1006 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.step[0]) *
1007 trace_step +
1008 offsetof(struct rtw89_btc_fbtc_steps, step);
1009 } else {
1010 pfinfo = &pfwinfo->rpt_fbtc_step.finfo_v1;
1011 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo_v1.step[0]) *
1012 trace_step +
1013 offsetof(struct rtw89_btc_fbtc_steps_v1, step);
1014 }
1015 pcinfo->req_fver = chip->fcxstep_ver;
1016 pcinfo->rx_len = rpt_len;
1017 pcinfo->rx_cnt++;
1018 break;
1019 case BTC_RPT_TYPE_NULLSTA:
1020 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1021 if (chip->chip_id == RTL8852A) {
1022 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo;
1023 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo);
1024 } else {
1025 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo_v1;
1026 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo_v1);
1027 }
1028 pcinfo->req_fver = chip->fcxnullsta_ver;
1029 pcinfo->rx_len = rpt_len;
1030 pcinfo->rx_cnt++;
1031 break;
1032 case BTC_RPT_TYPE_MREG:
1033 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1034 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo;
1035 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo);
1036 pcinfo->req_fver = chip->fcxmreg_ver;
1037 pcinfo->rx_len = rpt_len;
1038 pcinfo->rx_cnt++;
1039 break;
1040 case BTC_RPT_TYPE_GPIO_DBG:
1041 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1042 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
1043 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo);
1044 pcinfo->req_fver = chip->fcxgpiodbg_ver;
1045 pcinfo->rx_len = rpt_len;
1046 pcinfo->rx_cnt++;
1047 break;
1048 case BTC_RPT_TYPE_BT_VER:
1049 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1050 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo;
1051 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo);
1052 pcinfo->req_fver = chip->fcxbtver_ver;
1053 pcinfo->rx_len = rpt_len;
1054 pcinfo->rx_cnt++;
1055 break;
1056 case BTC_RPT_TYPE_BT_SCAN:
1057 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1058 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo;
1059 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo);
1060 pcinfo->req_fver = chip->fcxbtscan_ver;
1061 pcinfo->rx_len = rpt_len;
1062 pcinfo->rx_cnt++;
1063 break;
1064 case BTC_RPT_TYPE_BT_AFH:
1065 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1066 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo;
1067 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo);
1068 pcinfo->req_fver = chip->fcxbtafh_ver;
1069 pcinfo->rx_len = rpt_len;
1070 pcinfo->rx_cnt++;
1071 break;
1072 case BTC_RPT_TYPE_BT_DEVICE:
1073 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1074 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1075 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1076 pcinfo->req_fver = chip->fcxbtdevinfo_ver;
1077 pcinfo->rx_len = rpt_len;
1078 pcinfo->rx_cnt++;
1079 break;
1080 default:
1081 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1082 return 0;
1083 }
1084
1085 if (rpt_len != pcinfo->req_len) {
1086 if (rpt_type < BTC_RPT_TYPE_MAX)
1087 pfwinfo->len_mismch |= (0x1 << rpt_type);
1088 else
1089 pfwinfo->len_mismch |= BIT(31);
1090 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1091 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
1092 __func__, rpt_type, rpt_len, pcinfo->req_len);
1093
1094 pcinfo->valid = 0;
1095 return 0;
1096 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
1097 pfwinfo->err[BTFRE_EXCEPTION]++;
1098 pcinfo->valid = 0;
1099 return 0;
1100 }
1101
1102 memcpy(pfinfo, rpt_content, pcinfo->req_len);
1103 pcinfo->valid = 1;
1104
1105 if (rpt_type == BTC_RPT_TYPE_TDMA && chip->chip_id == RTL8852A) {
1106 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1107 "[BTC], %s(): check %d %zu\n", __func__,
1108 BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
1109
1110 if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo,
1111 sizeof(dm->tdma_now)) != 0) {
1112 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1113 "[BTC], %s(): %d tdma_now %x %x %x %x %x %x %x %x\n",
1114 __func__, BTC_DCNT_TDMA_NONSYNC,
1115 dm->tdma_now.type, dm->tdma_now.rxflctrl,
1116 dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
1117 dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
1118 dm->tdma_now.rxflctrl_role,
1119 dm->tdma_now.option_ctrl);
1120
1121 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1122 "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
1123 __func__, BTC_DCNT_TDMA_NONSYNC,
1124 pfwinfo->rpt_fbtc_tdma.finfo.type,
1125 pfwinfo->rpt_fbtc_tdma.finfo.rxflctrl,
1126 pfwinfo->rpt_fbtc_tdma.finfo.txpause,
1127 pfwinfo->rpt_fbtc_tdma.finfo.wtgle_n,
1128 pfwinfo->rpt_fbtc_tdma.finfo.leak_n,
1129 pfwinfo->rpt_fbtc_tdma.finfo.ext_ctrl,
1130 pfwinfo->rpt_fbtc_tdma.finfo.rxflctrl_role,
1131 pfwinfo->rpt_fbtc_tdma.finfo.option_ctrl);
1132 }
1133
1134 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1135 memcmp(&dm->tdma_now,
1136 &pfwinfo->rpt_fbtc_tdma.finfo,
1137 sizeof(dm->tdma_now)));
1138 } else if (rpt_type == BTC_RPT_TYPE_TDMA) {
1139 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1140 "[BTC], %s(): check %d %zu\n", __func__,
1141 BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
1142
1143 if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
1144 sizeof(dm->tdma_now)) != 0) {
1145 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1146 "[BTC], %s(): %d tdma_now %x %x %x %x %x %x %x %x\n",
1147 __func__, BTC_DCNT_TDMA_NONSYNC,
1148 dm->tdma_now.type, dm->tdma_now.rxflctrl,
1149 dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
1150 dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
1151 dm->tdma_now.rxflctrl_role,
1152 dm->tdma_now.option_ctrl);
1153 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1154 "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
1155 __func__, BTC_DCNT_TDMA_NONSYNC,
1156 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.type,
1157 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl,
1158 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.txpause,
1159 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.wtgle_n,
1160 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.leak_n,
1161 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.ext_ctrl,
1162 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl_role,
1163 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.option_ctrl);
1164 }
1165
1166 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1167 memcmp(&dm->tdma_now,
1168 &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
1169 sizeof(dm->tdma_now)));
1170 }
1171
1172 if (rpt_type == BTC_RPT_TYPE_SLOT) {
1173 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1174 "[BTC], %s(): check %d %zu\n",
1175 __func__, BTC_DCNT_SLOT_NONSYNC,
1176 sizeof(dm->slot_now));
1177
1178 if (memcmp(dm->slot_now, pfwinfo->rpt_fbtc_slots.finfo.slot,
1179 sizeof(dm->slot_now)) != 0) {
1180 for (i = 0; i < CXST_MAX; i++) {
1181 rtp_slot =
1182 &pfwinfo->rpt_fbtc_slots.finfo.slot[i];
1183 if (memcmp(&dm->slot_now[i], rtp_slot,
1184 sizeof(dm->slot_now[i])) != 0) {
1185 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1186 "[BTC], %s(): %d slot_now[%d] dur=0x%04x tbl=%08x type=0x%04x\n",
1187 __func__,
1188 BTC_DCNT_SLOT_NONSYNC, i,
1189 dm->slot_now[i].dur,
1190 dm->slot_now[i].cxtbl,
1191 dm->slot_now[i].cxtype);
1192
1193 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1194 "[BTC], %s(): %d rpt_fbtc_slots[%d] dur=0x%04x tbl=%08x type=0x%04x\n",
1195 __func__,
1196 BTC_DCNT_SLOT_NONSYNC, i,
1197 rtp_slot->dur,
1198 rtp_slot->cxtbl,
1199 rtp_slot->cxtype);
1200 }
1201 }
1202 }
1203 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1204 memcmp(dm->slot_now,
1205 pfwinfo->rpt_fbtc_slots.finfo.slot,
1206 sizeof(dm->slot_now)));
1207 }
1208
1209 if (rpt_type == BTC_RPT_TYPE_CYSTA && chip->chip_id == RTL8852A &&
1210 pcysta->cycles >= BTC_CYSTA_CHK_PERIOD) {
1211 /* Check Leak-AP */
1212 if (pcysta->slot_cnt[CXST_LK] != 0 &&
1213 pcysta->leakrx_cnt != 0 && dm->tdma_now.rxflctrl) {
1214 if (pcysta->slot_cnt[CXST_LK] <
1215 BTC_LEAK_AP_TH * pcysta->leakrx_cnt)
1216 dm->leak_ap = 1;
1217 }
1218
1219 /* Check diff time between WL slot and W1/E2G slot */
1220 if (dm->tdma_now.type == CXTDMA_OFF &&
1221 dm->tdma_now.ext_ctrl == CXECTL_EXT)
1222 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_E2G].dur);
1223 else
1224 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
1225
1226 if (pcysta->tavg_cycle[CXT_WL] > wl_slot_set) {
1227 diff_t = pcysta->tavg_cycle[CXT_WL] - wl_slot_set;
1228 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1229 }
1230
1231 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_W1]);
1232 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_B1]);
1233 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE, (u32)pcysta->cycles);
1234 } else if (rpt_type == BTC_RPT_TYPE_CYSTA && pcysta_v1 &&
1235 le16_to_cpu(pcysta_v1->cycles) >= BTC_CYSTA_CHK_PERIOD) {
1236 cnt_leak_slot = le32_to_cpu(pcysta_v1->slot_cnt[CXST_LK]);
1237 cnt_rx_imr = le32_to_cpu(pcysta_v1->leak_slot.cnt_rximr);
1238 /* Check Leak-AP */
1239 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1240 dm->tdma_now.rxflctrl) {
1241 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1242 dm->leak_ap = 1;
1243 }
1244
1245 /* Check diff time between real WL slot and W1 slot */
1246 if (dm->tdma_now.type == CXTDMA_OFF) {
1247 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
1248 wl_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_WL]);
1249 if (wl_slot_real > wl_slot_set) {
1250 diff_t = wl_slot_real - wl_slot_set;
1251 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1252 }
1253 }
1254
1255 /* Check diff time between real BT slot and EBT/E5G slot */
1256 if (dm->tdma_now.type == CXTDMA_OFF &&
1257 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1258 btc->bt_req_len != 0) {
1259 bt_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_BT]);
1260
1261 if (btc->bt_req_len > bt_slot_real) {
1262 diff_t = btc->bt_req_len - bt_slot_real;
1263 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1264 }
1265 }
1266
1267 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE,
1268 le32_to_cpu(pcysta_v1->slot_cnt[CXST_W1]));
1269 _chk_btc_err(rtwdev, BTC_DCNT_B1_FREEZE,
1270 le32_to_cpu(pcysta_v1->slot_cnt[CXST_B1]));
1271 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE,
1272 (u32)le16_to_cpu(pcysta_v1->cycles));
1273 }
1274
1275 if (rpt_type == BTC_RPT_TYPE_CTRL && chip->chip_id == RTL8852A) {
1276 prpt = &pfwinfo->rpt_ctrl.finfo;
1277 btc->fwinfo.rpt_en_map = prpt->rpt_enable;
1278 wl->ver_info.fw_coex = prpt->wl_fw_coex_ver;
1279 wl->ver_info.fw = prpt->wl_fw_ver;
1280 dm->wl_fw_cx_offload = !!prpt->wl_fw_cx_offload;
1281
1282 _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
1283 pfwinfo->event[BTF_EVNT_RPT]);
1284
1285 /* To avoid I/O if WL LPS or power-off */
1286 if (wl->status.map.lps != BTC_LPS_RF_OFF && !wl->status.map.rf_off) {
1287 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1288 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0);
1289
1290 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1291 rtw89_mac_get_plt_cnt(rtwdev, RTW89_MAC_0);
1292 }
1293 } else if (rpt_type == BTC_RPT_TYPE_CTRL) {
1294 prpt_v1 = &pfwinfo->rpt_ctrl.finfo_v1;
1295 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt_v1->rpt_info.en);
1296 wl->ver_info.fw_coex = le32_to_cpu(prpt_v1->wl_fw_info.cx_ver);
1297 wl->ver_info.fw = le32_to_cpu(prpt_v1->wl_fw_info.fw_ver);
1298 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt_v1->wl_fw_info.cx_offload);
1299
1300 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1301 memcpy(&dm->gnt.band[i], &prpt_v1->gnt_val[i],
1302 sizeof(dm->gnt.band[i]));
1303
1304 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_TX]);
1305 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_RX]);
1306 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_TX]);
1307 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_RX]);
1308 btc->cx.cnt_bt[BTC_BCNT_POLUT] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_POLLUTED]);
1309
1310 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0);
1311 _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
1312 pfwinfo->event[BTF_EVNT_RPT]);
1313
1314 if (le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1315 bt->rfk_info.map.timeout = 1;
1316 else
1317 bt->rfk_info.map.timeout = 0;
1318
1319 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1320 }
1321
1322 if (rpt_type >= BTC_RPT_TYPE_BT_VER &&
1323 rpt_type <= BTC_RPT_TYPE_BT_DEVICE)
1324 _update_bt_report(rtwdev, rpt_type, pfinfo);
1325
1326 return (rpt_len + BTC_RPT_HDR_SIZE);
1327}
1328
1329static void _parse_btc_report(struct rtw89_dev *rtwdev,
1330 struct rtw89_btc_btf_fwinfo *pfwinfo,
1331 u8 *pbuf, u32 buf_len)
1332{
1333 const struct rtw89_chip_info *chip = rtwdev->chip;
1334 struct rtw89_btc_prpt *btc_prpt = NULL;
1335 u32 index = 0, rpt_len = 0;
1336
1337 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1338 "[BTC], %s(): buf_len:%d\n",
1339 __func__, buf_len);
1340
1341 while (pbuf) {
1342 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
1343 if (index + 2 >= chip->btc_fwinfo_buf)
1344 break;
1345 /* At least 3 bytes: type(1) & len(2) */
1346 rpt_len = le16_to_cpu(btc_prpt->len);
1347 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
1348 break;
1349
1350 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
1351 if (!rpt_len)
1352 break;
1353 index += rpt_len;
1354 }
1355}
1356
1357#define BTC_TLV_HDR_LEN 2
1358
1359static void _append_tdma(struct rtw89_dev *rtwdev)
1360{
1361 const struct rtw89_chip_info *chip = rtwdev->chip;
1362 struct rtw89_btc *btc = &rtwdev->btc;
1363 struct rtw89_btc_dm *dm = &btc->dm;
1364 struct rtw89_btc_btf_tlv *tlv;
1365 struct rtw89_btc_fbtc_tdma *v;
1366 struct rtw89_btc_fbtc_tdma_v1 *v1;
1367 u16 len = btc->policy_len;
1368
1369 if (!btc->update_policy_force &&
1370 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
1371 rtw89_debug(rtwdev,
1372 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
1373 __func__);
1374 return;
1375 }
1376
1377 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
1378 tlv->type = CXPOLICY_TDMA;
1379 if (chip->chip_id == RTL8852A) {
1380 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
1381 tlv->len = sizeof(*v);
1382 memcpy(v, &dm->tdma, sizeof(*v));
1383 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
1384 } else {
1385 tlv->len = sizeof(*v1);
1386 v1 = (struct rtw89_btc_fbtc_tdma_v1 *)&tlv->val[0];
1387 v1->fver = chip->fcxtdma_ver;
1388 v1->tdma = dm->tdma;
1389 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v1);
1390 }
1391
1392 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1393 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
1394 __func__, dm->tdma.type, dm->tdma.rxflctrl,
1395 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
1396 dm->tdma.ext_ctrl);
1397}
1398
1399static void _append_slot(struct rtw89_dev *rtwdev)
1400{
1401 struct rtw89_btc *btc = &rtwdev->btc;
1402 struct rtw89_btc_dm *dm = &btc->dm;
1403 struct rtw89_btc_btf_tlv *tlv = NULL;
1404 struct btc_fbtc_1slot *v = NULL;
1405 u16 len = 0;
1406 u8 i, cnt = 0;
1407
1408 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1409 "[BTC], %s(): A:btc->policy_len = %d\n",
1410 __func__, btc->policy_len);
1411
1412 for (i = 0; i < CXST_MAX; i++) {
1413 if (!btc->update_policy_force &&
1414 !memcmp(&dm->slot[i], &dm->slot_now[i],
1415 sizeof(dm->slot[i])))
1416 continue;
1417
1418 len = btc->policy_len;
1419
1420 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
1421 v = (struct btc_fbtc_1slot *)&tlv->val[0];
1422 tlv->type = CXPOLICY_SLOT;
1423 tlv->len = sizeof(*v);
1424
1425 v->fver = FCXONESLOT_VER;
1426 v->sid = i;
1427 v->slot = dm->slot[i];
1428
1429 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1430 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
1431 __func__, i, dm->slot[i].dur, dm->slot[i].cxtbl,
1432 dm->slot[i].cxtype);
1433 cnt++;
1434
1435 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
1436 }
1437
1438 if (cnt > 0)
1439 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1440 "[BTC], %s(): slot update (cnt=%d)!!\n",
1441 __func__, cnt);
1442}
1443
1444static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
1445 u32 rpt_map, bool rpt_state)
1446{
1447 struct rtw89_btc *btc = &rtwdev->btc;
1448 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
1449 struct rtw89_btc_btf_set_report r = {0};
1450 u32 val = 0;
1451
1452 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1453 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
1454 __func__, rpt_map, rpt_state);
1455
1456 if (rpt_state)
1457 val = fwinfo->rpt_en_map | rpt_map;
1458 else
1459 val = fwinfo->rpt_en_map & ~rpt_map;
1460
1461 if (val == fwinfo->rpt_en_map)
1462 return;
1463
1464 fwinfo->rpt_en_map = val;
1465
1466 r.fver = BTF_SET_REPORT_VER;
1467 r.enable = cpu_to_le32(val);
1468 r.para = cpu_to_le32(rpt_state);
1469
1470 _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r, sizeof(r));
1471}
1472
1473static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num,
1474 struct rtw89_btc_fbtc_slot *s)
1475{
1476 struct rtw89_btc_btf_set_slot_table *tbl = NULL;
1477 u8 *ptr = NULL;
1478 u16 n = 0;
1479
1480 n = sizeof(*s) * num + sizeof(*tbl);
1481 tbl = kmalloc(n, GFP_KERNEL);
1482 if (!tbl)
1483 return;
1484
1485 tbl->fver = BTF_SET_SLOT_TABLE_VER;
1486 tbl->tbl_num = num;
1487 ptr = &tbl->buf[0];
1488 memcpy(ptr, s, num * sizeof(*s));
1489
1490 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
1491
1492 kfree(tbl);
1493}
1494
1495static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
1496{
1497 const struct rtw89_chip_info *chip = rtwdev->chip;
1498 struct rtw89_btc_btf_set_mon_reg *monreg = NULL;
1499 u8 n, *ptr = NULL, ulen;
1500 u16 sz = 0;
1501
1502 n = chip->mon_reg_num;
1503
1504 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1505 "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
1506 if (n > CXMREG_MAX) {
1507 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1508 "[BTC], %s(): mon reg count %d > %d\n",
1509 __func__, n, CXMREG_MAX);
1510 return;
1511 }
1512
1513 ulen = sizeof(struct rtw89_btc_fbtc_mreg);
1514 sz = (ulen * n) + sizeof(*monreg);
1515 monreg = kmalloc(sz, GFP_KERNEL);
1516 if (!monreg)
1517 return;
1518
1519 monreg->fver = BTF_SET_MON_REG_VER;
1520 monreg->reg_num = n;
1521 ptr = &monreg->buf[0];
1522 memcpy(ptr, chip->mon_reg, n * ulen);
1523 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1524 "[BTC], %s(): sz=%d ulen=%d n=%d\n",
1525 __func__, sz, ulen, n);
1526
1527 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, (u8 *)monreg, sz);
1528 kfree(monreg);
1529 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
1530}
1531
1532static void _update_dm_step(struct rtw89_dev *rtwdev,
1533 enum btc_reason_and_action reason_or_action)
1534{
1535 struct rtw89_btc *btc = &rtwdev->btc;
1536 struct rtw89_btc_dm *dm = &btc->dm;
1537
1538 /* use ring-structure to store dm step */
1539 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
1540 dm->dm_step.step_pos++;
1541
1542 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
1543 dm->dm_step.step_pos = 0;
1544 dm->dm_step.step_ov = true;
1545 }
1546}
1547
1548static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
1549 enum btc_reason_and_action action)
1550{
1551 struct rtw89_btc *btc = &rtwdev->btc;
1552 struct rtw89_btc_dm *dm = &btc->dm;
1553
1554 dm->run_action = action;
1555
1556 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
1557 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
1558
1559 btc->policy_len = 0;
1560 btc->policy_type = policy_type;
1561
1562 _append_tdma(rtwdev);
1563 _append_slot(rtwdev);
1564
1565 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
1566 return;
1567
1568 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1569 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
1570 __func__, action, policy_type, btc->policy_len);
1571
1572 if (dm->tdma.rxflctrl == CXFLC_NULLP ||
1573 dm->tdma.rxflctrl == CXFLC_QOSNULL)
1574 btc->lps = 1;
1575 else
1576 btc->lps = 0;
1577
1578 if (btc->lps == 1)
1579 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
1580
1581 _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
1582 btc->policy, btc->policy_len);
1583
1584 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
1585 memcpy(&dm->slot_now, &dm->slot, sizeof(dm->slot_now));
1586
1587 if (btc->update_policy_force)
1588 btc->update_policy_force = false;
1589
1590 if (btc->lps == 0)
1591 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
1592}
1593
1594static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
1595{
1596 const struct rtw89_chip_info *chip = rtwdev->chip;
1597
1598 switch (type) {
1599 case CXDRVINFO_INIT:
1600 rtw89_fw_h2c_cxdrv_init(rtwdev);
1601 break;
1602 case CXDRVINFO_ROLE:
1603 if (chip->chip_id == RTL8852A)
1604 rtw89_fw_h2c_cxdrv_role(rtwdev);
1605 else
1606 rtw89_fw_h2c_cxdrv_role_v1(rtwdev);
1607 break;
1608 case CXDRVINFO_CTRL:
1609 rtw89_fw_h2c_cxdrv_ctrl(rtwdev);
1610 break;
1611 case CXDRVINFO_RFK:
1612 rtw89_fw_h2c_cxdrv_rfk(rtwdev);
1613 break;
1614 default:
1615 break;
1616 }
1617}
1618
1619static
1620void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
1621{
1622 struct rtw89_btc *btc = &rtwdev->btc;
1623 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
1624
1625 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1626 "[BTC], %s(): evt_id:%d len:%d\n",
1627 __func__, evt_id, len);
1628
1629 if (!len || !data)
1630 return;
1631
1632 switch (evt_id) {
1633 case BTF_EVNT_RPT:
1634 _parse_btc_report(rtwdev, pfwinfo, data, len);
1635 break;
1636 default:
1637 break;
1638 }
1639}
1640
1641static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
1642{
1643 struct rtw89_btc *btc = &rtwdev->btc;
1644 struct rtw89_btc_dm *dm = &btc->dm;
1645 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
1646 u8 i;
1647
1648 if (phy_map > BTC_PHY_ALL)
1649 return;
1650
1651 for (i = 0; i < RTW89_PHY_MAX; i++) {
1652 if (!(phy_map & BIT(i)))
1653 continue;
1654
1655 switch (wl_state) {
1656 case BTC_GNT_HW:
1657 g[i].gnt_wl_sw_en = 0;
1658 g[i].gnt_wl = 0;
1659 break;
1660 case BTC_GNT_SW_LO:
1661 g[i].gnt_wl_sw_en = 1;
1662 g[i].gnt_wl = 0;
1663 break;
1664 case BTC_GNT_SW_HI:
1665 g[i].gnt_wl_sw_en = 1;
1666 g[i].gnt_wl = 1;
1667 break;
1668 }
1669
1670 switch (bt_state) {
1671 case BTC_GNT_HW:
1672 g[i].gnt_bt_sw_en = 0;
1673 g[i].gnt_bt = 0;
1674 break;
1675 case BTC_GNT_SW_LO:
1676 g[i].gnt_bt_sw_en = 1;
1677 g[i].gnt_bt = 0;
1678 break;
1679 case BTC_GNT_SW_HI:
1680 g[i].gnt_bt_sw_en = 1;
1681 g[i].gnt_bt = 1;
1682 break;
1683 }
1684 }
1685
1686 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
1687}
1688
1689#define BTC_TDMA_WLROLE_MAX 2
1690
1691static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
1692{
1693 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1694 "[BTC], %s(): set bt %s wlan_act\n", __func__,
1695 enable ? "ignore" : "do not ignore");
1696
1697 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
1698}
1699
1700#define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0)
1701#define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
1702#define WL_TX_POWER_WITH_BT GENMASK(31, 16)
1703#define WL_TX_POWER_INT_PART GENMASK(8, 2)
1704#define WL_TX_POWER_FRA_PART GENMASK(1, 0)
1705#define B_BTC_WL_TX_POWER_SIGN BIT(7)
1706#define B_TSSI_WL_TX_POWER_SIGN BIT(8)
1707
1708static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
1709{
1710 const struct rtw89_chip_info *chip = rtwdev->chip;
1711 struct rtw89_btc *btc = &rtwdev->btc;
1712 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1713 u32 pwr_val;
1714
1715 if (wl->rf_para.tx_pwr_freerun == level)
1716 return;
1717
1718 wl->rf_para.tx_pwr_freerun = level;
1719 btc->dm.rf_trx_para.wl_tx_power = level;
1720
1721 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1722 "[BTC], %s(): level = %d\n",
1723 __func__, level);
1724
1725 if (level == RTW89_BTC_WL_DEF_TX_PWR) {
1726 pwr_val = WL_TX_POWER_NO_BTC_CTRL;
1727 } else { /* only apply "force tx power" */
1728 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
1729 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
1730 pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
1731
1732 if (level & B_BTC_WL_TX_POWER_SIGN)
1733 pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
1734 pwr_val |= WL_TX_POWER_WITH_BT;
1735 }
1736
1737 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
1738}
1739
1740static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
1741{
1742 const struct rtw89_chip_info *chip = rtwdev->chip;
1743 struct rtw89_btc *btc = &rtwdev->btc;
1744 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1745
1746 if (wl->rf_para.rx_gain_freerun == level)
1747 return;
1748
1749 wl->rf_para.rx_gain_freerun = level;
1750 btc->dm.rf_trx_para.wl_rx_gain = level;
1751
1752 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1753 "[BTC], %s(): level = %d\n",
1754 __func__, level);
1755
1756 chip->ops->btc_set_wl_rx_gain(rtwdev, level);
1757}
1758
1759static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
1760{
1761 struct rtw89_btc *btc = &rtwdev->btc;
1762 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1763 u8 buf;
1764
1765 if (bt->rf_para.tx_pwr_freerun == level)
1766 return;
1767
1768 bt->rf_para.tx_pwr_freerun = level;
1769 btc->dm.rf_trx_para.bt_tx_power = level;
1770
1771 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1772 "[BTC], %s(): level = %d\n",
1773 __func__, level);
1774
1775 buf = (s8)(-level);
1776 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
1777}
1778
1779#define BTC_BT_RX_NORMAL_LVL 7
1780
1781static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
1782{
1783 struct rtw89_btc *btc = &rtwdev->btc;
1784 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1785
1786 if (bt->rf_para.rx_gain_freerun == level ||
1787 level > BTC_BT_RX_NORMAL_LVL)
1788 return;
1789
1790 bt->rf_para.rx_gain_freerun = level;
1791 btc->dm.rf_trx_para.bt_rx_gain = level;
1792
1793 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1794 "[BTC], %s(): level = %d\n",
1795 __func__, level);
1796
1797 if (level == BTC_BT_RX_NORMAL_LVL)
1798 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
1799 else
1800 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
1801
1802 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, 1);
1803}
1804
1805static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
1806{
1807 const struct rtw89_chip_info *chip = rtwdev->chip;
1808 struct rtw89_btc *btc = &rtwdev->btc;
1809 struct rtw89_btc_dm *dm = &btc->dm;
1810 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1811 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1812 struct rtw89_btc_bt_link_info *b = &bt->link_info;
1813 struct rtw89_btc_rf_trx_para para;
1814 u32 wl_stb_chg = 0;
1815 u8 level_id = 0;
1816
1817 if (!dm->freerun) {
1818 /* fix LNA2 = level-5 for BT ACI issue at BTG */
1819 if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) ||
1820 dm->bt_only == 1)
1821 dm->trx_para_level = 1;
1822 else
1823 dm->trx_para_level = 0;
1824 }
1825
1826 level_id = (u8)dm->trx_para_level;
1827
1828 if (level_id >= chip->rf_para_dlink_num ||
1829 level_id >= chip->rf_para_ulink_num) {
1830 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1831 "[BTC], %s(): invalid level_id: %d\n",
1832 __func__, level_id);
1833 return;
1834 }
1835
1836 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
1837 para = chip->rf_para_ulink[level_id];
1838 else
1839 para = chip->rf_para_dlink[level_id];
1840
1841 if (para.wl_tx_power != RTW89_BTC_WL_DEF_TX_PWR)
1842 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1843 "[BTC], %s(): wl_tx_power=%d\n",
1844 __func__, para.wl_tx_power);
1845 _set_wl_tx_power(rtwdev, para.wl_tx_power);
1846 _set_wl_rx_gain(rtwdev, para.wl_rx_gain);
1847 _set_bt_tx_power(rtwdev, para.bt_tx_power);
1848 _set_bt_rx_gain(rtwdev, para.bt_rx_gain);
1849
1850 if (bt->enable.now == 0 || wl->status.map.rf_off == 1 ||
1851 wl->status.map.lps == BTC_LPS_RF_OFF)
1852 wl_stb_chg = 0;
1853 else
1854 wl_stb_chg = 1;
1855
1856 if (wl_stb_chg != dm->wl_stb_chg) {
1857 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1858 "[BTC], %s(): wl_stb_chg=%d\n",
1859 __func__, wl_stb_chg);
1860 dm->wl_stb_chg = wl_stb_chg;
1861 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
1862 }
1863}
1864
1865static void _update_btc_state_map(struct rtw89_dev *rtwdev)
1866{
1867 struct rtw89_btc *btc = &rtwdev->btc;
1868 struct rtw89_btc_cx *cx = &btc->cx;
1869 struct rtw89_btc_wl_info *wl = &cx->wl;
1870 struct rtw89_btc_bt_info *bt = &cx->bt;
1871 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1872
1873 if (wl->status.map.connecting || wl->status.map._4way ||
1874 wl->status.map.roaming) {
1875 cx->state_map = BTC_WLINKING;
1876 } else if (wl->status.map.scan) { /* wl scan */
1877 if (bt_linfo->status.map.inq_pag)
1878 cx->state_map = BTC_WSCAN_BSCAN;
1879 else
1880 cx->state_map = BTC_WSCAN_BNOSCAN;
1881 } else if (wl->status.map.busy) { /* only busy */
1882 if (bt_linfo->status.map.inq_pag)
1883 cx->state_map = BTC_WBUSY_BSCAN;
1884 else
1885 cx->state_map = BTC_WBUSY_BNOSCAN;
1886 } else { /* wl idle */
1887 cx->state_map = BTC_WIDLE;
1888 }
1889}
1890
1891static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
1892{
1893 const struct rtw89_chip_info *chip = rtwdev->chip;
1894 struct rtw89_btc *btc = &rtwdev->btc;
1895 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1896 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1897 struct rtw89_btc_bt_link_info *b = &bt->link_info;
1898 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
1899 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
1900 struct rtw89_btc_wl_active_role *r;
1901 struct rtw89_btc_wl_active_role_v1 *r1;
1902 u8 en = 0, i, ch = 0, bw = 0;
1903 u8 mode, connect_cnt;
1904
1905 if (btc->ctrl.manual || wl->status.map.scan)
1906 return;
1907
1908 if (chip->chip_id == RTL8852A) {
1909 mode = wl_rinfo->link_mode;
1910 connect_cnt = wl_rinfo->connect_cnt;
1911 } else {
1912 mode = wl_rinfo_v1->link_mode;
1913 connect_cnt = wl_rinfo_v1->connect_cnt;
1914 }
1915
1916 if (wl->status.map.rf_off || bt->whql_test ||
1917 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
1918 connect_cnt > BTC_TDMA_WLROLE_MAX) {
1919 en = false;
1920 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
1921 en = true;
1922 /* get p2p channel */
1923 for (i = 0; i < RTW89_PORT_NUM; i++) {
1924 r = &wl_rinfo->active_role[i];
1925 r1 = &wl_rinfo_v1->active_role_v1[i];
1926
1927 if (chip->chip_id == RTL8852A &&
1928 (r->role == RTW89_WIFI_ROLE_P2P_GO ||
1929 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
1930 ch = r->ch;
1931 bw = r->bw;
1932 break;
1933 } else if (chip->chip_id != RTL8852A &&
1934 (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
1935 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
1936 ch = r1->ch;
1937 bw = r1->bw;
1938 break;
1939 }
1940 }
1941 } else {
1942 en = true;
1943 /* get 2g channel */
1944 for (i = 0; i < RTW89_PORT_NUM; i++) {
1945 r = &wl_rinfo->active_role[i];
1946 r1 = &wl_rinfo_v1->active_role_v1[i];
1947
1948 if (chip->chip_id == RTL8852A &&
1949 r->connected && r->band == RTW89_BAND_2G) {
1950 ch = r->ch;
1951 bw = r->bw;
1952 break;
1953 } else if (chip->chip_id != RTL8852A &&
1954 r1->connected && r1->band == RTW89_BAND_2G) {
1955 ch = r1->ch;
1956 bw = r1->bw;
1957 break;
1958 }
1959 }
1960 }
1961
1962 switch (bw) {
1963 case RTW89_CHANNEL_WIDTH_20:
1964 bw = 20 + chip->afh_guard_ch * 2;
1965 break;
1966 case RTW89_CHANNEL_WIDTH_40:
1967 bw = 40 + chip->afh_guard_ch * 2;
1968 break;
1969 case RTW89_CHANNEL_WIDTH_5:
1970 bw = 5 + chip->afh_guard_ch * 2;
1971 break;
1972 case RTW89_CHANNEL_WIDTH_10:
1973 bw = 10 + chip->afh_guard_ch * 2;
1974 break;
1975 default:
1976 bw = 0;
1977 en = false; /* turn off AFH info if BW > 40 */
1978 break;
1979 }
1980
1981 if (wl->afh_info.en == en &&
1982 wl->afh_info.ch == ch &&
1983 wl->afh_info.bw == bw &&
1984 b->profile_cnt.last == b->profile_cnt.now) {
1985 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1986 "[BTC], %s(): return because no change!\n",
1987 __func__);
1988 return;
1989 }
1990
1991 wl->afh_info.en = en;
1992 wl->afh_info.ch = ch;
1993 wl->afh_info.bw = bw;
1994
1995 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
1996
1997 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1998 "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
1999 __func__, en, ch, bw);
2000 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
2001}
2002
2003static bool _check_freerun(struct rtw89_dev *rtwdev)
2004{
2005 struct rtw89_btc *btc = &rtwdev->btc;
2006 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2007 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2008 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
2009 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
2010 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
2011 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
2012
2013 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
2014 btc->dm.trx_para_level = 0;
2015 return false;
2016 }
2017
2018 /* The below is dedicated antenna case */
2019 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX ||
2020 wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) {
2021 btc->dm.trx_para_level = 5;
2022 return true;
2023 }
2024
2025 if (bt_linfo->profile_cnt.now == 0) {
2026 btc->dm.trx_para_level = 5;
2027 return true;
2028 }
2029
2030 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
2031 btc->dm.trx_para_level = 5;
2032 return true;
2033 }
2034
2035 /* TODO get isolation by BT psd */
2036 if (btc->mdinfo.ant.isolation >= BTC_FREERUN_ANTISO_MIN) {
2037 btc->dm.trx_para_level = 5;
2038 return true;
2039 }
2040
2041 if (!wl->status.map.busy) {/* wl idle -> freerun */
2042 btc->dm.trx_para_level = 5;
2043 return true;
2044 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
2045 btc->dm.trx_para_level = 0;
2046 return false;
2047 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
2048 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
2049 btc->dm.trx_para_level = 6;
2050 return true;
2051 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
2052 btc->dm.trx_para_level = 7;
2053 return true;
2054 }
2055 btc->dm.trx_para_level = 0;
2056 return false;
2057 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
2058 if (bt_linfo->rssi > 28) {
2059 btc->dm.trx_para_level = 6;
2060 return true;
2061 }
2062 }
2063
2064 btc->dm.trx_para_level = 0;
2065 return false;
2066}
2067
2068#define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
2069#define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
2070#define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
2071#define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
2072
2073#define _slot_set(btc, sid, dura, tbl, type) \
2074 do { \
2075 typeof(sid) _sid = (sid); \
2076 typeof(btc) _btc = (btc); \
2077 _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\
2078 _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \
2079 _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \
2080 } while (0)
2081
2082#define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura)
2083#define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl)
2084#define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type)
2085
2086struct btc_btinfo_lb2 {
2087 u8 connect: 1;
2088 u8 sco_busy: 1;
2089 u8 inq_pag: 1;
2090 u8 acl_busy: 1;
2091 u8 hfp: 1;
2092 u8 hid: 1;
2093 u8 a2dp: 1;
2094 u8 pan: 1;
2095};
2096
2097struct btc_btinfo_lb3 {
2098 u8 retry: 4;
2099 u8 cqddr: 1;
2100 u8 inq: 1;
2101 u8 mesh_busy: 1;
2102 u8 pag: 1;
2103};
2104
2105struct btc_btinfo_hb0 {
2106 s8 rssi;
2107};
2108
2109struct btc_btinfo_hb1 {
2110 u8 ble_connect: 1;
2111 u8 reinit: 1;
2112 u8 relink: 1;
2113 u8 igno_wl: 1;
2114 u8 voice: 1;
2115 u8 ble_scan: 1;
2116 u8 role_sw: 1;
2117 u8 multi_link: 1;
2118};
2119
2120struct btc_btinfo_hb2 {
2121 u8 pan_active: 1;
2122 u8 afh_update: 1;
2123 u8 a2dp_active: 1;
2124 u8 slave: 1;
2125 u8 hid_slot: 2;
2126 u8 hid_cnt: 2;
2127};
2128
2129struct btc_btinfo_hb3 {
2130 u8 a2dp_bitpool: 6;
2131 u8 tx_3m: 1;
2132 u8 a2dp_sink: 1;
2133};
2134
2135union btc_btinfo {
2136 u8 val;
2137 struct btc_btinfo_lb2 lb2;
2138 struct btc_btinfo_lb3 lb3;
2139 struct btc_btinfo_hb0 hb0;
2140 struct btc_btinfo_hb1 hb1;
2141 struct btc_btinfo_hb2 hb2;
2142 struct btc_btinfo_hb3 hb3;
2143};
2144
2145static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
2146 enum btc_reason_and_action action)
2147{
2148 const struct rtw89_chip_info *chip = rtwdev->chip;
2149
2150 chip->ops->btc_set_policy(rtwdev, policy_type);
2151 _fw_set_policy(rtwdev, policy_type, action);
2152}
2153
2154#define BTC_B1_MAX 250 /* unit ms */
2155void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
2156{
2157 struct rtw89_btc *btc = &rtwdev->btc;
2158 struct rtw89_btc_dm *dm = &btc->dm;
2159 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
2160 struct rtw89_btc_fbtc_slot *s = dm->slot;
2161 u8 type;
2162 u32 tbl_w1, tbl_b1, tbl_b4;
2163
2164 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
2165 if (btc->cx.wl.status.map._4way)
2166 tbl_w1 = cxtbl[1];
2167 else
2168 tbl_w1 = cxtbl[8];
2169 tbl_b1 = cxtbl[3];
2170 tbl_b4 = cxtbl[3];
2171 } else {
2172 tbl_w1 = cxtbl[16];
2173 tbl_b1 = cxtbl[17];
2174 tbl_b4 = cxtbl[17];
2175 }
2176
2177 type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
2178 btc->bt_req_en = false;
2179
2180 switch (type) {
2181 case BTC_CXP_USERDEF0:
2182 *t = t_def[CXTD_OFF];
2183 s[CXST_OFF] = s_def[CXST_OFF];
2184 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2185 btc->update_policy_force = true;
2186 break;
2187 case BTC_CXP_OFF: /* TDMA off */
2188 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2189 *t = t_def[CXTD_OFF];
2190 s[CXST_OFF] = s_def[CXST_OFF];
2191
2192 switch (policy_type) {
2193 case BTC_CXP_OFF_BT:
2194 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2195 break;
2196 case BTC_CXP_OFF_WL:
2197 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
2198 break;
2199 case BTC_CXP_OFF_EQ0:
2200 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
2201 break;
2202 case BTC_CXP_OFF_EQ1:
2203 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
2204 break;
2205 case BTC_CXP_OFF_EQ2:
2206 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
2207 break;
2208 case BTC_CXP_OFF_EQ3:
2209 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
2210 break;
2211 case BTC_CXP_OFF_BWB0:
2212 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
2213 break;
2214 case BTC_CXP_OFF_BWB1:
2215 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2216 break;
2217 case BTC_CXP_OFF_BWB3:
2218 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
2219 break;
2220 }
2221 break;
2222 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
2223 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2224 *t = t_def[CXTD_OFF_B2];
2225 s[CXST_OFF] = s_def[CXST_OFF];
2226 switch (policy_type) {
2227 case BTC_CXP_OFFB_BWB0:
2228 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2229 break;
2230 }
2231 break;
2232 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
2233 btc->bt_req_en = true;
2234 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2235 *t = t_def[CXTD_OFF_EXT];
2236 switch (policy_type) {
2237 case BTC_CXP_OFFE_DEF:
2238 s[CXST_E2G] = s_def[CXST_E2G];
2239 s[CXST_E5G] = s_def[CXST_E5G];
2240 s[CXST_EBT] = s_def[CXST_EBT];
2241 s[CXST_ENULL] = s_def[CXST_ENULL];
2242 break;
2243 case BTC_CXP_OFFE_DEF2:
2244 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
2245 s[CXST_E5G] = s_def[CXST_E5G];
2246 s[CXST_EBT] = s_def[CXST_EBT];
2247 s[CXST_ENULL] = s_def[CXST_ENULL];
2248 break;
2249 }
2250 break;
2251 case BTC_CXP_FIX: /* TDMA Fix-Slot */
2252 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2253 *t = t_def[CXTD_FIX];
2254 switch (policy_type) {
2255 case BTC_CXP_FIX_TD3030:
2256 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2257 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2258 break;
2259 case BTC_CXP_FIX_TD5050:
2260 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2261 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2262 break;
2263 case BTC_CXP_FIX_TD2030:
2264 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2265 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2266 break;
2267 case BTC_CXP_FIX_TD4010:
2268 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
2269 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2270 break;
2271 case BTC_CXP_FIX_TD4020:
2272 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX);
2273 _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX);
2274 break;
2275 case BTC_CXP_FIX_TD7010:
2276 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
2277 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2278 break;
2279 case BTC_CXP_FIX_TD2060:
2280 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2281 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2282 break;
2283 case BTC_CXP_FIX_TD3060:
2284 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2285 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2286 break;
2287 case BTC_CXP_FIX_TD2080:
2288 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2289 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2290 break;
2291 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
2292 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2293 tbl_w1, SLOT_ISO);
2294 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2295 tbl_b1, SLOT_MIX);
2296 break;
2297 }
2298 break;
2299 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
2300 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2301 *t = t_def[CXTD_PFIX];
2302 if (btc->cx.wl.role_info.role_map.role.ap)
2303 _tdma_set_flctrl(btc, CXFLC_QOSNULL);
2304
2305 switch (policy_type) {
2306 case BTC_CXP_PFIX_TD3030:
2307 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2308 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2309 break;
2310 case BTC_CXP_PFIX_TD5050:
2311 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2312 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2313 break;
2314 case BTC_CXP_PFIX_TD2030:
2315 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2316 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2317 break;
2318 case BTC_CXP_PFIX_TD2060:
2319 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2320 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2321 break;
2322 case BTC_CXP_PFIX_TD3070:
2323 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2324 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2325 break;
2326 case BTC_CXP_PFIX_TD2080:
2327 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2328 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2329 break;
2330 }
2331 break;
2332 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
2333 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2334 *t = t_def[CXTD_AUTO];
2335 switch (policy_type) {
2336 case BTC_CXP_AUTO_TD50B1:
2337 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2338 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2339 break;
2340 case BTC_CXP_AUTO_TD60B1:
2341 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2342 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2343 break;
2344 case BTC_CXP_AUTO_TD20B1:
2345 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2346 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2347 break;
2348 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
2349 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2350 tbl_w1, SLOT_ISO);
2351 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2352 tbl_b1, SLOT_MIX);
2353 break;
2354 }
2355 break;
2356 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
2357 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2358 *t = t_def[CXTD_PAUTO];
2359 switch (policy_type) {
2360 case BTC_CXP_PAUTO_TD50B1:
2361 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2362 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2363 break;
2364 case BTC_CXP_PAUTO_TD60B1:
2365 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2366 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2367 break;
2368 case BTC_CXP_PAUTO_TD20B1:
2369 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2370 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2371 break;
2372 case BTC_CXP_PAUTO_TDW1B1:
2373 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2374 tbl_w1, SLOT_ISO);
2375 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2376 tbl_b1, SLOT_MIX);
2377 break;
2378 }
2379 break;
2380 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
2381 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2382 *t = t_def[CXTD_AUTO2];
2383 switch (policy_type) {
2384 case BTC_CXP_AUTO2_TD3050:
2385 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2386 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2387 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2388 break;
2389 case BTC_CXP_AUTO2_TD3070:
2390 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2391 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2392 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2393 break;
2394 case BTC_CXP_AUTO2_TD5050:
2395 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2396 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2397 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2398 break;
2399 case BTC_CXP_AUTO2_TD6060:
2400 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2401 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2402 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2403 break;
2404 case BTC_CXP_AUTO2_TD2080:
2405 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2406 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2407 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2408 break;
2409 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
2410 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2411 tbl_w1, SLOT_ISO);
2412 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2413 tbl_b4, SLOT_MIX);
2414 break;
2415 }
2416 break;
2417 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
2418 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2419 *t = t_def[CXTD_PAUTO2];
2420 switch (policy_type) {
2421 case BTC_CXP_PAUTO2_TD3050:
2422 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2423 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2424 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2425 break;
2426 case BTC_CXP_PAUTO2_TD3070:
2427 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2428 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2429 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2430 break;
2431 case BTC_CXP_PAUTO2_TD5050:
2432 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2433 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2434 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2435 break;
2436 case BTC_CXP_PAUTO2_TD6060:
2437 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2438 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2439 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2440 break;
2441 case BTC_CXP_PAUTO2_TD2080:
2442 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2443 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2444 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2445 break;
2446 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
2447 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2448 tbl_w1, SLOT_ISO);
2449 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2450 tbl_b4, SLOT_MIX);
2451 break;
2452 }
2453 break;
2454 }
2455}
2456EXPORT_SYMBOL(rtw89_btc_set_policy);
2457
2458void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
2459{
2460 struct rtw89_btc *btc = &rtwdev->btc;
2461 struct rtw89_btc_dm *dm = &btc->dm;
2462 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
2463 struct rtw89_btc_fbtc_slot *s = dm->slot;
2464 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
2465 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
2466 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
2467 u8 type, null_role;
2468 u32 tbl_w1, tbl_b1, tbl_b4;
2469
2470 type = FIELD_GET(BTC_CXP_MASK, policy_type);
2471
2472 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
2473 if (btc->cx.wl.status.map._4way)
2474 tbl_w1 = cxtbl[1];
2475 else if (hid->exist && hid->type == BTC_HID_218)
2476 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
2477 else
2478 tbl_w1 = cxtbl[8];
2479
2480 if (dm->leak_ap &&
2481 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
2482 tbl_b1 = cxtbl[3];
2483 tbl_b4 = cxtbl[3];
2484 } else if (hid->exist && hid->type == BTC_HID_218) {
2485 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
2486 tbl_b4 = cxtbl[4];
2487 } else {
2488 tbl_b1 = cxtbl[2];
2489 tbl_b4 = cxtbl[2];
2490 }
2491 } else {
2492 tbl_w1 = cxtbl[16];
2493 tbl_b1 = cxtbl[17];
2494 tbl_b4 = cxtbl[17];
2495 }
2496
2497 btc->bt_req_en = false;
2498
2499 switch (type) {
2500 case BTC_CXP_USERDEF0:
2501 btc->update_policy_force = true;
2502 *t = t_def[CXTD_OFF];
2503 s[CXST_OFF] = s_def[CXST_OFF];
2504 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2505 break;
2506 case BTC_CXP_OFF: /* TDMA off */
2507 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2508 *t = t_def[CXTD_OFF];
2509 s[CXST_OFF] = s_def[CXST_OFF];
2510
2511 switch (policy_type) {
2512 case BTC_CXP_OFF_BT:
2513 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2514 break;
2515 case BTC_CXP_OFF_WL:
2516 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
2517 break;
2518 case BTC_CXP_OFF_EQ0:
2519 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
2520 break;
2521 case BTC_CXP_OFF_EQ1:
2522 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
2523 break;
2524 case BTC_CXP_OFF_EQ2:
2525 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
2526 break;
2527 case BTC_CXP_OFF_EQ3:
2528 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
2529 break;
2530 case BTC_CXP_OFF_BWB0:
2531 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
2532 break;
2533 case BTC_CXP_OFF_BWB1:
2534 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2535 break;
2536 case BTC_CXP_OFF_BWB2:
2537 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
2538 break;
2539 case BTC_CXP_OFF_BWB3:
2540 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
2541 break;
2542 default:
2543 break;
2544 }
2545 break;
2546 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
2547 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2548 *t = t_def[CXTD_OFF_B2];
2549 s[CXST_OFF] = s_def[CXST_OFF];
2550
2551 switch (policy_type) {
2552 case BTC_CXP_OFFB_BWB0:
2553 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2554 break;
2555 default:
2556 break;
2557 }
2558 break;
2559 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
2560 btc->bt_req_en = true;
2561 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2562 *t = t_def[CXTD_OFF_EXT];
2563
2564 /* To avoid wl-s0 tx break by hid/hfp tx */
2565 if (hid->exist || hfp->exist)
2566 tbl_w1 = cxtbl[16];
2567
2568 switch (policy_type) {
2569 case BTC_CXP_OFFE_DEF:
2570 s[CXST_E2G] = s_def[CXST_E2G];
2571 s[CXST_E5G] = s_def[CXST_E5G];
2572 s[CXST_EBT] = s_def[CXST_EBT];
2573 s[CXST_ENULL] = s_def[CXST_ENULL];
2574 break;
2575 case BTC_CXP_OFFE_DEF2:
2576 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
2577 s[CXST_E5G] = s_def[CXST_E5G];
2578 s[CXST_EBT] = s_def[CXST_EBT];
2579 s[CXST_ENULL] = s_def[CXST_ENULL];
2580 break;
2581 default:
2582 break;
2583 }
2584 break;
2585 case BTC_CXP_FIX: /* TDMA Fix-Slot */
2586 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2587 *t = t_def[CXTD_FIX];
2588
2589 switch (policy_type) {
2590 case BTC_CXP_FIX_TD3030:
2591 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2592 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2593 break;
2594 case BTC_CXP_FIX_TD5050:
2595 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2596 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2597 break;
2598 case BTC_CXP_FIX_TD2030:
2599 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2600 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2601 break;
2602 case BTC_CXP_FIX_TD4010:
2603 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
2604 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2605 break;
2606 case BTC_CXP_FIX_TD4010ISO:
2607 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
2608 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2609 break;
2610 case BTC_CXP_FIX_TD7010:
2611 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
2612 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2613 break;
2614 case BTC_CXP_FIX_TD2060:
2615 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2616 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2617 break;
2618 case BTC_CXP_FIX_TD3060:
2619 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2620 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2621 break;
2622 case BTC_CXP_FIX_TD2080:
2623 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2624 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2625 break;
2626 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
2627 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2628 tbl_w1, SLOT_ISO);
2629 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2630 tbl_b1, SLOT_MIX);
2631 break;
2632 default:
2633 break;
2634 }
2635 break;
2636 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
2637 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2638 *t = t_def[CXTD_PFIX];
2639
2640 switch (policy_type) {
2641 case BTC_CXP_PFIX_TD3030:
2642 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2643 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2644 break;
2645 case BTC_CXP_PFIX_TD5050:
2646 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2647 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2648 break;
2649 case BTC_CXP_PFIX_TD2030:
2650 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2651 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2652 break;
2653 case BTC_CXP_PFIX_TD2060:
2654 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2655 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2656 break;
2657 case BTC_CXP_PFIX_TD3070:
2658 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2659 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2660 break;
2661 case BTC_CXP_PFIX_TD2080:
2662 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2663 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2664 break;
2665 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
2666 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2667 tbl_w1, SLOT_ISO);
2668 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2669 tbl_b1, SLOT_MIX);
2670 break;
2671 default:
2672 break;
2673 }
2674 break;
2675 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
2676 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2677 *t = t_def[CXTD_AUTO];
2678
2679 switch (policy_type) {
2680 case BTC_CXP_AUTO_TD50B1:
2681 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2682 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2683 break;
2684 case BTC_CXP_AUTO_TD60B1:
2685 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2686 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2687 break;
2688 case BTC_CXP_AUTO_TD20B1:
2689 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2690 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2691 break;
2692 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
2693 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2694 tbl_w1, SLOT_ISO);
2695 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2696 tbl_b1, SLOT_MIX);
2697 break;
2698 default:
2699 break;
2700 }
2701 break;
2702 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
2703 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2704 *t = t_def[CXTD_PAUTO];
2705
2706 switch (policy_type) {
2707 case BTC_CXP_PAUTO_TD50B1:
2708 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2709 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2710 break;
2711 case BTC_CXP_PAUTO_TD60B1:
2712 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2713 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2714 break;
2715 case BTC_CXP_PAUTO_TD20B1:
2716 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2717 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2718 break;
2719 case BTC_CXP_PAUTO_TDW1B1:
2720 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2721 tbl_w1, SLOT_ISO);
2722 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2723 tbl_b1, SLOT_MIX);
2724 break;
2725 default:
2726 break;
2727 }
2728 break;
2729 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
2730 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2731 *t = t_def[CXTD_AUTO2];
2732
2733 switch (policy_type) {
2734 case BTC_CXP_AUTO2_TD3050:
2735 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2736 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2737 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2738 break;
2739 case BTC_CXP_AUTO2_TD3070:
2740 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2741 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2742 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2743 break;
2744 case BTC_CXP_AUTO2_TD5050:
2745 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2746 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2747 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2748 break;
2749 case BTC_CXP_AUTO2_TD6060:
2750 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2751 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2752 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2753 break;
2754 case BTC_CXP_AUTO2_TD2080:
2755 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2756 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2757 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2758 break;
2759 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
2760 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2761 tbl_w1, SLOT_ISO);
2762 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2763 tbl_b1, SLOT_MIX);
2764 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2765 tbl_b4, SLOT_MIX);
2766 break;
2767 default:
2768 break;
2769 }
2770 break;
2771 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
2772 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2773 *t = t_def[CXTD_PAUTO2];
2774
2775 switch (policy_type) {
2776 case BTC_CXP_PAUTO2_TD3050:
2777 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2778 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2779 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2780 break;
2781 case BTC_CXP_PAUTO2_TD3070:
2782 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2783 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2784 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2785 break;
2786 case BTC_CXP_PAUTO2_TD5050:
2787 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2788 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2789 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2790 break;
2791 case BTC_CXP_PAUTO2_TD6060:
2792 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2793 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2794 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2795 break;
2796 case BTC_CXP_PAUTO2_TD2080:
2797 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2798 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2799 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2800 break;
2801 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
2802 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2803 tbl_w1, SLOT_ISO);
2804 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2805 tbl_b1, SLOT_MIX);
2806 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2807 tbl_b4, SLOT_MIX);
2808 break;
2809 default:
2810 break;
2811 }
2812 break;
2813 }
2814
2815 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
2816 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
2817 FIELD_PREP(0xf0, dm->wl_scc.null_role2);
2818 _tdma_set_flctrl_role(btc, null_role);
2819 }
2820
2821 /* enter leak_slot after each null-1 */
2822 if (dm->leak_ap && dm->tdma.leak_n > 1)
2823 _tdma_set_lek(btc, 1);
2824
2825 if (dm->tdma_instant_excute) {
2826 btc->dm.tdma.option_ctrl |= BIT(0);
2827 btc->update_policy_force = true;
2828 }
2829}
2830EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
2831
2832static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
2833 u8 tx_val, u8 rx_val)
2834{
2835 struct rtw89_mac_ax_plt plt;
2836
2837 plt.band = RTW89_MAC_0;
2838 plt.tx = tx_val;
2839 plt.rx = rx_val;
2840
2841 if (phy_map & BTC_PHY_0)
2842 rtw89_mac_cfg_plt(rtwdev, &plt);
2843
2844 if (!rtwdev->dbcc_en)
2845 return;
2846
2847 plt.band = RTW89_MAC_1;
2848 if (phy_map & BTC_PHY_1)
2849 rtw89_mac_cfg_plt(rtwdev, &plt);
2850}
2851
2852static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
2853 u8 phy_map, u8 type)
2854{
2855 struct rtw89_btc *btc = &rtwdev->btc;
2856 struct rtw89_btc_dm *dm = &btc->dm;
2857 struct rtw89_btc_cx *cx = &btc->cx;
2858 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2859 struct rtw89_btc_bt_info *bt = &cx->bt;
2860 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
2861 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
2862 u32 ant_path_type;
2863
2864 ant_path_type = ((phy_map << 8) + type);
2865
2866 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
2867 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
2868 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX)
2869 force_exec = FC_EXEC;
2870
2871 if (!force_exec && ant_path_type == dm->set_ant_path) {
2872 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2873 "[BTC], %s(): return by no change!!\n",
2874 __func__);
2875 return;
2876 } else if (bt->rfk_info.map.run) {
2877 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2878 "[BTC], %s(): return by bt rfk!!\n", __func__);
2879 return;
2880 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
2881 wl->rfk_info.state != BTC_WRFK_STOP) {
2882 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2883 "[BTC], %s(): return by wl rfk!!\n", __func__);
2884 return;
2885 }
2886
2887 dm->set_ant_path = ant_path_type;
2888
2889 rtw89_debug(rtwdev,
2890 RTW89_DBG_BTC,
2891 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
2892 __func__, phy_map, dm->set_ant_path & 0xff);
2893
2894 switch (type) {
2895 case BTC_ANT_WPOWERON:
2896 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
2897 break;
2898 case BTC_ANT_WINIT:
2899 if (bt->enable.now)
2900 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
2901 else
2902 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
2903
2904 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
2905 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
2906 break;
2907 case BTC_ANT_WONLY:
2908 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
2909 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
2910 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2911 break;
2912 case BTC_ANT_WOFF:
2913 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
2914 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2915 break;
2916 case BTC_ANT_W2G:
2917 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
2918 if (rtwdev->dbcc_en) {
2919 for (i = 0; i < RTW89_PHY_MAX; i++) {
2920 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
2921
2922 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
2923 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
2924 /* BT should control by GNT_BT if WL_2G at S0 */
2925 if (i == 1 &&
2926 wl_dinfo->real_band[0] == RTW89_BAND_2G &&
2927 wl_dinfo->real_band[1] == RTW89_BAND_5G)
2928 gnt_bt_ctrl = BTC_GNT_HW;
2929 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
2930 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
2931 _set_bt_plut(rtwdev, BIT(i),
2932 plt_ctrl, plt_ctrl);
2933 }
2934 } else {
2935 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
2936 _set_bt_plut(rtwdev, BTC_PHY_ALL,
2937 BTC_PLT_BT, BTC_PLT_BT);
2938 }
2939 break;
2940 case BTC_ANT_W5G:
2941 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
2942 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
2943 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2944 break;
2945 case BTC_ANT_W25G:
2946 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
2947 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
2948 _set_bt_plut(rtwdev, BTC_PHY_ALL,
2949 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
2950 break;
2951 case BTC_ANT_FREERUN:
2952 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
2953 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
2954 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2955 break;
2956 case BTC_ANT_WRFK:
2957 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
2958 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
2959 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
2960 break;
2961 case BTC_ANT_BRFK:
2962 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
2963 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
2964 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
2965 break;
2966 default:
2967 break;
2968 }
2969}
2970
2971static void _action_wl_only(struct rtw89_dev *rtwdev)
2972{
2973 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
2974 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
2975}
2976
2977static void _action_wl_init(struct rtw89_dev *rtwdev)
2978{
2979 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
2980
2981 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
2982 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
2983}
2984
2985static void _action_wl_off(struct rtw89_dev *rtwdev)
2986{
2987 struct rtw89_btc *btc = &rtwdev->btc;
2988 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2989
2990 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
2991
2992 if (wl->status.map.rf_off || btc->dm.bt_only)
2993 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
2994
2995 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
2996}
2997
2998static void _action_freerun(struct rtw89_dev *rtwdev)
2999{
3000 struct rtw89_btc *btc = &rtwdev->btc;
3001
3002 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3003
3004 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
3005 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
3006
3007 btc->dm.freerun = true;
3008}
3009
3010static void _action_bt_whql(struct rtw89_dev *rtwdev)
3011{
3012 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3013
3014 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3015 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
3016}
3017
3018static void _action_bt_off(struct rtw89_dev *rtwdev)
3019{
3020 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3021
3022 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
3023 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
3024}
3025
3026static void _action_bt_idle(struct rtw89_dev *rtwdev)
3027{
3028 struct rtw89_btc *btc = &rtwdev->btc;
3029 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
3030
3031 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3032
3033 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3034 switch (btc->cx.state_map) {
3035 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
3036 if (b->profile_cnt.now > 0)
3037 _set_policy(rtwdev, BTC_CXP_FIX_TD4010,
3038 BTC_ACT_BT_IDLE);
3039 else
3040 _set_policy(rtwdev, BTC_CXP_FIX_TD4020,
3041 BTC_ACT_BT_IDLE);
3042 break;
3043 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
3044 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
3045 BTC_ACT_BT_IDLE);
3046 break;
3047 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
3048 if (b->profile_cnt.now > 0)
3049 _set_policy(rtwdev, BTC_CXP_FIX_TD4010,
3050 BTC_ACT_BT_IDLE);
3051 else
3052 _set_policy(rtwdev, BTC_CXP_FIX_TD4020,
3053 BTC_ACT_BT_IDLE);
3054 break;
3055 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
3056 _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
3057 BTC_ACT_BT_IDLE);
3058 break;
3059 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
3060 _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
3061 BTC_ACT_BT_IDLE);
3062 break;
3063 case BTC_WIDLE: /* wl-idle + bt-idle */
3064 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
3065 break;
3066 }
3067 } else { /* dedicated-antenna */
3068 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
3069 }
3070}
3071
3072static void _action_bt_hfp(struct rtw89_dev *rtwdev)
3073{
3074 struct rtw89_btc *btc = &rtwdev->btc;
3075 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3076
3077 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3078
3079 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3080 if (btc->cx.wl.status.map._4way) {
3081 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
3082 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
3083 btc->cx.bt.scan_rx_low_pri = true;
3084 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
3085 } else {
3086 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
3087 }
3088 } else {
3089 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
3090 }
3091}
3092
3093static void _action_bt_hid(struct rtw89_dev *rtwdev)
3094{
3095 const struct rtw89_chip_info *chip = rtwdev->chip;
3096 struct rtw89_btc *btc = &rtwdev->btc;
3097 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3098 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3099 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
3100 u16 policy_type = BTC_CXP_OFF_BT;
3101
3102 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3103
3104 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3105 if (wl->status.map._4way) {
3106 policy_type = BTC_CXP_OFF_WL;
3107 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
3108 btc->cx.bt.scan_rx_low_pri = true;
3109 if (hid->type & BTC_HID_BLE)
3110 policy_type = BTC_CXP_OFF_BWB0;
3111 else
3112 policy_type = BTC_CXP_OFF_BWB2;
3113 } else if (hid->type == BTC_HID_218) {
3114 bt->scan_rx_low_pri = true;
3115 policy_type = BTC_CXP_OFF_BWB2;
3116 } else if (chip->para_ver == 0x1) {
3117 policy_type = BTC_CXP_OFF_BWB3;
3118 } else {
3119 policy_type = BTC_CXP_OFF_BWB1;
3120 }
3121 } else { /* dedicated-antenna */
3122 policy_type = BTC_CXP_OFF_EQ3;
3123 }
3124
3125 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
3126}
3127
3128static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
3129{
3130 struct rtw89_btc *btc = &rtwdev->btc;
3131 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
3132 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
3133 struct rtw89_btc_dm *dm = &btc->dm;
3134
3135 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3136
3137 switch (btc->cx.state_map) {
3138 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
3139 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3140 dm->slot_dur[CXST_W1] = 40;
3141 dm->slot_dur[CXST_B1] = 200;
3142 _set_policy(rtwdev,
3143 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
3144 } else {
3145 _set_policy(rtwdev,
3146 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
3147 }
3148 break;
3149 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
3150 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
3151 break;
3152 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
3153 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
3154 break;
3155 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
3156 case BTC_WLINKING: /* wl-connecting + bt-A2DP */
3157 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3158 dm->slot_dur[CXST_W1] = 40;
3159 dm->slot_dur[CXST_B1] = 200;
3160 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
3161 BTC_ACT_BT_A2DP);
3162 } else {
3163 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
3164 BTC_ACT_BT_A2DP);
3165 }
3166 break;
3167 case BTC_WIDLE: /* wl-idle + bt-A2DP */
3168 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
3169 break;
3170 }
3171}
3172
3173static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
3174{
3175 struct rtw89_btc *btc = &rtwdev->btc;
3176
3177 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3178
3179 switch (btc->cx.state_map) {
3180 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
3181 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
3182 break;
3183 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
3184 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
3185 break;
3186 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
3187 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
3188 break;
3189 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
3190 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
3191 break;
3192 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
3193 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
3194 break;
3195 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
3196 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
3197 break;
3198 }
3199}
3200
3201static void _action_bt_pan(struct rtw89_dev *rtwdev)
3202{
3203 struct rtw89_btc *btc = &rtwdev->btc;
3204
3205 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3206
3207 switch (btc->cx.state_map) {
3208 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
3209 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
3210 break;
3211 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
3212 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
3213 break;
3214 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
3215 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
3216 break;
3217 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
3218 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
3219 break;
3220 case BTC_WLINKING: /* wl-connecting + bt-PAN */
3221 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, BTC_ACT_BT_PAN);
3222 break;
3223 case BTC_WIDLE: /* wl-idle + bt-pan */
3224 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
3225 break;
3226 }
3227}
3228
3229static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
3230{
3231 struct rtw89_btc *btc = &rtwdev->btc;
3232 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
3233 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
3234 struct rtw89_btc_dm *dm = &btc->dm;
3235
3236 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3237
3238 switch (btc->cx.state_map) {
3239 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
3240 case BTC_WIDLE: /* wl-idle + bt-A2DP */
3241 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3242 dm->slot_dur[CXST_W1] = 40;
3243 dm->slot_dur[CXST_B1] = 200;
3244 _set_policy(rtwdev,
3245 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
3246 } else {
3247 _set_policy(rtwdev,
3248 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
3249 }
3250 break;
3251 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
3252 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
3253 break;
3254
3255 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
3256 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
3257 break;
3258 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
3259 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
3260 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3261 dm->slot_dur[CXST_W1] = 40;
3262 dm->slot_dur[CXST_B1] = 200;
3263 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
3264 BTC_ACT_BT_A2DP_HID);
3265 } else {
3266 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
3267 BTC_ACT_BT_A2DP_HID);
3268 }
3269 break;
3270 }
3271}
3272
3273static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
3274{
3275 struct rtw89_btc *btc = &rtwdev->btc;
3276
3277 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3278
3279 switch (btc->cx.state_map) {
3280 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
3281 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
3282 break;
3283 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
3284 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
3285 break;
3286 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
3287 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
3288 break;
3289 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
3290 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
3291 break;
3292 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
3293 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
3294 break;
3295 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
3296 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
3297 break;
3298 }
3299}
3300
3301static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
3302{
3303 struct rtw89_btc *btc = &rtwdev->btc;
3304
3305 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3306
3307 switch (btc->cx.state_map) {
3308 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
3309 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
3310 break;
3311 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
3312 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
3313 break;
3314 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
3315 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
3316 break;
3317 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
3318 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
3319 break;
3320 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
3321 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
3322 break;
3323 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
3324 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
3325 break;
3326 }
3327}
3328
3329static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
3330{
3331 struct rtw89_btc *btc = &rtwdev->btc;
3332
3333 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3334
3335 switch (btc->cx.state_map) {
3336 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
3337 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
3338 BTC_ACT_BT_A2DP_PAN_HID);
3339 break;
3340 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
3341 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
3342 BTC_ACT_BT_A2DP_PAN_HID);
3343 break;
3344 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
3345 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
3346 BTC_ACT_BT_A2DP_PAN_HID);
3347 break;
3348 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
3349 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
3350 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
3351 BTC_ACT_BT_A2DP_PAN_HID);
3352 break;
3353 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
3354 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
3355 BTC_ACT_BT_A2DP_PAN_HID);
3356 break;
3357 }
3358}
3359
3360static void _action_wl_5g(struct rtw89_dev *rtwdev)
3361{
3362 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
3363 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
3364}
3365
3366static void _action_wl_other(struct rtw89_dev *rtwdev)
3367{
3368 struct rtw89_btc *btc = &rtwdev->btc;
3369
3370 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3371
3372 if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
3373 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
3374 else
3375 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
3376}
3377
3378static void _action_wl_nc(struct rtw89_dev *rtwdev)
3379{
3380 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3381 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
3382}
3383
3384static void _action_wl_rfk(struct rtw89_dev *rtwdev)
3385{
3386 struct rtw89_btc *btc = &rtwdev->btc;
3387 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
3388
3389 if (rfk.state != BTC_WRFK_START)
3390 return;
3391
3392 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
3393 __func__, rfk.band);
3394
3395 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
3396 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
3397}
3398
3399static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
3400{
3401 const struct rtw89_chip_info *chip = rtwdev->chip;
3402 struct rtw89_btc *btc = &rtwdev->btc;
3403 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3404 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3405 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3406 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
3407 bool is_btg;
3408 u8 mode;
3409
3410 if (btc->ctrl.manual)
3411 return;
3412
3413 if (chip->chip_id == RTL8852A)
3414 mode = wl_rinfo->link_mode;
3415 else
3416 mode = wl_rinfo_v1->link_mode;
3417
3418 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
3419 if (mode == BTC_WLINK_5G) /* always 0 if 5G */
3420 is_btg = false;
3421 else if (mode == BTC_WLINK_25G_DBCC &&
3422 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
3423 is_btg = false;
3424 else
3425 is_btg = true;
3426
3427 if (btc->dm.run_reason != BTC_RSN_NTFY_INIT &&
3428 is_btg == btc->dm.wl_btg_rx)
3429 return;
3430
3431 btc->dm.wl_btg_rx = is_btg;
3432
3433 if (mode == BTC_WLINK_25G_MCC)
3434 return;
3435
3436 rtw89_ctrl_btg(rtwdev, is_btg);
3437}
3438
3439struct rtw89_txtime_data {
3440 struct rtw89_dev *rtwdev;
3441 int type;
3442 u32 tx_time;
3443 u8 tx_retry;
3444 u16 enable;
3445 bool reenable;
3446};
3447
3448static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
3449{
3450 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
3451 struct rtw89_txtime_data *iter_data =
3452 (struct rtw89_txtime_data *)data;
3453 struct rtw89_dev *rtwdev = iter_data->rtwdev;
3454 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
3455 struct rtw89_btc *btc = &rtwdev->btc;
3456 struct rtw89_btc_cx *cx = &btc->cx;
3457 struct rtw89_btc_wl_info *wl = &cx->wl;
3458 struct rtw89_btc_wl_link_info *plink = NULL;
3459 u8 port = rtwvif->port;
3460 u32 tx_time = iter_data->tx_time;
3461 u8 tx_retry = iter_data->tx_retry;
3462 u16 enable = iter_data->enable;
3463 bool reenable = iter_data->reenable;
3464
3465 plink = &wl->link_info[port];
3466
3467 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3468 "[BTC], %s(): port = %d\n", __func__, port);
3469
3470 if (!plink->connected) {
3471 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3472 "[BTC], %s(): connected = %d\n",
3473 __func__, plink->connected);
3474 return;
3475 }
3476
3477 /* backup the original tx time before tx-limit on */
3478 if (reenable) {
3479 rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time);
3480 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry);
3481 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3482 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
3483 __func__, plink->tx_time, plink->tx_retry);
3484 }
3485
3486 /* restore the original tx time if no tx-limit */
3487 if (!enable) {
3488 rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time);
3489 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true,
3490 plink->tx_retry);
3491 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3492 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
3493 __func__, plink->tx_time, plink->tx_retry);
3494
3495 } else {
3496 rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time);
3497 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry);
3498 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3499 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
3500 __func__, tx_time, tx_retry);
3501 }
3502}
3503
3504static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
3505{
3506 const struct rtw89_chip_info *chip = rtwdev->chip;
3507 struct rtw89_btc *btc = &rtwdev->btc;
3508 struct rtw89_btc_cx *cx = &btc->cx;
3509 struct rtw89_btc_dm *dm = &btc->dm;
3510 struct rtw89_btc_wl_info *wl = &cx->wl;
3511 struct rtw89_btc_bt_info *bt = &cx->bt;
3512 struct rtw89_btc_bt_link_info *b = &bt->link_info;
3513 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
3514 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
3515 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3516 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3517 struct rtw89_txtime_data data = {.rtwdev = rtwdev};
3518 u8 mode;
3519 u8 tx_retry;
3520 u32 tx_time;
3521 u16 enable;
3522 bool reenable = false;
3523
3524 if (btc->ctrl.manual)
3525 return;
3526
3527 if (chip->chip_id == RTL8852A)
3528 mode = wl_rinfo->link_mode;
3529 else
3530 mode = wl_rinfo_v1->link_mode;
3531
3532 if (btc->dm.freerun || btc->ctrl.igno_bt || b->profile_cnt.now == 0 ||
3533 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
3534 enable = 0;
3535 tx_time = BTC_MAX_TX_TIME_DEF;
3536 tx_retry = BTC_MAX_TX_RETRY_DEF;
3537 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
3538 enable = 1;
3539 tx_time = BTC_MAX_TX_TIME_L2;
3540 tx_retry = BTC_MAX_TX_RETRY_L1;
3541 } else if (hfp->exist || hid->exist) {
3542 enable = 1;
3543 tx_time = BTC_MAX_TX_TIME_L3;
3544 tx_retry = BTC_MAX_TX_RETRY_L1;
3545 } else {
3546 enable = 0;
3547 tx_time = BTC_MAX_TX_TIME_DEF;
3548 tx_retry = BTC_MAX_TX_RETRY_DEF;
3549 }
3550
3551 if (dm->wl_tx_limit.enable == enable &&
3552 dm->wl_tx_limit.tx_time == tx_time &&
3553 dm->wl_tx_limit.tx_retry == tx_retry)
3554 return;
3555
3556 if (!dm->wl_tx_limit.enable && enable)
3557 reenable = true;
3558
3559 dm->wl_tx_limit.enable = enable;
3560 dm->wl_tx_limit.tx_time = tx_time;
3561 dm->wl_tx_limit.tx_retry = tx_retry;
3562
3563 data.enable = enable;
3564 data.tx_time = tx_time;
3565 data.tx_retry = tx_retry;
3566 data.reenable = reenable;
3567
3568 ieee80211_iterate_stations_atomic(rtwdev->hw,
3569 rtw89_tx_time_iter,
3570 &data);
3571}
3572
3573static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
3574{
3575 const struct rtw89_chip_info *chip = rtwdev->chip;
3576 struct rtw89_btc *btc = &rtwdev->btc;
3577 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3578 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3579 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3580 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3581 bool bt_hi_lna_rx = false;
3582 u8 mode;
3583
3584 if (chip->chip_id == RTL8852A)
3585 mode = wl_rinfo->link_mode;
3586 else
3587 mode = wl_rinfo_v1->link_mode;
3588
3589 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
3590 bt_hi_lna_rx = true;
3591
3592 if (bt_hi_lna_rx == bt->hi_lna_rx)
3593 return;
3594
3595 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
3596}
3597
3598static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
3599{
3600 struct rtw89_btc *btc = &rtwdev->btc;
3601 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3602
3603 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
3604}
3605
3606/* TODO add these functions */
3607static void _action_common(struct rtw89_dev *rtwdev)
3608{
3609 struct rtw89_btc *btc = &rtwdev->btc;
3610 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3611
3612 _set_btg_ctrl(rtwdev);
3613 _set_wl_tx_limit(rtwdev);
3614 _set_bt_afh_info(rtwdev);
3615 _set_bt_rx_agc(rtwdev);
3616 _set_rf_trx_para(rtwdev);
3617 _set_bt_rx_scan_pri(rtwdev);
3618
3619 if (wl->scbd_change) {
3620 rtw89_mac_cfg_sb(rtwdev, wl->scbd);
3621 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
3622 wl->scbd);
3623 wl->scbd_change = false;
3624 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
3625 }
3626}
3627
3628static void _action_by_bt(struct rtw89_dev *rtwdev)
3629{
3630 struct rtw89_btc *btc = &rtwdev->btc;
3631 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3632 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3633 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
3634 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
3635 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
3636 u8 profile_map = 0;
3637
3638 if (bt_linfo->hfp_desc.exist)
3639 profile_map |= BTC_BT_HFP;
3640
3641 if (bt_linfo->hid_desc.exist)
3642 profile_map |= BTC_BT_HID;
3643
3644 if (bt_linfo->a2dp_desc.exist)
3645 profile_map |= BTC_BT_A2DP;
3646
3647 if (bt_linfo->pan_desc.exist)
3648 profile_map |= BTC_BT_PAN;
3649
3650 switch (profile_map) {
3651 case BTC_BT_NOPROFILE:
3652 if (_check_freerun(rtwdev))
3653 _action_freerun(rtwdev);
3654 else if (a2dp.active || pan.active)
3655 _action_bt_pan(rtwdev);
3656 else
3657 _action_bt_idle(rtwdev);
3658 break;
3659 case BTC_BT_HFP:
3660 if (_check_freerun(rtwdev))
3661 _action_freerun(rtwdev);
3662 else
3663 _action_bt_hfp(rtwdev);
3664 break;
3665 case BTC_BT_HFP | BTC_BT_HID:
3666 case BTC_BT_HID:
3667 if (_check_freerun(rtwdev))
3668 _action_freerun(rtwdev);
3669 else
3670 _action_bt_hid(rtwdev);
3671 break;
3672 case BTC_BT_A2DP:
3673 if (_check_freerun(rtwdev))
3674 _action_freerun(rtwdev);
3675 else if (a2dp.sink)
3676 _action_bt_a2dpsink(rtwdev);
3677 else if (bt_linfo->multi_link.now && !hid.pair_cnt)
3678 _action_bt_a2dp_pan(rtwdev);
3679 else
3680 _action_bt_a2dp(rtwdev);
3681 break;
3682 case BTC_BT_PAN:
3683 _action_bt_pan(rtwdev);
3684 break;
3685 case BTC_BT_A2DP | BTC_BT_HFP:
3686 case BTC_BT_A2DP | BTC_BT_HID:
3687 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
3688 if (_check_freerun(rtwdev))
3689 _action_freerun(rtwdev);
3690 else
3691 _action_bt_a2dp_hid(rtwdev);
3692 break;
3693 case BTC_BT_A2DP | BTC_BT_PAN:
3694 _action_bt_a2dp_pan(rtwdev);
3695 break;
3696 case BTC_BT_PAN | BTC_BT_HFP:
3697 case BTC_BT_PAN | BTC_BT_HID:
3698 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
3699 _action_bt_pan_hid(rtwdev);
3700 break;
3701 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
3702 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
3703 default:
3704 _action_bt_a2dp_pan_hid(rtwdev);
3705 break;
3706 }
3707}
3708
3709static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
3710{
3711 _action_by_bt(rtwdev);
3712}
3713
3714static void _action_wl_scan(struct rtw89_dev *rtwdev)
3715{
3716 struct rtw89_btc *btc = &rtwdev->btc;
3717 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3718 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
3719
3720 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
3721 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
3722 if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
3723 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3724 BTC_RSN_NTFY_SCAN_START);
3725 else
3726 _set_policy(rtwdev, BTC_CXP_OFF_EQ0,
3727 BTC_RSN_NTFY_SCAN_START);
3728
3729 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
3730 } else if (rtwdev->dbcc_en) {
3731 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
3732 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
3733 _action_wl_5g(rtwdev);
3734 else
3735 _action_by_bt(rtwdev);
3736 } else {
3737 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
3738 _action_wl_5g(rtwdev);
3739 else
3740 _action_by_bt(rtwdev);
3741 }
3742}
3743
3744static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
3745{
3746 struct rtw89_btc *btc = &rtwdev->btc;
3747
3748 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
3749
3750 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3751 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3752 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3753 BTC_ACT_WL_25G_MCC);
3754 else
3755 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3756 BTC_ACT_WL_25G_MCC);
3757 } else { /* dedicated-antenna */
3758 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_25G_MCC);
3759 }
3760}
3761
3762static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
3763{ struct rtw89_btc *btc = &rtwdev->btc;
3764
3765 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3766
3767 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3768 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3769 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3770 BTC_ACT_WL_2G_MCC);
3771 else
3772 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3773 BTC_ACT_WL_2G_MCC);
3774 } else { /* dedicated-antenna */
3775 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
3776 }
3777}
3778
3779static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
3780{
3781 struct rtw89_btc *btc = &rtwdev->btc;
3782
3783 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3784
3785 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3786 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3787 _set_policy(rtwdev,
3788 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
3789 else
3790 _set_policy(rtwdev,
3791 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
3792 } else { /* dedicated-antenna */
3793 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
3794 }
3795}
3796
3797static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
3798{
3799 struct rtw89_btc *btc = &rtwdev->btc;
3800 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3801 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3802 struct rtw89_btc_dm *dm = &btc->dm;
3803 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
3804 u16 policy_type = BTC_CXP_OFF_BT;
3805 u32 dur;
3806
3807 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) {
3808 policy_type = BTC_CXP_OFF_EQ0;
3809 } else {
3810 /* shared-antenna */
3811 switch (wl_rinfo->mrole_type) {
3812 case BTC_WLMROLE_STA_GC:
3813 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
3814 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
3815 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
3816 _action_by_bt(rtwdev);
3817 return;
3818 case BTC_WLMROLE_STA_STA:
3819 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
3820 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
3821 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
3822 _action_by_bt(rtwdev);
3823 return;
3824 case BTC_WLMROLE_STA_GC_NOA:
3825 case BTC_WLMROLE_STA_GO:
3826 case BTC_WLMROLE_STA_GO_NOA:
3827 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
3828 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
3829 dur = wl_rinfo->mrole_noa_duration;
3830
3831 if (wl->status.map._4way) {
3832 dm->wl_scc.ebt_null = 0;
3833 policy_type = BTC_CXP_OFFE_WL;
3834 } else if (bt->link_info.status.map.connect == 0) {
3835 dm->wl_scc.ebt_null = 0;
3836 policy_type = BTC_CXP_OFFE_2GISOB;
3837 } else if (bt->link_info.a2dp_desc.exist &&
3838 dur < btc->bt_req_len) {
3839 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
3840 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
3841 } else if (bt->link_info.a2dp_desc.exist ||
3842 bt->link_info.pan_desc.exist) {
3843 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
3844 policy_type = BTC_CXP_OFFE_2GBWISOB;
3845 } else {
3846 dm->wl_scc.ebt_null = 0;
3847 policy_type = BTC_CXP_OFFE_2GBWISOB;
3848 }
3849 break;
3850 default:
3851 break;
3852 }
3853 }
3854
3855 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3856 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
3857}
3858
3859static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
3860{
3861 struct rtw89_btc *btc = &rtwdev->btc;
3862
3863 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3864
3865 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3866 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3867 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3868 BTC_ACT_WL_2G_AP);
3869 else
3870 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
3871 } else {/* dedicated-antenna */
3872 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
3873 }
3874}
3875
3876static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
3877{
3878 struct rtw89_btc *btc = &rtwdev->btc;
3879
3880 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3881
3882 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3883 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3884 _set_policy(rtwdev,
3885 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
3886 else
3887 _set_policy(rtwdev,
3888 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
3889 } else { /* dedicated-antenna */
3890 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
3891 }
3892}
3893
3894static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
3895{
3896 struct rtw89_btc *btc = &rtwdev->btc;
3897
3898 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3899
3900 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3901 _action_by_bt(rtwdev);
3902 } else {/* dedicated-antenna */
3903 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
3904 }
3905}
3906
3907static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
3908{
3909 struct rtw89_btc *btc = &rtwdev->btc;
3910
3911 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3912
3913 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3914 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3915 _set_policy(rtwdev,
3916 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
3917 else
3918 _set_policy(rtwdev,
3919 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
3920 } else { /* dedicated-antenna */
3921 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
3922 }
3923}
3924
3925static u32 _read_scbd(struct rtw89_dev *rtwdev)
3926{
3927 const struct rtw89_chip_info *chip = rtwdev->chip;
3928 struct rtw89_btc *btc = &rtwdev->btc;
3929 u32 scbd_val = 0;
3930
3931 if (!chip->scbd)
3932 return 0;
3933
3934 scbd_val = rtw89_mac_get_sb(rtwdev);
3935 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
3936 scbd_val);
3937
3938 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
3939 return scbd_val;
3940}
3941
3942static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
3943{
3944 const struct rtw89_chip_info *chip = rtwdev->chip;
3945 struct rtw89_btc *btc = &rtwdev->btc;
3946 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3947 u32 scbd_val = 0;
3948 u8 force_exec = false;
3949
3950 if (!chip->scbd)
3951 return;
3952
3953 scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
3954
3955 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
3956 force_exec = true;
3957
3958 if (scbd_val != wl->scbd || force_exec) {
3959 wl->scbd = scbd_val;
3960 wl->scbd_change = true;
3961 }
3962}
3963
3964static u8
3965_update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
3966{
3967 const struct rtw89_chip_info *chip = rtwdev->chip;
3968 u8 next_state, tol = chip->rssi_tol;
3969
3970 if (pre_state == BTC_RSSI_ST_LOW ||
3971 pre_state == BTC_RSSI_ST_STAY_LOW) {
3972 if (rssi >= (thresh + tol))
3973 next_state = BTC_RSSI_ST_HIGH;
3974 else
3975 next_state = BTC_RSSI_ST_STAY_LOW;
3976 } else {
3977 if (rssi < thresh)
3978 next_state = BTC_RSSI_ST_LOW;
3979 else
3980 next_state = BTC_RSSI_ST_STAY_HIGH;
3981 }
3982
3983 return next_state;
3984}
3985
3986static
3987void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
3988{
3989 struct rtw89_btc *btc = &rtwdev->btc;
3990
3991 btc->cx.wl.dbcc_info.real_band[phy_idx] =
3992 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
3993 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
3994 btc->cx.wl.dbcc_info.op_band[phy_idx];
3995}
3996
3997static void _update_wl_info(struct rtw89_dev *rtwdev)
3998{
3999 struct rtw89_btc *btc = &rtwdev->btc;
4000 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4001 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
4002 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4003 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4004 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
4005 u8 cnt_2g = 0, cnt_5g = 0, phy;
4006 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
4007 bool b2g = false, b5g = false, client_joined = false;
4008
4009 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
4010
4011 for (i = 0; i < RTW89_PORT_NUM; i++) {
4012 /* check if role active? */
4013 if (!wl_linfo[i].active)
4014 continue;
4015
4016 cnt_active++;
4017 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
4018 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
4019 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
4020 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
4021 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
4022 wl_rinfo->active_role[cnt_active - 1].connected = 0;
4023
4024 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
4025
4026 phy = wl_linfo[i].phy;
4027
4028 /* check dbcc role */
4029 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
4030 wl_dinfo->role[phy] = wl_linfo[i].role;
4031 wl_dinfo->op_band[phy] = wl_linfo[i].band;
4032 _update_dbcc_band(rtwdev, phy);
4033 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4034 }
4035
4036 if (wl_linfo[i].connected == MLME_NO_LINK) {
4037 continue;
4038 } else if (wl_linfo[i].connected == MLME_LINKING) {
4039 cnt_connecting++;
4040 } else {
4041 cnt_connect++;
4042 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
4043 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
4044 wl_linfo[i].client_cnt > 1)
4045 client_joined = true;
4046 }
4047
4048 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
4049 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
4050 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
4051 wl_rinfo->active_role[cnt_active - 1].connected = 1;
4052
4053 /* only care 2 roles + BT coex */
4054 if (wl_linfo[i].band != RTW89_BAND_2G) {
4055 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
4056 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
4057 cnt_5g++;
4058 b5g = true;
4059 } else {
4060 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
4061 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
4062 cnt_2g++;
4063 b2g = true;
4064 }
4065 }
4066
4067 wl_rinfo->connect_cnt = cnt_connect;
4068
4069 /* Be careful to change the following sequence!! */
4070 if (cnt_connect == 0) {
4071 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4072 wl_rinfo->role_map.role.none = 1;
4073 } else if (!b2g && b5g) {
4074 wl_rinfo->link_mode = BTC_WLINK_5G;
4075 } else if (wl_rinfo->role_map.role.nan) {
4076 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
4077 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
4078 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4079 } else if (b2g && b5g && cnt_connect == 2) {
4080 if (rtwdev->dbcc_en) {
4081 switch (wl_dinfo->role[RTW89_PHY_0]) {
4082 case RTW89_WIFI_ROLE_STATION:
4083 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4084 break;
4085 case RTW89_WIFI_ROLE_P2P_GO:
4086 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4087 break;
4088 case RTW89_WIFI_ROLE_P2P_CLIENT:
4089 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4090 break;
4091 case RTW89_WIFI_ROLE_AP:
4092 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4093 break;
4094 default:
4095 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4096 break;
4097 }
4098 } else {
4099 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
4100 }
4101 } else if (!b5g && cnt_connect == 2) {
4102 if (wl_rinfo->role_map.role.station &&
4103 (wl_rinfo->role_map.role.p2p_go ||
4104 wl_rinfo->role_map.role.p2p_gc ||
4105 wl_rinfo->role_map.role.ap)) {
4106 if (wl_2g_ch[0] == wl_2g_ch[1])
4107 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
4108 else
4109 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4110 } else {
4111 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4112 }
4113 } else if (!b5g && cnt_connect == 1) {
4114 if (wl_rinfo->role_map.role.station)
4115 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4116 else if (wl_rinfo->role_map.role.ap)
4117 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4118 else if (wl_rinfo->role_map.role.p2p_go)
4119 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4120 else if (wl_rinfo->role_map.role.p2p_gc)
4121 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4122 else
4123 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4124 }
4125
4126 /* if no client_joined, don't care P2P-GO/AP role */
4127 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
4128 if (!client_joined) {
4129 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
4130 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
4131 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4132 wl_rinfo->connect_cnt = 1;
4133 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
4134 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
4135 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4136 wl_rinfo->connect_cnt = 0;
4137 }
4138 }
4139 }
4140
4141 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4142 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
4143 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
4144
4145 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
4146}
4147
4148static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
4149{
4150 struct rtw89_btc *btc = &rtwdev->btc;
4151 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4152 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
4153 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
4154 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4155 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
4156 u8 cnt_2g = 0, cnt_5g = 0, phy;
4157 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
4158 bool b2g = false, b5g = false, client_joined = false;
4159 u8 i;
4160
4161 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
4162
4163 for (i = 0; i < RTW89_PORT_NUM; i++) {
4164 if (!wl_linfo[i].active)
4165 continue;
4166
4167 cnt_active++;
4168 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
4169 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
4170 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
4171 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
4172 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
4173 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
4174
4175 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
4176
4177 phy = wl_linfo[i].phy;
4178
4179 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
4180 wl_dinfo->role[phy] = wl_linfo[i].role;
4181 wl_dinfo->op_band[phy] = wl_linfo[i].band;
4182 _update_dbcc_band(rtwdev, phy);
4183 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4184 }
4185
4186 if (wl_linfo[i].connected == MLME_NO_LINK) {
4187 continue;
4188 } else if (wl_linfo[i].connected == MLME_LINKING) {
4189 cnt_connecting++;
4190 } else {
4191 cnt_connect++;
4192 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
4193 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
4194 wl_linfo[i].client_cnt > 1)
4195 client_joined = true;
4196 }
4197
4198 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
4199 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
4200 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
4201 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
4202
4203 /* only care 2 roles + BT coex */
4204 if (wl_linfo[i].band != RTW89_BAND_2G) {
4205 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
4206 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
4207 cnt_5g++;
4208 b5g = true;
4209 } else {
4210 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
4211 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
4212 cnt_2g++;
4213 b2g = true;
4214 }
4215 }
4216
4217 wl_rinfo->connect_cnt = cnt_connect;
4218
4219 /* Be careful to change the following sequence!! */
4220 if (cnt_connect == 0) {
4221 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4222 wl_rinfo->role_map.role.none = 1;
4223 } else if (!b2g && b5g) {
4224 wl_rinfo->link_mode = BTC_WLINK_5G;
4225 } else if (wl_rinfo->role_map.role.nan) {
4226 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
4227 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
4228 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4229 } else if (b2g && b5g && cnt_connect == 2) {
4230 if (rtwdev->dbcc_en) {
4231 switch (wl_dinfo->role[RTW89_PHY_0]) {
4232 case RTW89_WIFI_ROLE_STATION:
4233 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4234 break;
4235 case RTW89_WIFI_ROLE_P2P_GO:
4236 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4237 break;
4238 case RTW89_WIFI_ROLE_P2P_CLIENT:
4239 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4240 break;
4241 case RTW89_WIFI_ROLE_AP:
4242 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4243 break;
4244 default:
4245 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4246 break;
4247 }
4248 } else {
4249 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
4250 }
4251 } else if (!b5g && cnt_connect == 2) {
4252 if (wl_rinfo->role_map.role.station &&
4253 (wl_rinfo->role_map.role.p2p_go ||
4254 wl_rinfo->role_map.role.p2p_gc ||
4255 wl_rinfo->role_map.role.ap)) {
4256 if (wl_2g_ch[0] == wl_2g_ch[1])
4257 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
4258 else
4259 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4260 } else {
4261 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4262 }
4263 } else if (!b5g && cnt_connect == 1) {
4264 if (wl_rinfo->role_map.role.station)
4265 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4266 else if (wl_rinfo->role_map.role.ap)
4267 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4268 else if (wl_rinfo->role_map.role.p2p_go)
4269 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4270 else if (wl_rinfo->role_map.role.p2p_gc)
4271 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4272 else
4273 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4274 }
4275
4276 /* if no client_joined, don't care P2P-GO/AP role */
4277 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
4278 if (!client_joined) {
4279 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
4280 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
4281 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4282 wl_rinfo->connect_cnt = 1;
4283 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
4284 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
4285 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4286 wl_rinfo->connect_cnt = 0;
4287 }
4288 }
4289 }
4290
4291 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4292 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
4293 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
4294
4295 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
4296}
4297
4298#define BTC_CHK_HANG_MAX 3
4299#define BTC_SCB_INV_VALUE GENMASK(31, 0)
4300
4301void rtw89_coex_act1_work(struct work_struct *work)
4302{
4303 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4304 coex_act1_work.work);
4305 struct rtw89_btc *btc = &rtwdev->btc;
4306 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4307 struct rtw89_btc_cx *cx = &btc->cx;
4308 struct rtw89_btc_wl_info *wl = &cx->wl;
4309
4310 mutex_lock(&rtwdev->mutex);
4311 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4312 dm->cnt_notify[BTC_NCNT_TIMER]++;
4313 if (wl->status.map._4way)
4314 wl->status.map._4way = false;
4315 if (wl->status.map.connecting)
4316 wl->status.map.connecting = false;
4317
4318 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
4319 mutex_unlock(&rtwdev->mutex);
4320}
4321
4322void rtw89_coex_bt_devinfo_work(struct work_struct *work)
4323{
4324 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4325 coex_bt_devinfo_work.work);
4326 struct rtw89_btc *btc = &rtwdev->btc;
4327 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4328 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
4329
4330 mutex_lock(&rtwdev->mutex);
4331 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4332 dm->cnt_notify[BTC_NCNT_TIMER]++;
4333 a2dp->play_latency = 0;
4334 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
4335 mutex_unlock(&rtwdev->mutex);
4336}
4337
4338void rtw89_coex_rfk_chk_work(struct work_struct *work)
4339{
4340 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4341 coex_rfk_chk_work.work);
4342 struct rtw89_btc *btc = &rtwdev->btc;
4343 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4344 struct rtw89_btc_cx *cx = &btc->cx;
4345 struct rtw89_btc_wl_info *wl = &cx->wl;
4346
4347 mutex_lock(&rtwdev->mutex);
4348 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4349 dm->cnt_notify[BTC_NCNT_TIMER]++;
4350 if (wl->rfk_info.state != BTC_WRFK_STOP) {
4351 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4352 "[BTC], %s(): RFK timeout\n", __func__);
4353 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
4354 dm->error.map.wl_rfk_timeout = true;
4355 wl->rfk_info.state = BTC_WRFK_STOP;
4356 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
4357 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
4358 }
4359 mutex_unlock(&rtwdev->mutex);
4360}
4361
4362static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
4363{
4364 const struct rtw89_chip_info *chip = rtwdev->chip;
4365 struct rtw89_btc *btc = &rtwdev->btc;
4366 struct rtw89_btc_cx *cx = &btc->cx;
4367 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4368 u32 val;
4369 bool status_change = false;
4370
4371 if (!chip->scbd)
4372 return;
4373
4374 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
4375
4376 val = _read_scbd(rtwdev);
4377 if (val == BTC_SCB_INV_VALUE) {
4378 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4379 "[BTC], %s(): return by invalid scbd value\n",
4380 __func__);
4381 return;
4382 }
4383
4384 if (!(val & BTC_BSCB_ON) ||
4385 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX)
4386 bt->enable.now = 0;
4387 else
4388 bt->enable.now = 1;
4389
4390 if (bt->enable.now != bt->enable.last)
4391 status_change = true;
4392
4393 /* reset bt info if bt re-enable */
4394 if (bt->enable.now && !bt->enable.last) {
4395 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
4396 cx->cnt_bt[BTC_BCNT_REENABLE]++;
4397 bt->enable.now = 1;
4398 }
4399
4400 bt->enable.last = bt->enable.now;
4401 bt->scbd = val;
4402 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
4403
4404 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
4405 status_change = true;
4406
4407 bt->whql_test = !!(val & BTC_BSCB_WHQL);
4408 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
4409 bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT);
4410
4411 /* if rfk run 1->0 */
4412 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
4413 status_change = true;
4414
4415 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
4416 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
4417 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
4418 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
4419 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
4420
4421 if (!only_update && status_change)
4422 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
4423}
4424
4425static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
4426{
4427 struct rtw89_btc *btc = &rtwdev->btc;
4428 struct rtw89_btc_cx *cx = &btc->cx;
4429 struct rtw89_btc_bt_info *bt = &cx->bt;
4430
4431 _update_bt_scbd(rtwdev, true);
4432
4433 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
4434
4435 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
4436 !bt->rfk_info.map.timeout) {
4437 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
4438 } else {
4439 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
4440 return true;
4441 }
4442 return false;
4443}
4444
4445static
4446void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
4447{
4448 const struct rtw89_chip_info *chip = rtwdev->chip;
4449 struct rtw89_btc *btc = &rtwdev->btc;
4450 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4451 struct rtw89_btc_cx *cx = &btc->cx;
4452 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4453 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4454 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4455 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4456 u8 mode;
4457
4458 lockdep_assert_held(&rtwdev->mutex);
4459
4460 dm->run_reason = reason;
4461 _update_dm_step(rtwdev, reason);
4462 _update_btc_state_map(rtwdev);
4463
4464 if (chip->chip_id == RTL8852A)
4465 mode = wl_rinfo->link_mode;
4466 else
4467 mode = wl_rinfo_v1->link_mode;
4468
4469 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
4470 __func__, reason, mode);
4471 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
4472 __func__, dm->wl_only, dm->bt_only);
4473
4474 /* Be careful to change the following function sequence!! */
4475 if (btc->ctrl.manual) {
4476 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4477 "[BTC], %s(): return for Manual CTRL!!\n",
4478 __func__);
4479 return;
4480 }
4481
4482 if (btc->ctrl.igno_bt &&
4483 (reason == BTC_RSN_UPDATE_BT_INFO ||
4484 reason == BTC_RSN_UPDATE_BT_SCBD)) {
4485 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4486 "[BTC], %s(): return for Stop Coex DM!!\n",
4487 __func__);
4488 return;
4489 }
4490
4491 if (!wl->status.map.init_ok) {
4492 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4493 "[BTC], %s(): return for WL init fail!!\n",
4494 __func__);
4495 return;
4496 }
4497
4498 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
4499 wl->status.map.lps_pre == wl->status.map.lps &&
4500 (reason == BTC_RSN_NTFY_POWEROFF ||
4501 reason == BTC_RSN_NTFY_RADIO_STATE)) {
4502 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4503 "[BTC], %s(): return for WL rf off state no change!!\n",
4504 __func__);
4505 return;
4506 }
4507
4508 dm->cnt_dm[BTC_DCNT_RUN]++;
4509
4510 if (btc->ctrl.always_freerun) {
4511 _action_freerun(rtwdev);
4512 btc->ctrl.igno_bt = true;
4513 goto exit;
4514 }
4515
4516 if (dm->wl_only) {
4517 _action_wl_only(rtwdev);
4518 btc->ctrl.igno_bt = true;
4519 goto exit;
4520 }
4521
4522 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
4523 _action_wl_off(rtwdev);
4524 btc->ctrl.igno_bt = true;
4525 goto exit;
4526 }
4527
4528 btc->ctrl.igno_bt = false;
4529 dm->freerun = false;
4530 bt->scan_rx_low_pri = false;
4531
4532 if (reason == BTC_RSN_NTFY_INIT) {
4533 _action_wl_init(rtwdev);
4534 goto exit;
4535 }
4536
4537 if (!cx->bt.enable.now && !cx->other.type) {
4538 _action_bt_off(rtwdev);
4539 goto exit;
4540 }
4541
4542 if (cx->bt.whql_test) {
4543 _action_bt_whql(rtwdev);
4544 goto exit;
4545 }
4546
4547 if (wl->rfk_info.state != BTC_WRFK_STOP) {
4548 _action_wl_rfk(rtwdev);
4549 goto exit;
4550 }
4551
4552 if (cx->state_map == BTC_WLINKING) {
4553 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
4554 mode == BTC_WLINK_5G) {
4555 _action_wl_scan(rtwdev);
4556 goto exit;
4557 }
4558 }
4559
4560 if (wl->status.map.scan) {
4561 _action_wl_scan(rtwdev);
4562 goto exit;
4563 }
4564
4565 switch (mode) {
4566 case BTC_WLINK_NOLINK:
4567 _action_wl_nc(rtwdev);
4568 break;
4569 case BTC_WLINK_2G_STA:
4570 _action_wl_2g_sta(rtwdev);
4571 break;
4572 case BTC_WLINK_2G_AP:
4573 bt->scan_rx_low_pri = true;
4574 _action_wl_2g_ap(rtwdev);
4575 break;
4576 case BTC_WLINK_2G_GO:
4577 bt->scan_rx_low_pri = true;
4578 _action_wl_2g_go(rtwdev);
4579 break;
4580 case BTC_WLINK_2G_GC:
4581 bt->scan_rx_low_pri = true;
4582 _action_wl_2g_gc(rtwdev);
4583 break;
4584 case BTC_WLINK_2G_SCC:
4585 bt->scan_rx_low_pri = true;
4586 if (chip->chip_id == RTL8852A)
4587 _action_wl_2g_scc(rtwdev);
4588 else if (chip->chip_id == RTL8852C)
4589 _action_wl_2g_scc_v1(rtwdev);
4590 break;
4591 case BTC_WLINK_2G_MCC:
4592 bt->scan_rx_low_pri = true;
4593 _action_wl_2g_mcc(rtwdev);
4594 break;
4595 case BTC_WLINK_25G_MCC:
4596 bt->scan_rx_low_pri = true;
4597 _action_wl_25g_mcc(rtwdev);
4598 break;
4599 case BTC_WLINK_5G:
4600 _action_wl_5g(rtwdev);
4601 break;
4602 case BTC_WLINK_2G_NAN:
4603 _action_wl_2g_nan(rtwdev);
4604 break;
4605 default:
4606 _action_wl_other(rtwdev);
4607 break;
4608 }
4609
4610exit:
4611 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
4612 _action_common(rtwdev);
4613}
4614
4615void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
4616{
4617 struct rtw89_btc *btc = &rtwdev->btc;
4618
4619 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4620 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
4621}
4622
4623void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
4624{
4625 struct rtw89_btc *btc = &rtwdev->btc;
4626 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4627
4628 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4629 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
4630
4631 btc->cx.wl.status.map.rf_off = 1;
4632 btc->cx.wl.status.map.busy = 0;
4633 wl->status.map.lps = BTC_LPS_OFF;
4634
4635 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
4636 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
4637
4638 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
4639
4640 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
4641}
4642
4643static void _set_init_info(struct rtw89_dev *rtwdev)
4644{
4645 const struct rtw89_chip_info *chip = rtwdev->chip;
4646 struct rtw89_btc *btc = &rtwdev->btc;
4647 struct rtw89_btc_dm *dm = &btc->dm;
4648 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4649
4650 dm->init_info.wl_only = (u8)dm->wl_only;
4651 dm->init_info.bt_only = (u8)dm->bt_only;
4652 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok;
4653 dm->init_info.dbcc_en = rtwdev->dbcc_en;
4654 dm->init_info.cx_other = btc->cx.other.type;
4655 dm->init_info.wl_guard_ch = chip->afh_guard_ch;
4656 dm->init_info.module = btc->mdinfo;
4657}
4658
4659void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
4660{
4661 struct rtw89_btc *btc = &rtwdev->btc;
4662 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4663 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4664 const struct rtw89_chip_info *chip = rtwdev->chip;
4665
4666 _reset_btc_var(rtwdev, BTC_RESET_ALL);
4667 btc->dm.run_reason = BTC_RSN_NONE;
4668 btc->dm.run_action = BTC_ACT_NONE;
4669 btc->ctrl.igno_bt = true;
4670
4671 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4672 "[BTC], %s(): mode=%d\n", __func__, mode);
4673
4674 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
4675 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
4676 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
4677 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
4678
4679 chip->ops->btc_set_rfe(rtwdev);
4680 chip->ops->btc_init_cfg(rtwdev);
4681
4682 if (!wl->status.map.init_ok) {
4683 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4684 "[BTC], %s(): return for WL init fail!!\n",
4685 __func__);
4686 dm->error.map.init = true;
4687 return;
4688 }
4689
4690 _write_scbd(rtwdev,
4691 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
4692 _update_bt_scbd(rtwdev, true);
4693 if (rtw89_mac_get_ctrl_path(rtwdev) && chip->chip_id == RTL8852A) {
4694 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4695 "[BTC], %s(): PTA owner warning!!\n",
4696 __func__);
4697 dm->error.map.pta_owner = true;
4698 }
4699
4700 _set_init_info(rtwdev);
4701 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
4702 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot);
4703 btc_fw_set_monreg(rtwdev);
4704 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
4705 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
4706
4707 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
4708}
4709
4710void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
4711{
4712 struct rtw89_btc *btc = &rtwdev->btc;
4713 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4714
4715 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4716 "[BTC], %s(): phy_idx=%d, band=%d\n",
4717 __func__, phy_idx, band);
4718 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
4719 wl->status.map.scan = true;
4720 wl->scan_info.band[phy_idx] = band;
4721 wl->scan_info.phy_map |= BIT(phy_idx);
4722 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4723
4724 if (rtwdev->dbcc_en) {
4725 wl->dbcc_info.scan_band[phy_idx] = band;
4726 _update_dbcc_band(rtwdev, phy_idx);
4727 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4728 }
4729
4730 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
4731}
4732
4733void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
4734{
4735 struct rtw89_btc *btc = &rtwdev->btc;
4736 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4737
4738 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4739 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
4740 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
4741
4742 wl->status.map.scan = false;
4743 wl->scan_info.phy_map &= ~BIT(phy_idx);
4744 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4745
4746 if (rtwdev->dbcc_en) {
4747 _update_dbcc_band(rtwdev, phy_idx);
4748 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4749 }
4750
4751 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
4752}
4753
4754void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
4755{
4756 struct rtw89_btc *btc = &rtwdev->btc;
4757 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4758
4759 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4760 "[BTC], %s(): phy_idx=%d, band=%d\n",
4761 __func__, phy_idx, band);
4762 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
4763
4764 wl->scan_info.band[phy_idx] = band;
4765 wl->scan_info.phy_map |= BIT(phy_idx);
4766 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4767
4768 if (rtwdev->dbcc_en) {
4769 wl->dbcc_info.scan_band[phy_idx] = band;
4770 _update_dbcc_band(rtwdev, phy_idx);
4771 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4772 }
4773 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
4774}
4775
4776void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
4777 enum btc_pkt_type pkt_type)
4778{
4779 struct rtw89_btc *btc = &rtwdev->btc;
4780 struct rtw89_btc_cx *cx = &btc->cx;
4781 struct rtw89_btc_wl_info *wl = &cx->wl;
4782 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
4783 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4784 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4785 u32 cnt;
4786 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
4787 bool delay_work = false;
4788
4789 switch (pkt_type) {
4790 case PACKET_DHCP:
4791 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
4792 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4793 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
4794 wl->status.map.connecting = true;
4795 delay_work = true;
4796 break;
4797 case PACKET_EAPOL:
4798 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
4799 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4800 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
4801 wl->status.map._4way = true;
4802 delay_work = true;
4803 if (hfp->exist || hid->exist)
4804 delay /= 2;
4805 break;
4806 case PACKET_EAPOL_END:
4807 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
4808 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4809 "[BTC], %s(): EAPOL_End cnt=%d\n",
4810 __func__, cnt);
4811 wl->status.map._4way = false;
4812 cancel_delayed_work(&rtwdev->coex_act1_work);
4813 break;
4814 case PACKET_ARP:
4815 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
4816 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4817 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
4818 return;
4819 case PACKET_ICMP:
4820 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4821 "[BTC], %s(): ICMP pkt\n", __func__);
4822 return;
4823 default:
4824 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4825 "[BTC], %s(): unknown packet type %d\n",
4826 __func__, pkt_type);
4827 return;
4828 }
4829
4830 if (delay_work) {
4831 cancel_delayed_work(&rtwdev->coex_act1_work);
4832 ieee80211_queue_delayed_work(rtwdev->hw,
4833 &rtwdev->coex_act1_work, delay);
4834 }
4835
4836 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
4837 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
4838}
4839
4840void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
4841{
4842 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4843 btc.eapol_notify_work);
4844
4845 mutex_lock(&rtwdev->mutex);
4846 rtw89_leave_ps_mode(rtwdev);
4847 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
4848 mutex_unlock(&rtwdev->mutex);
4849}
4850
4851void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
4852{
4853 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4854 btc.arp_notify_work);
4855
4856 mutex_lock(&rtwdev->mutex);
4857 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
4858 mutex_unlock(&rtwdev->mutex);
4859}
4860
4861void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
4862{
4863 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4864 btc.dhcp_notify_work);
4865
4866 mutex_lock(&rtwdev->mutex);
4867 rtw89_leave_ps_mode(rtwdev);
4868 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
4869 mutex_unlock(&rtwdev->mutex);
4870}
4871
4872void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
4873{
4874 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4875 btc.icmp_notify_work);
4876
4877 mutex_lock(&rtwdev->mutex);
4878 rtw89_leave_ps_mode(rtwdev);
4879 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
4880 mutex_unlock(&rtwdev->mutex);
4881}
4882
4883static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
4884{
4885 const struct rtw89_chip_info *chip = rtwdev->chip;
4886 struct rtw89_btc *btc = &rtwdev->btc;
4887 struct rtw89_btc_cx *cx = &btc->cx;
4888 struct rtw89_btc_bt_info *bt = &cx->bt;
4889 struct rtw89_btc_bt_link_info *b = &bt->link_info;
4890 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4891 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4892 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
4893 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
4894 union btc_btinfo btinfo;
4895
4896 if (buf[BTC_BTINFO_L1] != 6)
4897 return;
4898
4899 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
4900 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4901 "[BTC], %s(): return by bt-info duplicate!!\n",
4902 __func__);
4903 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
4904 return;
4905 }
4906
4907 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
4908
4909 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4910 "[BTC], %s(): bt_info[2]=0x%02x\n",
4911 __func__, bt->raw_info[2]);
4912
4913 /* reset to mo-connect before update */
4914 b->status.val = BTC_BLINK_NOCONNECT;
4915 b->profile_cnt.last = b->profile_cnt.now;
4916 b->relink.last = b->relink.now;
4917 a2dp->exist_last = a2dp->exist;
4918 b->multi_link.last = b->multi_link.now;
4919 bt->inq_pag.last = bt->inq_pag.now;
4920 b->profile_cnt.now = 0;
4921 hid->type = 0;
4922
4923 /* parse raw info low-Byte2 */
4924 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
4925 b->status.map.connect = btinfo.lb2.connect;
4926 b->status.map.sco_busy = btinfo.lb2.sco_busy;
4927 b->status.map.acl_busy = btinfo.lb2.acl_busy;
4928 b->status.map.inq_pag = btinfo.lb2.inq_pag;
4929 bt->inq_pag.now = btinfo.lb2.inq_pag;
4930 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
4931
4932 hfp->exist = btinfo.lb2.hfp;
4933 b->profile_cnt.now += (u8)hfp->exist;
4934 hid->exist = btinfo.lb2.hid;
4935 b->profile_cnt.now += (u8)hid->exist;
4936 a2dp->exist = btinfo.lb2.a2dp;
4937 b->profile_cnt.now += (u8)a2dp->exist;
4938 pan->active = btinfo.lb2.pan;
4939
4940 /* parse raw info low-Byte3 */
4941 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
4942 if (btinfo.lb3.retry != 0)
4943 cx->cnt_bt[BTC_BCNT_RETRY]++;
4944 b->cqddr = btinfo.lb3.cqddr;
4945 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
4946 bt->inq = btinfo.lb3.inq;
4947 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
4948 bt->pag = btinfo.lb3.pag;
4949
4950 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
4951 /* parse raw info high-Byte0 */
4952 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
4953 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
4954 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
4955
4956 /* parse raw info high-Byte1 */
4957 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
4958 b->status.map.ble_connect = btinfo.hb1.ble_connect;
4959 if (btinfo.hb1.ble_connect)
4960 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
4961
4962 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
4963 bt->reinit = btinfo.hb1.reinit;
4964 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
4965 b->relink.now = btinfo.hb1.relink;
4966 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
4967 bt->igno_wl = btinfo.hb1.igno_wl;
4968
4969 if (bt->igno_wl && !cx->wl.status.map.rf_off)
4970 _set_bt_ignore_wlan_act(rtwdev, false);
4971
4972 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
4973 bt->ble_scan_en = btinfo.hb1.ble_scan;
4974
4975 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
4976 b->role_sw = btinfo.hb1.role_sw;
4977
4978 b->multi_link.now = btinfo.hb1.multi_link;
4979
4980 /* parse raw info high-Byte2 */
4981 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
4982 pan->exist = btinfo.hb2.pan_active;
4983 b->profile_cnt.now += (u8)pan->exist;
4984
4985 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
4986 b->afh_update = btinfo.hb2.afh_update;
4987 a2dp->active = btinfo.hb2.a2dp_active;
4988 b->slave_role = btinfo.hb2.slave;
4989 hid->slot_info = btinfo.hb2.hid_slot;
4990 hid->pair_cnt = btinfo.hb2.hid_cnt;
4991 hid->type |= (hid->slot_info == BTC_HID_218 ?
4992 BTC_HID_218 : BTC_HID_418);
4993 /* parse raw info high-Byte3 */
4994 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
4995 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
4996
4997 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
4998 cx->cnt_bt[BTC_BCNT_RATECHG]++;
4999 b->tx_3m = (u32)btinfo.hb3.tx_3m;
5000
5001 a2dp->sink = btinfo.hb3.a2dp_sink;
5002
5003 if (b->profile_cnt.now || b->status.map.ble_connect)
5004 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 1);
5005 else
5006 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 0);
5007
5008 if (!a2dp->exist_last && a2dp->exist) {
5009 a2dp->vendor_id = 0;
5010 a2dp->flush_time = 0;
5011 a2dp->play_latency = 1;
5012 ieee80211_queue_delayed_work(rtwdev->hw,
5013 &rtwdev->coex_bt_devinfo_work,
5014 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
5015 }
5016
5017 if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 ||
5018 a2dp->play_latency == 1))
5019 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 1);
5020 else
5021 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 0);
5022
5023 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
5024}
5025
5026enum btc_wl_mode {
5027 BTC_WL_MODE_HT = 0,
5028 BTC_WL_MODE_VHT = 1,
5029 BTC_WL_MODE_HE = 2,
5030 BTC_WL_MODE_NUM,
5031};
5032
5033void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
5034 struct rtw89_sta *rtwsta, enum btc_role_state state)
5035{
5036 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
5037 const struct rtw89_chip_info *chip = rtwdev->chip;
5038 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
5039 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
5040 struct rtw89_btc *btc = &rtwdev->btc;
5041 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5042 struct rtw89_btc_wl_link_info r = {0};
5043 struct rtw89_btc_wl_link_info *wlinfo = NULL;
5044 u8 mode = 0;
5045
5046 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
5047 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5048 "[BTC], role is STA=%d\n",
5049 vif->type == NL80211_IFTYPE_STATION);
5050 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
5051 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
5052 chan->band_type, chan->channel, chan->band_width);
5053 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
5054 state == BTC_ROLE_MSTS_STA_CONN_END);
5055 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5056 "[BTC], bcn_period=%d dtim_period=%d\n",
5057 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
5058
5059 if (rtwsta) {
5060 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
5061 rtwsta->mac_id);
5062
5063 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5064 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
5065 sta->deflink.he_cap.has_he,
5066 sta->deflink.vht_cap.vht_supported,
5067 sta->deflink.ht_cap.ht_supported);
5068 if (sta->deflink.he_cap.has_he)
5069 mode |= BIT(BTC_WL_MODE_HE);
5070 if (sta->deflink.vht_cap.vht_supported)
5071 mode |= BIT(BTC_WL_MODE_VHT);
5072 if (sta->deflink.ht_cap.ht_supported)
5073 mode |= BIT(BTC_WL_MODE_HT);
5074
5075 r.mode = mode;
5076 }
5077
5078 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
5079 return;
5080
5081 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5082 "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
5083
5084 r.role = rtwvif->wifi_role;
5085 r.phy = rtwvif->phy_idx;
5086 r.pid = rtwvif->port;
5087 r.active = true;
5088 r.connected = MLME_LINKED;
5089 r.bcn_period = vif->bss_conf.beacon_int;
5090 r.dtim_period = vif->bss_conf.dtim_period;
5091 r.band = chan->band_type;
5092 r.ch = chan->channel;
5093 r.bw = chan->band_width;
5094 ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
5095
5096 if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
5097 r.mac_id = rtwsta->mac_id;
5098
5099 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
5100
5101 wlinfo = &wl->link_info[r.pid];
5102
5103 memcpy(wlinfo, &r, sizeof(*wlinfo));
5104 if (chip->chip_id == RTL8852A)
5105 _update_wl_info(rtwdev);
5106 else
5107 _update_wl_info_v1(rtwdev);
5108
5109 if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
5110 wlinfo->connected == MLME_NO_LINK)
5111 btc->dm.leak_ap = 0;
5112
5113 if (state == BTC_ROLE_MSTS_STA_CONN_START)
5114 wl->status.map.connecting = 1;
5115 else
5116 wl->status.map.connecting = 0;
5117
5118 if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
5119 wl->status.map._4way = false;
5120
5121 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
5122}
5123
5124void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
5125{
5126 const struct rtw89_chip_info *chip = rtwdev->chip;
5127 struct rtw89_btc *btc = &rtwdev->btc;
5128 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5129 u32 val;
5130
5131 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
5132 __func__, rf_state);
5133 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
5134
5135 switch (rf_state) {
5136 case BTC_RFCTRL_WL_OFF:
5137 wl->status.map.rf_off = 1;
5138 wl->status.map.lps = BTC_LPS_OFF;
5139 wl->status.map.busy = 0;
5140 break;
5141 case BTC_RFCTRL_FW_CTRL:
5142 wl->status.map.rf_off = 0;
5143 wl->status.map.lps = BTC_LPS_RF_OFF;
5144 wl->status.map.busy = 0;
5145 break;
5146 case BTC_RFCTRL_WL_ON:
5147 default:
5148 wl->status.map.rf_off = 0;
5149 wl->status.map.lps = BTC_LPS_OFF;
5150 break;
5151 }
5152
5153 if (rf_state == BTC_RFCTRL_WL_ON) {
5154 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
5155 rtw89_btc_fw_en_rpt(rtwdev,
5156 RPT_EN_MREG | RPT_EN_BT_VER_INFO, true);
5157 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
5158 _write_scbd(rtwdev, val, true);
5159 _update_bt_scbd(rtwdev, true);
5160 chip->ops->btc_init_cfg(rtwdev);
5161 } else {
5162 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
5163 if (rf_state == BTC_RFCTRL_WL_OFF)
5164 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
5165 }
5166
5167 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
5168
5169 wl->status.map.rf_off_pre = wl->status.map.rf_off;
5170 wl->status.map.lps_pre = wl->status.map.lps;
5171}
5172
5173static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
5174 enum btc_wl_rfk_type type,
5175 enum btc_wl_rfk_state state)
5176{
5177 struct rtw89_btc *btc = &rtwdev->btc;
5178 struct rtw89_btc_cx *cx = &btc->cx;
5179 struct rtw89_btc_wl_info *wl = &cx->wl;
5180 bool result = BTC_WRFK_REJECT;
5181
5182 wl->rfk_info.type = type;
5183 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
5184 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
5185 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
5186
5187 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5188 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
5189 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
5190 type, state);
5191
5192 switch (state) {
5193 case BTC_WRFK_START:
5194 result = _chk_wl_rfk_request(rtwdev);
5195 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
5196
5197 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
5198
5199 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
5200 break;
5201 case BTC_WRFK_ONESHOT_START:
5202 case BTC_WRFK_ONESHOT_STOP:
5203 if (wl->rfk_info.state == BTC_WRFK_STOP) {
5204 result = BTC_WRFK_REJECT;
5205 } else {
5206 result = BTC_WRFK_ALLOW;
5207 wl->rfk_info.state = state;
5208 }
5209 break;
5210 case BTC_WRFK_STOP:
5211 result = BTC_WRFK_ALLOW;
5212 wl->rfk_info.state = BTC_WRFK_STOP;
5213
5214 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
5215 cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
5216 break;
5217 default:
5218 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5219 "[BTC], %s() warning state=%d\n", __func__, state);
5220 break;
5221 }
5222
5223 if (result == BTC_WRFK_ALLOW) {
5224 if (wl->rfk_info.state == BTC_WRFK_START ||
5225 wl->rfk_info.state == BTC_WRFK_STOP)
5226 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
5227
5228 if (wl->rfk_info.state == BTC_WRFK_START)
5229 ieee80211_queue_delayed_work(rtwdev->hw,
5230 &rtwdev->coex_rfk_chk_work,
5231 RTW89_COEX_RFK_CHK_WORK_PERIOD);
5232 }
5233
5234 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5235 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
5236 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
5237
5238 return result == BTC_WRFK_ALLOW;
5239}
5240
5241void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
5242 enum btc_wl_rfk_type type,
5243 enum btc_wl_rfk_state state)
5244{
5245 u8 band;
5246 bool allow;
5247 int ret;
5248
5249 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
5250
5251 rtw89_debug(rtwdev, RTW89_DBG_RFK,
5252 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
5253 band == RTW89_BAND_2G ? "2G" :
5254 band == RTW89_BAND_5G ? "5G" : "6G",
5255 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
5256 type,
5257 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
5258 state == BTC_WRFK_STOP ? "RFK_STOP" :
5259 state == BTC_WRFK_START ? "RFK_START" :
5260 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
5261 "ONE-SHOT_STOP");
5262
5263 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
5264 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
5265 return;
5266 }
5267
5268 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
5269 rtwdev, phy_map, type, state);
5270 if (ret) {
5271 rtw89_warn(rtwdev, "RFK notify timeout\n");
5272 rtwdev->is_bt_iqk_timeout = true;
5273 }
5274}
5275EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
5276
5277struct rtw89_btc_wl_sta_iter_data {
5278 struct rtw89_dev *rtwdev;
5279 u8 busy_all;
5280 u8 dir_all;
5281 u8 rssi_map_all;
5282 bool is_sta_change;
5283 bool is_traffic_change;
5284};
5285
5286static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
5287{
5288 struct rtw89_btc_wl_sta_iter_data *iter_data =
5289 (struct rtw89_btc_wl_sta_iter_data *)data;
5290 struct rtw89_dev *rtwdev = iter_data->rtwdev;
5291 struct rtw89_btc *btc = &rtwdev->btc;
5292 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5293 struct rtw89_btc_wl_link_info *link_info = NULL;
5294 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
5295 struct rtw89_traffic_stats *link_info_t = NULL;
5296 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
5297 struct rtw89_traffic_stats *stats = &rtwvif->stats;
5298 const struct rtw89_chip_info *chip = rtwdev->chip;
5299 u32 last_tx_rate, last_rx_rate;
5300 u16 last_tx_lvl, last_rx_lvl;
5301 u8 port = rtwvif->port;
5302 u8 rssi;
5303 u8 busy = 0;
5304 u8 dir = 0;
5305 u8 rssi_map = 0;
5306 u8 i = 0;
5307 bool is_sta_change = false, is_traffic_change = false;
5308
5309 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
5310 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
5311
5312 link_info = &wl->link_info[port];
5313 link_info->stat.traffic = rtwvif->stats;
5314 link_info_t = &link_info->stat.traffic;
5315
5316 if (link_info->connected == MLME_NO_LINK) {
5317 link_info->rx_rate_drop_cnt = 0;
5318 return;
5319 }
5320
5321 link_info->stat.rssi = rssi;
5322 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
5323 link_info->rssi_state[i] =
5324 _update_rssi_state(rtwdev,
5325 link_info->rssi_state[i],
5326 link_info->stat.rssi,
5327 chip->wl_rssi_thres[i]);
5328 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
5329 rssi_map |= BIT(i);
5330
5331 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED &&
5332 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
5333 is_sta_change = true;
5334 }
5335 iter_data->rssi_map_all |= rssi_map;
5336
5337 last_tx_rate = link_info_t->tx_rate;
5338 last_rx_rate = link_info_t->rx_rate;
5339 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
5340 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
5341
5342 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
5343 stats->rx_tfc_lv != RTW89_TFC_IDLE)
5344 busy = 1;
5345
5346 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
5347 dir = RTW89_TFC_UL;
5348 else
5349 dir = RTW89_TFC_DL;
5350
5351 link_info = &wl->link_info[port];
5352 if (link_info->busy != busy || link_info->dir != dir) {
5353 is_sta_change = true;
5354 link_info->busy = busy;
5355 link_info->dir = dir;
5356 }
5357
5358 iter_data->busy_all |= busy;
5359 iter_data->dir_all |= BIT(dir);
5360
5361 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
5362 last_rx_rate > RTW89_HW_RATE_CCK2 &&
5363 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
5364 link_info->rx_rate_drop_cnt++;
5365
5366 if (last_tx_rate != rtwsta->ra_report.hw_rate ||
5367 last_rx_rate != rtwsta->rx_hw_rate ||
5368 last_tx_lvl != link_info_t->tx_tfc_lv ||
5369 last_rx_lvl != link_info_t->rx_tfc_lv)
5370 is_traffic_change = true;
5371
5372 link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
5373 link_info_t->rx_rate = rtwsta->rx_hw_rate;
5374
5375 wl->role_info.active_role[port].tx_lvl = (u16)stats->tx_tfc_lv;
5376 wl->role_info.active_role[port].rx_lvl = (u16)stats->rx_tfc_lv;
5377 wl->role_info.active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
5378 wl->role_info.active_role[port].rx_rate = rtwsta->rx_hw_rate;
5379
5380 if (is_sta_change)
5381 iter_data->is_sta_change = true;
5382
5383 if (is_traffic_change)
5384 iter_data->is_traffic_change = true;
5385}
5386
5387#define BTC_NHM_CHK_INTVL 20
5388
5389void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
5390{
5391 struct rtw89_btc *btc = &rtwdev->btc;
5392 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5393 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
5394 u8 i;
5395
5396 ieee80211_iterate_stations_atomic(rtwdev->hw,
5397 rtw89_btc_ntfy_wl_sta_iter,
5398 &data);
5399
5400 wl->rssi_level = 0;
5401 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
5402 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
5403 /* set RSSI level 4 ~ 0 if rssi bit map match */
5404 if (data.rssi_map_all & BIT(i - 1)) {
5405 wl->rssi_level = i;
5406 break;
5407 }
5408 }
5409
5410 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
5411 __func__, !!wl->status.map.busy);
5412
5413 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
5414
5415 if (data.is_traffic_change)
5416 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5417 if (data.is_sta_change) {
5418 wl->status.map.busy = data.busy_all;
5419 wl->status.map.traffic_dir = data.dir_all;
5420 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
5421 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
5422 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
5423 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
5424 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
5425 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
5426 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
5427 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
5428 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
5429 }
5430}
5431
5432void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
5433 u32 len, u8 class, u8 func)
5434{
5435 struct rtw89_btc *btc = &rtwdev->btc;
5436 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5437 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
5438
5439 len -= RTW89_C2H_HEADER_LEN;
5440
5441 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5442 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
5443 __func__, len, class, func);
5444
5445 if (class != BTFC_FW_EVENT)
5446 return;
5447
5448 switch (func) {
5449 case BTF_EVNT_RPT:
5450 case BTF_EVNT_BUF_OVERFLOW:
5451 pfwinfo->event[func]++;
5452 /* Don't need rtw89_leave_ps_mode() */
5453 btc_fw_event(rtwdev, func, buf, len);
5454 break;
5455 case BTF_EVNT_BT_INFO:
5456 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5457 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
5458 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
5459 _update_bt_info(rtwdev, buf, len);
5460 break;
5461 case BTF_EVNT_BT_SCBD:
5462 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5463 "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
5464 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
5465 _update_bt_scbd(rtwdev, false);
5466 break;
5467 case BTF_EVNT_BT_PSD:
5468 break;
5469 case BTF_EVNT_BT_REG:
5470 btc->dbg.rb_done = true;
5471 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
5472
5473 break;
5474 case BTF_EVNT_C2H_LOOPBACK:
5475 btc->dbg.rb_done = true;
5476 btc->dbg.rb_val = buf[0];
5477 break;
5478 case BTF_EVNT_CX_RUNINFO:
5479 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
5480 break;
5481 }
5482}
5483
5484#define BTC_CX_FW_OFFLOAD 0
5485
5486static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5487{
5488 const struct rtw89_chip_info *chip = rtwdev->chip;
5489 struct rtw89_hal *hal = &rtwdev->hal;
5490 struct rtw89_btc *btc = &rtwdev->btc;
5491 struct rtw89_btc_dm *dm = &btc->dm;
5492 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5493 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5494 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
5495
5496 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
5497 return;
5498
5499 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
5500
5501 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
5502 chip->chip_id);
5503
5504 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
5505 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
5506 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
5507 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
5508 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
5509 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
5510
5511 if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD)
5512 dm->error.map.offload_mismatch = true;
5513 else
5514 dm->error.map.offload_mismatch = false;
5515
5516 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
5517 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
5518 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
5519 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
5520 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
5521 ver_main, ver_sub, ver_hotfix, id_branch);
5522
5523 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
5524 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
5525 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
5526 seq_printf(m, "(%s, desired:%d.%d.%d), ",
5527 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
5528 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
5529
5530 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
5531 bt->ver_info.fw_coex,
5532 (bt->ver_info.fw_coex >= chip->btcx_desired ?
5533 "Match" : "Mismatch"), chip->btcx_desired);
5534
5535 if (bt->enable.now && bt->ver_info.fw == 0)
5536 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
5537 else
5538 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
5539
5540 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
5541 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
5542 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
5543 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
5544 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
5545 "[sub_module]",
5546 ver_main, ver_sub, ver_hotfix, id_branch,
5547 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
5548
5549 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
5550 "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type,
5551 btc->mdinfo.ant.isolation, btc->mdinfo.ant.num,
5552 (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ?
5553 "1Ant_Pos:S1, " : "1Ant_Pos:S0, ")));
5554
5555 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
5556 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
5557 hal->rx_nss);
5558}
5559
5560static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5561{
5562 struct rtw89_btc *btc = &rtwdev->btc;
5563 struct rtw89_btc_wl_link_info *plink = NULL;
5564 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5565 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5566 struct rtw89_traffic_stats *t;
5567 u8 i;
5568
5569 if (rtwdev->dbcc_en) {
5570 seq_printf(m,
5571 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
5572 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
5573 wl_dinfo->scan_band[RTW89_PHY_0],
5574 wl_dinfo->real_band[RTW89_PHY_0]);
5575 seq_printf(m,
5576 "PHY1_band(op:%d/scan:%d/real:%d)\n",
5577 wl_dinfo->op_band[RTW89_PHY_1],
5578 wl_dinfo->scan_band[RTW89_PHY_1],
5579 wl_dinfo->real_band[RTW89_PHY_1]);
5580 }
5581
5582 for (i = 0; i < RTW89_PORT_NUM; i++) {
5583 plink = &btc->cx.wl.link_info[i];
5584
5585 if (!plink->active)
5586 continue;
5587
5588 seq_printf(m,
5589 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
5590 plink->pid, (u32)plink->role, plink->phy,
5591 (u32)plink->connected, plink->client_cnt - 1,
5592 (u32)plink->mode, plink->ch, (u32)plink->bw);
5593
5594 if (plink->connected == MLME_NO_LINK)
5595 continue;
5596
5597 seq_printf(m,
5598 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
5599 plink->mac_id, plink->tx_time, plink->tx_retry);
5600
5601 seq_printf(m,
5602 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
5603 plink->pid, 110 - plink->stat.rssi,
5604 plink->stat.rssi, plink->busy,
5605 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
5606
5607 t = &plink->stat.traffic;
5608
5609 seq_printf(m,
5610 "tx[rate:%d/busy_level:%d], ",
5611 (u32)t->tx_rate, t->tx_tfc_lv);
5612
5613 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
5614 (u32)t->rx_rate,
5615 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
5616 }
5617}
5618
5619static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5620{
5621 const struct rtw89_chip_info *chip = rtwdev->chip;
5622 struct rtw89_btc *btc = &rtwdev->btc;
5623 struct rtw89_btc_cx *cx = &btc->cx;
5624 struct rtw89_btc_wl_info *wl = &cx->wl;
5625 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5626 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5627 u8 mode;
5628
5629 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
5630 return;
5631
5632 seq_puts(m, "========== [WL Status] ==========\n");
5633
5634 if (chip->chip_id == RTL8852A)
5635 mode = wl_rinfo->link_mode;
5636 else
5637 mode = wl_rinfo_v1->link_mode;
5638
5639 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
5640
5641 seq_printf(m,
5642 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
5643 wl->status.map.rf_off, wl->status.map.lps,
5644 wl->status.map.scan ? "Y" : "N",
5645 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
5646
5647 seq_printf(m,
5648 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
5649 wl->status.map.connecting ? "Y" : "N",
5650 wl->status.map.roaming ? "Y" : "N",
5651 wl->status.map._4way ? "Y" : "N",
5652 wl->status.map.init_ok ? "Y" : "N");
5653
5654 _show_wl_role_info(rtwdev, m);
5655}
5656
5657enum btc_bt_a2dp_type {
5658 BTC_A2DP_LEGACY = 0,
5659 BTC_A2DP_TWS_SNIFF = 1,
5660 BTC_A2DP_TWS_RELAY = 2,
5661};
5662
5663static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5664{
5665 struct rtw89_btc *btc = &rtwdev->btc;
5666 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
5667 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
5668 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5669 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5670 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5671
5672 if (hfp.exist) {
5673 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
5674 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
5675 bt_linfo->sut_pwr_level[0],
5676 bt_linfo->golden_rx_shift[0]);
5677 }
5678
5679 if (hid.exist) {
5680 seq_printf(m,
5681 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
5682 "[HID]",
5683 hid.type & BTC_HID_218 ? "2/18," : "",
5684 hid.type & BTC_HID_418 ? "4/18," : "",
5685 hid.type & BTC_HID_BLE ? "BLE," : "",
5686 hid.type & BTC_HID_RCU ? "RCU," : "",
5687 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
5688 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
5689 bt_linfo->golden_rx_shift[1]);
5690 }
5691
5692 if (a2dp.exist) {
5693 seq_printf(m,
5694 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
5695 "[A2DP]",
5696 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
5697 a2dp.bitpool, a2dp.flush_time);
5698
5699 seq_printf(m,
5700 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
5701 a2dp.vendor_id, a2dp.device_name,
5702 bt_linfo->sut_pwr_level[2],
5703 bt_linfo->golden_rx_shift[2]);
5704 }
5705
5706 if (pan.exist) {
5707 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
5708 "[PAN]",
5709 bt_linfo->sut_pwr_level[3],
5710 bt_linfo->golden_rx_shift[3]);
5711 }
5712}
5713
5714static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5715{
5716 struct rtw89_btc *btc = &rtwdev->btc;
5717 struct rtw89_btc_cx *cx = &btc->cx;
5718 struct rtw89_btc_bt_info *bt = &cx->bt;
5719 struct rtw89_btc_wl_info *wl = &cx->wl;
5720 struct rtw89_btc_module *module = &btc->mdinfo;
5721 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5722 u8 *afh = bt_linfo->afh_map;
5723
5724 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
5725 return;
5726
5727 seq_puts(m, "========== [BT Status] ==========\n");
5728
5729 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
5730 "[status]", bt->enable.now ? "Y" : "N",
5731 bt->btg_type ? "Y" : "N",
5732 (bt->enable.now && (bt->btg_type != module->bt_pos) ?
5733 "(efuse-mismatch!!)" : ""),
5734 (bt_linfo->status.map.connect ? "Y" : "N"));
5735
5736 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
5737 bt->igno_wl ? "Y" : "N",
5738 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
5739
5740 seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
5741 "[profile]",
5742 (bt_linfo->profile_cnt.now == 0) ? "None," : "",
5743 bt_linfo->hfp_desc.exist ? "HFP," : "",
5744 bt_linfo->hid_desc.exist ? "HID," : "",
5745 bt_linfo->a2dp_desc.exist ?
5746 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
5747 bt_linfo->pan_desc.exist ? "PAN," : "");
5748
5749 seq_printf(m,
5750 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
5751 bt_linfo->multi_link.now ? "Y" : "N",
5752 bt_linfo->slave_role ? "Slave" : "Master",
5753 bt_linfo->status.map.ble_connect ? "Y" : "N",
5754 bt_linfo->cqddr ? "Y" : "N",
5755 bt_linfo->a2dp_desc.active ? "Y" : "N",
5756 bt_linfo->pan_desc.active ? "Y" : "N");
5757
5758 seq_printf(m,
5759 " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s",
5760 "[link]", bt_linfo->rssi - 100,
5761 bt_linfo->tx_3m ? 3 : 2,
5762 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
5763 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
5764 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
5765
5766 seq_printf(m,
5767 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
5768 bt_linfo->relink.now ? " ReLink!!" : "",
5769 afh[0], afh[1], afh[2], afh[3], afh[4],
5770 afh[5], afh[6], afh[7], afh[8], afh[9]);
5771
5772 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
5773 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
5774
5775 seq_printf(m,
5776 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
5777 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
5778 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
5779 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
5780
5781 seq_printf(m,
5782 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
5783 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
5784 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
5785 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
5786
5787 _show_bt_profile_info(rtwdev, m);
5788
5789 seq_printf(m,
5790 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
5791 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
5792 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
5793 bt->raw_info[7],
5794 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
5795 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
5796 cx->cnt_bt[BTC_BCNT_INFOSAME]);
5797
5798 seq_printf(m,
5799 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n",
5800 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
5801 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
5802 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
5803}
5804
5805#define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
5806#define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
5807#define CASE_BTC_POLICY_STR(e) \
5808 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
5809#define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
5810
5811static const char *steps_to_str(u16 step)
5812{
5813 switch (step) {
5814 CASE_BTC_RSN_STR(NONE);
5815 CASE_BTC_RSN_STR(NTFY_INIT);
5816 CASE_BTC_RSN_STR(NTFY_SWBAND);
5817 CASE_BTC_RSN_STR(NTFY_WL_STA);
5818 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
5819 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
5820 CASE_BTC_RSN_STR(NTFY_WL_RFK);
5821 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
5822 CASE_BTC_RSN_STR(NTFY_SCAN_START);
5823 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
5824 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
5825 CASE_BTC_RSN_STR(NTFY_POWEROFF);
5826 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
5827 CASE_BTC_RSN_STR(CMD_SET_COEX);
5828 CASE_BTC_RSN_STR(ACT1_WORK);
5829 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
5830 CASE_BTC_RSN_STR(RFK_CHK_WORK);
5831
5832 CASE_BTC_ACT_STR(NONE);
5833 CASE_BTC_ACT_STR(WL_ONLY);
5834 CASE_BTC_ACT_STR(WL_5G);
5835 CASE_BTC_ACT_STR(WL_OTHER);
5836 CASE_BTC_ACT_STR(WL_IDLE);
5837 CASE_BTC_ACT_STR(WL_NC);
5838 CASE_BTC_ACT_STR(WL_RFK);
5839 CASE_BTC_ACT_STR(WL_INIT);
5840 CASE_BTC_ACT_STR(WL_OFF);
5841 CASE_BTC_ACT_STR(FREERUN);
5842 CASE_BTC_ACT_STR(BT_WHQL);
5843 CASE_BTC_ACT_STR(BT_RFK);
5844 CASE_BTC_ACT_STR(BT_OFF);
5845 CASE_BTC_ACT_STR(BT_IDLE);
5846 CASE_BTC_ACT_STR(BT_HFP);
5847 CASE_BTC_ACT_STR(BT_HID);
5848 CASE_BTC_ACT_STR(BT_A2DP);
5849 CASE_BTC_ACT_STR(BT_A2DPSINK);
5850 CASE_BTC_ACT_STR(BT_PAN);
5851 CASE_BTC_ACT_STR(BT_A2DP_HID);
5852 CASE_BTC_ACT_STR(BT_A2DP_PAN);
5853 CASE_BTC_ACT_STR(BT_PAN_HID);
5854 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
5855 CASE_BTC_ACT_STR(WL_25G_MCC);
5856 CASE_BTC_ACT_STR(WL_2G_MCC);
5857 CASE_BTC_ACT_STR(WL_2G_SCC);
5858 CASE_BTC_ACT_STR(WL_2G_AP);
5859 CASE_BTC_ACT_STR(WL_2G_GO);
5860 CASE_BTC_ACT_STR(WL_2G_GC);
5861 CASE_BTC_ACT_STR(WL_2G_NAN);
5862
5863 CASE_BTC_POLICY_STR(OFF_BT);
5864 CASE_BTC_POLICY_STR(OFF_WL);
5865 CASE_BTC_POLICY_STR(OFF_EQ0);
5866 CASE_BTC_POLICY_STR(OFF_EQ1);
5867 CASE_BTC_POLICY_STR(OFF_EQ2);
5868 CASE_BTC_POLICY_STR(OFF_EQ3);
5869 CASE_BTC_POLICY_STR(OFF_BWB0);
5870 CASE_BTC_POLICY_STR(OFF_BWB1);
5871 CASE_BTC_POLICY_STR(OFF_BWB2);
5872 CASE_BTC_POLICY_STR(OFF_BWB3);
5873 CASE_BTC_POLICY_STR(OFFB_BWB0);
5874 CASE_BTC_POLICY_STR(OFFE_DEF);
5875 CASE_BTC_POLICY_STR(OFFE_DEF2);
5876 CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
5877 CASE_BTC_POLICY_STR(OFFE_2GISOB);
5878 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
5879 CASE_BTC_POLICY_STR(OFFE_WL);
5880 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
5881 CASE_BTC_POLICY_STR(FIX_TD3030);
5882 CASE_BTC_POLICY_STR(FIX_TD5050);
5883 CASE_BTC_POLICY_STR(FIX_TD2030);
5884 CASE_BTC_POLICY_STR(FIX_TD4010);
5885 CASE_BTC_POLICY_STR(FIX_TD7010);
5886 CASE_BTC_POLICY_STR(FIX_TD2060);
5887 CASE_BTC_POLICY_STR(FIX_TD3060);
5888 CASE_BTC_POLICY_STR(FIX_TD2080);
5889 CASE_BTC_POLICY_STR(FIX_TDW1B1);
5890 CASE_BTC_POLICY_STR(FIX_TD4020);
5891 CASE_BTC_POLICY_STR(FIX_TD4010ISO);
5892 CASE_BTC_POLICY_STR(PFIX_TD3030);
5893 CASE_BTC_POLICY_STR(PFIX_TD5050);
5894 CASE_BTC_POLICY_STR(PFIX_TD2030);
5895 CASE_BTC_POLICY_STR(PFIX_TD2060);
5896 CASE_BTC_POLICY_STR(PFIX_TD3070);
5897 CASE_BTC_POLICY_STR(PFIX_TD2080);
5898 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
5899 CASE_BTC_POLICY_STR(AUTO_TD50B1);
5900 CASE_BTC_POLICY_STR(AUTO_TD60B1);
5901 CASE_BTC_POLICY_STR(AUTO_TD20B1);
5902 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
5903 CASE_BTC_POLICY_STR(PAUTO_TD50B1);
5904 CASE_BTC_POLICY_STR(PAUTO_TD60B1);
5905 CASE_BTC_POLICY_STR(PAUTO_TD20B1);
5906 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
5907 CASE_BTC_POLICY_STR(AUTO2_TD3050);
5908 CASE_BTC_POLICY_STR(AUTO2_TD3070);
5909 CASE_BTC_POLICY_STR(AUTO2_TD5050);
5910 CASE_BTC_POLICY_STR(AUTO2_TD6060);
5911 CASE_BTC_POLICY_STR(AUTO2_TD2080);
5912 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
5913 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
5914 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
5915 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
5916 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
5917 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
5918 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
5919 default:
5920 return "unknown step";
5921 }
5922}
5923
5924static const char *id_to_slot(u32 id)
5925{
5926 switch (id) {
5927 CASE_BTC_SLOT_STR(OFF);
5928 CASE_BTC_SLOT_STR(B2W);
5929 CASE_BTC_SLOT_STR(W1);
5930 CASE_BTC_SLOT_STR(W2);
5931 CASE_BTC_SLOT_STR(W2B);
5932 CASE_BTC_SLOT_STR(B1);
5933 CASE_BTC_SLOT_STR(B2);
5934 CASE_BTC_SLOT_STR(B3);
5935 CASE_BTC_SLOT_STR(B4);
5936 CASE_BTC_SLOT_STR(LK);
5937 CASE_BTC_SLOT_STR(BLK);
5938 CASE_BTC_SLOT_STR(E2G);
5939 CASE_BTC_SLOT_STR(E5G);
5940 CASE_BTC_SLOT_STR(EBT);
5941 CASE_BTC_SLOT_STR(ENULL);
5942 CASE_BTC_SLOT_STR(WLK);
5943 CASE_BTC_SLOT_STR(W1FDD);
5944 CASE_BTC_SLOT_STR(B1FDD);
5945 default:
5946 return "unknown";
5947 }
5948}
5949
5950static
5951void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
5952 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
5953{
5954 u8 i;
5955 u8 cur_index;
5956
5957 for (i = 0; i < len ; i++) {
5958 if ((i % seg_len) == 0)
5959 seq_printf(m, " %-15s : ", prefix);
5960 cur_index = (start_idx + i) % ring_len;
5961 if (i % 3 == 0)
5962 seq_printf(m, "-> %-20s",
5963 steps_to_str(*(data + cur_index)));
5964 else if (i % 3 == 1)
5965 seq_printf(m, "-> %-15s",
5966 steps_to_str(*(data + cur_index)));
5967 else
5968 seq_printf(m, "-> %-13s",
5969 steps_to_str(*(data + cur_index)));
5970 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
5971 seq_puts(m, "\n");
5972 }
5973}
5974
5975static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
5976{
5977 struct rtw89_btc *btc = &rtwdev->btc;
5978 struct rtw89_btc_dm *dm = &btc->dm;
5979 u8 start_idx;
5980 u8 len;
5981
5982 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
5983 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
5984
5985 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
5986 ARRAY_SIZE(dm->dm_step.step));
5987}
5988
5989static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5990{
5991 struct rtw89_btc *btc = &rtwdev->btc;
5992 struct rtw89_btc_module *module = &btc->mdinfo;
5993 struct rtw89_btc_dm *dm = &btc->dm;
5994 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5995 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5996
5997 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
5998 return;
5999
6000 seq_printf(m, "========== [Mechanism Status %s] ==========\n",
6001 (btc->ctrl.manual ? "(Manual)" : "(Auto)"));
6002
6003 seq_printf(m,
6004 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n",
6005 "[status]",
6006 module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated",
6007 steps_to_str(dm->run_reason),
6008 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
6009 FIELD_GET(GENMASK(7, 0), dm->set_ant_path),
6010 dm->cnt_dm[BTC_DCNT_RUN]);
6011
6012 _show_dm_step(rtwdev, m);
6013
6014 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
6015 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
6016 dm->freerun, btc->lps, dm->wl_mimo_ps);
6017
6018 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
6019 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
6020 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
6021 "" : "(Mismatch!!)"));
6022
6023 if (dm->rf_trx_para.wl_tx_power == 0xff)
6024 seq_printf(m,
6025 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
6026 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
6027
6028 else
6029 seq_printf(m,
6030 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
6031 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
6032 dm->rf_trx_para.wl_tx_power);
6033
6034 seq_printf(m,
6035 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
6036 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
6037 dm->rf_trx_para.bt_rx_gain,
6038 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
6039
6040 seq_printf(m,
6041 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
6042 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
6043 dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri);
6044}
6045
6046static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
6047{
6048 const struct rtw89_chip_info *chip = rtwdev->chip;
6049 struct rtw89_btc *btc = &rtwdev->btc;
6050 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6051 struct rtw89_btc_fbtc_cysta *pcysta;
6052 struct rtw89_btc_fbtc_cysta_v1 *pcysta_v1;
6053 u32 except_cnt, exception_map;
6054
6055 if (chip->chip_id == RTL8852A) {
6056 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
6057 except_cnt = le32_to_cpu(pcysta->except_cnt);
6058 exception_map = le32_to_cpu(pcysta->exception);
6059 } else {
6060 pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
6061 except_cnt = le32_to_cpu(pcysta_v1->except_cnt);
6062 exception_map = le32_to_cpu(pcysta_v1->except_map);
6063 }
6064
6065 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
6066 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
6067 return;
6068
6069 seq_printf(m, " %-15s : ", "[error]");
6070
6071 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
6072 seq_printf(m,
6073 "overflow-cnt: %d, ",
6074 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
6075 }
6076
6077 if (pfwinfo->len_mismch) {
6078 seq_printf(m,
6079 "len-mismatch: 0x%x, ",
6080 pfwinfo->len_mismch);
6081 }
6082
6083 if (pfwinfo->fver_mismch) {
6084 seq_printf(m,
6085 "fver-mismatch: 0x%x, ",
6086 pfwinfo->fver_mismch);
6087 }
6088
6089 /* cycle statistics exceptions */
6090 if (exception_map || except_cnt) {
6091 seq_printf(m,
6092 "exception-type: 0x%x, exception-cnt = %d",
6093 exception_map, except_cnt);
6094 }
6095 seq_puts(m, "\n");
6096}
6097
6098static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
6099{
6100 const struct rtw89_chip_info *chip = rtwdev->chip;
6101 struct rtw89_btc *btc = &rtwdev->btc;
6102 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6103 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6104 struct rtw89_btc_fbtc_tdma *t = NULL;
6105 struct rtw89_btc_fbtc_slot *s = NULL;
6106 struct rtw89_btc_dm *dm = &btc->dm;
6107 u8 i, cnt = 0;
6108
6109 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
6110 if (!pcinfo->valid)
6111 return;
6112
6113 if (chip->chip_id == RTL8852A)
6114 t = &pfwinfo->rpt_fbtc_tdma.finfo;
6115 else
6116 t = &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma;
6117
6118 seq_printf(m,
6119 " %-15s : ", "[tdma_policy]");
6120 seq_printf(m,
6121 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
6122 (u32)t->type,
6123 t->rxflctrl, t->txpause);
6124
6125 seq_printf(m,
6126 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
6127 t->wtgle_n, t->leak_n, t->ext_ctrl);
6128
6129 seq_printf(m,
6130 "policy_type:%d",
6131 (u32)btc->policy_type);
6132
6133 s = pfwinfo->rpt_fbtc_slots.finfo.slot;
6134
6135 for (i = 0; i < CXST_MAX; i++) {
6136 if (dm->update_slot_map == BIT(CXST_MAX) - 1)
6137 break;
6138
6139 if (!(dm->update_slot_map & BIT(i)))
6140 continue;
6141
6142 if (cnt % 6 == 0)
6143 seq_printf(m,
6144 " %-15s : %d[%d/0x%x/%d]",
6145 "[slot_policy]",
6146 (u32)i,
6147 s[i].dur, s[i].cxtbl, s[i].cxtype);
6148 else
6149 seq_printf(m,
6150 ", %d[%d/0x%x/%d]",
6151 (u32)i,
6152 s[i].dur, s[i].cxtbl, s[i].cxtype);
6153 if (cnt % 6 == 5)
6154 seq_puts(m, "\n");
6155 cnt++;
6156 }
6157 seq_puts(m, "\n");
6158}
6159
6160static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
6161{
6162 struct rtw89_btc *btc = &rtwdev->btc;
6163 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6164 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6165 struct rtw89_btc_fbtc_slots *pslots = NULL;
6166 struct rtw89_btc_fbtc_slot s;
6167 u8 i = 0;
6168
6169 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
6170 if (!pcinfo->valid)
6171 return;
6172
6173 pslots = &pfwinfo->rpt_fbtc_slots.finfo;
6174
6175 for (i = 0; i < CXST_MAX; i++) {
6176 s = pslots->slot[i];
6177 if (i % 6 == 0)
6178 seq_printf(m,
6179 " %-15s : %02d[%03d/0x%x/%d]",
6180 "[slot_list]",
6181 (u32)i,
6182 s.dur, s.cxtbl, s.cxtype);
6183 else
6184 seq_printf(m,
6185 ", %02d[%03d/0x%x/%d]",
6186 (u32)i,
6187 s.dur, s.cxtbl, s.cxtype);
6188 if (i % 6 == 5)
6189 seq_puts(m, "\n");
6190 }
6191}
6192
6193static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m)
6194{
6195 struct rtw89_btc *btc = &rtwdev->btc;
6196 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6197 struct rtw89_btc_dm *dm = &btc->dm;
6198 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
6199 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6200 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
6201 struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
6202 union rtw89_btc_fbtc_rxflct r;
6203 u8 i, cnt = 0, slot_pair;
6204 u16 cycle, c_begin, c_end, store_index;
6205
6206 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
6207 if (!pcinfo->valid)
6208 return;
6209
6210 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
6211 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
6212 seq_printf(m,
6213 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
6214 "[cycle_cnt]", pcysta->cycles, pcysta->bcn_cnt[CXBCN_ALL],
6215 pcysta->bcn_cnt[CXBCN_ALL_OK],
6216 pcysta->bcn_cnt[CXBCN_BT_SLOT],
6217 pcysta->bcn_cnt[CXBCN_BT_OK]);
6218
6219 for (i = 0; i < CXST_MAX; i++) {
6220 if (!pcysta->slot_cnt[i])
6221 continue;
6222 seq_printf(m,
6223 ", %d:%d", (u32)i, pcysta->slot_cnt[i]);
6224 }
6225
6226 if (dm->tdma_now.rxflctrl) {
6227 seq_printf(m,
6228 ", leak_rx:%d", pcysta->leakrx_cnt);
6229 }
6230
6231 if (pcysta->collision_cnt) {
6232 seq_printf(m,
6233 ", collision:%d", pcysta->collision_cnt);
6234 }
6235
6236 if (pcysta->skip_cnt) {
6237 seq_printf(m,
6238 ", skip:%d", pcysta->skip_cnt);
6239 }
6240 seq_puts(m, "\n");
6241
6242 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
6243 "[cycle_time]",
6244 pcysta->tavg_cycle[CXT_WL],
6245 pcysta->tavg_cycle[CXT_BT],
6246 pcysta->tavg_lk / 1000, pcysta->tavg_lk % 1000);
6247 seq_printf(m,
6248 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
6249 pcysta->tmax_cycle[CXT_WL],
6250 pcysta->tmax_cycle[CXT_BT],
6251 pcysta->tmax_lk / 1000, pcysta->tmax_lk % 1000);
6252 seq_printf(m,
6253 ", maxdiff_t[wl:%d/bt:%d]\n",
6254 pcysta->tmaxdiff_cycle[CXT_WL],
6255 pcysta->tmaxdiff_cycle[CXT_BT]);
6256
6257 if (pcysta->cycles == 0)
6258 return;
6259
6260 /* 1 cycle record 1 wl-slot and 1 bt-slot */
6261 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
6262
6263 if (pcysta->cycles <= slot_pair)
6264 c_begin = 1;
6265 else
6266 c_begin = pcysta->cycles - slot_pair + 1;
6267
6268 c_end = pcysta->cycles;
6269
6270 for (cycle = c_begin; cycle <= c_end; cycle++) {
6271 cnt++;
6272 store_index = ((cycle - 1) % slot_pair) * 2;
6273
6274 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
6275 seq_printf(m,
6276 " %-15s : ->b%02d->w%02d", "[cycle_step]",
6277 pcysta->tslot_cycle[store_index],
6278 pcysta->tslot_cycle[store_index + 1]);
6279 else
6280 seq_printf(m,
6281 "->b%02d->w%02d",
6282 pcysta->tslot_cycle[store_index],
6283 pcysta->tslot_cycle[store_index + 1]);
6284 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
6285 seq_puts(m, "\n");
6286 }
6287
6288 if (a2dp->exist) {
6289 seq_printf(m,
6290 " %-15s : a2dp_ept:%d, a2dp_late:%d",
6291 "[a2dp_t_sta]",
6292 pcysta->a2dpept, pcysta->a2dpeptto);
6293
6294 seq_printf(m,
6295 ", avg_t:%d, max_t:%d",
6296 pcysta->tavg_a2dpept, pcysta->tmax_a2dpept);
6297 r.val = dm->tdma_now.rxflctrl;
6298
6299 if (r.type && r.tgln_n) {
6300 seq_printf(m,
6301 ", cycle[PSTDMA:%d/TDMA:%d], ",
6302 pcysta->cycles_a2dp[CXT_FLCTRL_ON],
6303 pcysta->cycles_a2dp[CXT_FLCTRL_OFF]);
6304
6305 seq_printf(m,
6306 "avg_t[PSTDMA:%d/TDMA:%d], ",
6307 pcysta->tavg_a2dp[CXT_FLCTRL_ON],
6308 pcysta->tavg_a2dp[CXT_FLCTRL_OFF]);
6309
6310 seq_printf(m,
6311 "max_t[PSTDMA:%d/TDMA:%d]",
6312 pcysta->tmax_a2dp[CXT_FLCTRL_ON],
6313 pcysta->tmax_a2dp[CXT_FLCTRL_OFF]);
6314 }
6315 seq_puts(m, "\n");
6316 }
6317}
6318
6319static void _show_fbtc_cysta_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
6320{
6321 struct rtw89_btc *btc = &rtwdev->btc;
6322 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
6323 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6324 struct rtw89_btc_dm *dm = &btc->dm;
6325 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
6326 struct rtw89_btc_fbtc_cysta_v1 *pcysta;
6327 struct rtw89_btc_rpt_cmn_info *pcinfo;
6328 u8 i, cnt = 0, slot_pair, divide_cnt;
6329 u16 cycle, c_begin, c_end, store_index;
6330
6331 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
6332 if (!pcinfo->valid)
6333 return;
6334
6335 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
6336 seq_printf(m,
6337 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
6338 "[cycle_cnt]",
6339 le16_to_cpu(pcysta->cycles),
6340 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
6341 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
6342 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
6343 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
6344
6345 for (i = 0; i < CXST_MAX; i++) {
6346 if (!le32_to_cpu(pcysta->slot_cnt[i]))
6347 continue;
6348
6349 seq_printf(m, ", %s:%d", id_to_slot(i),
6350 le32_to_cpu(pcysta->slot_cnt[i]));
6351 }
6352
6353 if (dm->tdma_now.rxflctrl)
6354 seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr));
6355
6356 if (le32_to_cpu(pcysta->collision_cnt))
6357 seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt));
6358
6359 if (le32_to_cpu(pcysta->skip_cnt))
6360 seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt));
6361
6362 seq_puts(m, "\n");
6363
6364 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
6365 "[cycle_time]",
6366 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
6367 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
6368 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
6369 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
6370 seq_printf(m,
6371 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
6372 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
6373 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
6374 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
6375 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
6376 seq_printf(m,
6377 ", maxdiff_t[wl:%d/bt:%d]\n",
6378 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
6379 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
6380
6381 cycle = le16_to_cpu(pcysta->cycles);
6382 if (cycle == 0)
6383 return;
6384
6385 /* 1 cycle record 1 wl-slot and 1 bt-slot */
6386 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
6387
6388 if (cycle <= slot_pair)
6389 c_begin = 1;
6390 else
6391 c_begin = cycle - slot_pair + 1;
6392
6393 c_end = cycle;
6394
6395 if (a2dp->exist)
6396 divide_cnt = 3;
6397 else
6398 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
6399
6400 for (cycle = c_begin; cycle <= c_end; cycle++) {
6401 cnt++;
6402 store_index = ((cycle - 1) % slot_pair) * 2;
6403
6404 if (cnt % divide_cnt == 1) {
6405 seq_printf(m, "\n\r %-15s : ", "[cycle_step]");
6406 } else {
6407 seq_printf(m, "->b%02d",
6408 le16_to_cpu(pcysta->slot_step_time[store_index]));
6409 if (a2dp->exist) {
6410 a2dp_trx = &pcysta->a2dp_trx[store_index];
6411 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
6412 a2dp_trx->empty_cnt,
6413 a2dp_trx->retry_cnt,
6414 a2dp_trx->tx_rate ? 3 : 2,
6415 a2dp_trx->tx_cnt,
6416 a2dp_trx->ack_cnt,
6417 a2dp_trx->nack_cnt);
6418 }
6419 seq_printf(m, "->w%02d",
6420 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
6421 if (a2dp->exist) {
6422 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
6423 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
6424 a2dp_trx->empty_cnt,
6425 a2dp_trx->retry_cnt,
6426 a2dp_trx->tx_rate ? 3 : 2,
6427 a2dp_trx->tx_cnt,
6428 a2dp_trx->ack_cnt,
6429 a2dp_trx->nack_cnt);
6430 }
6431 }
6432 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
6433 seq_puts(m, "\n");
6434 }
6435
6436 if (a2dp->exist) {
6437 seq_printf(m, "%-15s : a2dp_ept:%d, a2dp_late:%d",
6438 "[a2dp_t_sta]",
6439 le16_to_cpu(pcysta->a2dp_ept.cnt),
6440 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
6441
6442 seq_printf(m, ", avg_t:%d, max_t:%d",
6443 le16_to_cpu(pcysta->a2dp_ept.tavg),
6444 le16_to_cpu(pcysta->a2dp_ept.tmax));
6445
6446 seq_puts(m, "\n");
6447 }
6448}
6449
6450static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
6451{
6452 const struct rtw89_chip_info *chip = rtwdev->chip;
6453 struct rtw89_btc *btc = &rtwdev->btc;
6454 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6455 struct rtw89_btc_rpt_cmn_info *pcinfo;
6456 struct rtw89_btc_fbtc_cynullsta *ns;
6457 struct rtw89_btc_fbtc_cynullsta_v1 *ns_v1;
6458 u8 i = 0;
6459
6460 if (!btc->dm.tdma_now.rxflctrl)
6461 return;
6462
6463 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
6464 if (!pcinfo->valid)
6465 return;
6466
6467 if (chip->chip_id == RTL8852A) {
6468 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
6469
6470 seq_printf(m, " %-15s : ", "[null_sta]");
6471
6472 for (i = 0; i < 2; i++) {
6473 if (i != 0)
6474 seq_printf(m, ", null-%d", i);
6475 else
6476 seq_printf(m, "null-%d", i);
6477 seq_printf(m, "[ok:%d/",
6478 le32_to_cpu(ns->result[i][1]));
6479 seq_printf(m, "fail:%d/",
6480 le32_to_cpu(ns->result[i][0]));
6481 seq_printf(m, "on_time:%d/",
6482 le32_to_cpu(ns->result[i][2]));
6483 seq_printf(m, "retry:%d/",
6484 le32_to_cpu(ns->result[i][3]));
6485 seq_printf(m, "avg_t:%d.%03d/",
6486 le32_to_cpu(ns->avg_t[i]) / 1000,
6487 le32_to_cpu(ns->avg_t[i]) % 1000);
6488 seq_printf(m, "max_t:%d.%03d]",
6489 le32_to_cpu(ns->max_t[i]) / 1000,
6490 le32_to_cpu(ns->max_t[i]) % 1000);
6491 }
6492 } else {
6493 ns_v1 = &pfwinfo->rpt_fbtc_nullsta.finfo_v1;
6494
6495 seq_printf(m, " %-15s : ", "[null_sta]");
6496
6497 for (i = 0; i < 2; i++) {
6498 if (i != 0)
6499 seq_printf(m, ", null-%d", i);
6500 else
6501 seq_printf(m, "null-%d", i);
6502 seq_printf(m, "[Tx:%d/",
6503 le32_to_cpu(ns_v1->result[i][4]));
6504 seq_printf(m, "[ok:%d/",
6505 le32_to_cpu(ns_v1->result[i][1]));
6506 seq_printf(m, "fail:%d/",
6507 le32_to_cpu(ns_v1->result[i][0]));
6508 seq_printf(m, "on_time:%d/",
6509 le32_to_cpu(ns_v1->result[i][2]));
6510 seq_printf(m, "retry:%d/",
6511 le32_to_cpu(ns_v1->result[i][3]));
6512 seq_printf(m, "avg_t:%d.%03d/",
6513 le32_to_cpu(ns_v1->avg_t[i]) / 1000,
6514 le32_to_cpu(ns_v1->avg_t[i]) % 1000);
6515 seq_printf(m, "max_t:%d.%03d]",
6516 le32_to_cpu(ns_v1->max_t[i]) / 1000,
6517 le32_to_cpu(ns_v1->max_t[i]) % 1000);
6518 }
6519 }
6520 seq_puts(m, "\n");
6521}
6522
6523static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m)
6524{
6525 struct rtw89_btc *btc = &rtwdev->btc;
6526 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6527 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6528 struct rtw89_btc_fbtc_steps *pstep = NULL;
6529 u8 type, val, cnt = 0, state = 0;
6530 bool outloop = false;
6531 u16 i, diff_t, n_start = 0, n_stop = 0;
6532 u16 pos_old, pos_new;
6533
6534 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
6535 if (!pcinfo->valid)
6536 return;
6537
6538 pstep = &pfwinfo->rpt_fbtc_step.finfo;
6539 pos_old = le16_to_cpu(pstep->pos_old);
6540 pos_new = le16_to_cpu(pstep->pos_new);
6541
6542 if (pcinfo->req_fver != pstep->fver)
6543 return;
6544
6545 /* store step info by using ring instead of FIFO*/
6546 do {
6547 switch (state) {
6548 case 0:
6549 n_start = pos_old;
6550 if (pos_new >= pos_old)
6551 n_stop = pos_new;
6552 else
6553 n_stop = btc->ctrl.trace_step - 1;
6554
6555 state = 1;
6556 break;
6557 case 1:
6558 for (i = n_start; i <= n_stop; i++) {
6559 type = pstep->step[i].type;
6560 val = pstep->step[i].val;
6561 diff_t = le16_to_cpu(pstep->step[i].difft);
6562
6563 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
6564 continue;
6565
6566 if (cnt % 10 == 0)
6567 seq_printf(m, " %-15s : ", "[steps]");
6568
6569 seq_printf(m, "-> %s(%02d)(%02d)",
6570 (type == CXSTEP_SLOT ? "SLT" :
6571 "EVT"), (u32)val, diff_t);
6572 if (cnt % 10 == 9)
6573 seq_puts(m, "\n");
6574 cnt++;
6575 }
6576
6577 state = 2;
6578 break;
6579 case 2:
6580 if (pos_new < pos_old && n_start != 0) {
6581 n_start = 0;
6582 n_stop = pos_new;
6583 state = 1;
6584 } else {
6585 outloop = true;
6586 }
6587 break;
6588 }
6589 } while (!outloop);
6590}
6591
6592static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
6593{
6594 const struct rtw89_chip_info *chip = rtwdev->chip;
6595 struct rtw89_btc *btc = &rtwdev->btc;
6596
6597 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
6598 return;
6599
6600 _show_error(rtwdev, m);
6601 _show_fbtc_tdma(rtwdev, m);
6602 _show_fbtc_slots(rtwdev, m);
6603
6604 if (chip->chip_id == RTL8852A)
6605 _show_fbtc_cysta(rtwdev, m);
6606 else
6607 _show_fbtc_cysta_v1(rtwdev, m);
6608
6609 _show_fbtc_nullsta(rtwdev, m);
6610 _show_fbtc_step(rtwdev, m);
6611}
6612
6613static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
6614{
6615 const struct rtw89_chip_info *chip = rtwdev->chip;
6616 struct rtw89_mac_ax_gnt *gnt;
6617 u32 val, status;
6618
6619 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B) {
6620 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
6621 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
6622
6623 gnt = &gnt_cfg->band[0];
6624 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
6625 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
6626 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
6627 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
6628
6629 gnt = &gnt_cfg->band[1];
6630 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
6631 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
6632 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
6633 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
6634 } else if (chip->chip_id == RTL8852C) {
6635 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
6636 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
6637
6638 gnt = &gnt_cfg->band[0];
6639 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
6640 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
6641 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
6642 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
6643
6644 gnt = &gnt_cfg->band[1];
6645 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
6646 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
6647 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
6648 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
6649 } else {
6650 return;
6651 }
6652}
6653
6654static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
6655{
6656 const struct rtw89_chip_info *chip = rtwdev->chip;
6657 struct rtw89_btc *btc = &rtwdev->btc;
6658 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6659 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6660 struct rtw89_btc_fbtc_mreg_val *pmreg = NULL;
6661 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
6662 struct rtw89_btc_cx *cx = &btc->cx;
6663 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6664 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6665 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
6666 struct rtw89_mac_ax_gnt gnt;
6667 u8 i = 0, type = 0, cnt = 0;
6668 u32 val, offset;
6669
6670 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
6671 return;
6672
6673 seq_puts(m, "========== [HW Status] ==========\n");
6674
6675 seq_printf(m,
6676 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
6677 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
6678 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
6679 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
6680
6681 /* To avoid I/O if WL LPS or power-off */
6682 if (!wl->status.map.lps && !wl->status.map.rf_off) {
6683 if (chip->chip_id == RTL8852A)
6684 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
6685 else if (chip->chip_id == RTL8852C)
6686 btc->dm.pta_owner = 0;
6687
6688 _get_gnt(rtwdev, &gnt_cfg);
6689 gnt = gnt_cfg.band[0];
6690 seq_printf(m,
6691 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
6692 "[gnt_status]",
6693 chip->chip_id == RTL8852C ? "HW" :
6694 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
6695 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
6696 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
6697
6698 gnt = gnt_cfg.band[1];
6699 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
6700 gnt.gnt_wl_sw_en ? "SW" : "HW",
6701 gnt.gnt_wl,
6702 gnt.gnt_bt_sw_en ? "SW" : "HW",
6703 gnt.gnt_bt);
6704 }
6705 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
6706 if (!pcinfo->valid) {
6707 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6708 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
6709 __func__);
6710 return;
6711 }
6712
6713 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo;
6714 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6715 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
6716 __func__, pmreg->reg_num);
6717
6718 for (i = 0; i < pmreg->reg_num; i++) {
6719 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
6720 offset = le32_to_cpu(chip->mon_reg[i].offset);
6721 val = le32_to_cpu(pmreg->mreg_val[i]);
6722
6723 if (cnt % 6 == 0)
6724 seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
6725 "[reg]", (u32)type, offset, val);
6726 else
6727 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
6728 offset, val);
6729 if (cnt % 6 == 5)
6730 seq_puts(m, "\n");
6731 cnt++;
6732 }
6733
6734 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
6735 if (!pcinfo->valid) {
6736 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6737 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
6738 __func__);
6739 return;
6740 }
6741
6742 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
6743 if (!gdbg->en_map)
6744 return;
6745
6746 seq_printf(m, " %-15s : enable_map:0x%08x",
6747 "[gpio_dbg]", gdbg->en_map);
6748
6749 for (i = 0; i < BTC_DBG_MAX1; i++) {
6750 if (!(gdbg->en_map & BIT(i)))
6751 continue;
6752 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]);
6753 }
6754 seq_puts(m, "\n");
6755}
6756
6757static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m)
6758{
6759 struct rtw89_btc *btc = &rtwdev->btc;
6760 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6761 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6762 struct rtw89_btc_fbtc_rpt_ctrl *prptctrl = NULL;
6763 struct rtw89_btc_cx *cx = &btc->cx;
6764 struct rtw89_btc_dm *dm = &btc->dm;
6765 struct rtw89_btc_wl_info *wl = &cx->wl;
6766 struct rtw89_btc_bt_info *bt = &cx->bt;
6767 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
6768 u8 i;
6769
6770 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
6771 return;
6772
6773 seq_puts(m, "========== [Statistics] ==========\n");
6774
6775 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
6776 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
6777 prptctrl = &pfwinfo->rpt_ctrl.finfo;
6778
6779 seq_printf(m,
6780 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
6781 "[summary]", pfwinfo->cnt_h2c,
6782 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
6783 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
6784
6785 seq_printf(m,
6786 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
6787 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
6788 prptctrl->rpt_enable, dm->error.val);
6789
6790 if (dm->error.map.wl_fw_hang)
6791 seq_puts(m, " (WL FW Hang!!)");
6792 seq_puts(m, "\n");
6793 seq_printf(m,
6794 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
6795 "[mailbox]", prptctrl->mb_send_ok_cnt,
6796 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
6797
6798 seq_printf(m,
6799 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
6800 prptctrl->mb_a2dp_empty_cnt,
6801 prptctrl->mb_a2dp_flct_cnt,
6802 prptctrl->mb_a2dp_full_cnt);
6803
6804 seq_printf(m,
6805 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
6806 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
6807 cx->cnt_wl[BTC_WCNT_RFK_GO],
6808 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
6809 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
6810
6811 seq_printf(m,
6812 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
6813 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
6814 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
6815 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
6816 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
6817 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
6818
6819 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
6820 bt->rfk_info.map.timeout = 1;
6821 else
6822 bt->rfk_info.map.timeout = 0;
6823
6824 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
6825 } else {
6826 seq_printf(m,
6827 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
6828 "[summary]", pfwinfo->cnt_h2c,
6829 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
6830 pfwinfo->event[BTF_EVNT_RPT],
6831 btc->fwinfo.rpt_en_map);
6832 seq_puts(m, " (WL FW report invalid!!)\n");
6833 }
6834
6835 for (i = 0; i < BTC_NCNT_NUM; i++)
6836 cnt_sum += dm->cnt_notify[i];
6837
6838 seq_printf(m,
6839 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
6840 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
6841 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
6842
6843 seq_printf(m,
6844 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
6845 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
6846 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
6847 cnt[BTC_NCNT_WL_STA]);
6848
6849 seq_printf(m,
6850 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
6851 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
6852 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
6853 cnt[BTC_NCNT_SPECIAL_PACKET]);
6854
6855 seq_printf(m,
6856 "timer=%d, control=%d, customerize=%d\n",
6857 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
6858 cnt[BTC_NCNT_CUSTOMERIZE]);
6859}
6860
6861static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
6862{
6863 struct rtw89_btc *btc = &rtwdev->btc;
6864 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6865 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl;
6866 struct rtw89_btc_rpt_cmn_info *pcinfo;
6867 struct rtw89_btc_cx *cx = &btc->cx;
6868 struct rtw89_btc_dm *dm = &btc->dm;
6869 struct rtw89_btc_wl_info *wl = &cx->wl;
6870 struct rtw89_btc_bt_info *bt = &cx->bt;
6871 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
6872 u8 i;
6873
6874 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
6875 return;
6876
6877 seq_puts(m, "========== [Statistics] ==========\n");
6878
6879 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
6880 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
6881 prptctrl = &pfwinfo->rpt_ctrl.finfo_v1;
6882
6883 seq_printf(m,
6884 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
6885 "[summary]", pfwinfo->cnt_h2c,
6886 pfwinfo->cnt_h2c_fail,
6887 le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
6888 pfwinfo->cnt_c2h,
6889 le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
6890
6891 seq_printf(m,
6892 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
6893 pfwinfo->event[BTF_EVNT_RPT],
6894 le32_to_cpu(prptctrl->rpt_info.cnt),
6895 le32_to_cpu(prptctrl->rpt_info.en),
6896 dm->error.val);
6897
6898 if (dm->error.map.wl_fw_hang)
6899 seq_puts(m, " (WL FW Hang!!)");
6900 seq_puts(m, "\n");
6901 seq_printf(m,
6902 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
6903 "[mailbox]",
6904 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
6905 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
6906 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
6907
6908 seq_printf(m,
6909 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
6910 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
6911 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
6912 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
6913 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
6914 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
6915
6916 seq_printf(m,
6917 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
6918 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
6919 cx->cnt_wl[BTC_WCNT_RFK_GO],
6920 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
6921 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
6922
6923 seq_printf(m,
6924 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
6925 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
6926 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
6927 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
6928 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
6929 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
6930
6931 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
6932 bt->rfk_info.map.timeout = 1;
6933 else
6934 bt->rfk_info.map.timeout = 0;
6935
6936 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
6937 } else {
6938 seq_printf(m,
6939 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
6940 "[summary]", pfwinfo->cnt_h2c,
6941 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
6942 pfwinfo->event[BTF_EVNT_RPT],
6943 btc->fwinfo.rpt_en_map);
6944 seq_puts(m, " (WL FW report invalid!!)\n");
6945 }
6946
6947 for (i = 0; i < BTC_NCNT_NUM; i++)
6948 cnt_sum += dm->cnt_notify[i];
6949
6950 seq_printf(m,
6951 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
6952 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
6953 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
6954
6955 seq_printf(m,
6956 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
6957 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
6958 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
6959 cnt[BTC_NCNT_WL_STA]);
6960
6961 seq_printf(m,
6962 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
6963 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
6964 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
6965 cnt[BTC_NCNT_SPECIAL_PACKET]);
6966
6967 seq_printf(m,
6968 "timer=%d, control=%d, customerize=%d\n",
6969 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
6970 cnt[BTC_NCNT_CUSTOMERIZE]);
6971}
6972
6973void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
6974{
6975 const struct rtw89_chip_info *chip = rtwdev->chip;
6976 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
6977 struct rtw89_btc *btc = &rtwdev->btc;
6978 struct rtw89_btc_cx *cx = &btc->cx;
6979 struct rtw89_btc_bt_info *bt = &cx->bt;
6980
6981 seq_puts(m, "=========================================\n");
6982 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n",
6983 fw_suit->major_ver, fw_suit->minor_ver,
6984 fw_suit->sub_ver, fw_suit->sub_idex);
6985 seq_printf(m, "manual %d\n", btc->ctrl.manual);
6986
6987 seq_puts(m, "=========================================\n");
6988
6989 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
6990 "[bt_info]",
6991 bt->raw_info[2], bt->raw_info[3],
6992 bt->raw_info[4], bt->raw_info[5],
6993 bt->raw_info[6], bt->raw_info[7],
6994 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
6995 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
6996 cx->cnt_bt[BTC_BCNT_INFOSAME]);
6997
6998 seq_puts(m, "\n=========================================\n");
6999
7000 _show_cx_info(rtwdev, m);
7001 _show_wl_info(rtwdev, m);
7002 _show_bt_info(rtwdev, m);
7003 _show_dm_info(rtwdev, m);
7004 _show_fw_dm_msg(rtwdev, m);
7005 _show_mreg(rtwdev, m);
7006 if (chip->chip_id == RTL8852A)
7007 _show_summary(rtwdev, m);
7008 else
7009 _show_summary_v1(rtwdev, m);
7010}