xref: /linux/drivers/net/wireless/realtek/rtw89/phy.c (revision 11a7351f30b98c1ab6ecc9d7f474f82823208931)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020  Realtek Corporation
3  */
4 
5 #include "acpi.h"
6 #include "chan.h"
7 #include "coex.h"
8 #include "debug.h"
9 #include "fw.h"
10 #include "mac.h"
11 #include "phy.h"
12 #include "ps.h"
13 #include "reg.h"
14 #include "sar.h"
15 #include "txrx.h"
16 #include "util.h"
17 
18 static u32 rtw89_phy0_phy1_offset(struct rtw89_dev *rtwdev, u32 addr)
19 {
20 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
21 
22 	return phy->phy0_phy1_offset(rtwdev, addr);
23 }
24 
25 static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev,
26 			     const struct rtw89_ra_report *report)
27 {
28 	u32 bit_rate = report->bit_rate;
29 
30 	/* lower than ofdm, do not aggregate */
31 	if (bit_rate < 550)
32 		return 1;
33 
34 	/* avoid AMSDU for legacy rate */
35 	if (report->might_fallback_legacy)
36 		return 1;
37 
38 	/* lower than 20M vht 2ss mcs8, make it small */
39 	if (bit_rate < 1800)
40 		return 1200;
41 
42 	/* lower than 40M vht 2ss mcs9, make it medium */
43 	if (bit_rate < 4000)
44 		return 2600;
45 
46 	/* not yet 80M vht 2ss mcs8/9, make it twice regular packet size */
47 	if (bit_rate < 7000)
48 		return 3500;
49 
50 	return rtwdev->chip->max_amsdu_limit;
51 }
52 
53 static u64 get_mcs_ra_mask(u16 mcs_map, u8 highest_mcs, u8 gap)
54 {
55 	u64 ra_mask = 0;
56 	u8 mcs_cap;
57 	int i, nss;
58 
59 	for (i = 0, nss = 12; i < 4; i++, mcs_map >>= 2, nss += 12) {
60 		mcs_cap = mcs_map & 0x3;
61 		switch (mcs_cap) {
62 		case 2:
63 			ra_mask |= GENMASK_ULL(highest_mcs, 0) << nss;
64 			break;
65 		case 1:
66 			ra_mask |= GENMASK_ULL(highest_mcs - gap, 0) << nss;
67 			break;
68 		case 0:
69 			ra_mask |= GENMASK_ULL(highest_mcs - gap * 2, 0) << nss;
70 			break;
71 		default:
72 			break;
73 		}
74 	}
75 
76 	return ra_mask;
77 }
78 
79 static u64 get_he_ra_mask(struct ieee80211_link_sta *link_sta)
80 {
81 	struct ieee80211_sta_he_cap cap = link_sta->he_cap;
82 	u16 mcs_map;
83 
84 	switch (link_sta->bandwidth) {
85 	case IEEE80211_STA_RX_BW_160:
86 		if (cap.he_cap_elem.phy_cap_info[0] &
87 		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
88 			mcs_map = le16_to_cpu(cap.he_mcs_nss_supp.rx_mcs_80p80);
89 		else
90 			mcs_map = le16_to_cpu(cap.he_mcs_nss_supp.rx_mcs_160);
91 		break;
92 	default:
93 		mcs_map = le16_to_cpu(cap.he_mcs_nss_supp.rx_mcs_80);
94 	}
95 
96 	/* MCS11, MCS9, MCS7 */
97 	return get_mcs_ra_mask(mcs_map, 11, 2);
98 }
99 
100 static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss)
101 {
102 	u64 nss_mcs_shift;
103 	u64 nss_mcs_val;
104 	u64 mask = 0;
105 	int i, j;
106 	u8 nss;
107 
108 	for (i = 0; i < n_nss; i++) {
109 		nss = u8_get_bits(max_nss[i], IEEE80211_EHT_MCS_NSS_RX);
110 		if (!nss)
111 			continue;
112 
113 		nss_mcs_val = GENMASK_ULL(start_mcs + i * 2, 0);
114 
115 		for (j = 0, nss_mcs_shift = 12; j < nss; j++, nss_mcs_shift += 16)
116 			mask |= nss_mcs_val << nss_mcs_shift;
117 	}
118 
119 	return mask;
120 }
121 
122 static u64 get_eht_ra_mask(struct rtw89_vif_link *rtwvif_link,
123 			   struct ieee80211_link_sta *link_sta)
124 {
125 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
126 	struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz;
127 	struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap;
128 	struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss;
129 	u8 *he_phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info;
130 
131 	switch (link_sta->bandwidth) {
132 	case IEEE80211_STA_RX_BW_320:
133 		mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320;
134 		/* MCS 9, 11, 13 */
135 		return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
136 	case IEEE80211_STA_RX_BW_160:
137 		mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._160;
138 		/* MCS 9, 11, 13 */
139 		return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
140 	case IEEE80211_STA_RX_BW_20:
141 		if (vif->type == NL80211_IFTYPE_AP &&
142 		    !(he_phy_cap[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
143 			mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz;
144 			/* MCS 7, 9, 11, 13 */
145 			return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4);
146 		}
147 		fallthrough;
148 	case IEEE80211_STA_RX_BW_80:
149 	default:
150 		mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._80;
151 		/* MCS 9, 11, 13 */
152 		return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
153 	}
154 }
155 
156 #define RA_FLOOR_TABLE_SIZE	7
157 #define RA_FLOOR_UP_GAP		3
158 static u64 rtw89_phy_ra_mask_rssi(struct rtw89_dev *rtwdev, u8 rssi,
159 				  u8 ratr_state)
160 {
161 	u8 rssi_lv_t[RA_FLOOR_TABLE_SIZE] = {30, 44, 48, 52, 56, 60, 100};
162 	u8 rssi_lv = 0;
163 	u8 i;
164 
165 	rssi >>= 1;
166 	for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) {
167 		if (i >= ratr_state)
168 			rssi_lv_t[i] += RA_FLOOR_UP_GAP;
169 		if (rssi < rssi_lv_t[i]) {
170 			rssi_lv = i;
171 			break;
172 		}
173 	}
174 	if (rssi_lv == 0)
175 		return 0xffffffffffffffffULL;
176 	else if (rssi_lv == 1)
177 		return 0xfffffffffffffff0ULL;
178 	else if (rssi_lv == 2)
179 		return 0xffffffffffffefe0ULL;
180 	else if (rssi_lv == 3)
181 		return 0xffffffffffffcfc0ULL;
182 	else if (rssi_lv == 4)
183 		return 0xffffffffffff8f80ULL;
184 	else if (rssi_lv >= 5)
185 		return 0xffffffffffff0f00ULL;
186 
187 	return 0xffffffffffffffffULL;
188 }
189 
190 static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak)
191 {
192 	if ((ra_mask & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES)) == 0)
193 		ra_mask |= (ra_mask_bak & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES));
194 
195 	if (ra_mask == 0)
196 		ra_mask |= (ra_mask_bak & (RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES));
197 
198 	return ra_mask;
199 }
200 
201 static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev,
202 				 struct rtw89_sta_link *rtwsta_link,
203 				 struct ieee80211_link_sta *link_sta,
204 				 const struct rtw89_chan *chan)
205 {
206 	struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask;
207 	enum nl80211_band band;
208 	u64 cfg_mask;
209 
210 	if (!rtwsta_link->use_cfg_mask)
211 		return -1;
212 
213 	switch (chan->band_type) {
214 	case RTW89_BAND_2G:
215 		band = NL80211_BAND_2GHZ;
216 		cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_2GHZ].legacy,
217 					   RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES);
218 		break;
219 	case RTW89_BAND_5G:
220 		band = NL80211_BAND_5GHZ;
221 		cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_5GHZ].legacy,
222 					   RA_MASK_OFDM_RATES);
223 		break;
224 	case RTW89_BAND_6G:
225 		band = NL80211_BAND_6GHZ;
226 		cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_6GHZ].legacy,
227 					   RA_MASK_OFDM_RATES);
228 		break;
229 	default:
230 		rtw89_warn(rtwdev, "unhandled band type %d\n", chan->band_type);
231 		return -1;
232 	}
233 
234 	if (link_sta->eht_cap.has_eht) {
235 		cfg_mask |= u64_encode_bits(mask->control[band].eht_mcs[0],
236 					    RA_MASK_EHT_1SS_RATES);
237 		cfg_mask |= u64_encode_bits(mask->control[band].eht_mcs[1],
238 					    RA_MASK_EHT_2SS_RATES);
239 	} else if (link_sta->he_cap.has_he) {
240 		cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[0],
241 					    RA_MASK_HE_1SS_RATES);
242 		cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[1],
243 					    RA_MASK_HE_2SS_RATES);
244 	} else if (link_sta->vht_cap.vht_supported) {
245 		cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0],
246 					    RA_MASK_VHT_1SS_RATES);
247 		cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1],
248 					    RA_MASK_VHT_2SS_RATES);
249 	} else if (link_sta->ht_cap.ht_supported) {
250 		cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0],
251 					    RA_MASK_HT_1SS_RATES);
252 		cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1],
253 					    RA_MASK_HT_2SS_RATES);
254 	}
255 
256 	return cfg_mask;
257 }
258 
259 static const u64
260 rtw89_ra_mask_ht_rates[4] = {RA_MASK_HT_1SS_RATES, RA_MASK_HT_2SS_RATES,
261 			     RA_MASK_HT_3SS_RATES, RA_MASK_HT_4SS_RATES};
262 static const u64
263 rtw89_ra_mask_vht_rates[4] = {RA_MASK_VHT_1SS_RATES, RA_MASK_VHT_2SS_RATES,
264 			      RA_MASK_VHT_3SS_RATES, RA_MASK_VHT_4SS_RATES};
265 static const u64
266 rtw89_ra_mask_he_rates[4] = {RA_MASK_HE_1SS_RATES, RA_MASK_HE_2SS_RATES,
267 			     RA_MASK_HE_3SS_RATES, RA_MASK_HE_4SS_RATES};
268 static const u64
269 rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES,
270 			      RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES};
271 static const u64
272 rtw89_ra_mask_eht_mcs0_11[4] = {RA_MASK_EHT_1SS_MCS0_11, RA_MASK_EHT_2SS_MCS0_11,
273 				RA_MASK_EHT_3SS_MCS0_11, RA_MASK_EHT_4SS_MCS0_11};
274 
275 static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
276 				struct rtw89_sta_link *rtwsta_link,
277 				struct ieee80211_link_sta *link_sta,
278 				const struct rtw89_chan *chan,
279 				bool *fix_giltf_en, u8 *fix_giltf)
280 {
281 	struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask;
282 	u8 band = chan->band_type;
283 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
284 	u8 ltf, gi;
285 
286 	*fix_giltf_en = true;
287 
288 	if (rtwdev->chip->chip_id == RTL8852C &&
289 	    chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
290 	    rtw89_sta_link_has_su_mu_4xhe08(link_sta))
291 		*fix_giltf = RTW89_GILTF_SGI_4XHE08;
292 	else
293 		*fix_giltf = RTW89_GILTF_2XHE08;
294 
295 	if (!rtwsta_link->use_cfg_mask)
296 		return;
297 
298 	if (link_sta->eht_cap.has_eht) {
299 		ltf = mask->control[nl_band].eht_ltf;
300 		gi = mask->control[nl_band].eht_gi;
301 	} else if (link_sta->he_cap.has_he) {
302 		ltf = mask->control[nl_band].he_ltf;
303 		gi = mask->control[nl_band].he_gi;
304 	} else {
305 		return;
306 	}
307 
308 	if (ltf == 2 && gi == 2)
309 		*fix_giltf = RTW89_GILTF_LGI_4XHE32;
310 	else if (ltf == 2 && gi == 0)
311 		*fix_giltf = RTW89_GILTF_SGI_4XHE08;
312 	else if (ltf == 1 && gi == 1)
313 		*fix_giltf = RTW89_GILTF_2XHE16;
314 	else if (ltf == 1 && gi == 0)
315 		*fix_giltf = RTW89_GILTF_2XHE08;
316 	else if (ltf == 0 && gi == 1)
317 		*fix_giltf = RTW89_GILTF_1XHE16;
318 	else if (ltf == 0 && gi == 0)
319 		*fix_giltf = RTW89_GILTF_1XHE08;
320 }
321 
322 static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
323 				    struct rtw89_vif_link *rtwvif_link,
324 				    struct rtw89_sta_link *rtwsta_link,
325 				    struct ieee80211_link_sta *link_sta,
326 				    bool p2p, bool csi)
327 {
328 	struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern;
329 	struct rtw89_ra_info *ra = &rtwsta_link->ra;
330 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
331 						       rtwvif_link->chanctx_idx);
332 	const u64 *high_rate_masks = rtw89_ra_mask_ht_rates;
333 	u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi);
334 	u64 ra_mask = 0;
335 	u64 ra_mask_bak;
336 	u8 mode = 0;
337 	u8 csi_mode = RTW89_RA_RPT_MODE_LEGACY;
338 	u8 bw_mode = 0;
339 	u8 stbc_en = 0;
340 	u8 ldpc_en = 0;
341 	u8 fix_giltf = 0;
342 	u8 i;
343 	bool sgi = false;
344 	bool fix_giltf_en = false;
345 
346 	memset(ra, 0, sizeof(*ra));
347 	/* Set the ra mask from sta's capability */
348 	if (link_sta->eht_cap.has_eht) {
349 		mode |= RTW89_RA_MODE_EHT;
350 		ra_mask |= get_eht_ra_mask(rtwvif_link, link_sta);
351 
352 		if (rtwdev->hal.no_mcs_12_13)
353 			high_rate_masks = rtw89_ra_mask_eht_mcs0_11;
354 		else
355 			high_rate_masks = rtw89_ra_mask_eht_rates;
356 
357 		rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, link_sta,
358 				    chan, &fix_giltf_en, &fix_giltf);
359 	} else if (link_sta->he_cap.has_he) {
360 		mode |= RTW89_RA_MODE_HE;
361 		csi_mode = RTW89_RA_RPT_MODE_HE;
362 		ra_mask |= get_he_ra_mask(link_sta);
363 		high_rate_masks = rtw89_ra_mask_he_rates;
364 		if (link_sta->he_cap.he_cap_elem.phy_cap_info[2] &
365 		    IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
366 			stbc_en = 1;
367 		if (link_sta->he_cap.he_cap_elem.phy_cap_info[1] &
368 		    IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
369 			ldpc_en = 1;
370 		rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, link_sta,
371 				    chan, &fix_giltf_en, &fix_giltf);
372 	} else if (link_sta->vht_cap.vht_supported) {
373 		u16 mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map);
374 
375 		mode |= RTW89_RA_MODE_VHT;
376 		csi_mode = RTW89_RA_RPT_MODE_VHT;
377 		/* MCS9 (non-20MHz), MCS8, MCS7 */
378 		if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
379 			ra_mask |= get_mcs_ra_mask(mcs_map, 8, 1);
380 		else
381 			ra_mask |= get_mcs_ra_mask(mcs_map, 9, 1);
382 		high_rate_masks = rtw89_ra_mask_vht_rates;
383 		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
384 			stbc_en = 1;
385 		if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
386 			ldpc_en = 1;
387 	} else if (link_sta->ht_cap.ht_supported) {
388 		mode |= RTW89_RA_MODE_HT;
389 		csi_mode = RTW89_RA_RPT_MODE_HT;
390 		ra_mask |= ((u64)link_sta->ht_cap.mcs.rx_mask[3] << 48) |
391 			   ((u64)link_sta->ht_cap.mcs.rx_mask[2] << 36) |
392 			   ((u64)link_sta->ht_cap.mcs.rx_mask[1] << 24) |
393 			   ((u64)link_sta->ht_cap.mcs.rx_mask[0] << 12);
394 		high_rate_masks = rtw89_ra_mask_ht_rates;
395 		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
396 			stbc_en = 1;
397 		if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
398 			ldpc_en = 1;
399 	}
400 
401 	switch (chan->band_type) {
402 	case RTW89_BAND_2G:
403 		ra_mask |= link_sta->supp_rates[NL80211_BAND_2GHZ];
404 		if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xf)
405 			mode |= RTW89_RA_MODE_CCK;
406 		if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xff0)
407 			mode |= RTW89_RA_MODE_OFDM;
408 		break;
409 	case RTW89_BAND_5G:
410 		ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_5GHZ] << 4;
411 		mode |= RTW89_RA_MODE_OFDM;
412 		break;
413 	case RTW89_BAND_6G:
414 		ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_6GHZ] << 4;
415 		mode |= RTW89_RA_MODE_OFDM;
416 		break;
417 	default:
418 		rtw89_err(rtwdev, "Unknown band type\n");
419 		break;
420 	}
421 
422 	ra_mask_bak = ra_mask;
423 
424 	if (mode >= RTW89_RA_MODE_HT) {
425 		u64 mask = 0;
426 		for (i = 0; i < rtwdev->hal.tx_nss; i++)
427 			mask |= high_rate_masks[i];
428 		if (mode & RTW89_RA_MODE_OFDM)
429 			mask |= RA_MASK_SUBOFDM_RATES;
430 		if (mode & RTW89_RA_MODE_CCK)
431 			mask |= RA_MASK_SUBCCK_RATES;
432 		ra_mask &= mask;
433 	} else if (mode & RTW89_RA_MODE_OFDM) {
434 		ra_mask &= (RA_MASK_OFDM_RATES | RA_MASK_SUBCCK_RATES);
435 	}
436 
437 	if (mode != RTW89_RA_MODE_CCK)
438 		ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0);
439 
440 	ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak);
441 	ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan);
442 
443 	switch (link_sta->bandwidth) {
444 	case IEEE80211_STA_RX_BW_160:
445 		bw_mode = RTW89_CHANNEL_WIDTH_160;
446 		sgi = link_sta->vht_cap.vht_supported &&
447 		      (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160);
448 		break;
449 	case IEEE80211_STA_RX_BW_80:
450 		bw_mode = RTW89_CHANNEL_WIDTH_80;
451 		sgi = link_sta->vht_cap.vht_supported &&
452 		      (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
453 		break;
454 	case IEEE80211_STA_RX_BW_40:
455 		bw_mode = RTW89_CHANNEL_WIDTH_40;
456 		sgi = link_sta->ht_cap.ht_supported &&
457 		      (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
458 		break;
459 	default:
460 		bw_mode = RTW89_CHANNEL_WIDTH_20;
461 		sgi = link_sta->ht_cap.ht_supported &&
462 		      (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
463 		break;
464 	}
465 
466 	if (link_sta->he_cap.he_cap_elem.phy_cap_info[3] &
467 	    IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM)
468 		ra->dcm_cap = 1;
469 
470 	if (rate_pattern->enable && !p2p) {
471 		ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan);
472 		ra_mask &= rate_pattern->ra_mask;
473 		mode = rate_pattern->ra_mode;
474 	}
475 
476 	ra->bw_cap = bw_mode;
477 	ra->er_cap = rtwsta_link->er_cap;
478 	ra->mode_ctrl = mode;
479 	ra->macid = rtwsta_link->mac_id;
480 	ra->stbc_cap = stbc_en;
481 	ra->ldpc_cap = ldpc_en;
482 	ra->ss_num = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1;
483 	ra->en_sgi = sgi;
484 	ra->ra_mask = ra_mask;
485 	ra->fix_giltf_en = fix_giltf_en;
486 	ra->fix_giltf = fix_giltf;
487 	ra->partial_bw_er = link_sta->he_cap.has_he ?
488 			    !!(link_sta->he_cap.he_cap_elem.phy_cap_info[6] &
489 			       IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE) : 0;
490 	ra->band = chan->band_type;
491 
492 	if (!csi)
493 		return;
494 
495 	ra->fixed_csi_rate_en = false;
496 	ra->ra_csi_rate_en = true;
497 	ra->cr_tbl_sel = false;
498 	ra->band_num = rtwvif_link->phy_idx;
499 	ra->csi_bw = bw_mode;
500 	ra->csi_gi_ltf = RTW89_GILTF_LGI_4XHE32;
501 	ra->csi_mcs_ss_idx = 5;
502 	ra->csi_mode = csi_mode;
503 }
504 
505 void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
506 				  struct rtw89_sta_link *rtwsta_link,
507 				  u32 changed)
508 {
509 	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
510 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
511 	struct rtw89_ra_info *ra = &rtwsta_link->ra;
512 	struct ieee80211_link_sta *link_sta;
513 
514 	rcu_read_lock();
515 
516 	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
517 	rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link,
518 				link_sta, vif->p2p, false);
519 
520 	rcu_read_unlock();
521 
522 	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED)
523 		ra->upd_mask = 1;
524 	if (changed & (IEEE80211_RC_BW_CHANGED | IEEE80211_RC_NSS_CHANGED))
525 		ra->upd_bw_nss_mask = 1;
526 
527 	rtw89_debug(rtwdev, RTW89_DBG_RA,
528 		    "ra update: macid = %d, bw = %d, nss = %d, gi = %d %d",
529 		    ra->macid,
530 		    ra->bw_cap,
531 		    ra->ss_num,
532 		    ra->en_sgi,
533 		    ra->giltf);
534 
535 	rtw89_fw_h2c_ra(rtwdev, ra, false);
536 }
537 
538 void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
539 			     u32 changed)
540 {
541 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
542 	struct rtw89_sta_link *rtwsta_link;
543 	unsigned int link_id;
544 
545 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
546 		rtw89_phy_ra_update_sta_link(rtwdev, rtwsta_link, changed);
547 }
548 
549 static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next,
550 				 u16 rate_base, u64 ra_mask, u8 ra_mode,
551 				 u32 rate_ctrl, u32 ctrl_skip, bool force)
552 {
553 	u8 n, c;
554 
555 	if (rate_ctrl == ctrl_skip)
556 		return true;
557 
558 	n = hweight32(rate_ctrl);
559 	if (n == 0)
560 		return true;
561 
562 	if (force && n != 1)
563 		return false;
564 
565 	if (next->enable)
566 		return false;
567 
568 	c = __fls(rate_ctrl);
569 	next->rate = rate_base + c;
570 	next->ra_mode = ra_mode;
571 	next->ra_mask = ra_mask;
572 	next->enable = true;
573 
574 	return true;
575 }
576 
577 enum __rtw89_hw_rate_invalid_bases {
578 	/* no EHT rate for ax chip */
579 	RTW89_HW_RATE_EHT_NSS1_MCS0 = RTW89_HW_RATE_INVAL,
580 	RTW89_HW_RATE_EHT_NSS2_MCS0 = RTW89_HW_RATE_INVAL,
581 	RTW89_HW_RATE_EHT_NSS3_MCS0 = RTW89_HW_RATE_INVAL,
582 	RTW89_HW_RATE_EHT_NSS4_MCS0 = RTW89_HW_RATE_INVAL,
583 };
584 
585 #define RTW89_HW_RATE_BY_CHIP_GEN(rate) \
586 	{ \
587 		[RTW89_CHIP_AX] = RTW89_HW_RATE_ ## rate, \
588 		[RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \
589 	}
590 
591 static
592 void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
593 				  struct rtw89_vif_link *rtwvif_link,
594 				  const struct cfg80211_bitrate_mask *mask)
595 {
596 	struct ieee80211_supported_band *sband;
597 	struct rtw89_phy_rate_pattern next_pattern = {0};
598 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
599 						       rtwvif_link->chanctx_idx);
600 	static const u16 hw_rate_eht[][RTW89_CHIP_GEN_NUM] = {
601 		RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS1_MCS0),
602 		RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS2_MCS0),
603 		RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS3_MCS0),
604 		RTW89_HW_RATE_BY_CHIP_GEN(EHT_NSS4_MCS0),
605 	};
606 	static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = {
607 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0),
608 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0),
609 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS3_MCS0),
610 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS4_MCS0),
611 	};
612 	static const u16 hw_rate_vht[][RTW89_CHIP_GEN_NUM] = {
613 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS1_MCS0),
614 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS2_MCS0),
615 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS3_MCS0),
616 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS4_MCS0),
617 	};
618 	static const u16 hw_rate_ht[][RTW89_CHIP_GEN_NUM] = {
619 		RTW89_HW_RATE_BY_CHIP_GEN(MCS0),
620 		RTW89_HW_RATE_BY_CHIP_GEN(MCS8),
621 		RTW89_HW_RATE_BY_CHIP_GEN(MCS16),
622 		RTW89_HW_RATE_BY_CHIP_GEN(MCS24),
623 	};
624 	u8 band = chan->band_type;
625 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
626 	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
627 	u8 tx_nss = rtwdev->hal.tx_nss;
628 	u8 i;
629 
630 	if (chip_gen == RTW89_CHIP_AX)
631 		goto rs_11ax;
632 
633 	for (i = 0; i < tx_nss; i++)
634 		if (!__check_rate_pattern(&next_pattern, hw_rate_eht[i][chip_gen],
635 					  RA_MASK_EHT_RATES, RTW89_RA_MODE_EHT,
636 					  mask->control[nl_band].eht_mcs[i],
637 					  0, true))
638 			goto out;
639 
640 rs_11ax:
641 	for (i = 0; i < tx_nss; i++)
642 		if (!__check_rate_pattern(&next_pattern, hw_rate_he[i][chip_gen],
643 					  RA_MASK_HE_RATES, RTW89_RA_MODE_HE,
644 					  mask->control[nl_band].he_mcs[i],
645 					  0, true))
646 			goto out;
647 
648 	for (i = 0; i < tx_nss; i++)
649 		if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i][chip_gen],
650 					  RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT,
651 					  mask->control[nl_band].vht_mcs[i],
652 					  0, true))
653 			goto out;
654 
655 	for (i = 0; i < tx_nss; i++)
656 		if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i][chip_gen],
657 					  RA_MASK_HT_RATES, RTW89_RA_MODE_HT,
658 					  mask->control[nl_band].ht_mcs[i],
659 					  0, true))
660 			goto out;
661 
662 	/* legacy cannot be empty for nl80211_parse_tx_bitrate_mask, and
663 	 * require at least one basic rate for ieee80211_set_bitrate_mask,
664 	 * so the decision just depends on if all bitrates are set or not.
665 	 */
666 	sband = rtwdev->hw->wiphy->bands[nl_band];
667 	if (band == RTW89_BAND_2G) {
668 		if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_CCK1,
669 					  RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES,
670 					  RTW89_RA_MODE_CCK | RTW89_RA_MODE_OFDM,
671 					  mask->control[nl_band].legacy,
672 					  BIT(sband->n_bitrates) - 1, false))
673 			goto out;
674 	} else {
675 		if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_OFDM6,
676 					  RA_MASK_OFDM_RATES, RTW89_RA_MODE_OFDM,
677 					  mask->control[nl_band].legacy,
678 					  BIT(sband->n_bitrates) - 1, false))
679 			goto out;
680 	}
681 
682 	if (!next_pattern.enable)
683 		goto out;
684 
685 	if (unlikely(next_pattern.rate >= RTW89_HW_RATE_INVAL)) {
686 		rtw89_debug(rtwdev, RTW89_DBG_RA,
687 			    "pattern invalid target: chip_gen %d, mode 0x%x\n",
688 			    chip_gen, next_pattern.ra_mode);
689 		goto out;
690 	}
691 
692 	rtwvif_link->rate_pattern = next_pattern;
693 	rtw89_debug(rtwdev, RTW89_DBG_RA,
694 		    "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n",
695 		    next_pattern.rate,
696 		    next_pattern.ra_mask,
697 		    next_pattern.ra_mode);
698 	return;
699 
700 out:
701 	rtwvif_link->rate_pattern.enable = false;
702 	rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n");
703 }
704 
705 void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
706 				struct ieee80211_vif *vif,
707 				const struct cfg80211_bitrate_mask *mask)
708 {
709 	struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
710 	struct rtw89_vif_link *rtwvif_link;
711 	unsigned int link_id;
712 
713 	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
714 		__rtw89_phy_rate_pattern_vif(rtwdev, rtwvif_link, mask);
715 }
716 
717 static void rtw89_phy_ra_update_sta_iter(void *data, struct ieee80211_sta *sta)
718 {
719 	struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
720 
721 	rtw89_phy_ra_update_sta(rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
722 }
723 
724 void rtw89_phy_ra_update(struct rtw89_dev *rtwdev)
725 {
726 	ieee80211_iterate_stations_atomic(rtwdev->hw,
727 					  rtw89_phy_ra_update_sta_iter,
728 					  rtwdev);
729 }
730 
731 void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link)
732 {
733 	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
734 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
735 	struct rtw89_ra_info *ra = &rtwsta_link->ra;
736 	u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
737 	struct ieee80211_link_sta *link_sta;
738 	bool csi;
739 
740 	rcu_read_lock();
741 
742 	link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
743 	csi = rtw89_sta_has_beamformer_cap(link_sta);
744 
745 	rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link,
746 				link_sta, vif->p2p, csi);
747 
748 	rcu_read_unlock();
749 
750 	if (rssi > 40)
751 		ra->init_rate_lv = 1;
752 	else if (rssi > 20)
753 		ra->init_rate_lv = 2;
754 	else if (rssi > 1)
755 		ra->init_rate_lv = 3;
756 	else
757 		ra->init_rate_lv = 0;
758 	ra->upd_all = 1;
759 	rtw89_debug(rtwdev, RTW89_DBG_RA,
760 		    "ra assoc: macid = %d, mode = %d, bw = %d, nss = %d, lv = %d",
761 		    ra->macid,
762 		    ra->mode_ctrl,
763 		    ra->bw_cap,
764 		    ra->ss_num,
765 		    ra->init_rate_lv);
766 	rtw89_debug(rtwdev, RTW89_DBG_RA,
767 		    "ra assoc: dcm = %d, er = %d, ldpc = %d, stbc = %d, gi = %d %d",
768 		    ra->dcm_cap,
769 		    ra->er_cap,
770 		    ra->ldpc_cap,
771 		    ra->stbc_cap,
772 		    ra->en_sgi,
773 		    ra->giltf);
774 
775 	rtw89_fw_h2c_ra(rtwdev, ra, csi);
776 }
777 
778 void rtw89_phy_ra_recalc_agg_limit(struct rtw89_dev *rtwdev)
779 {
780 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
781 	const struct rtw89_reg_def *ra_limit = &mac->ra_agg_limit;
782 	struct ieee80211_sta *sta;
783 	struct rtw89_sta *rtwsta;
784 	u16 agg_num = U16_MAX;
785 	u8 tid;
786 
787 	for_each_station(sta, rtwdev->hw) {
788 		rtwsta = sta_to_rtwsta(sta);
789 
790 		for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS)
791 			agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num);
792 	}
793 
794 	if (agg_num == U16_MAX)
795 		agg_num = 0x3F;
796 	else
797 		agg_num = clamp(agg_num, 1, 256) - 1;
798 
799 	rtw89_write32_idx(rtwdev, ra_limit->addr, ra_limit->mask, agg_num, RTW89_MAC_0);
800 	if (!rtwdev->dbcc_en)
801 		return;
802 	rtw89_write32_idx(rtwdev, ra_limit->addr, ra_limit->mask, agg_num, RTW89_MAC_1);
803 }
804 
805 u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
806 		      const struct rtw89_chan *chan,
807 		      enum rtw89_bandwidth dbw)
808 {
809 	enum rtw89_bandwidth cbw = chan->band_width;
810 	u8 pri_ch = chan->primary_channel;
811 	u8 central_ch = chan->channel;
812 	u8 txsc_idx = 0;
813 	u8 tmp = 0;
814 
815 	if (cbw == dbw || cbw == RTW89_CHANNEL_WIDTH_20)
816 		return txsc_idx;
817 
818 	switch (cbw) {
819 	case RTW89_CHANNEL_WIDTH_40:
820 		txsc_idx = pri_ch > central_ch ? 1 : 2;
821 		break;
822 	case RTW89_CHANNEL_WIDTH_80:
823 		if (dbw == RTW89_CHANNEL_WIDTH_20) {
824 			if (pri_ch > central_ch)
825 				txsc_idx = (pri_ch - central_ch) >> 1;
826 			else
827 				txsc_idx = ((central_ch - pri_ch) >> 1) + 1;
828 		} else {
829 			txsc_idx = pri_ch > central_ch ? 9 : 10;
830 		}
831 		break;
832 	case RTW89_CHANNEL_WIDTH_160:
833 		if (pri_ch > central_ch)
834 			tmp = (pri_ch - central_ch) >> 1;
835 		else
836 			tmp = ((central_ch - pri_ch) >> 1) + 1;
837 
838 		if (dbw == RTW89_CHANNEL_WIDTH_20) {
839 			txsc_idx = tmp;
840 		} else if (dbw == RTW89_CHANNEL_WIDTH_40) {
841 			if (tmp == 1 || tmp == 3)
842 				txsc_idx = 9;
843 			else if (tmp == 5 || tmp == 7)
844 				txsc_idx = 11;
845 			else if (tmp == 2 || tmp == 4)
846 				txsc_idx = 10;
847 			else if (tmp == 6 || tmp == 8)
848 				txsc_idx = 12;
849 			else
850 				return 0xff;
851 		} else {
852 			txsc_idx = pri_ch > central_ch ? 13 : 14;
853 		}
854 		break;
855 	case RTW89_CHANNEL_WIDTH_80_80:
856 		if (dbw == RTW89_CHANNEL_WIDTH_20) {
857 			if (pri_ch > central_ch)
858 				txsc_idx = (10 - (pri_ch - central_ch)) >> 1;
859 			else
860 				txsc_idx = ((central_ch - pri_ch) >> 1) + 5;
861 		} else if (dbw == RTW89_CHANNEL_WIDTH_40) {
862 			txsc_idx = pri_ch > central_ch ? 10 : 12;
863 		} else {
864 			txsc_idx = 14;
865 		}
866 		break;
867 	default:
868 		break;
869 	}
870 
871 	return txsc_idx;
872 }
873 EXPORT_SYMBOL(rtw89_phy_get_txsc);
874 
875 u8 rtw89_phy_get_txsb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
876 		      enum rtw89_bandwidth dbw)
877 {
878 	enum rtw89_bandwidth cbw = chan->band_width;
879 	u8 pri_ch = chan->primary_channel;
880 	u8 central_ch = chan->channel;
881 	u8 txsb_idx = 0;
882 
883 	if (cbw == dbw || cbw == RTW89_CHANNEL_WIDTH_20)
884 		return txsb_idx;
885 
886 	switch (cbw) {
887 	case RTW89_CHANNEL_WIDTH_40:
888 		txsb_idx = pri_ch > central_ch ? 1 : 0;
889 		break;
890 	case RTW89_CHANNEL_WIDTH_80:
891 		if (dbw == RTW89_CHANNEL_WIDTH_20)
892 			txsb_idx = (pri_ch - central_ch + 6) / 4;
893 		else
894 			txsb_idx = pri_ch > central_ch ? 1 : 0;
895 		break;
896 	case RTW89_CHANNEL_WIDTH_160:
897 		if (dbw == RTW89_CHANNEL_WIDTH_20)
898 			txsb_idx = (pri_ch - central_ch + 14) / 4;
899 		else if (dbw == RTW89_CHANNEL_WIDTH_40)
900 			txsb_idx = (pri_ch - central_ch + 12) / 8;
901 		else
902 			txsb_idx = pri_ch > central_ch ? 1 : 0;
903 		break;
904 	case RTW89_CHANNEL_WIDTH_320:
905 		if (dbw == RTW89_CHANNEL_WIDTH_20)
906 			txsb_idx = (pri_ch - central_ch + 30) / 4;
907 		else if (dbw == RTW89_CHANNEL_WIDTH_40)
908 			txsb_idx = (pri_ch - central_ch + 28) / 8;
909 		else if (dbw == RTW89_CHANNEL_WIDTH_80)
910 			txsb_idx = (pri_ch - central_ch + 24) / 16;
911 		else
912 			txsb_idx = pri_ch > central_ch ? 1 : 0;
913 		break;
914 	default:
915 		break;
916 	}
917 
918 	return txsb_idx;
919 }
920 EXPORT_SYMBOL(rtw89_phy_get_txsb);
921 
922 static bool rtw89_phy_check_swsi_busy(struct rtw89_dev *rtwdev)
923 {
924 	return !!rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, B_SWSI_W_BUSY_V1) ||
925 	       !!rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, B_SWSI_R_BUSY_V1);
926 }
927 
928 u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
929 		      u32 addr, u32 mask)
930 {
931 	const struct rtw89_chip_info *chip = rtwdev->chip;
932 	const u32 *base_addr = chip->rf_base_addr;
933 	u32 val, direct_addr;
934 
935 	if (rf_path >= rtwdev->chip->rf_path_num) {
936 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
937 		return INV_RF_DATA;
938 	}
939 
940 	addr &= 0xff;
941 	direct_addr = base_addr[rf_path] + (addr << 2);
942 	mask &= RFREG_MASK;
943 
944 	val = rtw89_phy_read32_mask(rtwdev, direct_addr, mask);
945 
946 	return val;
947 }
948 EXPORT_SYMBOL(rtw89_phy_read_rf);
949 
950 static u32 rtw89_phy_read_rf_a(struct rtw89_dev *rtwdev,
951 			       enum rtw89_rf_path rf_path, u32 addr, u32 mask)
952 {
953 	bool busy;
954 	bool done;
955 	u32 val;
956 	int ret;
957 
958 	ret = read_poll_timeout_atomic(rtw89_phy_check_swsi_busy, busy, !busy,
959 				       1, 30, false, rtwdev);
960 	if (ret) {
961 		rtw89_err(rtwdev, "read rf busy swsi\n");
962 		return INV_RF_DATA;
963 	}
964 
965 	mask &= RFREG_MASK;
966 
967 	val = FIELD_PREP(B_SWSI_READ_ADDR_PATH_V1, rf_path) |
968 	      FIELD_PREP(B_SWSI_READ_ADDR_ADDR_V1, addr);
969 	rtw89_phy_write32_mask(rtwdev, R_SWSI_READ_ADDR_V1, B_SWSI_READ_ADDR_V1, val);
970 	udelay(2);
971 
972 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done, 1,
973 				       30, false, rtwdev, R_SWSI_V1,
974 				       B_SWSI_R_DATA_DONE_V1);
975 	if (ret) {
976 		if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
977 			rtw89_err(rtwdev, "read swsi busy\n");
978 		return INV_RF_DATA;
979 	}
980 
981 	return rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, mask);
982 }
983 
984 u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
985 			 u32 addr, u32 mask)
986 {
987 	bool ad_sel = FIELD_GET(RTW89_RF_ADDR_ADSEL_MASK, addr);
988 
989 	if (rf_path >= rtwdev->chip->rf_path_num) {
990 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
991 		return INV_RF_DATA;
992 	}
993 
994 	if (ad_sel)
995 		return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
996 	else
997 		return rtw89_phy_read_rf_a(rtwdev, rf_path, addr, mask);
998 }
999 EXPORT_SYMBOL(rtw89_phy_read_rf_v1);
1000 
1001 static u32 rtw89_phy_read_full_rf_v2_a(struct rtw89_dev *rtwdev,
1002 				       enum rtw89_rf_path rf_path, u32 addr)
1003 {
1004 	static const u16 r_addr_ofst[2] = {0x2C24, 0x2D24};
1005 	static const u16 addr_ofst[2] = {0x2ADC, 0x2BDC};
1006 	bool busy, done;
1007 	int ret;
1008 	u32 val;
1009 
1010 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_CTL_MASK, 0x1);
1011 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
1012 				       1, 3800, false,
1013 				       rtwdev, r_addr_ofst[rf_path], B_HWSI_VAL_BUSY);
1014 	if (ret) {
1015 		rtw89_warn(rtwdev, "poll HWSI is busy\n");
1016 		return INV_RF_DATA;
1017 	}
1018 
1019 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_MASK, addr);
1020 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_RD, 0x1);
1021 	udelay(2);
1022 
1023 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done,
1024 				       1, 3800, false,
1025 				       rtwdev, r_addr_ofst[rf_path], B_HWSI_VAL_RDONE);
1026 	if (ret) {
1027 		rtw89_warn(rtwdev, "read HWSI is busy\n");
1028 		val = INV_RF_DATA;
1029 		goto out;
1030 	}
1031 
1032 	val = rtw89_phy_read32_mask(rtwdev, r_addr_ofst[rf_path], RFREG_MASK);
1033 out:
1034 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_POLL_MASK, 0);
1035 
1036 	return val;
1037 }
1038 
1039 static u32 rtw89_phy_read_rf_v2_a(struct rtw89_dev *rtwdev,
1040 				  enum rtw89_rf_path rf_path, u32 addr, u32 mask)
1041 {
1042 	u32 val;
1043 
1044 	val = rtw89_phy_read_full_rf_v2_a(rtwdev, rf_path, addr);
1045 
1046 	return (val & mask) >> __ffs(mask);
1047 }
1048 
1049 u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1050 			 u32 addr, u32 mask)
1051 {
1052 	bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
1053 
1054 	if (rf_path >= rtwdev->chip->rf_path_num) {
1055 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
1056 		return INV_RF_DATA;
1057 	}
1058 
1059 	if (ad_sel)
1060 		return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
1061 	else
1062 		return rtw89_phy_read_rf_v2_a(rtwdev, rf_path, addr, mask);
1063 }
1064 EXPORT_SYMBOL(rtw89_phy_read_rf_v2);
1065 
1066 static u32 rtw89_phy_read_full_rf_v3_a(struct rtw89_dev *rtwdev,
1067 				       enum rtw89_rf_path rf_path, u32 addr)
1068 {
1069 	bool done;
1070 	u32 busy;
1071 	int ret;
1072 	u32 val;
1073 
1074 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
1075 				       1, 30, false,
1076 				       rtwdev, R_SW_SI_DATA_BE4,
1077 				       B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4);
1078 	if (ret) {
1079 		rtw89_warn(rtwdev, "poll HWSI is busy\n");
1080 		return INV_RF_DATA;
1081 	}
1082 
1083 	val = u32_encode_bits(rf_path, GENMASK(10, 8)) |
1084 	      u32_encode_bits(addr, GENMASK(7, 0));
1085 
1086 	rtw89_phy_write32_mask(rtwdev, R_SW_SI_READ_ADDR_BE4, B_SW_SI_READ_ADDR_BE4, val);
1087 
1088 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done,
1089 				       1, 30, false,
1090 				       rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_DONE_BE4);
1091 	if (ret) {
1092 		rtw89_warn(rtwdev, "read HWSI is busy\n");
1093 		return INV_RF_DATA;
1094 	}
1095 
1096 	val = rtw89_phy_read32_mask(rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_BE4);
1097 
1098 	return val;
1099 }
1100 
1101 static u32 rtw89_phy_read_rf_v3_a(struct rtw89_dev *rtwdev,
1102 				  enum rtw89_rf_path rf_path, u32 addr, u32 mask)
1103 {
1104 	u32 val;
1105 
1106 	val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr);
1107 
1108 	return (val & mask) >> __ffs(mask);
1109 }
1110 
1111 u32 rtw89_phy_read_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1112 			 u32 addr, u32 mask)
1113 {
1114 	bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
1115 
1116 	if (rf_path >= rtwdev->chip->rf_path_num) {
1117 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
1118 		return INV_RF_DATA;
1119 	}
1120 
1121 	if (ad_sel)
1122 		return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
1123 	else
1124 		return rtw89_phy_read_rf_v3_a(rtwdev, rf_path, addr, mask);
1125 }
1126 EXPORT_SYMBOL(rtw89_phy_read_rf_v3);
1127 
1128 bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1129 			u32 addr, u32 mask, u32 data)
1130 {
1131 	const struct rtw89_chip_info *chip = rtwdev->chip;
1132 	const u32 *base_addr = chip->rf_base_addr;
1133 	u32 direct_addr;
1134 
1135 	if (rf_path >= rtwdev->chip->rf_path_num) {
1136 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
1137 		return false;
1138 	}
1139 
1140 	addr &= 0xff;
1141 	direct_addr = base_addr[rf_path] + (addr << 2);
1142 	mask &= RFREG_MASK;
1143 
1144 	rtw89_phy_write32_mask(rtwdev, direct_addr, mask, data);
1145 
1146 	/* delay to ensure writing properly */
1147 	udelay(1);
1148 
1149 	return true;
1150 }
1151 EXPORT_SYMBOL(rtw89_phy_write_rf);
1152 
1153 static bool rtw89_phy_write_rf_a(struct rtw89_dev *rtwdev,
1154 				 enum rtw89_rf_path rf_path, u32 addr, u32 mask,
1155 				 u32 data)
1156 {
1157 	u8 bit_shift;
1158 	u32 val;
1159 	bool busy, b_msk_en = false;
1160 	int ret;
1161 
1162 	ret = read_poll_timeout_atomic(rtw89_phy_check_swsi_busy, busy, !busy,
1163 				       1, 30, false, rtwdev);
1164 	if (ret) {
1165 		rtw89_err(rtwdev, "write rf busy swsi\n");
1166 		return false;
1167 	}
1168 
1169 	data &= RFREG_MASK;
1170 	mask &= RFREG_MASK;
1171 
1172 	if (mask != RFREG_MASK) {
1173 		b_msk_en = true;
1174 		rtw89_phy_write32_mask(rtwdev, R_SWSI_BIT_MASK_V1, RFREG_MASK,
1175 				       mask);
1176 		bit_shift = __ffs(mask);
1177 		data = (data << bit_shift) & RFREG_MASK;
1178 	}
1179 
1180 	val = FIELD_PREP(B_SWSI_DATA_BIT_MASK_EN_V1, b_msk_en) |
1181 	      FIELD_PREP(B_SWSI_DATA_PATH_V1, rf_path) |
1182 	      FIELD_PREP(B_SWSI_DATA_ADDR_V1, addr) |
1183 	      FIELD_PREP(B_SWSI_DATA_VAL_V1, data);
1184 
1185 	rtw89_phy_write32_mask(rtwdev, R_SWSI_DATA_V1, MASKDWORD, val);
1186 
1187 	return true;
1188 }
1189 
1190 bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1191 			   u32 addr, u32 mask, u32 data)
1192 {
1193 	bool ad_sel = FIELD_GET(RTW89_RF_ADDR_ADSEL_MASK, addr);
1194 
1195 	if (rf_path >= rtwdev->chip->rf_path_num) {
1196 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
1197 		return false;
1198 	}
1199 
1200 	if (ad_sel)
1201 		return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
1202 	else
1203 		return rtw89_phy_write_rf_a(rtwdev, rf_path, addr, mask, data);
1204 }
1205 EXPORT_SYMBOL(rtw89_phy_write_rf_v1);
1206 
1207 static
1208 bool rtw89_phy_write_full_rf_v2_a(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1209 				  u32 addr, u32 data)
1210 {
1211 	static const u32 addr_is_idle[2] = {0x2C24, 0x2D24};
1212 	static const u32 addr_ofst[2] = {0x2AE0, 0x2BE0};
1213 	bool busy;
1214 	u32 val;
1215 	int ret;
1216 
1217 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
1218 				       1, 3800, false,
1219 				       rtwdev, addr_is_idle[rf_path], BIT(29));
1220 	if (ret) {
1221 		rtw89_warn(rtwdev, "[%s] HWSI is busy\n", __func__);
1222 		return false;
1223 	}
1224 
1225 	val = u32_encode_bits(addr, B_HWSI_DATA_ADDR) |
1226 	      u32_encode_bits(data, B_HWSI_DATA_VAL);
1227 
1228 	rtw89_phy_write32(rtwdev, addr_ofst[rf_path], val);
1229 
1230 	return true;
1231 }
1232 
1233 static
1234 bool rtw89_phy_write_rf_a_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1235 			     u32 addr, u32 mask, u32 data)
1236 {
1237 	u32 val;
1238 
1239 	if (mask == RFREG_MASK) {
1240 		val = data;
1241 	} else {
1242 		val = rtw89_phy_read_full_rf_v2_a(rtwdev, rf_path, addr);
1243 		val &= ~mask;
1244 		val |= (data << __ffs(mask)) & mask;
1245 	}
1246 
1247 	return rtw89_phy_write_full_rf_v2_a(rtwdev, rf_path, addr, val);
1248 }
1249 
1250 bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1251 			   u32 addr, u32 mask, u32 data)
1252 {
1253 	bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
1254 
1255 	if (rf_path >= rtwdev->chip->rf_path_num) {
1256 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
1257 		return INV_RF_DATA;
1258 	}
1259 
1260 	if (ad_sel)
1261 		return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
1262 	else
1263 		return rtw89_phy_write_rf_a_v2(rtwdev, rf_path, addr, mask, data);
1264 }
1265 EXPORT_SYMBOL(rtw89_phy_write_rf_v2);
1266 
1267 static
1268 bool rtw89_phy_write_full_rf_v3_a(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1269 				  u32 addr, u32 data)
1270 {
1271 	u32 busy;
1272 	u32 val;
1273 	int ret;
1274 
1275 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
1276 				       1, 30, false,
1277 				       rtwdev, R_SW_SI_DATA_BE4,
1278 				       B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4);
1279 	if (ret) {
1280 		rtw89_warn(rtwdev, "[%s] HWSI is busy\n", __func__);
1281 		return false;
1282 	}
1283 
1284 	val = u32_encode_bits(rf_path, B_SW_SI_DATA_PATH_BE4) |
1285 	      u32_encode_bits(addr, B_SW_SI_DATA_ADR_BE4) |
1286 	      u32_encode_bits(data, B_SW_SI_DATA_DAT_BE4);
1287 
1288 	rtw89_phy_write32(rtwdev, R_SW_SI_WDATA_BE4, val);
1289 
1290 	return true;
1291 }
1292 
1293 static
1294 bool rtw89_phy_write_rf_a_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1295 			     u32 addr, u32 mask, u32 data)
1296 {
1297 	u32 val;
1298 
1299 	if (mask == RFREG_MASK) {
1300 		val = data;
1301 	} else {
1302 		val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr);
1303 		val &= ~mask;
1304 		val |= (data << __ffs(mask)) & mask;
1305 	}
1306 
1307 	return rtw89_phy_write_full_rf_v3_a(rtwdev, rf_path, addr, val);
1308 }
1309 
1310 bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1311 			   u32 addr, u32 mask, u32 data)
1312 {
1313 	bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
1314 
1315 	if (rf_path >= rtwdev->chip->rf_path_num) {
1316 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
1317 		return INV_RF_DATA;
1318 	}
1319 
1320 	if (ad_sel)
1321 		return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
1322 	else
1323 		return rtw89_phy_write_rf_a_v3(rtwdev, rf_path, addr, mask, data);
1324 }
1325 EXPORT_SYMBOL(rtw89_phy_write_rf_v3);
1326 
1327 static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev)
1328 {
1329 	return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1;
1330 }
1331 
1332 static void __rtw89_phy_bb_reset(struct rtw89_dev *rtwdev,
1333 				 enum rtw89_phy_idx phy_idx)
1334 {
1335 	const struct rtw89_chip_info *chip = rtwdev->chip;
1336 
1337 	chip->ops->bb_reset(rtwdev, phy_idx);
1338 }
1339 
1340 static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev)
1341 {
1342 	__rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0);
1343 	if (rtwdev->dbcc_en)
1344 		__rtw89_phy_bb_reset(rtwdev, RTW89_PHY_1);
1345 }
1346 
1347 static void rtw89_phy_config_bb_reg(struct rtw89_dev *rtwdev,
1348 				    const struct rtw89_reg2_def *reg,
1349 				    enum rtw89_rf_path rf_path,
1350 				    void *extra_data)
1351 {
1352 	u32 addr;
1353 
1354 	if (reg->addr == 0xfe) {
1355 		rtw89_io_mdelay(rtwdev, 50);
1356 	} else if (reg->addr == 0xfd) {
1357 		rtw89_io_mdelay(rtwdev, 5);
1358 	} else if (reg->addr == 0xfc) {
1359 		rtw89_io_mdelay(rtwdev, 1);
1360 	} else if (reg->addr == 0xfb) {
1361 		rtw89_io_udelay(rtwdev, 50);
1362 	} else if (reg->addr == 0xfa) {
1363 		rtw89_io_udelay(rtwdev, 5);
1364 	} else if (reg->addr == 0xf9) {
1365 		rtw89_io_udelay(rtwdev, 1);
1366 	} else if (reg->data == BYPASS_CR_DATA) {
1367 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "Bypass CR 0x%x\n", reg->addr);
1368 	} else {
1369 		addr = reg->addr;
1370 
1371 		if ((uintptr_t)extra_data == RTW89_PHY_1)
1372 			addr += rtw89_phy0_phy1_offset(rtwdev, reg->addr);
1373 
1374 		rtw89_phy_write32(rtwdev, addr, reg->data);
1375 	}
1376 }
1377 
1378 union rtw89_phy_bb_gain_arg {
1379 	u32 addr;
1380 	struct {
1381 		union {
1382 			u8 type;
1383 			struct {
1384 				u8 rxsc_start:4;
1385 				u8 bw:4;
1386 			};
1387 		};
1388 		u8 path;
1389 		u8 gain_band;
1390 		u8 cfg_type;
1391 	};
1392 } __packed;
1393 
1394 static void
1395 rtw89_phy_cfg_bb_gain_error(struct rtw89_dev *rtwdev,
1396 			    union rtw89_phy_bb_gain_arg arg, u32 data)
1397 {
1398 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
1399 	u8 type = arg.type;
1400 	u8 path = arg.path;
1401 	u8 gband = arg.gain_band;
1402 	int i;
1403 
1404 	switch (type) {
1405 	case 0:
1406 		for (i = 0; i < 4; i++, data >>= 8)
1407 			gain->lna_gain[gband][path][i] = data & 0xff;
1408 		break;
1409 	case 1:
1410 		for (i = 4; i < 7; i++, data >>= 8)
1411 			gain->lna_gain[gband][path][i] = data & 0xff;
1412 		break;
1413 	case 2:
1414 		for (i = 0; i < 2; i++, data >>= 8)
1415 			gain->tia_gain[gband][path][i] = data & 0xff;
1416 		break;
1417 	default:
1418 		rtw89_warn(rtwdev,
1419 			   "bb gain error {0x%x:0x%x} with unknown type: %d\n",
1420 			   arg.addr, data, type);
1421 		break;
1422 	}
1423 }
1424 
1425 enum rtw89_phy_bb_rxsc_start_idx {
1426 	RTW89_BB_RXSC_START_IDX_FULL = 0,
1427 	RTW89_BB_RXSC_START_IDX_20 = 1,
1428 	RTW89_BB_RXSC_START_IDX_20_1 = 5,
1429 	RTW89_BB_RXSC_START_IDX_40 = 9,
1430 	RTW89_BB_RXSC_START_IDX_80 = 13,
1431 };
1432 
1433 static void
1434 rtw89_phy_cfg_bb_rpl_ofst(struct rtw89_dev *rtwdev,
1435 			  union rtw89_phy_bb_gain_arg arg, u32 data)
1436 {
1437 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
1438 	u8 rxsc_start = arg.rxsc_start;
1439 	u8 bw = arg.bw;
1440 	u8 path = arg.path;
1441 	u8 gband = arg.gain_band;
1442 	u8 rxsc;
1443 	s8 ofst;
1444 	int i;
1445 
1446 	switch (bw) {
1447 	case RTW89_CHANNEL_WIDTH_20:
1448 		gain->rpl_ofst_20[gband][path] = (s8)data;
1449 		break;
1450 	case RTW89_CHANNEL_WIDTH_40:
1451 		if (rxsc_start == RTW89_BB_RXSC_START_IDX_FULL) {
1452 			gain->rpl_ofst_40[gband][path][0] = (s8)data;
1453 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20) {
1454 			for (i = 0; i < 2; i++, data >>= 8) {
1455 				rxsc = RTW89_BB_RXSC_START_IDX_20 + i;
1456 				ofst = (s8)(data & 0xff);
1457 				gain->rpl_ofst_40[gband][path][rxsc] = ofst;
1458 			}
1459 		}
1460 		break;
1461 	case RTW89_CHANNEL_WIDTH_80:
1462 		if (rxsc_start == RTW89_BB_RXSC_START_IDX_FULL) {
1463 			gain->rpl_ofst_80[gband][path][0] = (s8)data;
1464 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20) {
1465 			for (i = 0; i < 4; i++, data >>= 8) {
1466 				rxsc = RTW89_BB_RXSC_START_IDX_20 + i;
1467 				ofst = (s8)(data & 0xff);
1468 				gain->rpl_ofst_80[gband][path][rxsc] = ofst;
1469 			}
1470 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_40) {
1471 			for (i = 0; i < 2; i++, data >>= 8) {
1472 				rxsc = RTW89_BB_RXSC_START_IDX_40 + i;
1473 				ofst = (s8)(data & 0xff);
1474 				gain->rpl_ofst_80[gband][path][rxsc] = ofst;
1475 			}
1476 		}
1477 		break;
1478 	case RTW89_CHANNEL_WIDTH_160:
1479 		if (rxsc_start == RTW89_BB_RXSC_START_IDX_FULL) {
1480 			gain->rpl_ofst_160[gband][path][0] = (s8)data;
1481 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20) {
1482 			for (i = 0; i < 4; i++, data >>= 8) {
1483 				rxsc = RTW89_BB_RXSC_START_IDX_20 + i;
1484 				ofst = (s8)(data & 0xff);
1485 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
1486 			}
1487 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20_1) {
1488 			for (i = 0; i < 4; i++, data >>= 8) {
1489 				rxsc = RTW89_BB_RXSC_START_IDX_20_1 + i;
1490 				ofst = (s8)(data & 0xff);
1491 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
1492 			}
1493 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_40) {
1494 			for (i = 0; i < 4; i++, data >>= 8) {
1495 				rxsc = RTW89_BB_RXSC_START_IDX_40 + i;
1496 				ofst = (s8)(data & 0xff);
1497 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
1498 			}
1499 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_80) {
1500 			for (i = 0; i < 2; i++, data >>= 8) {
1501 				rxsc = RTW89_BB_RXSC_START_IDX_80 + i;
1502 				ofst = (s8)(data & 0xff);
1503 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
1504 			}
1505 		}
1506 		break;
1507 	default:
1508 		rtw89_warn(rtwdev,
1509 			   "bb rpl ofst {0x%x:0x%x} with unknown bw: %d\n",
1510 			   arg.addr, data, bw);
1511 		break;
1512 	}
1513 }
1514 
1515 static void
1516 rtw89_phy_cfg_bb_gain_bypass(struct rtw89_dev *rtwdev,
1517 			     union rtw89_phy_bb_gain_arg arg, u32 data)
1518 {
1519 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
1520 	u8 type = arg.type;
1521 	u8 path = arg.path;
1522 	u8 gband = arg.gain_band;
1523 	int i;
1524 
1525 	switch (type) {
1526 	case 0:
1527 		for (i = 0; i < 4; i++, data >>= 8)
1528 			gain->lna_gain_bypass[gband][path][i] = data & 0xff;
1529 		break;
1530 	case 1:
1531 		for (i = 4; i < 7; i++, data >>= 8)
1532 			gain->lna_gain_bypass[gband][path][i] = data & 0xff;
1533 		break;
1534 	default:
1535 		rtw89_warn(rtwdev,
1536 			   "bb gain bypass {0x%x:0x%x} with unknown type: %d\n",
1537 			   arg.addr, data, type);
1538 		break;
1539 	}
1540 }
1541 
1542 static void
1543 rtw89_phy_cfg_bb_gain_op1db(struct rtw89_dev *rtwdev,
1544 			    union rtw89_phy_bb_gain_arg arg, u32 data)
1545 {
1546 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
1547 	u8 type = arg.type;
1548 	u8 path = arg.path;
1549 	u8 gband = arg.gain_band;
1550 	int i;
1551 
1552 	switch (type) {
1553 	case 0:
1554 		for (i = 0; i < 4; i++, data >>= 8)
1555 			gain->lna_op1db[gband][path][i] = data & 0xff;
1556 		break;
1557 	case 1:
1558 		for (i = 4; i < 7; i++, data >>= 8)
1559 			gain->lna_op1db[gband][path][i] = data & 0xff;
1560 		break;
1561 	case 2:
1562 		for (i = 0; i < 4; i++, data >>= 8)
1563 			gain->tia_lna_op1db[gband][path][i] = data & 0xff;
1564 		break;
1565 	case 3:
1566 		for (i = 4; i < 8; i++, data >>= 8)
1567 			gain->tia_lna_op1db[gband][path][i] = data & 0xff;
1568 		break;
1569 	default:
1570 		rtw89_warn(rtwdev,
1571 			   "bb gain op1db {0x%x:0x%x} with unknown type: %d\n",
1572 			   arg.addr, data, type);
1573 		break;
1574 	}
1575 }
1576 
1577 static void rtw89_phy_config_bb_gain_ax(struct rtw89_dev *rtwdev,
1578 					const struct rtw89_reg2_def *reg,
1579 					enum rtw89_rf_path rf_path,
1580 					void *extra_data)
1581 {
1582 	const struct rtw89_chip_info *chip = rtwdev->chip;
1583 	union rtw89_phy_bb_gain_arg arg = { .addr = reg->addr };
1584 	struct rtw89_efuse *efuse = &rtwdev->efuse;
1585 
1586 	if (arg.gain_band >= RTW89_BB_GAIN_BAND_NR)
1587 		return;
1588 
1589 	if (arg.path >= chip->rf_path_num)
1590 		return;
1591 
1592 	if (arg.addr >= 0xf9 && arg.addr <= 0xfe) {
1593 		rtw89_warn(rtwdev, "bb gain table with flow ctrl\n");
1594 		return;
1595 	}
1596 
1597 	switch (arg.cfg_type) {
1598 	case 0:
1599 		rtw89_phy_cfg_bb_gain_error(rtwdev, arg, reg->data);
1600 		break;
1601 	case 1:
1602 		rtw89_phy_cfg_bb_rpl_ofst(rtwdev, arg, reg->data);
1603 		break;
1604 	case 2:
1605 		rtw89_phy_cfg_bb_gain_bypass(rtwdev, arg, reg->data);
1606 		break;
1607 	case 3:
1608 		rtw89_phy_cfg_bb_gain_op1db(rtwdev, arg, reg->data);
1609 		break;
1610 	case 4:
1611 		/* This cfg_type is only used by rfe_type >= 50 with eFEM */
1612 		if (efuse->rfe_type < 50)
1613 			break;
1614 		fallthrough;
1615 	default:
1616 		rtw89_warn(rtwdev,
1617 			   "bb gain {0x%x:0x%x} with unknown cfg type: %d\n",
1618 			   arg.addr, reg->data, arg.cfg_type);
1619 		break;
1620 	}
1621 }
1622 
1623 static void
1624 rtw89_phy_cofig_rf_reg_store(struct rtw89_dev *rtwdev,
1625 			     const struct rtw89_reg2_def *reg,
1626 			     enum rtw89_rf_path rf_path,
1627 			     struct rtw89_fw_h2c_rf_reg_info *info)
1628 {
1629 	u16 idx = info->curr_idx % RTW89_H2C_RF_PAGE_SIZE;
1630 	u8 page = info->curr_idx / RTW89_H2C_RF_PAGE_SIZE;
1631 
1632 	if (page >= RTW89_H2C_RF_PAGE_NUM) {
1633 		rtw89_warn(rtwdev, "RF parameters exceed size. path=%d, idx=%d",
1634 			   rf_path, info->curr_idx);
1635 		return;
1636 	}
1637 
1638 	info->rtw89_phy_config_rf_h2c[page][idx] =
1639 		cpu_to_le32((reg->addr << 20) | reg->data);
1640 	info->curr_idx++;
1641 }
1642 
1643 static int rtw89_phy_config_rf_reg_fw(struct rtw89_dev *rtwdev,
1644 				      struct rtw89_fw_h2c_rf_reg_info *info)
1645 {
1646 	u16 remain = info->curr_idx;
1647 	u16 len = 0;
1648 	u8 i;
1649 	int ret = 0;
1650 
1651 	if (remain > RTW89_H2C_RF_PAGE_NUM * RTW89_H2C_RF_PAGE_SIZE) {
1652 		rtw89_warn(rtwdev,
1653 			   "rf reg h2c total len %d larger than %d\n",
1654 			   remain, RTW89_H2C_RF_PAGE_NUM * RTW89_H2C_RF_PAGE_SIZE);
1655 		ret = -EINVAL;
1656 		goto out;
1657 	}
1658 
1659 	for (i = 0; i < RTW89_H2C_RF_PAGE_NUM && remain; i++, remain -= len) {
1660 		len = remain > RTW89_H2C_RF_PAGE_SIZE ? RTW89_H2C_RF_PAGE_SIZE : remain;
1661 		ret = rtw89_fw_h2c_rf_reg(rtwdev, info, len * 4, i);
1662 		if (ret)
1663 			goto out;
1664 	}
1665 out:
1666 	info->curr_idx = 0;
1667 
1668 	return ret;
1669 }
1670 
1671 static void rtw89_phy_config_rf_reg_noio(struct rtw89_dev *rtwdev,
1672 					 const struct rtw89_reg2_def *reg,
1673 					 enum rtw89_rf_path rf_path,
1674 					 void *extra_data)
1675 {
1676 	u32 addr = reg->addr;
1677 
1678 	if (addr == 0xfe || addr == 0xfd || addr == 0xfc || addr == 0xfb ||
1679 	    addr == 0xfa || addr == 0xf9)
1680 		return;
1681 
1682 	if (rtw89_chip_rf_v1(rtwdev) && addr < 0x100)
1683 		return;
1684 
1685 	rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path,
1686 				     (struct rtw89_fw_h2c_rf_reg_info *)extra_data);
1687 }
1688 
1689 void rtw89_phy_config_rf_reg(struct rtw89_dev *rtwdev,
1690 			     const struct rtw89_reg2_def *reg,
1691 			     enum rtw89_rf_path rf_path,
1692 			     void *extra_data)
1693 {
1694 	if (reg->addr == 0xfe) {
1695 		rtw89_io_mdelay(rtwdev, 50);
1696 	} else if (reg->addr == 0xfd) {
1697 		rtw89_io_mdelay(rtwdev, 5);
1698 	} else if (reg->addr == 0xfc) {
1699 		rtw89_io_mdelay(rtwdev, 1);
1700 	} else if (reg->addr == 0xfb) {
1701 		rtw89_io_udelay(rtwdev, 50);
1702 	} else if (reg->addr == 0xfa) {
1703 		rtw89_io_udelay(rtwdev, 5);
1704 	} else if (reg->addr == 0xf9) {
1705 		rtw89_io_udelay(rtwdev, 1);
1706 	} else {
1707 		rtw89_write_rf(rtwdev, rf_path, reg->addr, 0xfffff, reg->data);
1708 		rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path,
1709 					     (struct rtw89_fw_h2c_rf_reg_info *)extra_data);
1710 	}
1711 }
1712 
1713 void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
1714 				const struct rtw89_reg2_def *reg,
1715 				enum rtw89_rf_path rf_path,
1716 				void *extra_data)
1717 {
1718 	if (reg->addr == 0xfe) {
1719 		rtw89_io_mdelay(rtwdev, 50);
1720 		return;
1721 	}
1722 
1723 	rtw89_write_rf(rtwdev, rf_path, reg->addr, RFREG_MASK, reg->data);
1724 
1725 	if (reg->addr < 0x100)
1726 		return;
1727 
1728 	rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path,
1729 				     (struct rtw89_fw_h2c_rf_reg_info *)extra_data);
1730 }
1731 EXPORT_SYMBOL(rtw89_phy_config_rf_reg_v1);
1732 
1733 static int rtw89_phy_sel_headline(struct rtw89_dev *rtwdev,
1734 				  const struct rtw89_phy_table *table,
1735 				  u32 *headline_size, u32 *headline_idx,
1736 				  u8 rfe, u8 cv)
1737 {
1738 	const struct rtw89_reg2_def *reg;
1739 	u32 headline;
1740 	u32 compare, target;
1741 	u8 rfe_para, cv_para;
1742 	u8 cv_max = 0;
1743 	bool case_matched = false;
1744 	u32 i;
1745 
1746 	for (i = 0; i < table->n_regs; i++) {
1747 		reg = &table->regs[i];
1748 		headline = get_phy_headline(reg->addr);
1749 		if (headline != PHY_HEADLINE_VALID)
1750 			break;
1751 	}
1752 	*headline_size = i;
1753 	if (*headline_size == 0)
1754 		return 0;
1755 
1756 	/* case 1: RFE match, CV match */
1757 	compare = get_phy_compare(rfe, cv);
1758 	for (i = 0; i < *headline_size; i++) {
1759 		reg = &table->regs[i];
1760 		target = get_phy_target(reg->addr);
1761 		if (target == compare) {
1762 			*headline_idx = i;
1763 			return 0;
1764 		}
1765 	}
1766 
1767 	/* case 2: RFE match, CV don't care */
1768 	compare = get_phy_compare(rfe, PHY_COND_DONT_CARE);
1769 	for (i = 0; i < *headline_size; i++) {
1770 		reg = &table->regs[i];
1771 		target = get_phy_target(reg->addr);
1772 		if (target == compare) {
1773 			*headline_idx = i;
1774 			return 0;
1775 		}
1776 	}
1777 
1778 	/* case 3: RFE match, CV max in table */
1779 	for (i = 0; i < *headline_size; i++) {
1780 		reg = &table->regs[i];
1781 		rfe_para = get_phy_cond_rfe(reg->addr);
1782 		cv_para = get_phy_cond_cv(reg->addr);
1783 		if (rfe_para == rfe) {
1784 			if (cv_para >= cv_max) {
1785 				cv_max = cv_para;
1786 				*headline_idx = i;
1787 				case_matched = true;
1788 			}
1789 		}
1790 	}
1791 
1792 	if (case_matched)
1793 		return 0;
1794 
1795 	/* case 4: RFE don't care, CV max in table */
1796 	for (i = 0; i < *headline_size; i++) {
1797 		reg = &table->regs[i];
1798 		rfe_para = get_phy_cond_rfe(reg->addr);
1799 		cv_para = get_phy_cond_cv(reg->addr);
1800 		if (rfe_para == PHY_COND_DONT_CARE) {
1801 			if (cv_para >= cv_max) {
1802 				cv_max = cv_para;
1803 				*headline_idx = i;
1804 				case_matched = true;
1805 			}
1806 		}
1807 	}
1808 
1809 	if (case_matched)
1810 		return 0;
1811 
1812 	return -EINVAL;
1813 }
1814 
1815 static void rtw89_phy_init_reg(struct rtw89_dev *rtwdev,
1816 			       const struct rtw89_phy_table *table, bool by_acv,
1817 			       void (*config)(struct rtw89_dev *rtwdev,
1818 					      const struct rtw89_reg2_def *reg,
1819 					      enum rtw89_rf_path rf_path,
1820 					      void *data),
1821 			       void *extra_data)
1822 {
1823 	const struct rtw89_reg2_def *reg;
1824 	enum rtw89_rf_path rf_path = table->rf_path;
1825 	u8 cv = by_acv ? rtwdev->hal.acv : rtwdev->hal.cv;
1826 	u8 rfe = rtwdev->efuse.rfe_type;
1827 	u32 i;
1828 	u32 headline_size = 0, headline_idx = 0;
1829 	u32 target = 0, cfg_target;
1830 	u8 cond;
1831 	bool is_matched = true;
1832 	bool target_found = false;
1833 	int ret;
1834 
1835 	ret = rtw89_phy_sel_headline(rtwdev, table, &headline_size,
1836 				     &headline_idx, rfe, cv);
1837 	if (ret) {
1838 		rtw89_err(rtwdev, "invalid PHY package: %d/%d\n", rfe, cv);
1839 		return;
1840 	}
1841 
1842 	cfg_target = get_phy_target(table->regs[headline_idx].addr);
1843 	for (i = headline_size; i < table->n_regs; i++) {
1844 		reg = &table->regs[i];
1845 		cond = get_phy_cond(reg->addr);
1846 		switch (cond) {
1847 		case PHY_COND_BRANCH_IF:
1848 		case PHY_COND_BRANCH_ELIF:
1849 			target = get_phy_target(reg->addr);
1850 			break;
1851 		case PHY_COND_BRANCH_ELSE:
1852 			is_matched = false;
1853 			if (!target_found) {
1854 				rtw89_warn(rtwdev, "failed to load CR %x/%x\n",
1855 					   reg->addr, reg->data);
1856 				return;
1857 			}
1858 			break;
1859 		case PHY_COND_BRANCH_END:
1860 			is_matched = true;
1861 			target_found = false;
1862 			break;
1863 		case PHY_COND_CHECK:
1864 			if (target_found) {
1865 				is_matched = false;
1866 				break;
1867 			}
1868 
1869 			if (target == cfg_target) {
1870 				is_matched = true;
1871 				target_found = true;
1872 			} else {
1873 				is_matched = false;
1874 				target_found = false;
1875 			}
1876 			break;
1877 		default:
1878 			if (is_matched)
1879 				config(rtwdev, reg, rf_path, extra_data);
1880 			break;
1881 		}
1882 	}
1883 }
1884 
1885 void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev)
1886 {
1887 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
1888 	const struct rtw89_chip_info *chip = rtwdev->chip;
1889 	const struct rtw89_phy_table *bb_table;
1890 	const struct rtw89_phy_table *bb_gain_table;
1891 
1892 	bb_table = elm_info->bb_tbl ? elm_info->bb_tbl : chip->bb_table;
1893 
1894 	rtw89_io_pack(rtwdev);
1895 
1896 	rtw89_phy_init_reg(rtwdev, bb_table, false, rtw89_phy_config_bb_reg, NULL);
1897 	if (rtwdev->dbcc_en)
1898 		rtw89_phy_init_reg(rtwdev, bb_table, false, rtw89_phy_config_bb_reg,
1899 				   (void *)RTW89_PHY_1);
1900 
1901 	rtw89_io_unpack(rtwdev);
1902 
1903 	rtw89_chip_init_txpwr_unit(rtwdev);
1904 
1905 	bb_gain_table = elm_info->bb_gain ? elm_info->bb_gain : chip->bb_gain_table;
1906 	if (bb_gain_table)
1907 		rtw89_phy_init_reg(rtwdev, bb_gain_table, false,
1908 				   chip->phy_def->config_bb_gain, NULL);
1909 
1910 	rtw89_phy_bb_reset(rtwdev);
1911 }
1912 
1913 void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev)
1914 {
1915 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
1916 	const struct rtw89_fw_element_hdr *afe_elm = elm_info->afe;
1917 	const struct rtw89_phy_afe_info *info;
1918 	u32 action, cat, class;
1919 	u32 addr, mask, val;
1920 	u32 poll, rpt;
1921 	u32 n, i;
1922 
1923 	if (!afe_elm)
1924 		return;
1925 
1926 	n = le32_to_cpu(afe_elm->size) / sizeof(*info);
1927 
1928 	for (i = 0; i < n; i++) {
1929 		info = &afe_elm->u.afe.infos[i];
1930 
1931 		class = le32_to_cpu(info->class);
1932 		switch (class) {
1933 		case RTW89_FW_AFE_CLASS_P0:
1934 		case RTW89_FW_AFE_CLASS_P1:
1935 		case RTW89_FW_AFE_CLASS_CMN:
1936 			/* Currently support two paths */
1937 			break;
1938 		case RTW89_FW_AFE_CLASS_P2:
1939 		case RTW89_FW_AFE_CLASS_P3:
1940 		case RTW89_FW_AFE_CLASS_P4:
1941 		default:
1942 			rtw89_warn(rtwdev, "unexpected AFE class %u\n", class);
1943 			continue;
1944 		}
1945 
1946 		addr = le32_to_cpu(info->addr);
1947 		mask = le32_to_cpu(info->mask);
1948 		val = le32_to_cpu(info->val);
1949 		cat = le32_to_cpu(info->cat);
1950 		action = le32_to_cpu(info->action);
1951 
1952 		switch (action) {
1953 		case RTW89_FW_AFE_ACTION_WRITE:
1954 			switch (cat) {
1955 			case RTW89_FW_AFE_CAT_MAC:
1956 			case RTW89_FW_AFE_CAT_MAC1:
1957 				rtw89_write32_mask(rtwdev, addr, mask, val);
1958 				break;
1959 			case RTW89_FW_AFE_CAT_AFEDIG:
1960 			case RTW89_FW_AFE_CAT_AFEDIG1:
1961 				rtw89_write32_mask(rtwdev, addr, mask, val);
1962 				break;
1963 			case RTW89_FW_AFE_CAT_BB:
1964 				rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_0);
1965 				break;
1966 			case RTW89_FW_AFE_CAT_BB1:
1967 				rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_1);
1968 				break;
1969 			default:
1970 				rtw89_warn(rtwdev,
1971 					   "unexpected AFE writing action %u\n", action);
1972 				break;
1973 			}
1974 			break;
1975 		case RTW89_FW_AFE_ACTION_POLL:
1976 			for (poll = 0; poll <= 10; poll++) {
1977 				/*
1978 				 * For CAT_BB, AFE reads register with mcu_offset 0,
1979 				 * so both CAT_MAC and CAT_BB use the same method.
1980 				 */
1981 				rpt = rtw89_read32_mask(rtwdev, addr, mask);
1982 				if (rpt == val)
1983 					goto poll_done;
1984 
1985 				fsleep(1);
1986 			}
1987 			rtw89_warn(rtwdev, "failed to poll AFE cat=%u addr=0x%x mask=0x%x\n",
1988 				   cat, addr, mask);
1989 poll_done:
1990 			break;
1991 		case RTW89_FW_AFE_ACTION_DELAY:
1992 			fsleep(addr);
1993 			break;
1994 		}
1995 	}
1996 }
1997 
1998 static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev)
1999 {
2000 	rtw89_phy_write32(rtwdev, 0x8080, 0x4);
2001 	udelay(1);
2002 	return rtw89_phy_read32(rtwdev, 0x8080);
2003 }
2004 
2005 void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio)
2006 {
2007 	void (*config)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg,
2008 		       enum rtw89_rf_path rf_path, void *data);
2009 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
2010 	const struct rtw89_chip_info *chip = rtwdev->chip;
2011 	const struct rtw89_phy_table *rf_table;
2012 	struct rtw89_fw_h2c_rf_reg_info *rf_reg_info;
2013 	bool by_acv = chip->chip_id == RTL8922D;
2014 	u8 path;
2015 
2016 	rf_reg_info = kzalloc_obj(*rf_reg_info);
2017 	if (!rf_reg_info)
2018 		return;
2019 
2020 	for (path = RF_PATH_A; path < chip->rf_path_num; path++) {
2021 		rf_table = elm_info->rf_radio[path] ?
2022 			   elm_info->rf_radio[path] : chip->rf_table[path];
2023 		rf_reg_info->rf_path = rf_table->rf_path;
2024 		if (noio)
2025 			config = rtw89_phy_config_rf_reg_noio;
2026 		else
2027 			config = rf_table->config ? rf_table->config :
2028 				 rtw89_phy_config_rf_reg;
2029 
2030 		rtw89_io_pack(rtwdev);
2031 		rtw89_phy_init_reg(rtwdev, rf_table, by_acv, config, (void *)rf_reg_info);
2032 		rtw89_io_unpack(rtwdev);
2033 
2034 		if (rtw89_phy_config_rf_reg_fw(rtwdev, rf_reg_info))
2035 			rtw89_warn(rtwdev, "rf path %d reg h2c config failed\n",
2036 				   rf_reg_info->rf_path);
2037 	}
2038 	kfree(rf_reg_info);
2039 }
2040 
2041 static void rtw89_phy_preinit_rf_nctl_ax(struct rtw89_dev *rtwdev)
2042 {
2043 	const struct rtw89_chip_info *chip = rtwdev->chip;
2044 	u32 val;
2045 	int ret;
2046 
2047 	/* IQK/DPK clock & reset */
2048 	rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x3);
2049 	rtw89_phy_write32_set(rtwdev, R_GNT_BT_WGT_EN, 0x1);
2050 	rtw89_phy_write32_set(rtwdev, R_P0_PATH_RST, 0x8000000);
2051 	if (chip->chip_id != RTL8851B)
2052 		rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000);
2053 	if (chip->chip_id == RTL8852B || chip->chip_id == RTL8852BT)
2054 		rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x2);
2055 
2056 	/* check 0x8080 */
2057 	rtw89_phy_write32(rtwdev, R_NCTL_CFG, 0x8);
2058 
2059 	ret = read_poll_timeout(rtw89_phy_nctl_poll, val, val == 0x4, 10,
2060 				1000, false, rtwdev);
2061 	if (ret)
2062 		rtw89_err(rtwdev, "failed to poll nctl block\n");
2063 }
2064 
2065 static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev)
2066 {
2067 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
2068 	const struct rtw89_chip_info *chip = rtwdev->chip;
2069 	const struct rtw89_phy_table *nctl_table;
2070 
2071 	rtw89_phy_preinit_rf_nctl(rtwdev);
2072 
2073 	nctl_table = elm_info->rf_nctl ? elm_info->rf_nctl : chip->nctl_table;
2074 
2075 	rtw89_io_pack(rtwdev);
2076 	rtw89_phy_init_reg(rtwdev, nctl_table, false, rtw89_phy_config_bb_reg, NULL);
2077 	rtw89_io_unpack(rtwdev);
2078 
2079 	if (chip->nctl_post_table)
2080 		rtw89_rfk_parser(rtwdev, chip->nctl_post_table);
2081 }
2082 
2083 static u32 rtw89_phy0_phy1_offset_ax(struct rtw89_dev *rtwdev, u32 addr)
2084 {
2085 	u32 phy_page = addr >> 8;
2086 	u32 ofst = 0;
2087 
2088 	switch (phy_page) {
2089 	case 0x6:
2090 	case 0x7:
2091 	case 0x8:
2092 	case 0x9:
2093 	case 0xa:
2094 	case 0xb:
2095 	case 0xc:
2096 	case 0xd:
2097 	case 0x19:
2098 	case 0x1a:
2099 	case 0x1b:
2100 		ofst = 0x2000;
2101 		break;
2102 	default:
2103 		/* warning case */
2104 		ofst = 0;
2105 		break;
2106 	}
2107 
2108 	if (phy_page >= 0x40 && phy_page <= 0x4f)
2109 		ofst = 0x2000;
2110 
2111 	return ofst;
2112 }
2113 
2114 void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
2115 			   u32 data, enum rtw89_phy_idx phy_idx)
2116 {
2117 	if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
2118 		addr += rtw89_phy0_phy1_offset(rtwdev, addr);
2119 	rtw89_phy_write32_mask(rtwdev, addr, mask, data);
2120 }
2121 EXPORT_SYMBOL(rtw89_phy_write32_idx);
2122 
2123 void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits,
2124 			       enum rtw89_phy_idx phy_idx)
2125 {
2126 	if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
2127 		addr += rtw89_phy0_phy1_offset(rtwdev, addr);
2128 	rtw89_phy_write32_set(rtwdev, addr, bits);
2129 }
2130 EXPORT_SYMBOL(rtw89_phy_write32_idx_set);
2131 
2132 void rtw89_phy_write32_idx_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits,
2133 			       enum rtw89_phy_idx phy_idx)
2134 {
2135 	if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
2136 		addr += rtw89_phy0_phy1_offset(rtwdev, addr);
2137 	rtw89_phy_write32_clr(rtwdev, addr, bits);
2138 }
2139 EXPORT_SYMBOL(rtw89_phy_write32_idx_clr);
2140 
2141 u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
2142 			 enum rtw89_phy_idx phy_idx)
2143 {
2144 	if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
2145 		addr += rtw89_phy0_phy1_offset(rtwdev, addr);
2146 	return rtw89_phy_read32_mask(rtwdev, addr, mask);
2147 }
2148 EXPORT_SYMBOL(rtw89_phy_read32_idx);
2149 
2150 void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
2151 			    u32 val)
2152 {
2153 	rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_0);
2154 
2155 	if (!rtwdev->dbcc_en)
2156 		return;
2157 
2158 	rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_1);
2159 }
2160 EXPORT_SYMBOL(rtw89_phy_set_phy_regs);
2161 
2162 void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
2163 			      const struct rtw89_phy_reg3_tbl *tbl)
2164 {
2165 	const struct rtw89_reg3_def *reg3;
2166 	int i;
2167 
2168 	for (i = 0; i < tbl->size; i++) {
2169 		reg3 = &tbl->reg3[i];
2170 		rtw89_phy_write32_mask(rtwdev, reg3->addr, reg3->mask, reg3->data);
2171 	}
2172 }
2173 EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl);
2174 
2175 static u8 rtw89_phy_ant_gain_domain_to_regd(struct rtw89_dev *rtwdev, u8 ant_gain_regd)
2176 {
2177 	switch (ant_gain_regd) {
2178 	case RTW89_ANT_GAIN_ETSI:
2179 		return RTW89_ETSI;
2180 	default:
2181 		rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2182 			    "unknown antenna gain domain: %d\n",
2183 			    ant_gain_regd);
2184 		return RTW89_REGD_NUM;
2185 	}
2186 }
2187 
2188 /* antenna gain in unit of 0.25 dbm */
2189 #define RTW89_ANT_GAIN_2GHZ_MIN -8
2190 #define RTW89_ANT_GAIN_2GHZ_MAX 14
2191 #define RTW89_ANT_GAIN_5GHZ_MIN -8
2192 #define RTW89_ANT_GAIN_5GHZ_MAX 20
2193 #define RTW89_ANT_GAIN_6GHZ_MIN -8
2194 #define RTW89_ANT_GAIN_6GHZ_MAX 20
2195 
2196 #define RTW89_ANT_GAIN_REF_2GHZ 14
2197 #define RTW89_ANT_GAIN_REF_5GHZ 20
2198 #define RTW89_ANT_GAIN_REF_6GHZ 20
2199 
2200 void rtw89_phy_ant_gain_init(struct rtw89_dev *rtwdev)
2201 {
2202 	struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
2203 	const struct rtw89_chip_info *chip = rtwdev->chip;
2204 	struct rtw89_acpi_rtag_result res = {};
2205 	u32 domain;
2206 	int ret;
2207 	u8 i, j;
2208 	u8 regd;
2209 	u8 val;
2210 
2211 	if (!chip->support_ant_gain)
2212 		return;
2213 
2214 	ret = rtw89_acpi_evaluate_rtag(rtwdev, &res);
2215 	if (ret) {
2216 		rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2217 			    "acpi: cannot eval rtag: %d\n", ret);
2218 		return;
2219 	}
2220 
2221 	if (res.revision != 0) {
2222 		rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2223 			    "unknown rtag revision: %d\n", res.revision);
2224 		return;
2225 	}
2226 
2227 	domain = get_unaligned_le32(&res.domain);
2228 
2229 	for (i = 0; i < RTW89_ANT_GAIN_DOMAIN_NUM; i++) {
2230 		if (!(domain & BIT(i)))
2231 			continue;
2232 
2233 		regd = rtw89_phy_ant_gain_domain_to_regd(rtwdev, i);
2234 		if (regd >= RTW89_REGD_NUM)
2235 			continue;
2236 		ant_gain->regd_enabled |= BIT(regd);
2237 	}
2238 
2239 	for (i = 0; i < RTW89_ANT_GAIN_CHAIN_NUM; i++) {
2240 		for (j = 0; j < RTW89_ANT_GAIN_SUBBAND_NR; j++) {
2241 			val = res.ant_gain_table[i][j];
2242 			switch (j) {
2243 			default:
2244 			case RTW89_ANT_GAIN_2GHZ_SUBBAND:
2245 				val = RTW89_ANT_GAIN_REF_2GHZ -
2246 				      clamp_t(s8, val,
2247 					      RTW89_ANT_GAIN_2GHZ_MIN,
2248 					      RTW89_ANT_GAIN_2GHZ_MAX);
2249 				break;
2250 			case RTW89_ANT_GAIN_5GHZ_SUBBAND_1:
2251 			case RTW89_ANT_GAIN_5GHZ_SUBBAND_2:
2252 			case RTW89_ANT_GAIN_5GHZ_SUBBAND_2E:
2253 			case RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4:
2254 				val = RTW89_ANT_GAIN_REF_5GHZ -
2255 				      clamp_t(s8, val,
2256 					      RTW89_ANT_GAIN_5GHZ_MIN,
2257 					      RTW89_ANT_GAIN_5GHZ_MAX);
2258 				break;
2259 			case RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L:
2260 			case RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H:
2261 			case RTW89_ANT_GAIN_6GHZ_SUBBAND_6:
2262 			case RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L:
2263 			case RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H:
2264 			case RTW89_ANT_GAIN_6GHZ_SUBBAND_8:
2265 				val = RTW89_ANT_GAIN_REF_6GHZ -
2266 				      clamp_t(s8, val,
2267 					      RTW89_ANT_GAIN_6GHZ_MIN,
2268 					      RTW89_ANT_GAIN_6GHZ_MAX);
2269 			}
2270 			ant_gain->offset[i][j] = val;
2271 		}
2272 	}
2273 }
2274 
2275 static
2276 enum rtw89_ant_gain_subband rtw89_phy_ant_gain_get_subband(struct rtw89_dev *rtwdev,
2277 							   u32 center_freq)
2278 {
2279 	switch (center_freq) {
2280 	default:
2281 		rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2282 			    "center freq: %u to antenna gain subband is unhandled\n",
2283 			    center_freq);
2284 		fallthrough;
2285 	case 2412 ... 2484:
2286 		return RTW89_ANT_GAIN_2GHZ_SUBBAND;
2287 	case 5180 ... 5240:
2288 		return RTW89_ANT_GAIN_5GHZ_SUBBAND_1;
2289 	case 5250 ... 5320:
2290 		return RTW89_ANT_GAIN_5GHZ_SUBBAND_2;
2291 	case 5500 ... 5720:
2292 		return RTW89_ANT_GAIN_5GHZ_SUBBAND_2E;
2293 	case 5745 ... 5885:
2294 		return RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4;
2295 	case 5955 ... 6155:
2296 		return RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L;
2297 	case 6175 ... 6415:
2298 		return RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H;
2299 	case 6435 ... 6515:
2300 		return RTW89_ANT_GAIN_6GHZ_SUBBAND_6;
2301 	case 6535 ... 6695:
2302 		return RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L;
2303 	case 6715 ... 6855:
2304 		return RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H;
2305 
2306 	/* freq 6875 (ch 185, 20MHz) spans RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H
2307 	 * and RTW89_ANT_GAIN_6GHZ_SUBBAND_8, so directly describe it with
2308 	 * struct rtw89_6ghz_span.
2309 	 */
2310 
2311 	case 6895 ... 7115:
2312 		return RTW89_ANT_GAIN_6GHZ_SUBBAND_8;
2313 	}
2314 }
2315 
2316 static s8 rtw89_phy_ant_gain_query(struct rtw89_dev *rtwdev,
2317 				   enum rtw89_rf_path path, u32 center_freq)
2318 {
2319 	struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
2320 	enum rtw89_ant_gain_subband subband_l, subband_h;
2321 	const struct rtw89_6ghz_span *span;
2322 
2323 	span = rtw89_get_6ghz_span(rtwdev, center_freq);
2324 
2325 	if (span && RTW89_ANT_GAIN_SPAN_VALID(span)) {
2326 		subband_l = span->ant_gain_subband_low;
2327 		subband_h = span->ant_gain_subband_high;
2328 	} else {
2329 		subband_l = rtw89_phy_ant_gain_get_subband(rtwdev, center_freq);
2330 		subband_h = subband_l;
2331 	}
2332 
2333 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2334 		    "center_freq %u: antenna gain subband {%u, %u}\n",
2335 		    center_freq, subband_l, subband_h);
2336 
2337 	return min(ant_gain->offset[path][subband_l],
2338 		   ant_gain->offset[path][subband_h]);
2339 }
2340 
2341 static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u32 center_freq)
2342 {
2343 	s8 offset_patha, offset_pathb;
2344 
2345 	offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, center_freq);
2346 	offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, center_freq);
2347 
2348 	if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
2349 		return min(offset_patha, offset_pathb);
2350 
2351 	return max(offset_patha, offset_pathb);
2352 }
2353 
2354 static bool rtw89_can_apply_ant_gain(struct rtw89_dev *rtwdev, u8 band)
2355 {
2356 	const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
2357 	struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
2358 	const struct rtw89_chip_info *chip = rtwdev->chip;
2359 	u8 regd = rtw89_regd_get(rtwdev, band);
2360 
2361 	if (!chip->support_ant_gain)
2362 		return false;
2363 
2364 	if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
2365 		return false;
2366 
2367 	if (!rfe_parms->has_da)
2368 		return false;
2369 
2370 	return true;
2371 }
2372 
2373 s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev,
2374 				  const struct rtw89_chan *chan)
2375 {
2376 	s8 offset_patha, offset_pathb;
2377 
2378 	if (!rtw89_can_apply_ant_gain(rtwdev, chan->band_type))
2379 		return 0;
2380 
2381 	if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
2382 		return 0;
2383 
2384 	offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq);
2385 	offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, chan->freq);
2386 
2387 	return rtw89_phy_txpwr_rf_to_bb(rtwdev, offset_patha - offset_pathb);
2388 }
2389 EXPORT_SYMBOL(rtw89_phy_ant_gain_pwr_offset);
2390 
2391 int rtw89_print_ant_gain(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
2392 			 const struct rtw89_chan *chan)
2393 {
2394 	char *p = buf, *end = buf + bufsz;
2395 	s8 offset_patha, offset_pathb;
2396 
2397 	if (!rtw89_can_apply_ant_gain(rtwdev, chan->band_type)) {
2398 		p += scnprintf(p, end - p, "no DAG is applied\n");
2399 		goto out;
2400 	}
2401 
2402 	offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq);
2403 	offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, chan->freq);
2404 
2405 	p += scnprintf(p, end - p, "ChainA offset: %d dBm\n", offset_patha);
2406 	p += scnprintf(p, end - p, "ChainB offset: %d dBm\n", offset_pathb);
2407 
2408 out:
2409 	return p - buf;
2410 }
2411 
2412 static const u8 rtw89_rs_idx_num_ax[] = {
2413 	[RTW89_RS_CCK] = RTW89_RATE_CCK_NUM,
2414 	[RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM,
2415 	[RTW89_RS_MCS] = RTW89_RATE_MCS_NUM_AX,
2416 	[RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_NUM,
2417 	[RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_NUM_AX,
2418 };
2419 
2420 static const u8 rtw89_rs_nss_num_ax[] = {
2421 	[RTW89_RS_CCK] = 1,
2422 	[RTW89_RS_OFDM] = 1,
2423 	[RTW89_RS_MCS] = RTW89_NSS_NUM,
2424 	[RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_NUM,
2425 	[RTW89_RS_OFFSET] = 1,
2426 };
2427 
2428 s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
2429 			   struct rtw89_txpwr_byrate *head,
2430 			   const struct rtw89_rate_desc *desc)
2431 {
2432 	switch (desc->rs) {
2433 	case RTW89_RS_CCK:
2434 		return &head->cck[desc->idx];
2435 	case RTW89_RS_OFDM:
2436 		return &head->ofdm[desc->idx];
2437 	case RTW89_RS_MCS:
2438 		return &head->mcs[desc->ofdma][desc->nss][desc->idx];
2439 	case RTW89_RS_HEDCM:
2440 		return &head->hedcm[desc->ofdma][desc->nss][desc->idx];
2441 	case RTW89_RS_OFFSET:
2442 		return &head->offset[desc->idx];
2443 	default:
2444 		rtw89_warn(rtwdev, "unrecognized byr rs: %d\n", desc->rs);
2445 		return &head->trap;
2446 	}
2447 }
2448 
2449 void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
2450 				 const struct rtw89_txpwr_table *tbl)
2451 {
2452 	const struct rtw89_txpwr_byrate_cfg *cfg = tbl->data;
2453 	const struct rtw89_txpwr_byrate_cfg *end = cfg + tbl->size;
2454 	struct rtw89_txpwr_byrate *byr_head;
2455 	struct rtw89_rate_desc desc = {};
2456 	s8 *byr;
2457 	u32 data;
2458 	u8 i;
2459 
2460 	for (; cfg < end; cfg++) {
2461 		byr_head = &rtwdev->byr[cfg->band][0];
2462 		desc.rs = cfg->rs;
2463 		desc.nss = cfg->nss;
2464 		data = cfg->data;
2465 
2466 		for (i = 0; i < cfg->len; i++, data >>= 8) {
2467 			desc.idx = cfg->shf + i;
2468 			byr = rtw89_phy_raw_byr_seek(rtwdev, byr_head, &desc);
2469 			*byr = data & 0xff;
2470 		}
2471 	}
2472 }
2473 EXPORT_SYMBOL(rtw89_phy_load_txpwr_byrate);
2474 
2475 static s8 rtw89_phy_txpwr_dbm_without_tolerance(s8 dbm)
2476 {
2477 	const u8 tssi_deviation_point = 0;
2478 	const u8 tssi_max_deviation = 2;
2479 
2480 	if (dbm <= tssi_deviation_point)
2481 		dbm -= tssi_max_deviation;
2482 
2483 	return dbm;
2484 }
2485 
2486 static s8 rtw89_phy_get_tpe_constraint(struct rtw89_dev *rtwdev, u8 band)
2487 {
2488 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
2489 	const struct rtw89_reg_6ghz_tpe *tpe = &regulatory->reg_6ghz_tpe;
2490 	s8 cstr = S8_MAX;
2491 
2492 	if (band == RTW89_BAND_6G && tpe->valid)
2493 		cstr = rtw89_phy_txpwr_dbm_without_tolerance(tpe->constraint);
2494 
2495 	return rtw89_phy_txpwr_dbm_to_mac(rtwdev, cstr);
2496 }
2497 
2498 s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band, u8 bw,
2499 			       const struct rtw89_rate_desc *rate_desc)
2500 {
2501 	struct rtw89_txpwr_byrate *byr_head;
2502 	s8 *byr;
2503 
2504 	if (rate_desc->rs == RTW89_RS_CCK)
2505 		band = RTW89_BAND_2G;
2506 
2507 	byr_head = &rtwdev->byr[band][bw];
2508 	byr = rtw89_phy_raw_byr_seek(rtwdev, byr_head, rate_desc);
2509 
2510 	return rtw89_phy_txpwr_rf_to_mac(rtwdev, *byr);
2511 }
2512 
2513 static u8 rtw89_channel_6g_to_idx(struct rtw89_dev *rtwdev, u8 channel_6g)
2514 {
2515 	switch (channel_6g) {
2516 	case 1 ... 29:
2517 		return (channel_6g - 1) / 2;
2518 	case 33 ... 61:
2519 		return (channel_6g - 3) / 2;
2520 	case 65 ... 93:
2521 		return (channel_6g - 5) / 2;
2522 	case 97 ... 125:
2523 		return (channel_6g - 7) / 2;
2524 	case 129 ... 157:
2525 		return (channel_6g - 9) / 2;
2526 	case 161 ... 189:
2527 		return (channel_6g - 11) / 2;
2528 	case 193 ... 221:
2529 		return (channel_6g - 13) / 2;
2530 	case 225 ... 253:
2531 		return (channel_6g - 15) / 2;
2532 	default:
2533 		rtw89_warn(rtwdev, "unknown 6g channel: %d\n", channel_6g);
2534 		return 0;
2535 	}
2536 }
2537 
2538 static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel)
2539 {
2540 	if (band == RTW89_BAND_6G)
2541 		return rtw89_channel_6g_to_idx(rtwdev, channel);
2542 
2543 	switch (channel) {
2544 	case 1 ... 14:
2545 		return channel - 1;
2546 	case 36 ... 64:
2547 		return (channel - 36) / 2;
2548 	case 100 ... 144:
2549 		return ((channel - 100) / 2) + 15;
2550 	case 149 ... 177:
2551 		return ((channel - 149) / 2) + 38;
2552 	default:
2553 		rtw89_warn(rtwdev, "unknown channel: %d\n", channel);
2554 		return 0;
2555 	}
2556 }
2557 
2558 static bool rtw89_phy_validate_txpwr_limit_bw(struct rtw89_dev *rtwdev,
2559 					      u8 band, u8 bw)
2560 {
2561 	switch (band) {
2562 	case RTW89_BAND_2G:
2563 		return bw < RTW89_2G_BW_NUM;
2564 	case RTW89_BAND_5G:
2565 		return bw < RTW89_5G_BW_NUM;
2566 	case RTW89_BAND_6G:
2567 		return bw < RTW89_6G_BW_NUM;
2568 	default:
2569 		return false;
2570 	}
2571 }
2572 
2573 s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
2574 			      u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
2575 {
2576 	const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
2577 	const struct rtw89_txpwr_rule_2ghz *rule_da_2ghz = &rfe_parms->rule_da_2ghz;
2578 	const struct rtw89_txpwr_rule_5ghz *rule_da_5ghz = &rfe_parms->rule_da_5ghz;
2579 	const struct rtw89_txpwr_rule_6ghz *rule_da_6ghz = &rfe_parms->rule_da_6ghz;
2580 	const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
2581 	const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
2582 	const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
2583 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
2584 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
2585 	bool has_ant_gain = rtw89_can_apply_ant_gain(rtwdev, band);
2586 	u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
2587 	u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
2588 	s8 lmt = 0, da_lmt = S8_MAX, sar, offset = 0;
2589 	u8 regd = rtw89_regd_get(rtwdev, band);
2590 	u8 reg6 = regulatory->reg_6ghz_power;
2591 	struct rtw89_sar_parm sar_parm = {
2592 		.center_freq = freq,
2593 		.ntx = ntx,
2594 	};
2595 	s8 cstr;
2596 
2597 	if (!rtw89_phy_validate_txpwr_limit_bw(rtwdev, band, bw)) {
2598 		rtw89_warn(rtwdev, "invalid band %u bandwidth %u\n", band, bw);
2599 		return 0;
2600 	}
2601 
2602 	switch (band) {
2603 	case RTW89_BAND_2G:
2604 		if (has_ant_gain)
2605 			da_lmt = (*rule_da_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
2606 
2607 		lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
2608 		if (lmt)
2609 			break;
2610 
2611 		lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
2612 		break;
2613 	case RTW89_BAND_5G:
2614 		if (has_ant_gain)
2615 			da_lmt = (*rule_da_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
2616 
2617 		lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
2618 		if (lmt)
2619 			break;
2620 
2621 		lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
2622 		break;
2623 	case RTW89_BAND_6G:
2624 		if (has_ant_gain)
2625 			da_lmt = (*rule_da_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
2626 
2627 		lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
2628 		if (lmt)
2629 			break;
2630 
2631 		lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW]
2632 				       [RTW89_REG_6GHZ_POWER_DFLT]
2633 				       [ch_idx];
2634 		break;
2635 	default:
2636 		rtw89_warn(rtwdev, "unknown band type: %d\n", band);
2637 		return 0;
2638 	}
2639 
2640 	da_lmt = da_lmt ?: S8_MAX;
2641 	if (da_lmt != S8_MAX)
2642 		offset = rtw89_phy_ant_gain_offset(rtwdev, freq);
2643 
2644 	lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, min(lmt + offset, da_lmt));
2645 	sar = rtw89_query_sar(rtwdev, &sar_parm);
2646 	cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
2647 
2648 	return min3(lmt, sar, cstr);
2649 }
2650 EXPORT_SYMBOL(rtw89_phy_read_txpwr_limit);
2651 
2652 #define __fill_txpwr_limit_nonbf_bf(ptr, band, bw, ntx, rs, ch)		\
2653 	do {								\
2654 		u8 __i;							\
2655 		for (__i = 0; __i < RTW89_BF_NUM; __i++)		\
2656 			ptr[__i] = rtw89_phy_read_txpwr_limit(rtwdev,	\
2657 							      band,	\
2658 							      bw, ntx,	\
2659 							      rs, __i,	\
2660 							      (ch));	\
2661 	} while (0)
2662 
2663 static void rtw89_phy_fill_txpwr_limit_20m_ax(struct rtw89_dev *rtwdev,
2664 					      struct rtw89_txpwr_limit_ax *lmt,
2665 					      u8 band, u8 ntx, u8 ch)
2666 {
2667 	__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
2668 				    ntx, RTW89_RS_CCK, ch);
2669 	__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
2670 				    ntx, RTW89_RS_CCK, ch);
2671 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
2672 				    ntx, RTW89_RS_OFDM, ch);
2673 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
2674 				    RTW89_CHANNEL_WIDTH_20,
2675 				    ntx, RTW89_RS_MCS, ch);
2676 }
2677 
2678 static void rtw89_phy_fill_txpwr_limit_40m_ax(struct rtw89_dev *rtwdev,
2679 					      struct rtw89_txpwr_limit_ax *lmt,
2680 					      u8 band, u8 ntx, u8 ch, u8 pri_ch)
2681 {
2682 	__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
2683 				    ntx, RTW89_RS_CCK, ch - 2);
2684 	__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
2685 				    ntx, RTW89_RS_CCK, ch);
2686 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
2687 				    ntx, RTW89_RS_OFDM, pri_ch);
2688 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
2689 				    RTW89_CHANNEL_WIDTH_20,
2690 				    ntx, RTW89_RS_MCS, ch - 2);
2691 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
2692 				    RTW89_CHANNEL_WIDTH_20,
2693 				    ntx, RTW89_RS_MCS, ch + 2);
2694 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
2695 				    RTW89_CHANNEL_WIDTH_40,
2696 				    ntx, RTW89_RS_MCS, ch);
2697 }
2698 
2699 static void rtw89_phy_fill_txpwr_limit_80m_ax(struct rtw89_dev *rtwdev,
2700 					      struct rtw89_txpwr_limit_ax *lmt,
2701 					      u8 band, u8 ntx, u8 ch, u8 pri_ch)
2702 {
2703 	s8 val_0p5_n[RTW89_BF_NUM];
2704 	s8 val_0p5_p[RTW89_BF_NUM];
2705 	u8 i;
2706 
2707 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
2708 				    ntx, RTW89_RS_OFDM, pri_ch);
2709 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
2710 				    RTW89_CHANNEL_WIDTH_20,
2711 				    ntx, RTW89_RS_MCS, ch - 6);
2712 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
2713 				    RTW89_CHANNEL_WIDTH_20,
2714 				    ntx, RTW89_RS_MCS, ch - 2);
2715 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
2716 				    RTW89_CHANNEL_WIDTH_20,
2717 				    ntx, RTW89_RS_MCS, ch + 2);
2718 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
2719 				    RTW89_CHANNEL_WIDTH_20,
2720 				    ntx, RTW89_RS_MCS, ch + 6);
2721 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
2722 				    RTW89_CHANNEL_WIDTH_40,
2723 				    ntx, RTW89_RS_MCS, ch - 4);
2724 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
2725 				    RTW89_CHANNEL_WIDTH_40,
2726 				    ntx, RTW89_RS_MCS, ch + 4);
2727 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
2728 				    RTW89_CHANNEL_WIDTH_80,
2729 				    ntx, RTW89_RS_MCS, ch);
2730 
2731 	__fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
2732 				    ntx, RTW89_RS_MCS, ch - 4);
2733 	__fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
2734 				    ntx, RTW89_RS_MCS, ch + 4);
2735 
2736 	for (i = 0; i < RTW89_BF_NUM; i++)
2737 		lmt->mcs_40m_0p5[i] = min_t(s8, val_0p5_n[i], val_0p5_p[i]);
2738 }
2739 
2740 static void rtw89_phy_fill_txpwr_limit_160m_ax(struct rtw89_dev *rtwdev,
2741 					       struct rtw89_txpwr_limit_ax *lmt,
2742 					       u8 band, u8 ntx, u8 ch, u8 pri_ch)
2743 {
2744 	s8 val_0p5_n[RTW89_BF_NUM];
2745 	s8 val_0p5_p[RTW89_BF_NUM];
2746 	s8 val_2p5_n[RTW89_BF_NUM];
2747 	s8 val_2p5_p[RTW89_BF_NUM];
2748 	u8 i;
2749 
2750 	/* fill ofdm section */
2751 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
2752 				    ntx, RTW89_RS_OFDM, pri_ch);
2753 
2754 	/* fill mcs 20m section */
2755 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
2756 				    RTW89_CHANNEL_WIDTH_20,
2757 				    ntx, RTW89_RS_MCS, ch - 14);
2758 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
2759 				    RTW89_CHANNEL_WIDTH_20,
2760 				    ntx, RTW89_RS_MCS, ch - 10);
2761 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
2762 				    RTW89_CHANNEL_WIDTH_20,
2763 				    ntx, RTW89_RS_MCS, ch - 6);
2764 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
2765 				    RTW89_CHANNEL_WIDTH_20,
2766 				    ntx, RTW89_RS_MCS, ch - 2);
2767 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[4], band,
2768 				    RTW89_CHANNEL_WIDTH_20,
2769 				    ntx, RTW89_RS_MCS, ch + 2);
2770 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[5], band,
2771 				    RTW89_CHANNEL_WIDTH_20,
2772 				    ntx, RTW89_RS_MCS, ch + 6);
2773 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[6], band,
2774 				    RTW89_CHANNEL_WIDTH_20,
2775 				    ntx, RTW89_RS_MCS, ch + 10);
2776 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[7], band,
2777 				    RTW89_CHANNEL_WIDTH_20,
2778 				    ntx, RTW89_RS_MCS, ch + 14);
2779 
2780 	/* fill mcs 40m section */
2781 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
2782 				    RTW89_CHANNEL_WIDTH_40,
2783 				    ntx, RTW89_RS_MCS, ch - 12);
2784 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
2785 				    RTW89_CHANNEL_WIDTH_40,
2786 				    ntx, RTW89_RS_MCS, ch - 4);
2787 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[2], band,
2788 				    RTW89_CHANNEL_WIDTH_40,
2789 				    ntx, RTW89_RS_MCS, ch + 4);
2790 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[3], band,
2791 				    RTW89_CHANNEL_WIDTH_40,
2792 				    ntx, RTW89_RS_MCS, ch + 12);
2793 
2794 	/* fill mcs 80m section */
2795 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
2796 				    RTW89_CHANNEL_WIDTH_80,
2797 				    ntx, RTW89_RS_MCS, ch - 8);
2798 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[1], band,
2799 				    RTW89_CHANNEL_WIDTH_80,
2800 				    ntx, RTW89_RS_MCS, ch + 8);
2801 
2802 	/* fill mcs 160m section */
2803 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_160m, band,
2804 				    RTW89_CHANNEL_WIDTH_160,
2805 				    ntx, RTW89_RS_MCS, ch);
2806 
2807 	/* fill mcs 40m 0p5 section */
2808 	__fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
2809 				    ntx, RTW89_RS_MCS, ch - 4);
2810 	__fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
2811 				    ntx, RTW89_RS_MCS, ch + 4);
2812 
2813 	for (i = 0; i < RTW89_BF_NUM; i++)
2814 		lmt->mcs_40m_0p5[i] = min_t(s8, val_0p5_n[i], val_0p5_p[i]);
2815 
2816 	/* fill mcs 40m 2p5 section */
2817 	__fill_txpwr_limit_nonbf_bf(val_2p5_n, band, RTW89_CHANNEL_WIDTH_40,
2818 				    ntx, RTW89_RS_MCS, ch - 8);
2819 	__fill_txpwr_limit_nonbf_bf(val_2p5_p, band, RTW89_CHANNEL_WIDTH_40,
2820 				    ntx, RTW89_RS_MCS, ch + 8);
2821 
2822 	for (i = 0; i < RTW89_BF_NUM; i++)
2823 		lmt->mcs_40m_2p5[i] = min_t(s8, val_2p5_n[i], val_2p5_p[i]);
2824 }
2825 
2826 static
2827 void rtw89_phy_fill_txpwr_limit_ax(struct rtw89_dev *rtwdev,
2828 				   const struct rtw89_chan *chan,
2829 				   struct rtw89_txpwr_limit_ax *lmt,
2830 				   u8 ntx)
2831 {
2832 	u8 band = chan->band_type;
2833 	u8 pri_ch = chan->primary_channel;
2834 	u8 ch = chan->channel;
2835 	u8 bw = chan->band_width;
2836 
2837 	memset(lmt, 0, sizeof(*lmt));
2838 
2839 	switch (bw) {
2840 	case RTW89_CHANNEL_WIDTH_20:
2841 		rtw89_phy_fill_txpwr_limit_20m_ax(rtwdev, lmt, band, ntx, ch);
2842 		break;
2843 	case RTW89_CHANNEL_WIDTH_40:
2844 		rtw89_phy_fill_txpwr_limit_40m_ax(rtwdev, lmt, band, ntx, ch,
2845 						  pri_ch);
2846 		break;
2847 	case RTW89_CHANNEL_WIDTH_80:
2848 		rtw89_phy_fill_txpwr_limit_80m_ax(rtwdev, lmt, band, ntx, ch,
2849 						  pri_ch);
2850 		break;
2851 	case RTW89_CHANNEL_WIDTH_160:
2852 		rtw89_phy_fill_txpwr_limit_160m_ax(rtwdev, lmt, band, ntx, ch,
2853 						   pri_ch);
2854 		break;
2855 	}
2856 }
2857 
2858 s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
2859 				 u8 ru, u8 ntx, u8 ch)
2860 {
2861 	const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
2862 	const struct rtw89_txpwr_rule_2ghz *rule_da_2ghz = &rfe_parms->rule_da_2ghz;
2863 	const struct rtw89_txpwr_rule_5ghz *rule_da_5ghz = &rfe_parms->rule_da_5ghz;
2864 	const struct rtw89_txpwr_rule_6ghz *rule_da_6ghz = &rfe_parms->rule_da_6ghz;
2865 	const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
2866 	const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
2867 	const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
2868 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
2869 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
2870 	bool has_ant_gain = rtw89_can_apply_ant_gain(rtwdev, band);
2871 	u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
2872 	u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
2873 	s8 lmt_ru = 0, da_lmt_ru = S8_MAX, sar, offset = 0;
2874 	u8 regd = rtw89_regd_get(rtwdev, band);
2875 	u8 reg6 = regulatory->reg_6ghz_power;
2876 	struct rtw89_sar_parm sar_parm = {
2877 		.center_freq = freq,
2878 		.ntx = ntx,
2879 	};
2880 	s8 cstr;
2881 
2882 	switch (band) {
2883 	case RTW89_BAND_2G:
2884 		if (has_ant_gain)
2885 			da_lmt_ru = (*rule_da_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
2886 
2887 		lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
2888 		if (lmt_ru)
2889 			break;
2890 
2891 		lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
2892 		break;
2893 	case RTW89_BAND_5G:
2894 		if (has_ant_gain)
2895 			da_lmt_ru = (*rule_da_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
2896 
2897 		lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
2898 		if (lmt_ru)
2899 			break;
2900 
2901 		lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
2902 		break;
2903 	case RTW89_BAND_6G:
2904 		if (has_ant_gain)
2905 			da_lmt_ru = (*rule_da_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
2906 
2907 		lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
2908 		if (lmt_ru)
2909 			break;
2910 
2911 		lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW]
2912 					     [RTW89_REG_6GHZ_POWER_DFLT]
2913 					     [ch_idx];
2914 		break;
2915 	default:
2916 		rtw89_warn(rtwdev, "unknown band type: %d\n", band);
2917 		return 0;
2918 	}
2919 
2920 	da_lmt_ru = da_lmt_ru ?: S8_MAX;
2921 	if (da_lmt_ru != S8_MAX)
2922 		offset = rtw89_phy_ant_gain_offset(rtwdev, freq);
2923 
2924 	lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, min(lmt_ru + offset, da_lmt_ru));
2925 	sar = rtw89_query_sar(rtwdev, &sar_parm);
2926 	cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
2927 
2928 	return min3(lmt_ru, sar, cstr);
2929 }
2930 
2931 static void
2932 rtw89_phy_fill_txpwr_limit_ru_20m_ax(struct rtw89_dev *rtwdev,
2933 				     struct rtw89_txpwr_limit_ru_ax *lmt_ru,
2934 				     u8 band, u8 ntx, u8 ch)
2935 {
2936 	lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2937 							RTW89_RU26,
2938 							ntx, ch);
2939 	lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2940 							RTW89_RU52,
2941 							ntx, ch);
2942 	lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2943 							 RTW89_RU106,
2944 							 ntx, ch);
2945 }
2946 
2947 static void
2948 rtw89_phy_fill_txpwr_limit_ru_40m_ax(struct rtw89_dev *rtwdev,
2949 				     struct rtw89_txpwr_limit_ru_ax *lmt_ru,
2950 				     u8 band, u8 ntx, u8 ch)
2951 {
2952 	lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2953 							RTW89_RU26,
2954 							ntx, ch - 2);
2955 	lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2956 							RTW89_RU26,
2957 							ntx, ch + 2);
2958 	lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2959 							RTW89_RU52,
2960 							ntx, ch - 2);
2961 	lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2962 							RTW89_RU52,
2963 							ntx, ch + 2);
2964 	lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2965 							 RTW89_RU106,
2966 							 ntx, ch - 2);
2967 	lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2968 							 RTW89_RU106,
2969 							 ntx, ch + 2);
2970 }
2971 
2972 static void
2973 rtw89_phy_fill_txpwr_limit_ru_80m_ax(struct rtw89_dev *rtwdev,
2974 				     struct rtw89_txpwr_limit_ru_ax *lmt_ru,
2975 				     u8 band, u8 ntx, u8 ch)
2976 {
2977 	lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2978 							RTW89_RU26,
2979 							ntx, ch - 6);
2980 	lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2981 							RTW89_RU26,
2982 							ntx, ch - 2);
2983 	lmt_ru->ru26[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2984 							RTW89_RU26,
2985 							ntx, ch + 2);
2986 	lmt_ru->ru26[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2987 							RTW89_RU26,
2988 							ntx, ch + 6);
2989 	lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2990 							RTW89_RU52,
2991 							ntx, ch - 6);
2992 	lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2993 							RTW89_RU52,
2994 							ntx, ch - 2);
2995 	lmt_ru->ru52[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2996 							RTW89_RU52,
2997 							ntx, ch + 2);
2998 	lmt_ru->ru52[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
2999 							RTW89_RU52,
3000 							ntx, ch + 6);
3001 	lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
3002 							 RTW89_RU106,
3003 							 ntx, ch - 6);
3004 	lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
3005 							 RTW89_RU106,
3006 							 ntx, ch - 2);
3007 	lmt_ru->ru106[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
3008 							 RTW89_RU106,
3009 							 ntx, ch + 2);
3010 	lmt_ru->ru106[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
3011 							 RTW89_RU106,
3012 							 ntx, ch + 6);
3013 }
3014 
3015 static void
3016 rtw89_phy_fill_txpwr_limit_ru_160m_ax(struct rtw89_dev *rtwdev,
3017 				      struct rtw89_txpwr_limit_ru_ax *lmt_ru,
3018 				      u8 band, u8 ntx, u8 ch)
3019 {
3020 	static const int ofst[] = { -14, -10, -6, -2, 2, 6, 10, 14 };
3021 	int i;
3022 
3023 	static_assert(ARRAY_SIZE(ofst) == RTW89_RU_SEC_NUM_AX);
3024 	for (i = 0; i < RTW89_RU_SEC_NUM_AX; i++) {
3025 		lmt_ru->ru26[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
3026 								RTW89_RU26,
3027 								ntx,
3028 								ch + ofst[i]);
3029 		lmt_ru->ru52[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
3030 								RTW89_RU52,
3031 								ntx,
3032 								ch + ofst[i]);
3033 		lmt_ru->ru106[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
3034 								 RTW89_RU106,
3035 								 ntx,
3036 								 ch + ofst[i]);
3037 	}
3038 }
3039 
3040 static
3041 void rtw89_phy_fill_txpwr_limit_ru_ax(struct rtw89_dev *rtwdev,
3042 				      const struct rtw89_chan *chan,
3043 				      struct rtw89_txpwr_limit_ru_ax *lmt_ru,
3044 				      u8 ntx)
3045 {
3046 	u8 band = chan->band_type;
3047 	u8 ch = chan->channel;
3048 	u8 bw = chan->band_width;
3049 
3050 	memset(lmt_ru, 0, sizeof(*lmt_ru));
3051 
3052 	switch (bw) {
3053 	case RTW89_CHANNEL_WIDTH_20:
3054 		rtw89_phy_fill_txpwr_limit_ru_20m_ax(rtwdev, lmt_ru, band, ntx,
3055 						     ch);
3056 		break;
3057 	case RTW89_CHANNEL_WIDTH_40:
3058 		rtw89_phy_fill_txpwr_limit_ru_40m_ax(rtwdev, lmt_ru, band, ntx,
3059 						     ch);
3060 		break;
3061 	case RTW89_CHANNEL_WIDTH_80:
3062 		rtw89_phy_fill_txpwr_limit_ru_80m_ax(rtwdev, lmt_ru, band, ntx,
3063 						     ch);
3064 		break;
3065 	case RTW89_CHANNEL_WIDTH_160:
3066 		rtw89_phy_fill_txpwr_limit_ru_160m_ax(rtwdev, lmt_ru, band, ntx,
3067 						      ch);
3068 		break;
3069 	}
3070 }
3071 
3072 static void rtw89_phy_set_txpwr_byrate_ax(struct rtw89_dev *rtwdev,
3073 					  const struct rtw89_chan *chan,
3074 					  enum rtw89_phy_idx phy_idx)
3075 {
3076 	u8 max_nss_num = rtwdev->chip->rf_path_num;
3077 	static const u8 rs[] = {
3078 		RTW89_RS_CCK,
3079 		RTW89_RS_OFDM,
3080 		RTW89_RS_MCS,
3081 		RTW89_RS_HEDCM,
3082 	};
3083 	struct rtw89_rate_desc cur = {};
3084 	u8 band = chan->band_type;
3085 	u8 ch = chan->channel;
3086 	u32 addr, val;
3087 	s8 v[4] = {};
3088 	u8 i;
3089 
3090 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
3091 		    "[TXPWR] set txpwr byrate with ch=%d\n", ch);
3092 
3093 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_CCK] % 4);
3094 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_OFDM] % 4);
3095 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_MCS] % 4);
3096 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_HEDCM] % 4);
3097 
3098 	addr = R_AX_PWR_BY_RATE;
3099 	for (cur.nss = 0; cur.nss < max_nss_num; cur.nss++) {
3100 		for (i = 0; i < ARRAY_SIZE(rs); i++) {
3101 			if (cur.nss >= rtw89_rs_nss_num_ax[rs[i]])
3102 				continue;
3103 
3104 			cur.rs = rs[i];
3105 			for (cur.idx = 0; cur.idx < rtw89_rs_idx_num_ax[rs[i]];
3106 			     cur.idx++) {
3107 				v[cur.idx % 4] =
3108 					rtw89_phy_read_txpwr_byrate(rtwdev,
3109 								    band, 0,
3110 								    &cur);
3111 
3112 				if ((cur.idx + 1) % 4)
3113 					continue;
3114 
3115 				val = FIELD_PREP(GENMASK(7, 0), v[0]) |
3116 				      FIELD_PREP(GENMASK(15, 8), v[1]) |
3117 				      FIELD_PREP(GENMASK(23, 16), v[2]) |
3118 				      FIELD_PREP(GENMASK(31, 24), v[3]);
3119 
3120 				rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr,
3121 							val);
3122 				addr += 4;
3123 			}
3124 		}
3125 	}
3126 }
3127 
3128 static
3129 void rtw89_phy_set_txpwr_offset_ax(struct rtw89_dev *rtwdev,
3130 				   const struct rtw89_chan *chan,
3131 				   enum rtw89_phy_idx phy_idx)
3132 {
3133 	struct rtw89_rate_desc desc = {
3134 		.nss = RTW89_NSS_1,
3135 		.rs = RTW89_RS_OFFSET,
3136 	};
3137 	u8 band = chan->band_type;
3138 	s8 v[RTW89_RATE_OFFSET_NUM_AX] = {};
3139 	u32 val;
3140 
3141 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
3142 
3143 	for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_NUM_AX; desc.idx++)
3144 		v[desc.idx] = rtw89_phy_read_txpwr_byrate(rtwdev, band, 0, &desc);
3145 
3146 	BUILD_BUG_ON(RTW89_RATE_OFFSET_NUM_AX != 5);
3147 	val = FIELD_PREP(GENMASK(3, 0), v[0]) |
3148 	      FIELD_PREP(GENMASK(7, 4), v[1]) |
3149 	      FIELD_PREP(GENMASK(11, 8), v[2]) |
3150 	      FIELD_PREP(GENMASK(15, 12), v[3]) |
3151 	      FIELD_PREP(GENMASK(19, 16), v[4]);
3152 
3153 	rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_OFST_CTRL,
3154 				     GENMASK(19, 0), val);
3155 }
3156 
3157 static void rtw89_phy_set_txpwr_limit_ax(struct rtw89_dev *rtwdev,
3158 					 const struct rtw89_chan *chan,
3159 					 enum rtw89_phy_idx phy_idx)
3160 {
3161 	u8 max_ntx_num = rtwdev->chip->rf_path_num;
3162 	struct rtw89_txpwr_limit_ax lmt;
3163 	u8 ch = chan->channel;
3164 	u8 bw = chan->band_width;
3165 	const s8 *ptr;
3166 	u32 addr, val;
3167 	u8 i, j;
3168 
3169 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
3170 		    "[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
3171 
3172 	BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ax) !=
3173 		     RTW89_TXPWR_LMT_PAGE_SIZE_AX);
3174 
3175 	addr = R_AX_PWR_LMT;
3176 	for (i = 0; i < max_ntx_num; i++) {
3177 		rtw89_phy_fill_txpwr_limit_ax(rtwdev, chan, &lmt, i);
3178 
3179 		ptr = (s8 *)&lmt;
3180 		for (j = 0; j < RTW89_TXPWR_LMT_PAGE_SIZE_AX;
3181 		     j += 4, addr += 4, ptr += 4) {
3182 			val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
3183 			      FIELD_PREP(GENMASK(15, 8), ptr[1]) |
3184 			      FIELD_PREP(GENMASK(23, 16), ptr[2]) |
3185 			      FIELD_PREP(GENMASK(31, 24), ptr[3]);
3186 
3187 			rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
3188 		}
3189 	}
3190 }
3191 
3192 static void rtw89_phy_set_txpwr_limit_ru_ax(struct rtw89_dev *rtwdev,
3193 					    const struct rtw89_chan *chan,
3194 					    enum rtw89_phy_idx phy_idx)
3195 {
3196 	u8 max_ntx_num = rtwdev->chip->rf_path_num;
3197 	struct rtw89_txpwr_limit_ru_ax lmt_ru;
3198 	u8 ch = chan->channel;
3199 	u8 bw = chan->band_width;
3200 	const s8 *ptr;
3201 	u32 addr, val;
3202 	u8 i, j;
3203 
3204 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
3205 		    "[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
3206 
3207 	BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ru_ax) !=
3208 		     RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX);
3209 
3210 	addr = R_AX_PWR_RU_LMT;
3211 	for (i = 0; i < max_ntx_num; i++) {
3212 		rtw89_phy_fill_txpwr_limit_ru_ax(rtwdev, chan, &lmt_ru, i);
3213 
3214 		ptr = (s8 *)&lmt_ru;
3215 		for (j = 0; j < RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX;
3216 		     j += 4, addr += 4, ptr += 4) {
3217 			val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
3218 			      FIELD_PREP(GENMASK(15, 8), ptr[1]) |
3219 			      FIELD_PREP(GENMASK(23, 16), ptr[2]) |
3220 			      FIELD_PREP(GENMASK(31, 24), ptr[3]);
3221 
3222 			rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
3223 		}
3224 	}
3225 }
3226 
3227 static int get_max_agg_wait(struct ieee80211_link_sta *link_sta, u16 amsdu_len)
3228 {
3229 	struct ieee80211_sta *sta = link_sta->sta;
3230 	int max_agg_wait = amsdu_len / 1500 - 1;
3231 
3232 	if (sta->max_amsdu_subframes)
3233 		max_agg_wait = min(max_agg_wait, sta->max_amsdu_subframes - 1);
3234 
3235 	return max_agg_wait;
3236 }
3237 
3238 struct rtw89_phy_iter_ra_data {
3239 	struct rtw89_dev *rtwdev;
3240 	struct sk_buff *c2h;
3241 };
3242 
3243 static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link,
3244 					struct ieee80211_link_sta *link_sta,
3245 					struct rtw89_phy_iter_ra_data *ra_data,
3246 					bool *changed)
3247 {
3248 	struct rtw89_dev *rtwdev = ra_data->rtwdev;
3249 	const struct rtw89_c2h_ra_rpt *c2h =
3250 		(const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data;
3251 	struct rtw89_ra_report *ra_report = &rtwsta_link->ra_report;
3252 	const struct rtw89_chip_info *chip = rtwdev->chip;
3253 	bool format_v1 = chip->chip_gen == RTW89_CHIP_BE;
3254 	u8 mode, rate, bw, giltf, mac_id;
3255 	u16 legacy_bitrate, amsdu_len;
3256 	u8 retry_ratio = 0;
3257 	bool valid;
3258 	u8 mcs = 0;
3259 	u8 t;
3260 
3261 	mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID);
3262 	if (mac_id != rtwsta_link->mac_id)
3263 		return;
3264 
3265 	rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS);
3266 	bw = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW);
3267 	giltf = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_GILTF);
3268 	mode = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL);
3269 
3270 	if (format_v1) {
3271 		t = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MCSNSS_B7);
3272 		rate |= u8_encode_bits(t, BIT(7));
3273 		t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW_B2);
3274 		bw |= u8_encode_bits(t, BIT(2));
3275 		t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL_B2);
3276 		mode |= u8_encode_bits(t, BIT(2));
3277 		retry_ratio = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_RETRY_RATIO);
3278 	}
3279 
3280 	if (mode == RTW89_RA_RPT_MODE_LEGACY) {
3281 		valid = rtw89_legacy_rate_to_bitrate(rtwdev, rate, &legacy_bitrate);
3282 		if (!valid)
3283 			return;
3284 	}
3285 
3286 	memset(&ra_report->txrate, 0, sizeof(ra_report->txrate));
3287 
3288 	switch (mode) {
3289 	case RTW89_RA_RPT_MODE_LEGACY:
3290 		ra_report->txrate.legacy = legacy_bitrate;
3291 		break;
3292 	case RTW89_RA_RPT_MODE_HT:
3293 		ra_report->txrate.flags |= RATE_INFO_FLAGS_MCS;
3294 		if (RTW89_CHK_FW_FEATURE(OLD_HT_RA_FORMAT, &rtwdev->fw))
3295 			rate = RTW89_MK_HT_RATE(FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate),
3296 						FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate));
3297 		else
3298 			rate = FIELD_GET(RTW89_RA_RATE_MASK_HT_MCS, rate);
3299 		ra_report->txrate.mcs = rate;
3300 		if (giltf)
3301 			ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
3302 		mcs = ra_report->txrate.mcs & 0x07;
3303 		break;
3304 	case RTW89_RA_RPT_MODE_VHT:
3305 		ra_report->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
3306 		ra_report->txrate.mcs = format_v1 ?
3307 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) :
3308 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS);
3309 		ra_report->txrate.nss = format_v1 ?
3310 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 :
3311 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1;
3312 		if (giltf)
3313 			ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
3314 		mcs = ra_report->txrate.mcs;
3315 		break;
3316 	case RTW89_RA_RPT_MODE_HE:
3317 		ra_report->txrate.flags |= RATE_INFO_FLAGS_HE_MCS;
3318 		ra_report->txrate.mcs = format_v1 ?
3319 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) :
3320 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS);
3321 		ra_report->txrate.nss  = format_v1 ?
3322 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 :
3323 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1;
3324 		if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08)
3325 			ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_0_8;
3326 		else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16)
3327 			ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_1_6;
3328 		else
3329 			ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_3_2;
3330 		mcs = ra_report->txrate.mcs;
3331 		break;
3332 	case RTW89_RA_RPT_MODE_EHT:
3333 		ra_report->txrate.flags |= RATE_INFO_FLAGS_EHT_MCS;
3334 		ra_report->txrate.mcs = u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1);
3335 		ra_report->txrate.nss = u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1;
3336 		if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08)
3337 			ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_0_8;
3338 		else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16)
3339 			ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_1_6;
3340 		else
3341 			ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_3_2;
3342 		mcs = ra_report->txrate.mcs;
3343 		break;
3344 	}
3345 
3346 	ra_report->txrate.bw = rtw89_hw_to_rate_info_bw(bw);
3347 	ra_report->bit_rate = cfg80211_calculate_bitrate(&ra_report->txrate);
3348 	ra_report->hw_rate = format_v1 ?
3349 			     u16_encode_bits(mode, RTW89_HW_RATE_V1_MASK_MOD) |
3350 			     u16_encode_bits(rate, RTW89_HW_RATE_V1_MASK_VAL) :
3351 			     u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) |
3352 			     u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL);
3353 	ra_report->retry_ratio = retry_ratio;
3354 	ra_report->might_fallback_legacy = mcs <= 2;
3355 
3356 	amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
3357 	if (link_sta->agg.max_rc_amsdu_len != amsdu_len) {
3358 		link_sta->agg.max_rc_amsdu_len = amsdu_len;
3359 		*changed = true;
3360 	}
3361 
3362 	rtwsta_link->max_agg_wait = get_max_agg_wait(link_sta, amsdu_len);
3363 }
3364 
3365 static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
3366 {
3367 	struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data;
3368 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
3369 	struct rtw89_sta_link *rtwsta_link;
3370 	struct ieee80211_link_sta *link_sta;
3371 	unsigned int link_id;
3372 	bool changed = false;
3373 
3374 	rcu_read_lock();
3375 
3376 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
3377 		link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
3378 		__rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data, &changed);
3379 	}
3380 
3381 	if (changed)
3382 		ieee80211_sta_recalc_aggregates(sta);
3383 
3384 	rcu_read_unlock();
3385 }
3386 
3387 static void
3388 rtw89_phy_c2h_ra_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3389 {
3390 	struct rtw89_phy_iter_ra_data ra_data;
3391 
3392 	ra_data.rtwdev = rtwdev;
3393 	ra_data.c2h = c2h;
3394 	ieee80211_iterate_stations_atomic(rtwdev->hw,
3395 					  rtw89_phy_c2h_ra_rpt_iter,
3396 					  &ra_data);
3397 }
3398 
3399 static void
3400 rtw89_phy_c2h_tx_history(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3401 {
3402 	const struct rtw89_c2h_ra_tx_history *history = (const void *)c2h->data;
3403 	u32 *tx_rate_cnt = rtwdev->phystat.tx_rate_cnt;
3404 	u32 i;
3405 
3406 	for (i = 0; i < RTW89_TX_RATE_NR; i++)
3407 		tx_rate_cnt[i] = le32_to_cpu(history->tx_rate_tot_cnt_hist[i]);
3408 }
3409 
3410 static
3411 void (* const rtw89_phy_c2h_ra_handler[])(struct rtw89_dev *rtwdev,
3412 					  struct sk_buff *c2h, u32 len) = {
3413 	[RTW89_PHY_C2H_FUNC_STS_RPT] = rtw89_phy_c2h_ra_rpt,
3414 	[RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT] = NULL,
3415 	[RTW89_PHY_C2H_FUNC_TXSTS] = NULL,
3416 	[RTW89_PHY_C2H_FUNC_TX_HISTORY] = rtw89_phy_c2h_tx_history,
3417 	[RTW89_PHY_C2H_FUNC_ACCELERATE_EN] = rtw89_fw_c2h_dummy_handler,
3418 };
3419 
3420 static void
3421 rtw89_phy_c2h_lowrt_rty(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3422 {
3423 }
3424 
3425 static void
3426 rtw89_phy_c2h_lps_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3427 {
3428 	const struct rtw89_c2h_lps_rpt *c2h_rpt = (const void *)c2h->data;
3429 	const __le32 *data_a, *data_b;
3430 	u16 len_info, cr_len, idx;
3431 	const __le16 *addr;
3432 	const u8 *info;
3433 
3434 	/* elements size of BBCR/BBMCUCR/RFCR are 6/6/10 bytes respectively */
3435 	cr_len = c2h_rpt->cnt_bbcr * 6 +
3436 		 c2h_rpt->cnt_bbmcucr * 6 +
3437 		 c2h_rpt->cnt_rfcr * 10;
3438 	len_info = len - (sizeof(*c2h_rpt) + cr_len);
3439 
3440 	if (len < sizeof(*c2h_rpt) + cr_len || len_info % 4 != 0) {
3441 		rtw89_debug(rtwdev, RTW89_DBG_PS,
3442 			    "Invalid LPS RPT len(%d) TYPE(%d) CRCNT: BB(%d) MCU(%d) RF(%d)\n",
3443 			    len, c2h_rpt->type, c2h_rpt->cnt_bbcr,
3444 			    c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr);
3445 		return;
3446 	}
3447 
3448 	rtw89_debug(rtwdev, RTW89_DBG_PS,
3449 		    "LPS RPT TYPE(%d), CRCNT: BB(%d) MCU(%d) RF(%d)\n",
3450 		    c2h_rpt->type, c2h_rpt->cnt_bbcr,
3451 		    c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr);
3452 
3453 	info = &c2h_rpt->data[0];
3454 	for (idx = 0; idx < len_info; idx += 4, info += 4)
3455 		rtw89_debug(rtwdev, RTW89_DBG_PS,
3456 			    "BB LPS INFO (%02d) - 0x%02x,0x%02x,0x%02x,0x%02x\n",
3457 			    idx, info[3], info[2], info[1], info[0]);
3458 
3459 	addr = (const void *)(info);
3460 	data_a = (const void *)(addr + c2h_rpt->cnt_bbcr);
3461 	for (idx = 0; idx < c2h_rpt->cnt_bbcr; idx++, addr++, data_a++)
3462 		rtw89_debug(rtwdev, RTW89_DBG_PS,
3463 			    "LPS BB CR - 0x%04x=0x%08x\n",
3464 			    le16_to_cpu(*addr), le32_to_cpu(*data_a));
3465 
3466 	addr = (const void *)data_a;
3467 	data_a = (const void *)(addr + c2h_rpt->cnt_bbmcucr);
3468 	for (idx = 0; idx < c2h_rpt->cnt_bbmcucr; idx++, addr++, data_a++)
3469 		rtw89_debug(rtwdev, RTW89_DBG_PS,
3470 			    "LPS BBMCU - 0x%04x=0x%08x\n",
3471 			    le16_to_cpu(*addr), le32_to_cpu(*data_a));
3472 
3473 	addr = (const void *)data_a;
3474 	data_a = (const void *)(addr + c2h_rpt->cnt_rfcr);
3475 	data_b = (const void *)(data_a + c2h_rpt->cnt_rfcr);
3476 	for (idx = 0; idx < c2h_rpt->cnt_rfcr; idx++, addr++, data_a++, data_b++)
3477 		rtw89_debug(rtwdev, RTW89_DBG_PS,
3478 			    "LPS RFCR - 0x%04x=0x%05x,0x%05x\n",
3479 			    le16_to_cpu(*addr), le32_to_cpu(*data_a),
3480 			    le32_to_cpu(*data_b));
3481 }
3482 
3483 static void
3484 rtw89_phy_c2h_fw_scan_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3485 {
3486 	const struct rtw89_c2h_fw_scan_rpt *c2h_rpt =
3487 		(const struct rtw89_c2h_fw_scan_rpt *)c2h->data;
3488 
3489 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
3490 		    "%s: band: %u, op_chan: %u, PD_low_bd(ofdm, cck): (-%d, %d), phy_idx: %u\n",
3491 		    __func__, c2h_rpt->band, c2h_rpt->center_ch,
3492 		    PD_LOWER_BOUND_BASE - (c2h_rpt->ofdm_pd_idx << 1),
3493 		    c2h_rpt->cck_pd_idx, c2h_rpt->phy_idx);
3494 }
3495 
3496 static
3497 void (* const rtw89_phy_c2h_dm_handler[])(struct rtw89_dev *rtwdev,
3498 					  struct sk_buff *c2h, u32 len) = {
3499 	[RTW89_PHY_C2H_DM_FUNC_FW_TEST] = NULL,
3500 	[RTW89_PHY_C2H_DM_FUNC_FW_TRIG_TX_RPT] = NULL,
3501 	[RTW89_PHY_C2H_DM_FUNC_SIGB] = NULL,
3502 	[RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY] = rtw89_phy_c2h_lowrt_rty,
3503 	[RTW89_PHY_C2H_DM_FUNC_MCC_DIG] = NULL,
3504 	[RTW89_PHY_C2H_DM_FUNC_LPS] = rtw89_phy_c2h_lps_rpt,
3505 	[RTW89_PHY_C2H_DM_FUNC_ENV_MNTR] = rtw89_fw_c2h_dummy_handler,
3506 	[RTW89_PHY_C2H_DM_FUNC_FW_SCAN] = rtw89_phy_c2h_fw_scan_rpt,
3507 };
3508 
3509 static
3510 void rtw89_phy_c2h_rfk_tas_pwr(struct rtw89_dev *rtwdev,
3511 			       const struct rtw89_c2h_rf_tas_rpt_log *content)
3512 {
3513 	const enum rtw89_sar_sources src = rtwdev->sar.src;
3514 	struct rtw89_tas_info *tas = &rtwdev->tas;
3515 	u64 linear = 0;
3516 	u32 i, cur_idx;
3517 	s16 txpwr;
3518 
3519 	if (!tas->enable || src == RTW89_SAR_SOURCE_NONE)
3520 		return;
3521 
3522 	cur_idx = le32_to_cpu(content->cur_idx);
3523 	for (i = 0; i < cur_idx; i++) {
3524 		txpwr = le16_to_cpu(content->txpwr_history[i]);
3525 		linear += rtw89_db_quarter_to_linear(txpwr);
3526 
3527 		rtw89_debug(rtwdev, RTW89_DBG_SAR,
3528 			    "tas: index: %u, txpwr: %d\n", i, txpwr);
3529 	}
3530 
3531 	if (cur_idx == 0)
3532 		tas->instant_txpwr = rtw89_db_to_linear(0);
3533 	else
3534 		tas->instant_txpwr = DIV_ROUND_DOWN_ULL(linear, cur_idx);
3535 }
3536 
3537 static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
3538 				      enum rtw89_phy_c2h_rfk_log_func func,
3539 				      void *content, u16 len)
3540 {
3541 	struct rtw89_c2h_rf_txgapk_rpt_log *txgapk;
3542 	struct rtw89_c2h_rf_rxdck_rpt_log *rxdck;
3543 	struct rtw89_c2h_rf_txiqk_rpt_log *txiqk;
3544 	struct rtw89_c2h_rf_cim3k_rpt_log *cim3k;
3545 	struct rtw89_c2h_rf_dack_rpt_log *dack;
3546 	struct rtw89_c2h_rf_tssi_rpt_log *tssi;
3547 	struct rtw89_c2h_rf_dpk_rpt_log *dpk;
3548 	struct rtw89_c2h_rf_iqk_rpt_log *iqk;
3549 	int i, j, k;
3550 
3551 	switch (func) {
3552 	case RTW89_PHY_C2H_RFK_LOG_FUNC_IQK:
3553 		if (len != sizeof(*iqk))
3554 			goto out;
3555 
3556 		iqk = content;
3557 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3558 			    "[IQK] iqk->is_iqk_init = %x\n", iqk->is_iqk_init);
3559 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3560 			    "[IQK] iqk->is_reload = %x\n", iqk->is_reload);
3561 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3562 			    "[IQK] iqk->is_nbiqk = %x\n", iqk->is_nbiqk);
3563 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3564 			    "[IQK] iqk->txiqk_en = %x\n", iqk->txiqk_en);
3565 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3566 			    "[IQK] iqk->rxiqk_en = %x\n", iqk->rxiqk_en);
3567 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3568 			    "[IQK] iqk->lok_en = %x\n", iqk->lok_en);
3569 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3570 			    "[IQK] iqk->iqk_xym_en = %x\n", iqk->iqk_xym_en);
3571 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3572 			    "[IQK] iqk->iqk_sram_en = %x\n", iqk->iqk_sram_en);
3573 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3574 			    "[IQK] iqk->iqk_fft_en = %x\n", iqk->iqk_fft_en);
3575 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3576 			    "[IQK] iqk->is_fw_iqk = %x\n", iqk->is_fw_iqk);
3577 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3578 			    "[IQK] iqk->is_iqk_enable = %x\n", iqk->is_iqk_enable);
3579 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3580 			    "[IQK] iqk->iqk_cfir_en = %x\n", iqk->iqk_cfir_en);
3581 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3582 			    "[IQK] iqk->thermal_rek_en = %x\n", iqk->thermal_rek_en);
3583 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3584 			    "[IQK] iqk->version = %x\n", iqk->version);
3585 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3586 			    "[IQK] iqk->phy = %x\n", iqk->phy);
3587 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3588 			    "[IQK] iqk->fwk_status = %x\n", iqk->fwk_status);
3589 
3590 		for (i = 0; i < 2; i++) {
3591 			struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
3592 
3593 			rtw89_debug(rtwdev, RTW89_DBG_RFK,
3594 				    "[IQK] ======== Path %x  ========\n", i);
3595 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_band[%d] = %x\n",
3596 				    i, iqk->iqk_band[i]);
3597 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_ch[%d] = %x\n",
3598 				    i, iqk->iqk_ch[i]);
3599 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_bw[%d] = %x\n",
3600 				    i, iqk->iqk_bw[i]);
3601 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->rf_0x18[%d] = %x\n",
3602 				    i, le32_to_cpu(iqk->rf_0x18[i]));
3603 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_idac[%d] = %x\n",
3604 				    i, le32_to_cpu(iqk->lok_idac[i]));
3605 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_vbuf[%d] = %x\n",
3606 				    i, le32_to_cpu(iqk->lok_vbuf[i]));
3607 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_tx_fail[%d] = %x\n",
3608 				    i, iqk->iqk_tx_fail[i]);
3609 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_rx_fail[%d] = %x\n",
3610 				    i, iqk->iqk_rx_fail[i]);
3611 
3612 			iqk_info->iqk_rx_fail[0][i] = iqk->iqk_rx_fail[i];
3613 
3614 			for (j = 0; j < 6; j++)
3615 				rtw89_debug(rtwdev, RTW89_DBG_RFK,
3616 					    "[IQK] iqk->rftxgain[%d][%d] = %x\n",
3617 					    i, j, le32_to_cpu(iqk->rftxgain[i][j]));
3618 			for (j = 0; j < 6; j++)
3619 				rtw89_debug(rtwdev, RTW89_DBG_RFK,
3620 					    "[IQK] iqk->tx_xym[%d][%d] = %x\n",
3621 					    i, j, le32_to_cpu(iqk->tx_xym[i][j]));
3622 			for (j = 0; j < 6; j++)
3623 				rtw89_debug(rtwdev, RTW89_DBG_RFK,
3624 					    "[IQK] iqk->rfrxgain[%d][%d] = %x\n",
3625 					    i, j, le32_to_cpu(iqk->rfrxgain[i][j]));
3626 			for (j = 0; j < 6; j++)
3627 				rtw89_debug(rtwdev, RTW89_DBG_RFK,
3628 					    "[IQK] iqk->rx_xym[%d][%d] = %x\n",
3629 					    i, j, le32_to_cpu(iqk->rx_xym[i][j]));
3630 
3631 			if (!iqk->iqk_xym_en)
3632 				continue;
3633 
3634 			for (j = 0; j < 32; j++)
3635 				rtw89_debug(rtwdev, RTW89_DBG_RFK,
3636 					    "[IQK] iqk->rx_wb_xym[%d][%d] = %x\n",
3637 					    i, j, iqk->rx_wb_xym[i][j]);
3638 		}
3639 		return;
3640 	case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK:
3641 		if (len != sizeof(*dpk))
3642 			goto out;
3643 
3644 		dpk = content;
3645 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3646 			    "DPK ver:%d idx:%2ph band:%2ph bw:%2ph ch:%2ph path:%2ph\n",
3647 			    dpk->ver, dpk->idx, dpk->band, dpk->bw, dpk->ch, dpk->path_ok);
3648 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3649 			    "DPK txagc:%2ph ther:%2ph gs:%2ph dc_i:%4ph dc_q:%4ph\n",
3650 			    dpk->txagc, dpk->ther, dpk->gs, dpk->dc_i, dpk->dc_q);
3651 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3652 			    "DPK corr_v:%2ph corr_i:%2ph to:%2ph ov:%2ph\n",
3653 			    dpk->corr_val, dpk->corr_idx, dpk->is_timeout, dpk->rxbb_ov);
3654 		return;
3655 	case RTW89_PHY_C2H_RFK_LOG_FUNC_DACK:
3656 		if (len != sizeof(*dack))
3657 			goto out;
3658 
3659 		dack = content;
3660 
3661 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]FWDACK SUMMARY!!!!!\n");
3662 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3663 			    "[DACK]FWDACK ver = 0x%x, FWDACK rpt_ver = 0x%x, driver rpt_ver = 0x%x\n",
3664 			    dack->fwdack_ver, dack->fwdack_info_ver, 0x2);
3665 
3666 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3667 			    "[DACK]timeout code = [0x%x 0x%x 0x%x 0x%x 0x%x]\n",
3668 			    dack->addck_timeout, dack->cdack_timeout, dack->dadck_timeout,
3669 			    dack->adgaink_timeout, dack->msbk_timeout);
3670 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3671 			    "[DACK]DACK fail = 0x%x\n", dack->dack_fail);
3672 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3673 			    "[DACK]S0 WBADCK = [0x%x]\n", dack->wbdck_d[0]);
3674 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3675 			    "[DACK]S1 WBADCK = [0x%x]\n", dack->wbdck_d[1]);
3676 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3677 			    "[DACK]DRCK = [0x%x]\n", dack->rck_d);
3678 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK ic = [0x%x, 0x%x]\n",
3679 			    dack->cdack_d[0][0][0], dack->cdack_d[0][0][1]);
3680 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK qc = [0x%x, 0x%x]\n",
3681 			    dack->cdack_d[0][1][0], dack->cdack_d[0][1][1]);
3682 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 CDACK ic = [0x%x, 0x%x]\n",
3683 			    dack->cdack_d[1][0][0], dack->cdack_d[1][0][1]);
3684 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 CDACK qc = [0x%x, 0x%x]\n",
3685 			    dack->cdack_d[1][1][0], dack->cdack_d[1][1][1]);
3686 
3687 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = [0x%x, 0x%x]\n",
3688 			    ((u32)dack->addck2_hd[0][0][0] << 8) | dack->addck2_ld[0][0][0],
3689 			    ((u32)dack->addck2_hd[0][0][1] << 8) | dack->addck2_ld[0][0][1]);
3690 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK qc = [0x%x, 0x%x]\n",
3691 			    ((u32)dack->addck2_hd[0][1][0] << 8) | dack->addck2_ld[0][1][0],
3692 			    ((u32)dack->addck2_hd[0][1][1] << 8) | dack->addck2_ld[0][1][1]);
3693 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK ic = [0x%x, 0x%x]\n",
3694 			    ((u32)dack->addck2_hd[1][0][0] << 8) | dack->addck2_ld[1][0][0],
3695 			    ((u32)dack->addck2_hd[1][0][1] << 8) | dack->addck2_ld[1][0][1]);
3696 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK qc = [0x%x, 0x%x]\n",
3697 			    ((u32)dack->addck2_hd[1][1][0] << 8) | dack->addck2_ld[1][1][0],
3698 			    ((u32)dack->addck2_hd[1][1][1] << 8) | dack->addck2_ld[1][1][1]);
3699 
3700 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_GAINK ic = 0x%x, qc = 0x%x\n",
3701 			    dack->adgaink_d[0][0], dack->adgaink_d[0][1]);
3702 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_GAINK ic = 0x%x, qc = 0x%x\n",
3703 			    dack->adgaink_d[1][0], dack->adgaink_d[1][1]);
3704 
3705 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DAC_DCK ic = 0x%x, qc = 0x%x\n",
3706 			    dack->dadck_d[0][0], dack->dadck_d[0][1]);
3707 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 DAC_DCK ic = 0x%x, qc = 0x%x\n",
3708 			    dack->dadck_d[1][0], dack->dadck_d[1][1]);
3709 
3710 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask iqc = 0x%x\n",
3711 			    ((u32)dack->biask_hd[0][0] << 8) | dack->biask_ld[0][0]);
3712 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 biask iqc = 0x%x\n",
3713 			    ((u32)dack->biask_hd[1][0] << 8) | dack->biask_ld[1][0]);
3714 
3715 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n");
3716 		for (i = 0; i < 0x10; i++)
3717 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
3718 				    dack->msbk_d[0][0][i]);
3719 
3720 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n");
3721 		for (i = 0; i < 0x10; i++)
3722 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
3723 				    dack->msbk_d[0][1][i]);
3724 
3725 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic:\n");
3726 		for (i = 0; i < 0x10; i++)
3727 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
3728 				    dack->msbk_d[1][0][i]);
3729 
3730 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc:\n");
3731 		for (i = 0; i < 0x10; i++)
3732 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n",
3733 				    dack->msbk_d[1][1][i]);
3734 		return;
3735 	case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK:
3736 		if (len != sizeof(*rxdck))
3737 			goto out;
3738 
3739 		rxdck = content;
3740 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3741 			    "RXDCK ver:%d band:%2ph bw:%2ph ch:%2ph to:%2ph\n",
3742 			    rxdck->ver, rxdck->band, rxdck->bw, rxdck->ch,
3743 			    rxdck->timeout);
3744 		return;
3745 	case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI:
3746 		if (len != sizeof(*tssi))
3747 			goto out;
3748 
3749 		tssi = content;
3750 		for (i = 0; i < 2; i++) {
3751 			for (j = 0; j < 2; j++) {
3752 				for (k = 0; k < 4; k++) {
3753 					rtw89_debug(rtwdev, RTW89_DBG_RFK,
3754 						    "[TSSI] alignment_power_cw_h[%d][%d][%d]=%d\n",
3755 						    i, j, k, tssi->alignment_power_cw_h[i][j][k]);
3756 					rtw89_debug(rtwdev, RTW89_DBG_RFK,
3757 						    "[TSSI] alignment_power_cw_l[%d][%d][%d]=%d\n",
3758 						    i, j, k, tssi->alignment_power_cw_l[i][j][k]);
3759 					rtw89_debug(rtwdev, RTW89_DBG_RFK,
3760 						    "[TSSI] alignment_power[%d][%d][%d]=%d\n",
3761 						    i, j, k, tssi->alignment_power[i][j][k]);
3762 					rtw89_debug(rtwdev, RTW89_DBG_RFK,
3763 						    "[TSSI] alignment_power_cw[%d][%d][%d]=%d\n",
3764 						    i, j, k,
3765 						    (tssi->alignment_power_cw_h[i][j][k] << 8) +
3766 						     tssi->alignment_power_cw_l[i][j][k]);
3767 				}
3768 
3769 				rtw89_debug(rtwdev, RTW89_DBG_RFK,
3770 					    "[TSSI] tssi_alimk_state[%d][%d]=%d\n",
3771 					    i, j, tssi->tssi_alimk_state[i][j]);
3772 				rtw89_debug(rtwdev, RTW89_DBG_RFK,
3773 					    "[TSSI] default_txagc_offset[%d]=%d\n",
3774 					    j, tssi->default_txagc_offset[0][j]);
3775 			}
3776 		}
3777 		return;
3778 	case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK:
3779 		if (len != sizeof(*txgapk))
3780 			goto out;
3781 
3782 		txgapk = content;
3783 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
3784 			    "[TXGAPK]rpt r0x8010[0]=0x%x, r0x8010[1]=0x%x\n",
3785 			    le32_to_cpu(txgapk->r0x8010[0]),
3786 			    le32_to_cpu(txgapk->r0x8010[1]));
3787 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt chk_id = %d\n",
3788 			    txgapk->chk_id);
3789 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt chk_cnt = %d\n",
3790 			    le32_to_cpu(txgapk->chk_cnt));
3791 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt ver = 0x%x\n",
3792 			    txgapk->ver);
3793 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt d_bnd_ok = %d\n",
3794 			    txgapk->d_bnd_ok);
3795 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt stage[0] = 0x%x\n",
3796 			    le32_to_cpu(txgapk->stage[0]));
3797 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt stage[1] = 0x%x\n",
3798 			    le32_to_cpu(txgapk->stage[1]));
3799 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]failcode[0] = 0x%x\n",
3800 			    le16_to_cpu(txgapk->failcode[0]));
3801 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]failcode[1] = 0x%x\n",
3802 			    le16_to_cpu(txgapk->failcode[1]));
3803 
3804 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt track_d[0] = %*ph\n",
3805 			    (int)sizeof(txgapk->track_d[0]), txgapk->track_d[0]);
3806 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt power_d[0] = %*ph\n",
3807 			    (int)sizeof(txgapk->power_d[0]), txgapk->power_d[0]);
3808 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt track_d[1] = %*ph\n",
3809 			    (int)sizeof(txgapk->track_d[1]), txgapk->track_d[1]);
3810 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt power_d[1] = %*ph\n",
3811 			    (int)sizeof(txgapk->power_d[1]), txgapk->power_d[1]);
3812 		return;
3813 	case RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR:
3814 		if (len != sizeof(struct rtw89_c2h_rf_tas_rpt_log))
3815 			goto out;
3816 
3817 		rtw89_phy_c2h_rfk_tas_pwr(rtwdev, content);
3818 		return;
3819 	case RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK:
3820 		if (len != sizeof(*txiqk))
3821 			goto out;
3822 		return;
3823 	case RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K:
3824 		if (len != sizeof(*cim3k))
3825 			goto out;
3826 		return;
3827 	default:
3828 		break;
3829 	}
3830 
3831 out:
3832 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
3833 		    "unexpected RFK func %d report log with length %d\n", func, len);
3834 }
3835 
3836 static bool rtw89_phy_c2h_rfk_run_log(struct rtw89_dev *rtwdev,
3837 				      enum rtw89_phy_c2h_rfk_log_func func,
3838 				      void *content, u16 len)
3839 {
3840 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
3841 	const struct rtw89_c2h_rf_run_log *log = content;
3842 	const struct rtw89_fw_element_hdr *elm;
3843 	u32 fmt_idx;
3844 	u16 offset;
3845 
3846 	if (sizeof(*log) != len)
3847 		return false;
3848 
3849 	if (!elm_info->rfk_log_fmt)
3850 		return false;
3851 
3852 	elm = elm_info->rfk_log_fmt->elm[func];
3853 	fmt_idx = le32_to_cpu(log->fmt_idx);
3854 	if (!elm || fmt_idx >= elm->u.rfk_log_fmt.nr)
3855 		return false;
3856 
3857 	offset = le16_to_cpu(elm->u.rfk_log_fmt.offset[fmt_idx]);
3858 	if (offset == 0)
3859 		return false;
3860 
3861 	rtw89_debug(rtwdev, RTW89_DBG_RFK, &elm->u.common.contents[offset],
3862 		    le32_to_cpu(log->arg[0]), le32_to_cpu(log->arg[1]),
3863 		    le32_to_cpu(log->arg[2]), le32_to_cpu(log->arg[3]));
3864 
3865 	return true;
3866 }
3867 
3868 static void rtw89_phy_c2h_rfk_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
3869 				  u32 len, enum rtw89_phy_c2h_rfk_log_func func,
3870 				  const char *rfk_name)
3871 {
3872 	struct rtw89_c2h_hdr *c2h_hdr = (struct rtw89_c2h_hdr *)c2h->data;
3873 	struct rtw89_c2h_rf_log_hdr *log_hdr;
3874 	void *log_ptr = c2h_hdr;
3875 	u16 content_len;
3876 	u16 chunk_len;
3877 	bool handled;
3878 
3879 	log_ptr += sizeof(*c2h_hdr);
3880 	len -= sizeof(*c2h_hdr);
3881 
3882 	while (len > sizeof(*log_hdr)) {
3883 		log_hdr = log_ptr;
3884 		content_len = le16_to_cpu(log_hdr->len);
3885 		chunk_len = content_len + sizeof(*log_hdr);
3886 
3887 		if (chunk_len > len)
3888 			break;
3889 
3890 		switch (log_hdr->type) {
3891 		case RTW89_RF_RUN_LOG:
3892 			handled = rtw89_phy_c2h_rfk_run_log(rtwdev, func,
3893 							    log_hdr->content, content_len);
3894 			if (handled)
3895 				break;
3896 
3897 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "%s run: %*ph\n",
3898 				    rfk_name, content_len, log_hdr->content);
3899 			break;
3900 		case RTW89_RF_RPT_LOG:
3901 			rtw89_phy_c2h_rfk_rpt_log(rtwdev, func,
3902 						  log_hdr->content, content_len);
3903 			break;
3904 		default:
3905 			return;
3906 		}
3907 
3908 		log_ptr += chunk_len;
3909 		len -= chunk_len;
3910 	}
3911 }
3912 
3913 static void
3914 rtw89_phy_c2h_rfk_log_iqk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3915 {
3916 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3917 			      RTW89_PHY_C2H_RFK_LOG_FUNC_IQK, "IQK");
3918 }
3919 
3920 static void
3921 rtw89_phy_c2h_rfk_log_dpk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3922 {
3923 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3924 			      RTW89_PHY_C2H_RFK_LOG_FUNC_DPK, "DPK");
3925 }
3926 
3927 static void
3928 rtw89_phy_c2h_rfk_log_dack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3929 {
3930 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3931 			      RTW89_PHY_C2H_RFK_LOG_FUNC_DACK, "DACK");
3932 }
3933 
3934 static void
3935 rtw89_phy_c2h_rfk_log_rxdck(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3936 {
3937 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3938 			      RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK, "RX_DCK");
3939 }
3940 
3941 static void
3942 rtw89_phy_c2h_rfk_log_tssi(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3943 {
3944 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3945 			      RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI, "TSSI");
3946 }
3947 
3948 static void
3949 rtw89_phy_c2h_rfk_log_txgapk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3950 {
3951 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3952 			      RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK, "TXGAPK");
3953 }
3954 
3955 static void
3956 rtw89_phy_c2h_rfk_log_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3957 {
3958 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3959 			      RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR, "TAS");
3960 }
3961 
3962 static void
3963 rtw89_phy_c2h_rfk_log_txiqk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3964 {
3965 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3966 			      RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK, "TXIQK");
3967 }
3968 
3969 static void
3970 rtw89_phy_c2h_rfk_log_cim3k(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3971 {
3972 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
3973 			      RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K, "CIM3K");
3974 }
3975 
3976 static
3977 void (* const rtw89_phy_c2h_rfk_log_handler[])(struct rtw89_dev *rtwdev,
3978 					       struct sk_buff *c2h, u32 len) = {
3979 	[RTW89_PHY_C2H_RFK_LOG_FUNC_IQK] = rtw89_phy_c2h_rfk_log_iqk,
3980 	[RTW89_PHY_C2H_RFK_LOG_FUNC_DPK] = rtw89_phy_c2h_rfk_log_dpk,
3981 	[RTW89_PHY_C2H_RFK_LOG_FUNC_DACK] = rtw89_phy_c2h_rfk_log_dack,
3982 	[RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK] = rtw89_phy_c2h_rfk_log_rxdck,
3983 	[RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI] = rtw89_phy_c2h_rfk_log_tssi,
3984 	[RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK] = rtw89_phy_c2h_rfk_log_txgapk,
3985 	[RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR] = rtw89_phy_c2h_rfk_log_tas_pwr,
3986 	[RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK] = rtw89_phy_c2h_rfk_log_txiqk,
3987 	[RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K] = rtw89_phy_c2h_rfk_log_cim3k,
3988 };
3989 
3990 #define NAME_RTW89_RFK_REPORT(type) \
3991 	[RTW89_RFK_REPORT_ ## type] = #type
3992 
3993 const char * const rtw89_rfk_report_names[] = {
3994 	NAME_RTW89_RFK_REPORT(PRE_NTFY),
3995 	NAME_RTW89_RFK_REPORT(TSSI),
3996 	NAME_RTW89_RFK_REPORT(IQK),
3997 	NAME_RTW89_RFK_REPORT(DPK),
3998 	NAME_RTW89_RFK_REPORT(TXGAPK),
3999 	NAME_RTW89_RFK_REPORT(DACK),
4000 	NAME_RTW89_RFK_REPORT(RX_DCK),
4001 	NAME_RTW89_RFK_REPORT(TX_IQK),
4002 	NAME_RTW89_RFK_REPORT(CIM3k),
4003 };
4004 
4005 static_assert(ARRAY_SIZE(rtw89_rfk_report_names) == NUM_OF_RTW89_RFK_REPORT_TYPES);
4006 
4007 static
4008 void rtw89_phy_rfk_report_prep(struct rtw89_dev *rtwdev)
4009 {
4010 	struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
4011 
4012 	wait->state = RTW89_RFK_STATE_START;
4013 	wait->start_time = ktime_get();
4014 	reinit_completion(&wait->completion);
4015 }
4016 
4017 static
4018 int ____rtw89_phy_rfk_report_wait(struct rtw89_dev *rtwdev, const char *rfk_name,
4019 				  unsigned int ms)
4020 {
4021 	struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
4022 	unsigned long time_left;
4023 
4024 	/*
4025 	 * USB transport adds latency to H2C/C2H round-trips, so RF
4026 	 * calibrations take longer than on PCIe. Apply a 4x multiplier
4027 	 * to avoid spurious timeouts.
4028 	 */
4029 	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
4030 		ms *= 4;
4031 
4032 	/* Since we can't receive C2H event during SER, use a fixed delay. */
4033 	if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) {
4034 		fsleep(1000 * ms / 2);
4035 		goto out;
4036 	}
4037 
4038 	time_left = wait_for_completion_timeout(&wait->completion,
4039 						msecs_to_jiffies(ms));
4040 	if (time_left == 0) {
4041 		rtw89_warn(rtwdev, "failed to wait RF %s\n", rfk_name);
4042 		return -ETIMEDOUT;
4043 	} else if (wait->state != RTW89_RFK_STATE_OK) {
4044 		rtw89_warn(rtwdev, "failed to do RF %s result from state %d\n",
4045 			   rfk_name, wait->state);
4046 		return -EFAULT;
4047 	}
4048 
4049 out:
4050 	rtw89_debug(rtwdev, RTW89_DBG_RFK, "RF %s takes %lld ms to complete\n",
4051 		    rfk_name, ktime_ms_delta(ktime_get(), wait->start_time));
4052 
4053 	return 0;
4054 }
4055 
4056 static
4057 int __rtw89_phy_rfk_report_wait(struct rtw89_dev *rtwdev,
4058 				enum rtw89_rfk_report_types rfk_type,
4059 				enum rtw89_phy_idx phy_idx,
4060 				const struct rtw89_chan *chan,
4061 				unsigned int ms)
4062 {
4063 	const char *rfk_name = rtw89_rfk_report_names[rfk_type];
4064 	struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
4065 	struct rtw89_rfk_record *record = wait->record_ptr;
4066 	int ret;
4067 
4068 	ret = ____rtw89_phy_rfk_report_wait(rtwdev, rfk_name, ms);
4069 
4070 	if (record)
4071 		record->states[rfk_type] = wait->state;
4072 
4073 	return ret;
4074 }
4075 
4076 #define rtw89_phy_rfk_report_wait(rtwdev, type, phy_idx, chan, ms) \
4077 	__rtw89_phy_rfk_report_wait(rtwdev, RTW89_RFK_REPORT_ ## type, phy_idx, chan, ms)
4078 
4079 static void
4080 rtw89_phy_c2h_rfk_report_state(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
4081 {
4082 	const struct rtw89_c2h_rfk_report *report =
4083 		(const struct rtw89_c2h_rfk_report *)c2h->data;
4084 	struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
4085 
4086 	wait->state = report->state;
4087 	wait->version = report->version;
4088 
4089 	complete(&wait->completion);
4090 
4091 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
4092 		    "RFK report state %d with version %d (%*ph)\n",
4093 		    wait->state, wait->version,
4094 		    (int)(len - sizeof(report->hdr)), &report->state);
4095 }
4096 
4097 static void
4098 rtw89_phy_c2h_rfk_report_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
4099 {
4100 	const struct rtw89_c2h_rf_tas_info *report =
4101 		(const struct rtw89_c2h_rf_tas_info *)c2h->data;
4102 
4103 	rtw89_phy_c2h_rfk_tas_pwr(rtwdev, &report->content);
4104 }
4105 
4106 static
4107 void (* const rtw89_phy_c2h_rfk_report_handler[])(struct rtw89_dev *rtwdev,
4108 						  struct sk_buff *c2h, u32 len) = {
4109 	[RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE] = rtw89_phy_c2h_rfk_report_state,
4110 	[RTW89_PHY_C2H_RFK_REPORT_FUNC_TAS_PWR] = rtw89_phy_c2h_rfk_report_tas_pwr,
4111 };
4112 
4113 bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
4114 {
4115 	switch (class) {
4116 	case RTW89_PHY_C2H_RFK_LOG:
4117 		switch (func) {
4118 		case RTW89_PHY_C2H_RFK_LOG_FUNC_IQK:
4119 		case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK:
4120 		case RTW89_PHY_C2H_RFK_LOG_FUNC_DACK:
4121 		case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK:
4122 		case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI:
4123 		case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK:
4124 		case RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK:
4125 			return true;
4126 		default:
4127 			return false;
4128 		}
4129 	case RTW89_PHY_C2H_RFK_REPORT:
4130 		switch (func) {
4131 		case RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE:
4132 			return true;
4133 		default:
4134 			return false;
4135 		}
4136 	default:
4137 		return false;
4138 	}
4139 }
4140 
4141 void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
4142 			  u32 len, u8 class, u8 func)
4143 {
4144 	void (*handler)(struct rtw89_dev *rtwdev,
4145 			struct sk_buff *c2h, u32 len) = NULL;
4146 
4147 	switch (class) {
4148 	case RTW89_PHY_C2H_CLASS_RA:
4149 		if (func < ARRAY_SIZE(rtw89_phy_c2h_ra_handler))
4150 			handler = rtw89_phy_c2h_ra_handler[func];
4151 		break;
4152 	case RTW89_PHY_C2H_RFK_LOG:
4153 		if (func < ARRAY_SIZE(rtw89_phy_c2h_rfk_log_handler))
4154 			handler = rtw89_phy_c2h_rfk_log_handler[func];
4155 		break;
4156 	case RTW89_PHY_C2H_RFK_REPORT:
4157 		if (func < ARRAY_SIZE(rtw89_phy_c2h_rfk_report_handler))
4158 			handler = rtw89_phy_c2h_rfk_report_handler[func];
4159 		break;
4160 	case RTW89_PHY_C2H_CLASS_DM:
4161 		if (func < ARRAY_SIZE(rtw89_phy_c2h_dm_handler))
4162 			handler = rtw89_phy_c2h_dm_handler[func];
4163 		break;
4164 	default:
4165 		break;
4166 	}
4167 	if (!handler) {
4168 		rtw89_info_once(rtwdev, "PHY c2h class %d func %d not support\n",
4169 				class, func);
4170 		return;
4171 	}
4172 	handler(rtwdev, skb, len);
4173 }
4174 
4175 int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev,
4176 				    enum rtw89_phy_idx phy_idx,
4177 				    unsigned int ms)
4178 {
4179 	int ret;
4180 
4181 	if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) {
4182 		rtw89_phy_rfk_report_prep(rtwdev);
4183 		rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx);
4184 		ret = rtw89_phy_rfk_report_wait(rtwdev, PRE_NTFY, phy_idx, NULL, ms);
4185 		if (ret)
4186 			return ret;
4187 	}
4188 
4189 	if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY_MCC, &rtwdev->fw)) {
4190 		ret = rtw89_fw_h2c_rf_pre_ntfy_mcc(rtwdev, phy_idx);
4191 		if (ret)
4192 			return ret;
4193 	}
4194 
4195 	return 0;
4196 
4197 }
4198 EXPORT_SYMBOL(rtw89_phy_rfk_pre_ntfy_and_wait);
4199 
4200 int rtw89_phy_rfk_tssi_and_wait(struct rtw89_dev *rtwdev,
4201 				enum rtw89_phy_idx phy_idx,
4202 				const struct rtw89_chan *chan,
4203 				enum rtw89_tssi_mode tssi_mode,
4204 				unsigned int ms)
4205 {
4206 	int ret;
4207 
4208 	rtw89_phy_rfk_report_prep(rtwdev);
4209 
4210 	ret = rtw89_fw_h2c_rf_tssi(rtwdev, phy_idx, chan, tssi_mode);
4211 	if (ret)
4212 		return ret;
4213 
4214 	return rtw89_phy_rfk_report_wait(rtwdev, TSSI, phy_idx, chan, ms);
4215 }
4216 EXPORT_SYMBOL(rtw89_phy_rfk_tssi_and_wait);
4217 
4218 int rtw89_phy_rfk_iqk_and_wait(struct rtw89_dev *rtwdev,
4219 			       enum rtw89_phy_idx phy_idx,
4220 			       const struct rtw89_chan *chan,
4221 			       unsigned int ms)
4222 {
4223 	int ret;
4224 
4225 	rtw89_phy_rfk_report_prep(rtwdev);
4226 
4227 	ret = rtw89_fw_h2c_rf_iqk(rtwdev, phy_idx, chan);
4228 	if (ret)
4229 		return ret;
4230 
4231 	return rtw89_phy_rfk_report_wait(rtwdev, IQK, phy_idx, chan, ms);
4232 }
4233 EXPORT_SYMBOL(rtw89_phy_rfk_iqk_and_wait);
4234 
4235 int rtw89_phy_rfk_dpk_and_wait(struct rtw89_dev *rtwdev,
4236 			       enum rtw89_phy_idx phy_idx,
4237 			       const struct rtw89_chan *chan,
4238 			       unsigned int ms)
4239 {
4240 	int ret;
4241 
4242 	rtw89_phy_rfk_report_prep(rtwdev);
4243 
4244 	ret = rtw89_fw_h2c_rf_dpk(rtwdev, phy_idx, chan);
4245 	if (ret)
4246 		return ret;
4247 
4248 	return rtw89_phy_rfk_report_wait(rtwdev, DPK, phy_idx, chan, ms);
4249 }
4250 EXPORT_SYMBOL(rtw89_phy_rfk_dpk_and_wait);
4251 
4252 int rtw89_phy_rfk_txgapk_and_wait(struct rtw89_dev *rtwdev,
4253 				  enum rtw89_phy_idx phy_idx,
4254 				  const struct rtw89_chan *chan,
4255 				  unsigned int ms)
4256 {
4257 	int ret;
4258 
4259 	rtw89_phy_rfk_report_prep(rtwdev);
4260 
4261 	ret = rtw89_fw_h2c_rf_txgapk(rtwdev, phy_idx, chan);
4262 	if (ret)
4263 		return ret;
4264 
4265 	return rtw89_phy_rfk_report_wait(rtwdev, TXGAPK, phy_idx, chan, ms);
4266 }
4267 EXPORT_SYMBOL(rtw89_phy_rfk_txgapk_and_wait);
4268 
4269 int rtw89_phy_rfk_dack_and_wait(struct rtw89_dev *rtwdev,
4270 				enum rtw89_phy_idx phy_idx,
4271 				const struct rtw89_chan *chan,
4272 				unsigned int ms)
4273 {
4274 	int ret;
4275 
4276 	rtw89_phy_rfk_report_prep(rtwdev);
4277 
4278 	ret = rtw89_fw_h2c_rf_dack(rtwdev, phy_idx, chan);
4279 	if (ret)
4280 		return ret;
4281 
4282 	return rtw89_phy_rfk_report_wait(rtwdev, DACK, phy_idx, chan, ms);
4283 }
4284 EXPORT_SYMBOL(rtw89_phy_rfk_dack_and_wait);
4285 
4286 int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
4287 				 enum rtw89_phy_idx phy_idx,
4288 				 const struct rtw89_chan *chan,
4289 				 bool is_chl_k, unsigned int ms)
4290 {
4291 	int ret;
4292 
4293 	rtw89_phy_rfk_report_prep(rtwdev);
4294 
4295 	ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx, chan, is_chl_k);
4296 	if (ret)
4297 		return ret;
4298 
4299 	return rtw89_phy_rfk_report_wait(rtwdev, RX_DCK, phy_idx, chan, ms);
4300 }
4301 EXPORT_SYMBOL(rtw89_phy_rfk_rxdck_and_wait);
4302 
4303 int rtw89_phy_rfk_txiqk_and_wait(struct rtw89_dev *rtwdev,
4304 				 enum rtw89_phy_idx phy_idx,
4305 				 const struct rtw89_chan *chan,
4306 				 unsigned int ms)
4307 {
4308 	int ret;
4309 
4310 	rtw89_phy_rfk_report_prep(rtwdev);
4311 
4312 	ret = rtw89_fw_h2c_rf_txiqk(rtwdev, phy_idx, chan);
4313 	if (ret)
4314 		return ret;
4315 
4316 	return rtw89_phy_rfk_report_wait(rtwdev, TX_IQK, phy_idx, chan, ms);
4317 }
4318 EXPORT_SYMBOL(rtw89_phy_rfk_txiqk_and_wait);
4319 
4320 int rtw89_phy_rfk_cim3k_and_wait(struct rtw89_dev *rtwdev,
4321 				 enum rtw89_phy_idx phy_idx,
4322 				 const struct rtw89_chan *chan,
4323 				 unsigned int ms)
4324 {
4325 	int ret;
4326 
4327 	rtw89_phy_rfk_report_prep(rtwdev);
4328 
4329 	ret = rtw89_fw_h2c_rf_cim3k(rtwdev, phy_idx, chan);
4330 	if (ret)
4331 		return ret;
4332 
4333 	return rtw89_phy_rfk_report_wait(rtwdev, CIM3k, phy_idx, chan, ms);
4334 }
4335 EXPORT_SYMBOL(rtw89_phy_rfk_cim3k_and_wait);
4336 
4337 static u32 phy_tssi_get_cck_group(u8 ch)
4338 {
4339 	switch (ch) {
4340 	case 1 ... 2:
4341 		return 0;
4342 	case 3 ... 5:
4343 		return 1;
4344 	case 6 ... 8:
4345 		return 2;
4346 	case 9 ... 11:
4347 		return 3;
4348 	case 12 ... 13:
4349 		return 4;
4350 	case 14:
4351 		return 5;
4352 	}
4353 
4354 	return 0;
4355 }
4356 
4357 #define PHY_TSSI_EXTRA_GROUP_BIT BIT(31)
4358 #define PHY_TSSI_EXTRA_GROUP(idx) (PHY_TSSI_EXTRA_GROUP_BIT | (idx))
4359 #define PHY_IS_TSSI_EXTRA_GROUP(group) ((group) & PHY_TSSI_EXTRA_GROUP_BIT)
4360 #define PHY_TSSI_EXTRA_GET_GROUP_IDX1(group) \
4361 	((group) & ~PHY_TSSI_EXTRA_GROUP_BIT)
4362 #define PHY_TSSI_EXTRA_GET_GROUP_IDX2(group) \
4363 	(PHY_TSSI_EXTRA_GET_GROUP_IDX1(group) + 1)
4364 
4365 static u32 phy_tssi_get_ofdm_group(u8 ch)
4366 {
4367 	switch (ch) {
4368 	case 1 ... 2:
4369 		return 0;
4370 	case 3 ... 5:
4371 		return 1;
4372 	case 6 ... 8:
4373 		return 2;
4374 	case 9 ... 11:
4375 		return 3;
4376 	case 12 ... 14:
4377 		return 4;
4378 	case 36 ... 40:
4379 		return 5;
4380 	case 41 ... 43:
4381 		return PHY_TSSI_EXTRA_GROUP(5);
4382 	case 44 ... 48:
4383 		return 6;
4384 	case 49 ... 51:
4385 		return PHY_TSSI_EXTRA_GROUP(6);
4386 	case 52 ... 56:
4387 		return 7;
4388 	case 57 ... 59:
4389 		return PHY_TSSI_EXTRA_GROUP(7);
4390 	case 60 ... 64:
4391 		return 8;
4392 	case 100 ... 104:
4393 		return 9;
4394 	case 105 ... 107:
4395 		return PHY_TSSI_EXTRA_GROUP(9);
4396 	case 108 ... 112:
4397 		return 10;
4398 	case 113 ... 115:
4399 		return PHY_TSSI_EXTRA_GROUP(10);
4400 	case 116 ... 120:
4401 		return 11;
4402 	case 121 ... 123:
4403 		return PHY_TSSI_EXTRA_GROUP(11);
4404 	case 124 ... 128:
4405 		return 12;
4406 	case 129 ... 131:
4407 		return PHY_TSSI_EXTRA_GROUP(12);
4408 	case 132 ... 136:
4409 		return 13;
4410 	case 137 ... 139:
4411 		return PHY_TSSI_EXTRA_GROUP(13);
4412 	case 140 ... 144:
4413 		return 14;
4414 	case 149 ... 153:
4415 		return 15;
4416 	case 154 ... 156:
4417 		return PHY_TSSI_EXTRA_GROUP(15);
4418 	case 157 ... 161:
4419 		return 16;
4420 	case 162 ... 164:
4421 		return PHY_TSSI_EXTRA_GROUP(16);
4422 	case 165 ... 169:
4423 		return 17;
4424 	case 170 ... 172:
4425 		return PHY_TSSI_EXTRA_GROUP(17);
4426 	case 173 ... 177:
4427 		return 18;
4428 	}
4429 
4430 	return 0;
4431 }
4432 
4433 static u32 phy_tssi_get_6g_ofdm_group(u8 ch)
4434 {
4435 	switch (ch) {
4436 	case 1 ... 5:
4437 		return 0;
4438 	case 6 ... 8:
4439 		return PHY_TSSI_EXTRA_GROUP(0);
4440 	case 9 ... 13:
4441 		return 1;
4442 	case 14 ... 16:
4443 		return PHY_TSSI_EXTRA_GROUP(1);
4444 	case 17 ... 21:
4445 		return 2;
4446 	case 22 ... 24:
4447 		return PHY_TSSI_EXTRA_GROUP(2);
4448 	case 25 ... 29:
4449 		return 3;
4450 	case 33 ... 37:
4451 		return 4;
4452 	case 38 ... 40:
4453 		return PHY_TSSI_EXTRA_GROUP(4);
4454 	case 41 ... 45:
4455 		return 5;
4456 	case 46 ... 48:
4457 		return PHY_TSSI_EXTRA_GROUP(5);
4458 	case 49 ... 53:
4459 		return 6;
4460 	case 54 ... 56:
4461 		return PHY_TSSI_EXTRA_GROUP(6);
4462 	case 57 ... 61:
4463 		return 7;
4464 	case 65 ... 69:
4465 		return 8;
4466 	case 70 ... 72:
4467 		return PHY_TSSI_EXTRA_GROUP(8);
4468 	case 73 ... 77:
4469 		return 9;
4470 	case 78 ... 80:
4471 		return PHY_TSSI_EXTRA_GROUP(9);
4472 	case 81 ... 85:
4473 		return 10;
4474 	case 86 ... 88:
4475 		return PHY_TSSI_EXTRA_GROUP(10);
4476 	case 89 ... 93:
4477 		return 11;
4478 	case 97 ... 101:
4479 		return 12;
4480 	case 102 ... 104:
4481 		return PHY_TSSI_EXTRA_GROUP(12);
4482 	case 105 ... 109:
4483 		return 13;
4484 	case 110 ... 112:
4485 		return PHY_TSSI_EXTRA_GROUP(13);
4486 	case 113 ... 117:
4487 		return 14;
4488 	case 118 ... 120:
4489 		return PHY_TSSI_EXTRA_GROUP(14);
4490 	case 121 ... 125:
4491 		return 15;
4492 	case 129 ... 133:
4493 		return 16;
4494 	case 134 ... 136:
4495 		return PHY_TSSI_EXTRA_GROUP(16);
4496 	case 137 ... 141:
4497 		return 17;
4498 	case 142 ... 144:
4499 		return PHY_TSSI_EXTRA_GROUP(17);
4500 	case 145 ... 149:
4501 		return 18;
4502 	case 150 ... 152:
4503 		return PHY_TSSI_EXTRA_GROUP(18);
4504 	case 153 ... 157:
4505 		return 19;
4506 	case 161 ... 165:
4507 		return 20;
4508 	case 166 ... 168:
4509 		return PHY_TSSI_EXTRA_GROUP(20);
4510 	case 169 ... 173:
4511 		return 21;
4512 	case 174 ... 176:
4513 		return PHY_TSSI_EXTRA_GROUP(21);
4514 	case 177 ... 181:
4515 		return 22;
4516 	case 182 ... 184:
4517 		return PHY_TSSI_EXTRA_GROUP(22);
4518 	case 185 ... 189:
4519 		return 23;
4520 	case 193 ... 197:
4521 		return 24;
4522 	case 198 ... 200:
4523 		return PHY_TSSI_EXTRA_GROUP(24);
4524 	case 201 ... 205:
4525 		return 25;
4526 	case 206 ... 208:
4527 		return PHY_TSSI_EXTRA_GROUP(25);
4528 	case 209 ... 213:
4529 		return 26;
4530 	case 214 ... 216:
4531 		return PHY_TSSI_EXTRA_GROUP(26);
4532 	case 217 ... 221:
4533 		return 27;
4534 	case 225 ... 229:
4535 		return 28;
4536 	case 230 ... 232:
4537 		return PHY_TSSI_EXTRA_GROUP(28);
4538 	case 233 ... 237:
4539 		return 29;
4540 	case 238 ... 240:
4541 		return PHY_TSSI_EXTRA_GROUP(29);
4542 	case 241 ... 245:
4543 		return 30;
4544 	case 246 ... 248:
4545 		return PHY_TSSI_EXTRA_GROUP(30);
4546 	case 249 ... 253:
4547 		return 31;
4548 	}
4549 
4550 	return 0;
4551 }
4552 
4553 static u32 phy_tssi_get_trim_group(u8 ch)
4554 {
4555 	switch (ch) {
4556 	case 1 ... 8:
4557 		return 0;
4558 	case 9 ... 14:
4559 		return 1;
4560 	case 36 ... 48:
4561 		return 2;
4562 	case 49 ... 51:
4563 		return PHY_TSSI_EXTRA_GROUP(2);
4564 	case 52 ... 64:
4565 		return 3;
4566 	case 100 ... 112:
4567 		return 4;
4568 	case 113 ... 115:
4569 		return PHY_TSSI_EXTRA_GROUP(4);
4570 	case 116 ... 128:
4571 		return 5;
4572 	case 132 ... 144:
4573 		return 6;
4574 	case 149 ... 177:
4575 		return 7;
4576 	}
4577 
4578 	return 0;
4579 }
4580 
4581 static u32 phy_tssi_get_6g_trim_group(u8 ch)
4582 {
4583 	switch (ch) {
4584 	case 1 ... 13:
4585 		return 0;
4586 	case 14 ... 16:
4587 		return PHY_TSSI_EXTRA_GROUP(0);
4588 	case 17 ... 29:
4589 		return 1;
4590 	case 33 ... 45:
4591 		return 2;
4592 	case 46 ... 48:
4593 		return PHY_TSSI_EXTRA_GROUP(2);
4594 	case 49 ... 61:
4595 		return 3;
4596 	case 65 ... 77:
4597 		return 4;
4598 	case 78 ... 80:
4599 		return PHY_TSSI_EXTRA_GROUP(4);
4600 	case 81 ... 93:
4601 		return 5;
4602 	case 97 ... 109:
4603 		return 6;
4604 	case 110 ... 112:
4605 		return PHY_TSSI_EXTRA_GROUP(6);
4606 	case 113 ... 125:
4607 		return 7;
4608 	case 129 ... 141:
4609 		return 8;
4610 	case 142 ... 144:
4611 		return PHY_TSSI_EXTRA_GROUP(8);
4612 	case 145 ... 157:
4613 		return 9;
4614 	case 161 ... 173:
4615 		return 10;
4616 	case 174 ... 176:
4617 		return PHY_TSSI_EXTRA_GROUP(10);
4618 	case 177 ... 189:
4619 		return 11;
4620 	case 193 ... 205:
4621 		return 12;
4622 	case 206 ... 208:
4623 		return PHY_TSSI_EXTRA_GROUP(12);
4624 	case 209 ... 221:
4625 		return 13;
4626 	case 225 ... 237:
4627 		return 14;
4628 	case 238 ... 240:
4629 		return PHY_TSSI_EXTRA_GROUP(14);
4630 	case 241 ... 253:
4631 		return 15;
4632 	}
4633 
4634 	return 0;
4635 }
4636 
4637 static s8 phy_tssi_get_ofdm_de(struct rtw89_dev *rtwdev,
4638 			       enum rtw89_phy_idx phy,
4639 			       const struct rtw89_chan *chan,
4640 			       enum rtw89_rf_path path)
4641 {
4642 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
4643 	enum rtw89_band band = chan->band_type;
4644 	u8 ch = chan->channel;
4645 	u32 gidx_1st;
4646 	u32 gidx_2nd;
4647 	s8 de_1st;
4648 	s8 de_2nd;
4649 	u32 gidx;
4650 	s8 val;
4651 
4652 	if (band == RTW89_BAND_6G)
4653 		goto calc_6g;
4654 
4655 	gidx = phy_tssi_get_ofdm_group(ch);
4656 
4657 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4658 		    "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n",
4659 		    path, gidx);
4660 
4661 	if (PHY_IS_TSSI_EXTRA_GROUP(gidx)) {
4662 		gidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(gidx);
4663 		gidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(gidx);
4664 		de_1st = tssi_info->tssi_mcs[path][gidx_1st];
4665 		de_2nd = tssi_info->tssi_mcs[path][gidx_2nd];
4666 		val = (de_1st + de_2nd) / 2;
4667 
4668 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4669 			    "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n",
4670 			    path, val, de_1st, de_2nd);
4671 	} else {
4672 		val = tssi_info->tssi_mcs[path][gidx];
4673 
4674 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4675 			    "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val);
4676 	}
4677 
4678 	return val;
4679 
4680 calc_6g:
4681 	gidx = phy_tssi_get_6g_ofdm_group(ch);
4682 
4683 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4684 		    "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n",
4685 		    path, gidx);
4686 
4687 	if (PHY_IS_TSSI_EXTRA_GROUP(gidx)) {
4688 		gidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(gidx);
4689 		gidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(gidx);
4690 		de_1st = tssi_info->tssi_6g_mcs[path][gidx_1st];
4691 		de_2nd = tssi_info->tssi_6g_mcs[path][gidx_2nd];
4692 		val = (de_1st + de_2nd) / 2;
4693 
4694 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4695 			    "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n",
4696 			    path, val, de_1st, de_2nd);
4697 	} else {
4698 		val = tssi_info->tssi_6g_mcs[path][gidx];
4699 
4700 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4701 			    "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val);
4702 	}
4703 
4704 	return val;
4705 }
4706 
4707 static s8 phy_tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev,
4708 				    enum rtw89_phy_idx phy,
4709 				    const struct rtw89_chan *chan,
4710 				    enum rtw89_rf_path path)
4711 {
4712 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
4713 	enum rtw89_band band = chan->band_type;
4714 	u8 ch = chan->channel;
4715 	u32 tgidx_1st;
4716 	u32 tgidx_2nd;
4717 	s8 tde_1st;
4718 	s8 tde_2nd;
4719 	u32 tgidx;
4720 	s8 val;
4721 
4722 	if (band == RTW89_BAND_6G)
4723 		goto calc_6g;
4724 
4725 	tgidx = phy_tssi_get_trim_group(ch);
4726 
4727 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4728 		    "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n",
4729 		    path, tgidx);
4730 
4731 	if (PHY_IS_TSSI_EXTRA_GROUP(tgidx)) {
4732 		tgidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(tgidx);
4733 		tgidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(tgidx);
4734 		tde_1st = tssi_info->tssi_trim[path][tgidx_1st];
4735 		tde_2nd = tssi_info->tssi_trim[path][tgidx_2nd];
4736 		val = (tde_1st + tde_2nd) / 2;
4737 
4738 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4739 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n",
4740 			    path, val, tde_1st, tde_2nd);
4741 	} else {
4742 		val = tssi_info->tssi_trim[path][tgidx];
4743 
4744 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4745 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d\n",
4746 			    path, val);
4747 	}
4748 
4749 	return val;
4750 
4751 calc_6g:
4752 	tgidx = phy_tssi_get_6g_trim_group(ch);
4753 
4754 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4755 		    "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n",
4756 		    path, tgidx);
4757 
4758 	if (PHY_IS_TSSI_EXTRA_GROUP(tgidx)) {
4759 		tgidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(tgidx);
4760 		tgidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(tgidx);
4761 		tde_1st = tssi_info->tssi_trim_6g[path][tgidx_1st];
4762 		tde_2nd = tssi_info->tssi_trim_6g[path][tgidx_2nd];
4763 		val = (tde_1st + tde_2nd) / 2;
4764 
4765 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4766 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n",
4767 			    path, val, tde_1st, tde_2nd);
4768 	} else {
4769 		val = tssi_info->tssi_trim_6g[path][tgidx];
4770 
4771 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4772 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d\n",
4773 			    path, val);
4774 	}
4775 
4776 	return val;
4777 }
4778 
4779 void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
4780 					       enum rtw89_phy_idx phy,
4781 					       const struct rtw89_chan *chan,
4782 					       struct rtw89_h2c_rf_tssi *h2c)
4783 {
4784 	const struct rtw89_chip_info *chip = rtwdev->chip;
4785 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
4786 	u8 ch = chan->channel;
4787 	s8 trim_de;
4788 	s8 ofdm_de;
4789 	s8 cck_de;
4790 	u8 gidx;
4791 	s8 val;
4792 	int i;
4793 
4794 	rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI][TRIM]: phy=%d ch=%d\n",
4795 		    phy, ch);
4796 
4797 	for (i = RF_PATH_A; i <= RF_PATH_B; i++) {
4798 		trim_de = phy_tssi_get_ofdm_trim_de(rtwdev, phy, chan, i);
4799 		h2c->curr_tssi_trim_de[i] = trim_de;
4800 
4801 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4802 			    "[TSSI][TRIM]: path=%d trim_de=0x%x\n", i, trim_de);
4803 
4804 		gidx = phy_tssi_get_cck_group(ch);
4805 		cck_de = tssi_info->tssi_cck[i][gidx];
4806 		val = u32_get_bits(cck_de + trim_de, 0xff);
4807 
4808 		if (chip->chip_id == RTL8922A) {
4809 			h2c->curr_tssi_cck_de[i] = 0x0;
4810 			h2c->curr_tssi_cck_de_20m[i] = val;
4811 			h2c->curr_tssi_cck_de_40m[i] = val;
4812 		} else {
4813 			h2c->curr_tssi_cck_de[i] = val;
4814 		}
4815 
4816 		h2c->curr_tssi_efuse_cck_de[i] = cck_de;
4817 
4818 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4819 			    "[TSSI][TRIM]: path=%d cck_de=0x%x\n", i, cck_de);
4820 
4821 		ofdm_de = phy_tssi_get_ofdm_de(rtwdev, phy, chan, i);
4822 		val = u32_get_bits(ofdm_de + trim_de, 0xff);
4823 
4824 		if (chip->chip_id == RTL8922A) {
4825 			h2c->curr_tssi_ofdm_de[i] = 0x0;
4826 			h2c->curr_tssi_ofdm_de_20m[i] = val;
4827 			h2c->curr_tssi_ofdm_de_40m[i] = val;
4828 			h2c->curr_tssi_ofdm_de_80m[i] = val;
4829 			h2c->curr_tssi_ofdm_de_160m[i] = val;
4830 			h2c->curr_tssi_ofdm_de_320m[i] = val;
4831 		} else {
4832 			h2c->curr_tssi_ofdm_de[i] = val;
4833 		}
4834 
4835 		h2c->curr_tssi_efuse_ofdm_de[i] = ofdm_de;
4836 
4837 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4838 			    "[TSSI][TRIM]: path=%d ofdm_de=0x%x\n", i, ofdm_de);
4839 	}
4840 }
4841 
4842 void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev,
4843 					      enum rtw89_phy_idx phy,
4844 					      const struct rtw89_chan *chan,
4845 					      struct rtw89_h2c_rf_tssi *h2c)
4846 {
4847 	struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
4848 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
4849 	const struct rtw89_chip_info *chip = rtwdev->chip;
4850 	const s8 *thm_up[RF_PATH_B + 1] = {};
4851 	const s8 *thm_down[RF_PATH_B + 1] = {};
4852 	u8 subband = chan->subband_type;
4853 	s8 thm_ofst[128] = {};
4854 	int multiplier;
4855 	u8 thermal;
4856 	u8 path;
4857 	u8 i, j;
4858 
4859 	switch (subband) {
4860 	default:
4861 	case RTW89_CH_2G:
4862 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P][0];
4863 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N][0];
4864 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P][0];
4865 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N][0];
4866 		break;
4867 	case RTW89_CH_5G_BAND_1:
4868 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][0];
4869 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][0];
4870 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][0];
4871 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][0];
4872 		break;
4873 	case RTW89_CH_5G_BAND_3:
4874 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][1];
4875 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][1];
4876 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][1];
4877 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][1];
4878 		break;
4879 	case RTW89_CH_5G_BAND_4:
4880 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][2];
4881 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][2];
4882 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][2];
4883 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][2];
4884 		break;
4885 	case RTW89_CH_6G_BAND_IDX0:
4886 	case RTW89_CH_6G_BAND_IDX1:
4887 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][0];
4888 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][0];
4889 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][0];
4890 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][0];
4891 		break;
4892 	case RTW89_CH_6G_BAND_IDX2:
4893 	case RTW89_CH_6G_BAND_IDX3:
4894 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][1];
4895 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][1];
4896 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][1];
4897 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][1];
4898 		break;
4899 	case RTW89_CH_6G_BAND_IDX4:
4900 	case RTW89_CH_6G_BAND_IDX5:
4901 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][2];
4902 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][2];
4903 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][2];
4904 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][2];
4905 		break;
4906 	case RTW89_CH_6G_BAND_IDX6:
4907 	case RTW89_CH_6G_BAND_IDX7:
4908 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][3];
4909 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][3];
4910 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][3];
4911 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][3];
4912 		break;
4913 	}
4914 
4915 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4916 		    "[TSSI] tmeter tbl on subband: %u\n", subband);
4917 
4918 	if (chip->chip_id == RTL8922A)
4919 		multiplier = 1;
4920 	else
4921 		multiplier = -1;
4922 
4923 	for (path = RF_PATH_A; path <= RF_PATH_B; path++) {
4924 		thermal = tssi_info->thermal[path];
4925 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4926 			    "path: %u, pg thermal: 0x%x\n", path, thermal);
4927 
4928 		if (thermal == 0xff) {
4929 			h2c->pg_thermal[path] = 0x38;
4930 			memset(h2c->ftable[path], 0, sizeof(h2c->ftable[path]));
4931 			continue;
4932 		}
4933 
4934 		h2c->pg_thermal[path] = thermal;
4935 
4936 		i = 0;
4937 		for (j = 0; j < 64; j++) {
4938 			thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
4939 				      thm_up[path][i++] :
4940 				      thm_up[path][DELTA_SWINGIDX_SIZE - 1];
4941 			thm_ofst[j] *= multiplier;
4942 		}
4943 
4944 		i = 1;
4945 		for (j = 127; j >= 64; j--) {
4946 			thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
4947 				      -thm_down[path][i++] :
4948 				      -thm_down[path][DELTA_SWINGIDX_SIZE - 1];
4949 			thm_ofst[j] *= multiplier;
4950 		}
4951 
4952 		for (i = 0; i < 128; i += 4) {
4953 			h2c->ftable[path][i + 0] = thm_ofst[i + 3];
4954 			h2c->ftable[path][i + 1] = thm_ofst[i + 2];
4955 			h2c->ftable[path][i + 2] = thm_ofst[i + 1];
4956 			h2c->ftable[path][i + 3] = thm_ofst[i + 0];
4957 
4958 			rtw89_debug(rtwdev, RTW89_DBG_TSSI,
4959 				    "thm ofst [%x]: %02x %02x %02x %02x\n",
4960 				    i, thm_ofst[i], thm_ofst[i + 1],
4961 				    thm_ofst[i + 2], thm_ofst[i + 3]);
4962 		}
4963 	}
4964 }
4965 
4966 static u8 rtw89_phy_cfo_get_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo)
4967 {
4968 	const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
4969 	u32 reg_mask;
4970 
4971 	if (sc_xo)
4972 		reg_mask = xtal->sc_xo_mask;
4973 	else
4974 		reg_mask = xtal->sc_xi_mask;
4975 
4976 	return (u8)rtw89_read32_mask(rtwdev, xtal->xcap_reg, reg_mask);
4977 }
4978 
4979 static void rtw89_phy_cfo_set_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo,
4980 				       u8 val)
4981 {
4982 	const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
4983 	u32 reg_mask;
4984 
4985 	if (sc_xo)
4986 		reg_mask = xtal->sc_xo_mask;
4987 	else
4988 		reg_mask = xtal->sc_xi_mask;
4989 
4990 	rtw89_write32_mask(rtwdev, xtal->xcap_reg, reg_mask, val);
4991 }
4992 
4993 static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
4994 					  u8 crystal_cap, bool force)
4995 {
4996 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
4997 	const struct rtw89_chip_info *chip = rtwdev->chip;
4998 	u8 sc_xi_val = 0, sc_xo_val = 0;
4999 
5000 	if (!force && cfo->crystal_cap == crystal_cap)
5001 		return;
5002 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8851B) {
5003 		rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap);
5004 		rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap);
5005 		sc_xo_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, true);
5006 		sc_xi_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, false);
5007 	} else {
5008 		rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XO,
5009 					crystal_cap, XTAL_SC_XO_MASK);
5010 		rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XI,
5011 					crystal_cap, XTAL_SC_XI_MASK);
5012 		rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XO, &sc_xo_val);
5013 		rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XI, &sc_xi_val);
5014 	}
5015 	cfo->crystal_cap = sc_xi_val;
5016 	cfo->x_cap_ofst = (s8)((int)cfo->crystal_cap - cfo->def_x_cap);
5017 
5018 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Set sc_xi=0x%x\n", sc_xi_val);
5019 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Set sc_xo=0x%x\n", sc_xo_val);
5020 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Get xcap_ofst=%d\n",
5021 		    cfo->x_cap_ofst);
5022 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Set xcap OK\n");
5023 }
5024 
5025 static void rtw89_phy_cfo_reset(struct rtw89_dev *rtwdev)
5026 {
5027 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5028 	u8 cap;
5029 
5030 	cfo->def_x_cap = cfo->crystal_cap_default & B_AX_XTAL_SC_MASK;
5031 	cfo->is_adjust = false;
5032 	if (cfo->crystal_cap == cfo->def_x_cap)
5033 		return;
5034 	cap = cfo->crystal_cap;
5035 	cap += (cap > cfo->def_x_cap ? -1 : 1);
5036 	rtw89_phy_cfo_set_crystal_cap(rtwdev, cap, false);
5037 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
5038 		    "(0x%x) approach to dflt_val=(0x%x)\n", cfo->crystal_cap,
5039 		    cfo->def_x_cap);
5040 }
5041 
5042 static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo)
5043 {
5044 	const struct rtw89_reg_def *dcfo_comp = rtwdev->chip->dcfo_comp;
5045 	bool is_linked = rtwdev->total_sta_assoc > 0;
5046 	s32 cfo_avg_312;
5047 	s32 dcfo_comp_val;
5048 	int sign;
5049 
5050 	if (!dcfo_comp)
5051 		return;
5052 
5053 	if (!is_linked) {
5054 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "DCFO: is_linked=%d\n",
5055 			    is_linked);
5056 		return;
5057 	}
5058 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "DCFO: curr_cfo=%d\n", curr_cfo);
5059 	if (curr_cfo == 0)
5060 		return;
5061 	dcfo_comp_val = rtw89_phy_read32_mask(rtwdev, R_DCFO, B_DCFO);
5062 	sign = curr_cfo > 0 ? 1 : -1;
5063 	cfo_avg_312 = curr_cfo / 625 + sign * dcfo_comp_val;
5064 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "avg_cfo_312=%d step\n", cfo_avg_312);
5065 	if (rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv == CHIP_CBV)
5066 		cfo_avg_312 = -cfo_avg_312;
5067 	rtw89_phy_set_phy_regs(rtwdev, dcfo_comp->addr, dcfo_comp->mask,
5068 			       cfo_avg_312);
5069 }
5070 
5071 static void rtw89_dcfo_comp_init(struct rtw89_dev *rtwdev)
5072 {
5073 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
5074 	const struct rtw89_chip_info *chip = rtwdev->chip;
5075 	const struct rtw89_cfo_regs *cfo = phy->cfo;
5076 
5077 	rtw89_phy_set_phy_regs(rtwdev, cfo->comp_seg0, cfo->valid_0_mask, 1);
5078 	rtw89_phy_set_phy_regs(rtwdev, cfo->comp, cfo->weighting_mask, 8);
5079 
5080 	if (chip->chip_gen == RTW89_CHIP_AX) {
5081 		if (chip->cfo_hw_comp) {
5082 			rtw89_write32_mask(rtwdev, R_AX_PWR_UL_CTRL2,
5083 					   B_AX_PWR_UL_CFO_MASK, 0x6);
5084 		} else {
5085 			rtw89_phy_set_phy_regs(rtwdev, R_DCFO, B_DCFO, 1);
5086 			rtw89_write32_clr(rtwdev, R_AX_PWR_UL_CTRL2,
5087 					  B_AX_PWR_UL_CFO_MASK);
5088 		}
5089 	}
5090 }
5091 
5092 static void rtw89_phy_cfo_init(struct rtw89_dev *rtwdev)
5093 {
5094 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5095 	struct rtw89_efuse *efuse = &rtwdev->efuse;
5096 
5097 	cfo->crystal_cap_default = efuse->xtal_cap & B_AX_XTAL_SC_MASK;
5098 	cfo->crystal_cap = cfo->crystal_cap_default;
5099 	cfo->def_x_cap = cfo->crystal_cap;
5100 	cfo->x_cap_ub = min_t(int, cfo->def_x_cap + CFO_BOUND, 0x7f);
5101 	cfo->x_cap_lb = max_t(int, cfo->def_x_cap - CFO_BOUND, 0x1);
5102 	cfo->is_adjust = false;
5103 	cfo->divergence_lock_en = false;
5104 	cfo->x_cap_ofst = 0;
5105 	cfo->lock_cnt = 0;
5106 	cfo->rtw89_multi_cfo_mode = RTW89_TP_BASED_AVG_MODE;
5107 	cfo->apply_compensation = false;
5108 	cfo->residual_cfo_acc = 0;
5109 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Default xcap=%0x\n",
5110 		    cfo->crystal_cap_default);
5111 	rtw89_phy_cfo_set_crystal_cap(rtwdev, cfo->crystal_cap_default, true);
5112 	rtw89_dcfo_comp_init(rtwdev);
5113 	cfo->cfo_timer_ms = 2000;
5114 	cfo->cfo_trig_by_timer_en = false;
5115 	cfo->phy_cfo_trk_cnt = 0;
5116 	cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
5117 	cfo->cfo_ul_ofdma_acc_mode = RTW89_CFO_UL_OFDMA_ACC_ENABLE;
5118 }
5119 
5120 static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev,
5121 					     s32 curr_cfo)
5122 {
5123 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5124 	int crystal_cap = cfo->crystal_cap;
5125 	s32 cfo_abs = abs(curr_cfo);
5126 	int sign;
5127 
5128 	if (curr_cfo == 0) {
5129 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "curr_cfo=0\n");
5130 		return;
5131 	}
5132 	if (!cfo->is_adjust) {
5133 		if (cfo_abs > CFO_TRK_ENABLE_TH)
5134 			cfo->is_adjust = true;
5135 	} else {
5136 		if (cfo_abs <= CFO_TRK_STOP_TH)
5137 			cfo->is_adjust = false;
5138 	}
5139 	if (!cfo->is_adjust) {
5140 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Stop CFO tracking\n");
5141 		return;
5142 	}
5143 	sign = curr_cfo > 0 ? 1 : -1;
5144 	if (cfo_abs > CFO_TRK_STOP_TH_4)
5145 		crystal_cap += 3 * sign;
5146 	else if (cfo_abs > CFO_TRK_STOP_TH_3)
5147 		crystal_cap += 3 * sign;
5148 	else if (cfo_abs > CFO_TRK_STOP_TH_2)
5149 		crystal_cap += 1 * sign;
5150 	else if (cfo_abs > CFO_TRK_STOP_TH_1)
5151 		crystal_cap += 1 * sign;
5152 	else
5153 		return;
5154 
5155 	crystal_cap = clamp(crystal_cap, 0, 127);
5156 	rtw89_phy_cfo_set_crystal_cap(rtwdev, (u8)crystal_cap, false);
5157 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
5158 		    "X_cap{Curr,Default}={0x%x,0x%x}\n",
5159 		    cfo->crystal_cap, cfo->def_x_cap);
5160 }
5161 
5162 static s32 rtw89_phy_average_cfo_calc(struct rtw89_dev *rtwdev)
5163 {
5164 	const struct rtw89_chip_info *chip = rtwdev->chip;
5165 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5166 	s32 cfo_khz_all = 0;
5167 	s32 cfo_cnt_all = 0;
5168 	s32 cfo_all_avg = 0;
5169 	u8 i;
5170 
5171 	if (rtwdev->total_sta_assoc != 1)
5172 		return 0;
5173 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "one_entry_only\n");
5174 	for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
5175 		if (cfo->cfo_cnt[i] == 0)
5176 			continue;
5177 		cfo_khz_all += cfo->cfo_tail[i];
5178 		cfo_cnt_all += cfo->cfo_cnt[i];
5179 		cfo_all_avg = phy_div(cfo_khz_all, cfo_cnt_all);
5180 		cfo->pre_cfo_avg[i] = cfo->cfo_avg[i];
5181 		cfo->dcfo_avg = phy_div(cfo_khz_all << chip->dcfo_comp_sft,
5182 					cfo_cnt_all);
5183 	}
5184 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
5185 		    "CFO track for macid = %d\n", i);
5186 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
5187 		    "Total cfo=%dK, pkt_cnt=%d, avg_cfo=%dK\n",
5188 		    cfo_khz_all, cfo_cnt_all, cfo_all_avg);
5189 	return cfo_all_avg;
5190 }
5191 
5192 static s32 rtw89_phy_multi_sta_cfo_calc(struct rtw89_dev *rtwdev)
5193 {
5194 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5195 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
5196 	s32 target_cfo = 0;
5197 	s32 cfo_khz_all = 0;
5198 	s32 cfo_khz_all_tp_wgt = 0;
5199 	s32 cfo_avg = 0;
5200 	s32 max_cfo_lb = BIT(31);
5201 	s32 min_cfo_ub = GENMASK(30, 0);
5202 	u16 cfo_cnt_all = 0;
5203 	u8 active_entry_cnt = 0;
5204 	u8 sta_cnt = 0;
5205 	u32 tp_all = 0;
5206 	u8 i;
5207 	u8 cfo_tol = 0;
5208 
5209 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Multi entry cfo_trk\n");
5210 	if (cfo->rtw89_multi_cfo_mode == RTW89_PKT_BASED_AVG_MODE) {
5211 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Pkt based avg mode\n");
5212 		for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
5213 			if (cfo->cfo_cnt[i] == 0)
5214 				continue;
5215 			cfo_khz_all += cfo->cfo_tail[i];
5216 			cfo_cnt_all += cfo->cfo_cnt[i];
5217 			cfo_avg = phy_div(cfo_khz_all, (s32)cfo_cnt_all);
5218 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
5219 				    "Msta cfo=%d, pkt_cnt=%d, avg_cfo=%d\n",
5220 				    cfo_khz_all, cfo_cnt_all, cfo_avg);
5221 			target_cfo = cfo_avg;
5222 		}
5223 	} else if (cfo->rtw89_multi_cfo_mode == RTW89_ENTRY_BASED_AVG_MODE) {
5224 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Entry based avg mode\n");
5225 		for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
5226 			if (cfo->cfo_cnt[i] == 0)
5227 				continue;
5228 			cfo->cfo_avg[i] = phy_div(cfo->cfo_tail[i],
5229 						  (s32)cfo->cfo_cnt[i]);
5230 			cfo_khz_all += cfo->cfo_avg[i];
5231 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
5232 				    "Macid=%d, cfo_avg=%d\n", i,
5233 				    cfo->cfo_avg[i]);
5234 		}
5235 		sta_cnt = rtwdev->total_sta_assoc;
5236 		cfo_avg = phy_div(cfo_khz_all, (s32)sta_cnt);
5237 		rtw89_debug(rtwdev, RTW89_DBG_CFO,
5238 			    "Msta cfo_acc=%d, ent_cnt=%d, avg_cfo=%d\n",
5239 			    cfo_khz_all, sta_cnt, cfo_avg);
5240 		target_cfo = cfo_avg;
5241 	} else if (cfo->rtw89_multi_cfo_mode == RTW89_TP_BASED_AVG_MODE) {
5242 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "TP based avg mode\n");
5243 		cfo_tol = cfo->sta_cfo_tolerance;
5244 		for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
5245 			sta_cnt++;
5246 			if (cfo->cfo_cnt[i] != 0) {
5247 				cfo->cfo_avg[i] = phy_div(cfo->cfo_tail[i],
5248 							  (s32)cfo->cfo_cnt[i]);
5249 				active_entry_cnt++;
5250 			} else {
5251 				cfo->cfo_avg[i] = cfo->pre_cfo_avg[i];
5252 			}
5253 			max_cfo_lb = max(cfo->cfo_avg[i] - cfo_tol, max_cfo_lb);
5254 			min_cfo_ub = min(cfo->cfo_avg[i] + cfo_tol, min_cfo_ub);
5255 			cfo_khz_all += cfo->cfo_avg[i];
5256 			/* need tp for each entry */
5257 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
5258 				    "[%d] cfo_avg=%d, tp=tbd\n",
5259 				    i, cfo->cfo_avg[i]);
5260 			if (sta_cnt >= rtwdev->total_sta_assoc)
5261 				break;
5262 		}
5263 		tp_all = stats->rx_throughput; /* need tp for each entry */
5264 		cfo_avg =  phy_div(cfo_khz_all_tp_wgt, (s32)tp_all);
5265 
5266 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Assoc sta cnt=%d\n",
5267 			    sta_cnt);
5268 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Active sta cnt=%d\n",
5269 			    active_entry_cnt);
5270 		rtw89_debug(rtwdev, RTW89_DBG_CFO,
5271 			    "Msta cfo with tp_wgt=%d, avg_cfo=%d\n",
5272 			    cfo_khz_all_tp_wgt, cfo_avg);
5273 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "cfo_lb=%d,cfo_ub=%d\n",
5274 			    max_cfo_lb, min_cfo_ub);
5275 		if (max_cfo_lb <= min_cfo_ub) {
5276 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
5277 				    "cfo win_size=%d\n",
5278 				    min_cfo_ub - max_cfo_lb);
5279 			target_cfo = clamp(cfo_avg, max_cfo_lb, min_cfo_ub);
5280 		} else {
5281 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
5282 				    "No intersection of cfo tolerance windows\n");
5283 			target_cfo = phy_div(cfo_khz_all, (s32)sta_cnt);
5284 		}
5285 		for (i = 0; i < CFO_TRACK_MAX_USER; i++)
5286 			cfo->pre_cfo_avg[i] = cfo->cfo_avg[i];
5287 	}
5288 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Target cfo=%d\n", target_cfo);
5289 	return target_cfo;
5290 }
5291 
5292 static void rtw89_phy_cfo_statistics_reset(struct rtw89_dev *rtwdev)
5293 {
5294 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5295 
5296 	memset(&cfo->cfo_tail, 0, sizeof(cfo->cfo_tail));
5297 	memset(&cfo->cfo_cnt, 0, sizeof(cfo->cfo_cnt));
5298 	cfo->packet_count = 0;
5299 	cfo->packet_count_pre = 0;
5300 	cfo->cfo_avg_pre = 0;
5301 }
5302 
5303 static void rtw89_phy_cfo_dm(struct rtw89_dev *rtwdev)
5304 {
5305 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5306 	s32 new_cfo = 0;
5307 	bool x_cap_update = false;
5308 	u8 pre_x_cap = cfo->crystal_cap;
5309 	u8 dcfo_comp_sft = rtwdev->chip->dcfo_comp_sft;
5310 
5311 	cfo->dcfo_avg = 0;
5312 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "CFO:total_sta_assoc=%d\n",
5313 		    rtwdev->total_sta_assoc);
5314 	if (rtwdev->total_sta_assoc == 0 || rtw89_is_mlo_1_1(rtwdev)) {
5315 		rtw89_phy_cfo_reset(rtwdev);
5316 		return;
5317 	}
5318 	if (cfo->packet_count == 0) {
5319 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Pkt cnt = 0\n");
5320 		return;
5321 	}
5322 	if (cfo->packet_count == cfo->packet_count_pre) {
5323 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Pkt cnt doesn't change\n");
5324 		return;
5325 	}
5326 	if (rtwdev->total_sta_assoc == 1)
5327 		new_cfo = rtw89_phy_average_cfo_calc(rtwdev);
5328 	else
5329 		new_cfo = rtw89_phy_multi_sta_cfo_calc(rtwdev);
5330 	if (cfo->divergence_lock_en) {
5331 		cfo->lock_cnt++;
5332 		if (cfo->lock_cnt > CFO_PERIOD_CNT) {
5333 			cfo->divergence_lock_en = false;
5334 			cfo->lock_cnt = 0;
5335 		} else {
5336 			rtw89_phy_cfo_reset(rtwdev);
5337 		}
5338 		return;
5339 	}
5340 	if (cfo->crystal_cap >= cfo->x_cap_ub ||
5341 	    cfo->crystal_cap <= cfo->x_cap_lb) {
5342 		cfo->divergence_lock_en = true;
5343 		rtw89_phy_cfo_reset(rtwdev);
5344 		return;
5345 	}
5346 
5347 	rtw89_phy_cfo_crystal_cap_adjust(rtwdev, new_cfo);
5348 	cfo->cfo_avg_pre = new_cfo;
5349 	cfo->dcfo_avg_pre = cfo->dcfo_avg;
5350 	x_cap_update =  cfo->crystal_cap != pre_x_cap;
5351 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Xcap_up=%d\n", x_cap_update);
5352 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Xcap: D:%x C:%x->%x, ofst=%d\n",
5353 		    cfo->def_x_cap, pre_x_cap, cfo->crystal_cap,
5354 		    cfo->x_cap_ofst);
5355 	if (x_cap_update) {
5356 		if (cfo->dcfo_avg > 0)
5357 			cfo->dcfo_avg -= CFO_SW_COMP_FINE_TUNE << dcfo_comp_sft;
5358 		else
5359 			cfo->dcfo_avg += CFO_SW_COMP_FINE_TUNE << dcfo_comp_sft;
5360 	}
5361 	rtw89_dcfo_comp(rtwdev, cfo->dcfo_avg);
5362 	rtw89_phy_cfo_statistics_reset(rtwdev);
5363 }
5364 
5365 void rtw89_phy_cfo_track_work(struct wiphy *wiphy, struct wiphy_work *work)
5366 {
5367 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
5368 						cfo_track_work.work);
5369 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5370 
5371 	lockdep_assert_wiphy(wiphy);
5372 
5373 	if (!cfo->cfo_trig_by_timer_en)
5374 		return;
5375 	rtw89_leave_ps_mode(rtwdev);
5376 	rtw89_phy_cfo_dm(rtwdev);
5377 	wiphy_delayed_work_queue(wiphy, &rtwdev->cfo_track_work,
5378 				 msecs_to_jiffies(cfo->cfo_timer_ms));
5379 }
5380 
5381 static void rtw89_phy_cfo_start_work(struct rtw89_dev *rtwdev)
5382 {
5383 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5384 
5385 	wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->cfo_track_work,
5386 				 msecs_to_jiffies(cfo->cfo_timer_ms));
5387 }
5388 
5389 void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev)
5390 {
5391 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5392 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
5393 	bool is_ul_ofdma = false, ofdma_acc_en = false;
5394 
5395 	if (stats->rx_tf_periodic > CFO_TF_CNT_TH)
5396 		is_ul_ofdma = true;
5397 	if (cfo->cfo_ul_ofdma_acc_mode == RTW89_CFO_UL_OFDMA_ACC_ENABLE &&
5398 	    is_ul_ofdma)
5399 		ofdma_acc_en = true;
5400 
5401 	switch (cfo->phy_cfo_status) {
5402 	case RTW89_PHY_DCFO_STATE_NORMAL:
5403 		if (stats->tx_throughput >= CFO_TP_UPPER) {
5404 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_ENHANCE;
5405 			cfo->cfo_trig_by_timer_en = true;
5406 			cfo->cfo_timer_ms = CFO_COMP_PERIOD;
5407 			rtw89_phy_cfo_start_work(rtwdev);
5408 		}
5409 		break;
5410 	case RTW89_PHY_DCFO_STATE_ENHANCE:
5411 		if (stats->tx_throughput <= CFO_TP_LOWER)
5412 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
5413 		else if (ofdma_acc_en &&
5414 			 cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT)
5415 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_HOLD;
5416 		else
5417 			cfo->phy_cfo_trk_cnt++;
5418 
5419 		if (cfo->phy_cfo_status == RTW89_PHY_DCFO_STATE_NORMAL) {
5420 			cfo->phy_cfo_trk_cnt = 0;
5421 			cfo->cfo_trig_by_timer_en = false;
5422 		}
5423 		break;
5424 	case RTW89_PHY_DCFO_STATE_HOLD:
5425 		if (stats->tx_throughput <= CFO_TP_LOWER) {
5426 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
5427 			cfo->phy_cfo_trk_cnt = 0;
5428 			cfo->cfo_trig_by_timer_en = false;
5429 		} else {
5430 			cfo->phy_cfo_trk_cnt++;
5431 		}
5432 		break;
5433 	default:
5434 		cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
5435 		cfo->phy_cfo_trk_cnt = 0;
5436 		break;
5437 	}
5438 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
5439 		    "[CFO]WatchDog tp=%d,state=%d,timer_en=%d,trk_cnt=%d,thermal=%ld\n",
5440 		    stats->tx_throughput, cfo->phy_cfo_status,
5441 		    cfo->cfo_trig_by_timer_en, cfo->phy_cfo_trk_cnt,
5442 		    ewma_thermal_read(&rtwdev->phystat.avg_thermal[0]));
5443 	if (cfo->cfo_trig_by_timer_en)
5444 		return;
5445 	rtw89_phy_cfo_dm(rtwdev);
5446 }
5447 
5448 void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val,
5449 			 struct rtw89_rx_phy_ppdu *phy_ppdu)
5450 {
5451 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
5452 	u8 macid = phy_ppdu->mac_id;
5453 
5454 	if (macid >= CFO_TRACK_MAX_USER) {
5455 		rtw89_warn(rtwdev, "mac_id %d is out of range\n", macid);
5456 		return;
5457 	}
5458 
5459 	cfo->cfo_tail[macid] += cfo_val;
5460 	cfo->cfo_cnt[macid]++;
5461 	cfo->packet_count++;
5462 }
5463 
5464 void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
5465 {
5466 	const struct rtw89_chip_info *chip = rtwdev->chip;
5467 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
5468 						       rtwvif_link->chanctx_idx);
5469 	struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;
5470 
5471 	if (!chip->ul_tb_waveform_ctrl)
5472 		return;
5473 
5474 	rtwvif_link->def_tri_idx =
5475 		rtw89_phy_read32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG);
5476 
5477 	if (chip->chip_id == RTL8852B && rtwdev->hal.cv > CHIP_CBV)
5478 		rtwvif_link->dyn_tb_bedge_en = false;
5479 	else if (chan->band_type >= RTW89_BAND_5G &&
5480 		 chan->band_width >= RTW89_CHANNEL_WIDTH_40)
5481 		rtwvif_link->dyn_tb_bedge_en = true;
5482 	else
5483 		rtwvif_link->dyn_tb_bedge_en = false;
5484 
5485 	rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
5486 		    "[ULTB] def_if_bandedge=%d, def_tri_idx=%d\n",
5487 		    ul_tb_info->def_if_bandedge, rtwvif_link->def_tri_idx);
5488 	rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
5489 		    "[ULTB] dyn_tb_begde_en=%d, dyn_tb_tri_en=%d\n",
5490 		    rtwvif_link->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en);
5491 }
5492 
5493 struct rtw89_phy_ul_tb_check_data {
5494 	bool valid;
5495 	bool high_tf_client;
5496 	bool low_tf_client;
5497 	bool dyn_tb_bedge_en;
5498 	u8 def_tri_idx;
5499 };
5500 
5501 struct rtw89_phy_power_diff {
5502 	u32 q_00;
5503 	u32 q_11;
5504 	u32 q_matrix_en;
5505 	u32 ultb_1t_norm_160;
5506 	u32 ultb_2t_norm_160;
5507 	u32 com1_norm_1sts;
5508 	u32 com2_resp_1sts_path;
5509 };
5510 
5511 static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev,
5512 				       struct rtw89_vif_link *rtwvif_link)
5513 {
5514 	static const struct rtw89_phy_power_diff table[2] = {
5515 		{0x0, 0x0, 0x0, 0x0, 0xf4, 0x3, 0x3},
5516 		{0xb50, 0xb50, 0x1, 0xc, 0x0, 0x1, 0x1},
5517 	};
5518 	const struct rtw89_phy_power_diff *param;
5519 	u32 reg;
5520 
5521 	if (!rtwdev->chip->ul_tb_pwr_diff)
5522 		return;
5523 
5524 	if (rtwvif_link->pwr_diff_en == rtwvif_link->pre_pwr_diff_en) {
5525 		rtwvif_link->pwr_diff_en = false;
5526 		return;
5527 	}
5528 
5529 	rtwvif_link->pre_pwr_diff_en = rtwvif_link->pwr_diff_en;
5530 	param = &table[rtwvif_link->pwr_diff_en];
5531 
5532 	rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_00, B_Q_MATRIX_00_REAL,
5533 			       param->q_00);
5534 	rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_11, B_Q_MATRIX_11_REAL,
5535 			       param->q_11);
5536 	rtw89_phy_write32_mask(rtwdev, R_CUSTOMIZE_Q_MATRIX,
5537 			       B_CUSTOMIZE_Q_MATRIX_EN, param->q_matrix_en);
5538 
5539 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif_link->mac_idx);
5540 	rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_NORM_BW160,
5541 			   param->ultb_1t_norm_160);
5542 
5543 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif_link->mac_idx);
5544 	rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_NORM_BW160,
5545 			   param->ultb_2t_norm_160);
5546 
5547 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif_link->mac_idx);
5548 	rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM1_NORM_1STS,
5549 			   param->com1_norm_1sts);
5550 
5551 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif_link->mac_idx);
5552 	rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM2_RESP_1STS_PATH,
5553 			   param->com2_resp_1sts_path);
5554 }
5555 
5556 static
5557 void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev,
5558 				struct rtw89_vif_link *rtwvif_link,
5559 				struct rtw89_phy_ul_tb_check_data *ul_tb_data)
5560 {
5561 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
5562 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
5563 
5564 	if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION)
5565 		return;
5566 
5567 	if (!vif->cfg.assoc)
5568 		return;
5569 
5570 	if (rtwdev->chip->ul_tb_waveform_ctrl) {
5571 		if (stats->rx_tf_periodic > UL_TB_TF_CNT_L2H_TH)
5572 			ul_tb_data->high_tf_client = true;
5573 		else if (stats->rx_tf_periodic < UL_TB_TF_CNT_H2L_TH)
5574 			ul_tb_data->low_tf_client = true;
5575 
5576 		ul_tb_data->valid = true;
5577 		ul_tb_data->def_tri_idx = rtwvif_link->def_tri_idx;
5578 		ul_tb_data->dyn_tb_bedge_en = rtwvif_link->dyn_tb_bedge_en;
5579 	}
5580 
5581 	rtw89_phy_ofdma_power_diff(rtwdev, rtwvif_link);
5582 }
5583 
5584 static void rtw89_phy_ul_tb_waveform_ctrl(struct rtw89_dev *rtwdev,
5585 					  struct rtw89_phy_ul_tb_check_data *ul_tb_data)
5586 {
5587 	struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;
5588 
5589 	if (!rtwdev->chip->ul_tb_waveform_ctrl)
5590 		return;
5591 
5592 	if (ul_tb_data->dyn_tb_bedge_en) {
5593 		if (ul_tb_data->high_tf_client) {
5594 			rtw89_phy_write32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN, 0);
5595 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
5596 				    "[ULTB] Turn off if_bandedge\n");
5597 		} else if (ul_tb_data->low_tf_client) {
5598 			rtw89_phy_write32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN,
5599 					       ul_tb_info->def_if_bandedge);
5600 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
5601 				    "[ULTB] Set to default if_bandedge = %d\n",
5602 				    ul_tb_info->def_if_bandedge);
5603 		}
5604 	}
5605 
5606 	if (ul_tb_info->dyn_tb_tri_en) {
5607 		if (ul_tb_data->high_tf_client) {
5608 			rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT,
5609 					       B_TXSHAPE_TRIANGULAR_CFG, 0);
5610 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
5611 				    "[ULTB] Turn off Tx triangle\n");
5612 		} else if (ul_tb_data->low_tf_client) {
5613 			rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT,
5614 					       B_TXSHAPE_TRIANGULAR_CFG,
5615 					       ul_tb_data->def_tri_idx);
5616 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
5617 				    "[ULTB] Set to default tx_shap_idx = %d\n",
5618 				    ul_tb_data->def_tri_idx);
5619 		}
5620 	}
5621 }
5622 
5623 void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev)
5624 {
5625 	const struct rtw89_chip_info *chip = rtwdev->chip;
5626 	struct rtw89_phy_ul_tb_check_data ul_tb_data = {};
5627 	struct rtw89_vif_link *rtwvif_link;
5628 	struct rtw89_vif *rtwvif;
5629 	unsigned int link_id;
5630 
5631 	if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff)
5632 		return;
5633 
5634 	if (rtwdev->total_sta_assoc != 1)
5635 		return;
5636 
5637 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
5638 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
5639 			rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data);
5640 
5641 	if (!ul_tb_data.valid)
5642 		return;
5643 
5644 	rtw89_phy_ul_tb_waveform_ctrl(rtwdev, &ul_tb_data);
5645 }
5646 
5647 static void rtw89_phy_ul_tb_info_init(struct rtw89_dev *rtwdev)
5648 {
5649 	const struct rtw89_chip_info *chip = rtwdev->chip;
5650 	struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;
5651 
5652 	if (!chip->ul_tb_waveform_ctrl)
5653 		return;
5654 
5655 	ul_tb_info->dyn_tb_tri_en = true;
5656 	ul_tb_info->def_if_bandedge =
5657 		rtw89_phy_read32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN);
5658 }
5659 
5660 static
5661 void rtw89_phy_antdiv_sts_instance_reset(struct rtw89_antdiv_stats *antdiv_sts)
5662 {
5663 	ewma_rssi_init(&antdiv_sts->cck_rssi_avg);
5664 	ewma_rssi_init(&antdiv_sts->ofdm_rssi_avg);
5665 	ewma_rssi_init(&antdiv_sts->non_legacy_rssi_avg);
5666 	antdiv_sts->pkt_cnt_cck = 0;
5667 	antdiv_sts->pkt_cnt_ofdm = 0;
5668 	antdiv_sts->pkt_cnt_non_legacy = 0;
5669 	antdiv_sts->evm = 0;
5670 }
5671 
5672 static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev,
5673 					      struct rtw89_rx_phy_ppdu *phy_ppdu,
5674 					      struct rtw89_antdiv_stats *stats)
5675 {
5676 	if (rtw89_get_data_rate_mode(rtwdev, phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) {
5677 		if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) {
5678 			ewma_rssi_add(&stats->cck_rssi_avg, phy_ppdu->rssi_avg);
5679 			stats->pkt_cnt_cck++;
5680 		} else {
5681 			ewma_rssi_add(&stats->ofdm_rssi_avg, phy_ppdu->rssi_avg);
5682 			stats->pkt_cnt_ofdm++;
5683 			stats->evm += phy_ppdu->ofdm.evm_min;
5684 		}
5685 	} else {
5686 		ewma_rssi_add(&stats->non_legacy_rssi_avg, phy_ppdu->rssi_avg);
5687 		stats->pkt_cnt_non_legacy++;
5688 		stats->evm += phy_ppdu->ofdm.evm_min;
5689 	}
5690 }
5691 
5692 static u8 rtw89_phy_antdiv_sts_instance_get_rssi(struct rtw89_antdiv_stats *stats)
5693 {
5694 	if (stats->pkt_cnt_non_legacy >= stats->pkt_cnt_cck &&
5695 	    stats->pkt_cnt_non_legacy >= stats->pkt_cnt_ofdm)
5696 		return ewma_rssi_read(&stats->non_legacy_rssi_avg);
5697 	else if (stats->pkt_cnt_ofdm >= stats->pkt_cnt_cck &&
5698 		 stats->pkt_cnt_ofdm >= stats->pkt_cnt_non_legacy)
5699 		return ewma_rssi_read(&stats->ofdm_rssi_avg);
5700 	else
5701 		return ewma_rssi_read(&stats->cck_rssi_avg);
5702 }
5703 
5704 static u8 rtw89_phy_antdiv_sts_instance_get_evm(struct rtw89_antdiv_stats *stats)
5705 {
5706 	return phy_div(stats->evm, stats->pkt_cnt_non_legacy + stats->pkt_cnt_ofdm);
5707 }
5708 
5709 void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
5710 			    struct rtw89_rx_phy_ppdu *phy_ppdu)
5711 {
5712 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
5713 	struct rtw89_hal *hal = &rtwdev->hal;
5714 
5715 	if (!hal->ant_diversity || hal->ant_diversity_fixed)
5716 		return;
5717 
5718 	rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->target_stats);
5719 
5720 	if (!antdiv->get_stats)
5721 		return;
5722 
5723 	if (hal->antenna_rx == RF_A)
5724 		rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->main_stats);
5725 	else if (hal->antenna_rx == RF_B)
5726 		rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->aux_stats);
5727 }
5728 
5729 static void rtw89_phy_antdiv_reg_init(struct rtw89_dev *rtwdev)
5730 {
5731 	rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_ANT_TRAIN_EN,
5732 			      0x0, RTW89_PHY_0);
5733 	rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_TX_ANT_SEL,
5734 			      0x0, RTW89_PHY_0);
5735 
5736 	rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_TRSW_TX_EXTEND,
5737 			      0x0, RTW89_PHY_0);
5738 	rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_HW_ANTSW_DIS_BY_GNT_BT,
5739 			      0x0, RTW89_PHY_0);
5740 
5741 	rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_BT_FORCE_ANTIDX_EN,
5742 			      0x0, RTW89_PHY_0);
5743 
5744 	rtw89_phy_write32_idx(rtwdev, R_RFSW_CTRL_ANT0_BASE, B_RFSW_CTRL_ANT_MAPPING,
5745 			      0x0100, RTW89_PHY_0);
5746 
5747 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_BTG_TRX,
5748 			      0x1, RTW89_PHY_0);
5749 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_HW_CTRL,
5750 			      0x0, RTW89_PHY_0);
5751 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_2G,
5752 			      0x0, RTW89_PHY_0);
5753 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_5G,
5754 			      0x0, RTW89_PHY_0);
5755 }
5756 
5757 static void rtw89_phy_antdiv_sts_reset(struct rtw89_dev *rtwdev)
5758 {
5759 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
5760 
5761 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
5762 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->main_stats);
5763 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->aux_stats);
5764 }
5765 
5766 static void rtw89_phy_antdiv_init(struct rtw89_dev *rtwdev)
5767 {
5768 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
5769 	struct rtw89_hal *hal = &rtwdev->hal;
5770 
5771 	if (!hal->ant_diversity)
5772 		return;
5773 
5774 	antdiv->get_stats = false;
5775 	antdiv->rssi_pre = 0;
5776 	rtw89_phy_antdiv_sts_reset(rtwdev);
5777 	rtw89_phy_antdiv_reg_init(rtwdev);
5778 }
5779 
5780 static void rtw89_phy_thermal_protect_vcore(struct rtw89_dev *rtwdev)
5781 {
5782 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
5783 	struct rtw89_hal *hal = &rtwdev->hal;
5784 	bool vcore_enabled = !!hal->thermal_prot_vmax;
5785 	u8 th_max = phystat->last_thermal_max;
5786 	u8 vlv = hal->thermal_prot_vlv;
5787 	u8 prot_th;
5788 
5789 	if (!vcore_enabled || (hal->disabled_dm_bitmap & BIT(RTW89_DM_VCORE)))
5790 		return;
5791 
5792 	prot_th = hal->thermal_prot_th - RTW89_THERMAL_PROT_VLV_TH_OFFSET;
5793 	if (th_max > prot_th && vlv < RTW89_THERMAL_PROT_VLV_MAX)
5794 		vlv++;
5795 	else if (th_max < prot_th - 2 && vlv > 0)
5796 		vlv--;
5797 	else
5798 		return;
5799 
5800 	rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, "thermal protection vlv=%d\n", vlv);
5801 
5802 	hal->thermal_prot_vlv = vlv;
5803 	rtw89_mac_set_vcore_cfg(rtwdev, vlv);
5804 }
5805 
5806 static void rtw89_phy_thermal_protect(struct rtw89_dev *rtwdev)
5807 {
5808 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
5809 	struct rtw89_hal *hal = &rtwdev->hal;
5810 	u8 th_max = phystat->last_thermal_max;
5811 	u8 lv = hal->thermal_prot_lv;
5812 
5813 	if (!hal->thermal_prot_th ||
5814 	    (hal->disabled_dm_bitmap & BIT(RTW89_DM_THERMAL_PROTECT)))
5815 		return;
5816 
5817 	if (th_max > hal->thermal_prot_th && lv < RTW89_THERMAL_PROT_LV_MAX)
5818 		lv++;
5819 	else if (th_max < hal->thermal_prot_th - 2 && lv > 0)
5820 		lv--;
5821 	else
5822 		return;
5823 
5824 	hal->thermal_prot_lv = lv;
5825 
5826 	rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, "thermal protection lv=%d\n", lv);
5827 
5828 	rtw89_fw_h2c_tx_duty(rtwdev, hal->thermal_prot_lv);
5829 }
5830 
5831 static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev)
5832 {
5833 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
5834 	u8 th, th_max = 0;
5835 	int i;
5836 
5837 	for (i = 0; i < rtwdev->chip->rf_path_num; i++) {
5838 		th = rtw89_chip_get_thermal(rtwdev, i);
5839 		if (th)
5840 			ewma_thermal_add(&phystat->avg_thermal[i], th);
5841 
5842 		rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
5843 			    "path(%d) thermal cur=%u avg=%ld", i, th,
5844 			    ewma_thermal_read(&phystat->avg_thermal[i]));
5845 
5846 		th_max = max(th_max, th);
5847 	}
5848 
5849 	phystat->last_thermal_max = th_max;
5850 }
5851 
5852 struct rtw89_phy_iter_rssi_data {
5853 	struct rtw89_dev *rtwdev;
5854 	bool rssi_changed;
5855 };
5856 
5857 static
5858 void __rtw89_phy_stat_rssi_update_iter(struct rtw89_sta_link *rtwsta_link,
5859 				       struct rtw89_phy_iter_rssi_data *rssi_data)
5860 {
5861 	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
5862 	struct rtw89_dev *rtwdev = rssi_data->rtwdev;
5863 	struct rtw89_phy_ch_info *ch_info;
5864 	struct rtw89_bb_ctx *bb;
5865 	unsigned long rssi_curr;
5866 
5867 	rssi_curr = ewma_rssi_read(&rtwsta_link->avg_rssi);
5868 	bb = rtw89_get_bb_ctx(rtwdev, rtwvif_link->phy_idx);
5869 	ch_info = &bb->ch_info;
5870 
5871 	if (rssi_curr < ch_info->rssi_min) {
5872 		ch_info->rssi_min = rssi_curr;
5873 		ch_info->rssi_min_macid = rtwsta_link->mac_id;
5874 	}
5875 
5876 	if (rtwsta_link->prev_rssi == 0) {
5877 		rtwsta_link->prev_rssi = rssi_curr;
5878 	} else if (abs((int)rtwsta_link->prev_rssi - (int)rssi_curr) >
5879 		   (3 << RSSI_FACTOR)) {
5880 		rtwsta_link->prev_rssi = rssi_curr;
5881 		rssi_data->rssi_changed = true;
5882 	}
5883 }
5884 
5885 static void rtw89_phy_stat_rssi_update_iter(void *data,
5886 					    struct ieee80211_sta *sta)
5887 {
5888 	struct rtw89_phy_iter_rssi_data *rssi_data =
5889 					(struct rtw89_phy_iter_rssi_data *)data;
5890 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
5891 	struct rtw89_sta_link *rtwsta_link;
5892 	unsigned int link_id;
5893 
5894 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
5895 		__rtw89_phy_stat_rssi_update_iter(rtwsta_link, rssi_data);
5896 }
5897 
5898 static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev)
5899 {
5900 	struct rtw89_phy_iter_rssi_data rssi_data = {};
5901 	struct rtw89_bb_ctx *bb;
5902 
5903 	rssi_data.rtwdev = rtwdev;
5904 	rtw89_for_each_active_bb(rtwdev, bb)
5905 		bb->ch_info.rssi_min = U8_MAX;
5906 
5907 	ieee80211_iterate_stations_atomic(rtwdev->hw,
5908 					  rtw89_phy_stat_rssi_update_iter,
5909 					  &rssi_data);
5910 	if (rssi_data.rssi_changed)
5911 		rtw89_btc_ntfy_wl_sta(rtwdev);
5912 }
5913 
5914 static void rtw89_phy_stat_init(struct rtw89_dev *rtwdev)
5915 {
5916 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
5917 	struct rtw89_bb_ctx *bb;
5918 	int i;
5919 
5920 	for (i = 0; i < rtwdev->chip->rf_path_num; i++)
5921 		ewma_thermal_init(&phystat->avg_thermal[i]);
5922 
5923 	rtw89_phy_stat_thermal_update(rtwdev);
5924 
5925 	rtw89_for_each_capab_bb(rtwdev, bb) {
5926 		memset(&bb->cur_pkt_stat, 0, sizeof(bb->cur_pkt_stat));
5927 		memset(&bb->last_pkt_stat, 0, sizeof(bb->last_pkt_stat));
5928 
5929 		ewma_rssi_init(&bb->bcn_rssi);
5930 		bb->path_diff.raw = 0;
5931 		ewma_path_diff_init(&bb->path_diff.avg);
5932 		bb->path_diff.bf_smo_en = false;
5933 	}
5934 
5935 	rtwdev->hal.thermal_prot_lv = 0;
5936 }
5937 
5938 static void rtw89_phy_pmac_diag(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
5939 {
5940 #define RTW89_DIAG_BB_FA_RATIO_TH 80
5941 #define RTW89_DIAG_BB_NO_RX_TH 5
5942 #define RTW89_DIAG_BB_HANG_TH 30
5943 	struct rtw89_pmac_stat_info *pmac_stat = &bb->pmac_stat;
5944 	bool is_linked = rtwdev->total_sta_assoc > 0;
5945 	struct rtw89_diag_bb *diag = &bb->diag;
5946 	u8 fa_ratio = 0;
5947 
5948 	if (!(pmac_stat->cck_mac_txen || pmac_stat->ofdm_mac_txen))
5949 		diag->consecutive_no_tx_cnt++;
5950 	else
5951 		diag->consecutive_no_tx_cnt = 0;
5952 
5953 	if (!pmac_stat->cnt_cca_all)
5954 		diag->consecutive_no_rx_cnt++;
5955 	else
5956 		diag->consecutive_no_rx_cnt = 0;
5957 
5958 	if (pmac_stat->cnt_cca_all)
5959 		fa_ratio = pmac_stat->cnt_fail_all * PERCENT / pmac_stat->cnt_cca_all;
5960 
5961 	diag->diag_bb_bitmap &= ~(BIT(RTW89_DIAG_BB_NO_RX) |
5962 				  BIT(RTW89_DIAG_BB_HANG) |
5963 				  BIT(RTW89_DIAG_BB_FA));
5964 
5965 	if (diag->consecutive_no_rx_cnt >= RTW89_DIAG_BB_NO_RX_TH && is_linked) {
5966 		diag->diag_bb_bitmap |= BIT(RTW89_DIAG_BB_NO_RX);
5967 		diag->diag_bb_cnt[RTW89_DIAG_BB_NO_RX]++;
5968 	}
5969 
5970 	if (fa_ratio >= RTW89_DIAG_BB_FA_RATIO_TH && is_linked) {
5971 		diag->diag_bb_bitmap |= BIT(RTW89_DIAG_BB_FA);
5972 		diag->diag_bb_cnt[RTW89_DIAG_BB_FA]++;
5973 	}
5974 
5975 	if (diag->consecutive_no_tx_cnt > RTW89_DIAG_BB_HANG_TH &&
5976 	    diag->consecutive_no_rx_cnt > RTW89_DIAG_BB_HANG_TH) {
5977 		diag->diag_bb_bitmap |= BIT(RTW89_DIAG_BB_HANG);
5978 		diag->diag_bb_cnt[RTW89_DIAG_BB_HANG]++;
5979 	}
5980 }
5981 
5982 static void rtw89_phy_pmac_stat_reset(struct rtw89_dev *rtwdev,
5983 				      struct rtw89_bb_ctx *bb, bool cck)
5984 {
5985 	const struct rtw89_pmac_regs *regs = rtwdev->chip->pmac_regs;
5986 
5987 	if (cck) {
5988 		rtw89_phy_write32_clr(rtwdev, regs->r1b_rx_rpt_rst.addr,
5989 				      regs->r1b_rx_rpt_rst.mask);
5990 		rtw89_phy_write32_set(rtwdev, regs->r1b_rx_rpt_rst.addr,
5991 				      regs->r1b_rx_rpt_rst.mask);
5992 	}
5993 
5994 	rtw89_phy_write32_idx_set(rtwdev, regs->enable_all_cnt.addr,
5995 				  regs->enable_all_cnt.mask, bb->phy_idx);
5996 	rtw89_phy_write32_idx_set(rtwdev, regs->rst_all_cnt.addr,
5997 				  regs->rst_all_cnt.mask, bb->phy_idx);
5998 	rtw89_phy_write32_idx_clr(rtwdev, regs->rst_all_cnt.addr,
5999 				  regs->rst_all_cnt.mask, bb->phy_idx);
6000 }
6001 
6002 static void rtw89_phy_pmac_stat_cck(struct rtw89_dev *rtwdev,
6003 				    struct rtw89_bb_ctx *bb)
6004 {
6005 	const struct rtw89_pmac_regs *regs = rtwdev->chip->pmac_regs;
6006 	struct rtw89_pmac_stat_info *pmac = &bb->pmac_stat;
6007 	const struct rtw89_chip_info *chip = rtwdev->chip;
6008 	u32 val;
6009 
6010 	pmac->cck_phy_txon =
6011 		rtw89_phy_read32_mask(rtwdev, regs->cck_txon.addr, regs->cck_txon.mask);
6012 	pmac->cck_mac_txen =
6013 		rtw89_phy_read32_mask(rtwdev, regs->cck_txen.addr, regs->cck_txen.mask);
6014 
6015 	if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
6016 		rtw89_phy_write32_mask(rtwdev, regs->r1b_rr_sel.addr,
6017 				       regs->r1b_rr_sel.mask, 0x2);
6018 
6019 	if (bb->phy_idx == RTW89_PHY_1)
6020 		pmac->cnt_cck_cca =
6021 			rtw89_phy_read32_mask(rtwdev, regs->cck_cca.addr + 8,
6022 					      regs->cck_cca.mask);
6023 	else
6024 		pmac->cnt_cck_cca =
6025 			rtw89_phy_read32_mask(rtwdev, regs->cck_cca.addr,
6026 					      regs->cck_cca.mask);
6027 
6028 	if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
6029 		rtw89_phy_write32_mask(rtwdev, regs->r1b_rr_sel.addr,
6030 				       regs->r1b_rr_sel.mask, 0x1);
6031 
6032 	if (bb->phy_idx == RTW89_PHY_1)
6033 		val = rtw89_phy_read32(rtwdev, regs->cck_crc32 + 8);
6034 	else
6035 		val = rtw89_phy_read32(rtwdev, regs->cck_crc32);
6036 	pmac->cnt_cck_crc32_ok = field_get(regs->cck_crc32_ok_mask, val);
6037 	pmac->cnt_cck_crc32_error = field_get(regs->cck_crc32_fail_mask, val);
6038 
6039 	pmac->cnt_sfd_gg =
6040 		rtw89_phy_read32_idx(rtwdev, regs->cck_sfd_gg.addr,
6041 				     regs->cck_sfd_gg.mask, bb->phy_idx);
6042 	pmac->cnt_sig_gg =
6043 		rtw89_phy_read32_idx(rtwdev, regs->cck_sig_gg.addr,
6044 				     regs->cck_sig_gg.mask, bb->phy_idx);
6045 	pmac->cnt_cck_spoofing =
6046 		rtw89_phy_read32_idx(rtwdev, regs->cck_spoofing.addr,
6047 				     regs->cck_spoofing.mask, bb->phy_idx);
6048 
6049 	if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
6050 		pmac->cnt_cck_fail =
6051 			pmac->cnt_cck_cca - pmac->cnt_cck_crc32_ok -
6052 			pmac->cnt_cck_crc32_error - pmac->cnt_cck_spoofing;
6053 	else
6054 		pmac->cnt_cck_fail =
6055 			rtw89_phy_read32_idx(rtwdev, regs->cck_brk.addr,
6056 					     regs->cck_brk.mask, bb->phy_idx);
6057 }
6058 
6059 static void rtw89_phy_pmac_stat_ofdm(struct rtw89_dev *rtwdev,
6060 				     struct rtw89_bb_ctx *bb)
6061 {
6062 	const struct rtw89_pmac_regs *regs = rtwdev->chip->pmac_regs;
6063 	struct rtw89_pmac_stat_info *pmac = &bb->pmac_stat;
6064 	const struct rtw89_chip_info *chip = rtwdev->chip;
6065 	u32 val;
6066 
6067 	val = rtw89_phy_read32_idx(rtwdev, regs->ofdm_txon, MASKDWORD, bb->phy_idx);
6068 	pmac->ofdm_phy_txon = field_get(regs->ofdm_txon_mask, val);
6069 	pmac->ofdm_mac_txen = field_get(regs->ofdm_txen_mask, val);
6070 
6071 	val = rtw89_phy_read32_idx(rtwdev, regs->l_crc, MASKDWORD, bb->phy_idx);
6072 	pmac->cnt_ofdm_crc32_ok = field_get(regs->l_crc_ok_mask, val);
6073 	pmac->cnt_ofdm_crc32_error = field_get(regs->l_crc_err_mask, val);
6074 
6075 	val = rtw89_phy_read32_idx(rtwdev, regs->ht_crc, MASKDWORD, bb->phy_idx);
6076 	pmac->cnt_ht_crc32_ok = field_get(regs->ht_crc_ok_mask, val);
6077 	pmac->cnt_ht_crc32_error = field_get(regs->ht_crc_err_mask, val);
6078 
6079 	val = rtw89_phy_read32_idx(rtwdev, regs->vht_crc, MASKDWORD, bb->phy_idx);
6080 	pmac->cnt_vht_crc32_ok = field_get(regs->vht_crc_ok_mask, val);
6081 	pmac->cnt_vht_crc32_error = field_get(regs->vht_crc_err_mask, val);
6082 
6083 	val = rtw89_phy_read32_idx(rtwdev, regs->he_crc, MASKDWORD, bb->phy_idx);
6084 	pmac->cnt_he_crc32_ok = field_get(regs->he_crc_ok_mask, val);
6085 	pmac->cnt_he_crc32_error = field_get(regs->he_crc_err_mask, val);
6086 
6087 	if (chip->chip_gen == RTW89_CHIP_BE) {
6088 		val = rtw89_phy_read32_idx(rtwdev, regs->eht_crc,
6089 					   MASKDWORD, bb->phy_idx);
6090 		pmac->cnt_eht_crc32_ok = field_get(regs->eht_crc_ok_mask, val);
6091 		pmac->cnt_eht_crc32_error = field_get(regs->eht_crc_err_mask, val);
6092 	}
6093 
6094 	val = rtw89_phy_read32_idx(rtwdev, regs->ampdu_crc, MASKDWORD, bb->phy_idx);
6095 	pmac->cnt_ampdu_crc_ok = field_get(regs->ampdu_crc_ok_mask, val);
6096 	pmac->cnt_ampdu_crc_error = field_get(regs->ampdu_crc_err_mask, val);
6097 
6098 	val = rtw89_phy_read32_idx(rtwdev, regs->brk.addr, regs->brk.mask, bb->phy_idx);
6099 	if (chip->chip_id == RTL8852C &&
6100 	    rtw89_phy_read32_idx(rtwdev, regs->brk_option.addr,
6101 				 regs->brk_option.mask, bb->phy_idx) == 1) {
6102 		u32 tmp = pmac->ofdm_phy_txon + pmac->cck_phy_txon;
6103 
6104 		val = (val > tmp) ? (val - tmp) : 0;
6105 	}
6106 	pmac->cnt_ofdm_fail = val;
6107 
6108 	pmac->cnt_sb_search_fail =
6109 		rtw89_phy_read32_idx(rtwdev, regs->search_fail.addr,
6110 				     regs->search_fail.mask, bb->phy_idx);
6111 	pmac->cnt_lsig_brk_s_th =
6112 		rtw89_phy_read32_idx(rtwdev, regs->lsig_brk_s_th.addr,
6113 				     regs->lsig_brk_s_th.mask, bb->phy_idx);
6114 	pmac->cnt_lsig_brk_l_th =
6115 		rtw89_phy_read32_idx(rtwdev, regs->lsig_brk_l_th.addr,
6116 				     regs->lsig_brk_l_th.mask, bb->phy_idx);
6117 	pmac->cnt_parity_fail =
6118 		rtw89_phy_read32_idx(rtwdev, regs->rxl_err_parity.addr,
6119 				     regs->rxl_err_parity.mask, bb->phy_idx);
6120 	pmac->cnt_rate_illegal =
6121 		rtw89_phy_read32_idx(rtwdev, regs->rxl_err_rate.addr,
6122 				     regs->rxl_err_rate.mask, bb->phy_idx);
6123 	pmac->cnt_ofdm_cca =
6124 		rtw89_phy_read32_idx(rtwdev, regs->ofdm_cca.addr,
6125 				     regs->ofdm_cca.mask, bb->phy_idx);
6126 	pmac->cnt_ofdm_spoofing =
6127 		rtw89_phy_read32_idx(rtwdev, regs->cca_spoofing.addr,
6128 				     regs->cca_spoofing.mask, bb->phy_idx);
6129 	pmac->cnt_ampdu_miss =
6130 		rtw89_phy_read32_idx(rtwdev, regs->ampdu_miss.addr,
6131 				     regs->ampdu_miss.mask, bb->phy_idx);
6132 }
6133 
6134 static void rtw89_phy_pmac_stat_update(struct rtw89_dev *rtwdev,
6135 				       struct rtw89_bb_ctx *bb)
6136 {
6137 	struct rtw89_pmac_stat_info *pmac = &bb->pmac_stat;
6138 	const struct rtw89_chip_info *chip = rtwdev->chip;
6139 	struct rtw89_entity_conf conf;
6140 	const struct rtw89_chan *chan;
6141 	bool cck;
6142 
6143 	rtw89_entity_get_conf(rtwdev, &conf);
6144 	chan = conf.chans[bb->phy_idx];
6145 	cck = chan->band_type == RTW89_BAND_2G;
6146 
6147 	if (cck)
6148 		rtw89_phy_pmac_stat_cck(rtwdev, bb);
6149 
6150 	rtw89_phy_pmac_stat_ofdm(rtwdev, bb);
6151 
6152 	pmac->cnt_fail_all = pmac->cnt_ofdm_fail;
6153 	pmac->cnt_cca_all = pmac->cnt_ofdm_cca;
6154 
6155 	if (cck) {
6156 		pmac->cnt_fail_all += pmac->cnt_cck_fail;
6157 		pmac->cnt_cca_all += pmac->cnt_cck_cca;
6158 	}
6159 
6160 	pmac->cnt_crc32_error_all = pmac->cnt_he_crc32_error +
6161 				    pmac->cnt_vht_crc32_error +
6162 				    pmac->cnt_ht_crc32_error +
6163 				    pmac->cnt_ofdm_crc32_error +
6164 				    pmac->cnt_cck_crc32_error;
6165 
6166 	pmac->cnt_crc32_ok_all = pmac->cnt_he_crc32_ok +
6167 				 pmac->cnt_vht_crc32_ok +
6168 				 pmac->cnt_ht_crc32_ok +
6169 				 pmac->cnt_ofdm_crc32_ok +
6170 				 pmac->cnt_cck_crc32_ok;
6171 
6172 	if (chip->chip_gen == RTW89_CHIP_BE) {
6173 		pmac->cnt_crc32_error_all += pmac->cnt_eht_crc32_error;
6174 		pmac->cnt_crc32_ok_all += pmac->cnt_eht_crc32_ok;
6175 	}
6176 
6177 	rtw89_phy_pmac_diag(rtwdev, bb);
6178 	rtw89_phy_pmac_stat_reset(rtwdev, bb, cck);
6179 }
6180 
6181 static void rtw89_phy_tx_stat_update(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
6182 {
6183 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6184 	const struct rtw89_physts_regs *physts = phy->physts;
6185 	struct rtw89_tx_stat_info *tx_stat = &bb->tx_stat;
6186 	const struct rtw89_chip_info *chip = rtwdev->chip;
6187 	u32 reg_nr;
6188 	u32 val;
6189 	u32 i;
6190 
6191 	if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF &&
6192 	    bb->phy_idx != RTW89_PHY_0)
6193 		val = 1;
6194 	else
6195 		val = 0;
6196 
6197 	rtw89_phy_write32_mask(rtwdev, physts->mac_phy_intf_sel.addr,
6198 			       physts->mac_phy_intf_sel.mask, val);
6199 
6200 	reg_nr = min(physts->tx_info.reg_nr, ARRAY_SIZE(tx_stat->info));
6201 	for (i = 0; i < reg_nr; i++)
6202 		tx_stat->info[i] = rtw89_phy_read32(rtwdev, physts->tx_info.regs[i]);
6203 
6204 	reg_nr = min(physts->tx_common_ctrl.reg_nr, ARRAY_SIZE(tx_stat->common_ctrl));
6205 	for (i = 0; i < reg_nr; i++)
6206 		tx_stat->common_ctrl[i] =
6207 			rtw89_phy_read32(rtwdev, physts->tx_common_ctrl.regs[i]);
6208 
6209 	reg_nr = min(chip->rf_path_num, ARRAY_SIZE(tx_stat->txpwr));
6210 	for (i = 0; i < reg_nr; i++)
6211 		tx_stat->txpwr[i] = rtw89_phy_read32_mask(rtwdev, physts->txpwr[i].addr,
6212 							  physts->txpwr[i].mask);
6213 
6214 	tx_stat->type = u32_get_bits(tx_stat->info[0], TX_STATUS_TYPE);
6215 
6216 	if (chip->chip_gen == RTW89_CHIP_AX) {
6217 		tx_stat->tx_path_en = u32_get_bits(tx_stat->info[0], TX_STATUS_TX_PATH_EN);
6218 		tx_stat->path_map = u32_get_bits(tx_stat->info[0], TX_STATUS_PATH_MAP);
6219 		tx_stat->txcmd = u32_get_bits(tx_stat->info[0], TX_STATUS_TXCMD);
6220 		tx_stat->txsc = u32_get_bits(tx_stat->info[1], TX_STATUS_TXSC);
6221 		tx_stat->bw = u32_get_bits(tx_stat->info[1], TX_STATUS_BW);
6222 		tx_stat->tmac_txpwr = u32_get_bits(tx_stat->info[1], TX_STATUS_TMAC_TXPWR);
6223 
6224 		if (!(chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)))
6225 			tx_stat->max_mcs = u32_get_bits(tx_stat->info[3], TX_STATUS_MAX_MCS);
6226 	} else {
6227 		tx_stat->type = u32_get_bits(tx_stat->info[0], TX_STATUS_TYPE);
6228 		tx_stat->subtype = u32_get_bits(tx_stat->info[0], TX_STATUS_SUBTYPE);
6229 
6230 		if (chip->chip_id == RTL8922A)
6231 			tx_stat->txcmd = u32_get_bits(tx_stat->info[0], TX_STATUS_TXCMD_V1);
6232 		else
6233 			tx_stat->txcmd = u32_get_bits(tx_stat->info[0], TX_STATUS_TXCMD_V2);
6234 
6235 		tx_stat->txsc = u32_get_bits(tx_stat->info[0], TX_STATUS_TXSC_V1);
6236 		tx_stat->bw = u32_get_bits(tx_stat->info[1], TX_STATUS_BW_V1);
6237 		tx_stat->tmac_txpwr = u32_get_bits(tx_stat->info[1], TX_STATUS_TMAC_TXPWR_V1);
6238 		tx_stat->tx_path_en = u32_get_bits(tx_stat->info[2], TX_STATUS_TX_PATH_EN_V1);
6239 		tx_stat->path_map = u32_get_bits(tx_stat->info[2], TX_STATUS_PATH_MAP_V1);
6240 		tx_stat->max_mcs = u32_get_bits(tx_stat->info[4], TX_STATUS_MAX_MCS_V1);
6241 	}
6242 
6243 	tx_stat->stbc = !!(tx_stat->common_ctrl[0] & TX_STATUS_STBC);
6244 }
6245 
6246 static void rtw89_phy_trigger_tx_count(struct rtw89_dev *rtwdev)
6247 {
6248 	if (RTW89_CHK_FW_FEATURE(TX_HISTORY_V1, &rtwdev->fw))
6249 		rtw89_fw_h2c_phy_ch_rpt(rtwdev);
6250 	else
6251 		rtw89_fw_h2c_drv_ctrl_fw(rtwdev);
6252 }
6253 
6254 static void rtw89_phy_stat_update(struct rtw89_dev *rtwdev)
6255 {
6256 	struct rtw89_bb_ctx *bb;
6257 
6258 	if (!rtwdev->phy_info.bb_stat_cfg.enable)
6259 		return;
6260 
6261 	rtw89_phy_trigger_tx_count(rtwdev);
6262 
6263 	rtw89_for_each_active_bb(rtwdev, bb) {
6264 		rtw89_phy_pmac_stat_update(rtwdev, bb);
6265 		rtw89_phy_tx_stat_update(rtwdev, bb);
6266 	}
6267 }
6268 
6269 void rtw89_phy_stat_track(struct rtw89_dev *rtwdev)
6270 {
6271 	struct rtw89_bb_ctx *bb;
6272 
6273 	rtw89_phy_stat_thermal_update(rtwdev);
6274 	rtw89_phy_thermal_protect_vcore(rtwdev);
6275 	rtw89_phy_thermal_protect(rtwdev);
6276 	rtw89_phy_stat_rssi_update(rtwdev);
6277 	rtw89_phy_stat_update(rtwdev);
6278 
6279 	rtw89_for_each_active_bb(rtwdev, bb) {
6280 		bb->last_pkt_stat = bb->cur_pkt_stat;
6281 		memset(&bb->cur_pkt_stat, 0, sizeof(bb->cur_pkt_stat));
6282 
6283 		rtw89_chip_path_diff_update(rtwdev, bb);
6284 	}
6285 }
6286 
6287 static u16 rtw89_phy_ccx_us_to_idx(struct rtw89_dev *rtwdev,
6288 				   struct rtw89_bb_ctx *bb, u32 time_us)
6289 {
6290 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6291 
6292 	return time_us >> (ilog2(CCX_US_BASE_RATIO) + env->ccx_unit_idx);
6293 }
6294 
6295 static u32 rtw89_phy_ccx_idx_to_us(struct rtw89_dev *rtwdev,
6296 				   struct rtw89_bb_ctx *bb, u16 idx)
6297 {
6298 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6299 
6300 	return idx << (ilog2(CCX_US_BASE_RATIO) + env->ccx_unit_idx);
6301 }
6302 
6303 static void rtw89_phy_ccx_top_setting_init(struct rtw89_dev *rtwdev,
6304 					   struct rtw89_bb_ctx *bb)
6305 {
6306 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6307 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6308 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6309 
6310 	env->ccx_manual_ctrl = false;
6311 	env->ccx_ongoing = false;
6312 	env->ccx_rac_lv = RTW89_RAC_RELEASE;
6313 	env->ccx_period = 0;
6314 	env->ccx_unit_idx = RTW89_CCX_32_US;
6315 
6316 	rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->en_mask, 1, bb->phy_idx);
6317 	rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->trig_opt_mask, 1,
6318 			      bb->phy_idx);
6319 	rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 1,
6320 			      bb->phy_idx);
6321 	rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->edcca_opt_mask,
6322 			      RTW89_CCX_EDCCA_BW20_0, bb->phy_idx);
6323 }
6324 
6325 static u16 rtw89_phy_ccx_get_report(struct rtw89_dev *rtwdev,
6326 				    struct rtw89_bb_ctx *bb,
6327 				    u16 report, u16 score)
6328 {
6329 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6330 	u32 numer = 0;
6331 	u16 ret = 0;
6332 
6333 	numer = report * score + (env->ccx_period >> 1);
6334 	if (env->ccx_period)
6335 		ret = numer / env->ccx_period;
6336 
6337 	return ret >= score ? score - 1 : ret;
6338 }
6339 
6340 static void rtw89_phy_ccx_ms_to_period_unit(struct rtw89_dev *rtwdev,
6341 					    u16 time_ms, u32 *period,
6342 					    u32 *unit_idx)
6343 {
6344 	u32 idx;
6345 	u8 quotient;
6346 
6347 	if (time_ms >= CCX_MAX_PERIOD)
6348 		time_ms = CCX_MAX_PERIOD;
6349 
6350 	quotient = CCX_MAX_PERIOD_UNIT * time_ms / CCX_MAX_PERIOD;
6351 
6352 	if (quotient < 4)
6353 		idx = RTW89_CCX_4_US;
6354 	else if (quotient < 8)
6355 		idx = RTW89_CCX_8_US;
6356 	else if (quotient < 16)
6357 		idx = RTW89_CCX_16_US;
6358 	else
6359 		idx = RTW89_CCX_32_US;
6360 
6361 	*unit_idx = idx;
6362 	*period = (time_ms * MS_TO_4US_RATIO) >> idx;
6363 
6364 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6365 		    "[Trigger Time] period:%d, unit_idx:%d\n",
6366 		    *period, *unit_idx);
6367 }
6368 
6369 static void rtw89_phy_ccx_racing_release(struct rtw89_dev *rtwdev,
6370 					 struct rtw89_bb_ctx *bb)
6371 {
6372 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6373 
6374 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6375 		    "lv:(%d)->(0)\n", env->ccx_rac_lv);
6376 
6377 	env->ccx_ongoing = false;
6378 	env->ccx_rac_lv = RTW89_RAC_RELEASE;
6379 	env->ifs_clm_app = RTW89_IFS_CLM_BACKGROUND;
6380 }
6381 
6382 static bool rtw89_phy_ifs_clm_th_update_check(struct rtw89_dev *rtwdev,
6383 					      struct rtw89_bb_ctx *bb,
6384 					      struct rtw89_ccx_para_info *para)
6385 {
6386 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6387 	bool is_update = env->ifs_clm_app != para->ifs_clm_app;
6388 	u8 i = 0;
6389 	u16 *ifs_th_l = env->ifs_clm_th_l;
6390 	u16 *ifs_th_h = env->ifs_clm_th_h;
6391 	u32 ifs_th0_us = 0, ifs_th_times = 0;
6392 	u32 ifs_th_h_us[RTW89_IFS_CLM_NUM] = {0};
6393 
6394 	if (!is_update)
6395 		goto ifs_update_finished;
6396 
6397 	switch (para->ifs_clm_app) {
6398 	case RTW89_IFS_CLM_INIT:
6399 	case RTW89_IFS_CLM_BACKGROUND:
6400 	case RTW89_IFS_CLM_ACS:
6401 	case RTW89_IFS_CLM_DBG:
6402 	case RTW89_IFS_CLM_DIG:
6403 	case RTW89_IFS_CLM_TDMA_DIG:
6404 		ifs_th0_us = IFS_CLM_TH0_UPPER;
6405 		ifs_th_times = IFS_CLM_TH_MUL;
6406 		break;
6407 	case RTW89_IFS_CLM_DBG_MANUAL:
6408 		ifs_th0_us = para->ifs_clm_manual_th0;
6409 		ifs_th_times = para->ifs_clm_manual_th_times;
6410 		break;
6411 	default:
6412 		break;
6413 	}
6414 
6415 	/* Set sampling threshold for 4 different regions, unit in idx_cnt.
6416 	 * low[i] = high[i-1] + 1
6417 	 * high[i] = high[i-1] * ifs_th_times
6418 	 */
6419 	ifs_th_l[IFS_CLM_TH_START_IDX] = 0;
6420 	ifs_th_h_us[IFS_CLM_TH_START_IDX] = ifs_th0_us;
6421 	ifs_th_h[IFS_CLM_TH_START_IDX] = rtw89_phy_ccx_us_to_idx(rtwdev, bb,
6422 								 ifs_th0_us);
6423 	for (i = 1; i < RTW89_IFS_CLM_NUM; i++) {
6424 		ifs_th_l[i] = ifs_th_h[i - 1] + 1;
6425 		ifs_th_h_us[i] = ifs_th_h_us[i - 1] * ifs_th_times;
6426 		ifs_th_h[i] = rtw89_phy_ccx_us_to_idx(rtwdev, bb, ifs_th_h_us[i]);
6427 	}
6428 
6429 ifs_update_finished:
6430 	if (!is_update)
6431 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6432 			    "No need to update IFS_TH\n");
6433 
6434 	return is_update;
6435 }
6436 
6437 static void rtw89_phy_ifs_clm_set_th_reg(struct rtw89_dev *rtwdev,
6438 					 struct rtw89_bb_ctx *bb)
6439 {
6440 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6441 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6442 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6443 	u8 i = 0;
6444 
6445 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_th_l_mask,
6446 			      env->ifs_clm_th_l[0], bb->phy_idx);
6447 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_th_l_mask,
6448 			      env->ifs_clm_th_l[1], bb->phy_idx);
6449 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_th_l_mask,
6450 			      env->ifs_clm_th_l[2], bb->phy_idx);
6451 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_th_l_mask,
6452 			      env->ifs_clm_th_l[3], bb->phy_idx);
6453 
6454 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_th_h_mask,
6455 			      env->ifs_clm_th_h[0], bb->phy_idx);
6456 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_th_h_mask,
6457 			      env->ifs_clm_th_h[1], bb->phy_idx);
6458 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_th_h_mask,
6459 			      env->ifs_clm_th_h[2], bb->phy_idx);
6460 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_th_h_mask,
6461 			      env->ifs_clm_th_h[3], bb->phy_idx);
6462 
6463 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++)
6464 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6465 			    "Update IFS_T%d_th{low, high} : {%d, %d}\n",
6466 			    i + 1, env->ifs_clm_th_l[i], env->ifs_clm_th_h[i]);
6467 }
6468 
6469 static void __rtw89_phy_nhm_setting_init(struct rtw89_dev *rtwdev,
6470 					 struct rtw89_bb_ctx *bb)
6471 {
6472 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6473 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6474 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6475 
6476 	env->nhm_include_cca = false;
6477 	env->nhm_mntr_time = 0;
6478 	env->nhm_sum = 0;
6479 
6480 	rtw89_phy_write32_idx_set(rtwdev, ccx->nhm_config, ccx->nhm_en_mask, bb->phy_idx);
6481 	rtw89_phy_write32_idx_set(rtwdev, ccx->nhm_method, ccx->nhm_pwr_method_msk,
6482 				  bb->phy_idx);
6483 }
6484 
6485 void rtw89_phy_nhm_setting_init(struct rtw89_dev *rtwdev)
6486 {
6487 	const struct rtw89_chip_info *chip = rtwdev->chip;
6488 	struct rtw89_bb_ctx *bb;
6489 
6490 	if (!chip->support_noise)
6491 		return;
6492 
6493 	rtw89_for_each_active_bb(rtwdev, bb)
6494 		__rtw89_phy_nhm_setting_init(rtwdev, bb);
6495 }
6496 
6497 static void rtw89_phy_ifs_clm_setting_init(struct rtw89_dev *rtwdev,
6498 					   struct rtw89_bb_ctx *bb)
6499 {
6500 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6501 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6502 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6503 	struct rtw89_ccx_para_info para = {};
6504 
6505 	env->ifs_clm_app = RTW89_IFS_CLM_BACKGROUND;
6506 	env->ifs_clm_mntr_time = 0;
6507 
6508 	para.ifs_clm_app = RTW89_IFS_CLM_INIT;
6509 	if (rtw89_phy_ifs_clm_th_update_check(rtwdev, bb, &para))
6510 		rtw89_phy_ifs_clm_set_th_reg(rtwdev, bb);
6511 
6512 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_collect_en_mask, true,
6513 			      bb->phy_idx);
6514 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_en_mask, true,
6515 			      bb->phy_idx);
6516 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_en_mask, true,
6517 			      bb->phy_idx);
6518 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_en_mask, true,
6519 			      bb->phy_idx);
6520 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_en_mask, true,
6521 			      bb->phy_idx);
6522 }
6523 
6524 static int rtw89_phy_ccx_racing_ctrl(struct rtw89_dev *rtwdev,
6525 				     struct rtw89_bb_ctx *bb,
6526 				     enum rtw89_env_racing_lv level)
6527 {
6528 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6529 	int ret = 0;
6530 
6531 	if (level >= RTW89_RAC_MAX_NUM) {
6532 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6533 			    "[WARNING] Wrong LV=%d\n", level);
6534 		return -EINVAL;
6535 	}
6536 
6537 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6538 		    "ccx_ongoing=%d, level:(%d)->(%d)\n", env->ccx_ongoing,
6539 		    env->ccx_rac_lv, level);
6540 
6541 	if (env->ccx_ongoing) {
6542 		if (level <= env->ccx_rac_lv)
6543 			ret = -EINVAL;
6544 		else
6545 			env->ccx_ongoing = false;
6546 	}
6547 
6548 	if (ret == 0)
6549 		env->ccx_rac_lv = level;
6550 
6551 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "ccx racing success=%d\n",
6552 		    !ret);
6553 
6554 	return ret;
6555 }
6556 
6557 static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev,
6558 				  struct rtw89_bb_ctx *bb, u8 sel)
6559 {
6560 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6561 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6562 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6563 
6564 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_clm_cnt_clear_mask, 0,
6565 			      bb->phy_idx);
6566 	rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 0,
6567 			      bb->phy_idx);
6568 	if (sel & RTW89_PHY_ENV_MON_NHM)
6569 		rtw89_phy_write32_idx_clr(rtwdev, ccx->nhm_config,
6570 					  ccx->nhm_en_mask, bb->phy_idx);
6571 
6572 	rtw89_phy_write32_idx(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_clm_cnt_clear_mask, 1,
6573 			      bb->phy_idx);
6574 	rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 1,
6575 			      bb->phy_idx);
6576 	if (sel & RTW89_PHY_ENV_MON_NHM)
6577 		rtw89_phy_write32_idx_set(rtwdev, ccx->nhm_config,
6578 					  ccx->nhm_en_mask, bb->phy_idx);
6579 
6580 	env->ccx_ongoing = true;
6581 }
6582 
6583 static void rtw89_phy_ifs_clm_get_utility(struct rtw89_dev *rtwdev,
6584 					  struct rtw89_bb_ctx *bb)
6585 {
6586 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6587 	u8 i = 0;
6588 	u32 res = 0;
6589 
6590 	env->ifs_clm_tx_ratio =
6591 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_tx, PERCENT);
6592 	env->ifs_clm_edcca_excl_cca_ratio =
6593 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_edcca_excl_cca,
6594 					 PERCENT);
6595 	env->ifs_clm_cck_fa_ratio =
6596 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_cckfa, PERCENT);
6597 	env->ifs_clm_ofdm_fa_ratio =
6598 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_ofdmfa, PERCENT);
6599 	env->ifs_clm_cck_cca_excl_fa_ratio =
6600 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_cckcca_excl_fa,
6601 					 PERCENT);
6602 	env->ifs_clm_ofdm_cca_excl_fa_ratio =
6603 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_ofdmcca_excl_fa,
6604 					 PERCENT);
6605 	env->ifs_clm_cck_fa_permil =
6606 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_cckfa, PERMIL);
6607 	env->ifs_clm_ofdm_fa_permil =
6608 		rtw89_phy_ccx_get_report(rtwdev, bb, env->ifs_clm_ofdmfa, PERMIL);
6609 
6610 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++) {
6611 		if (env->ifs_clm_his[i] > ENV_MNTR_IFSCLM_HIS_MAX) {
6612 			env->ifs_clm_ifs_avg[i] = ENV_MNTR_FAIL_DWORD;
6613 		} else {
6614 			env->ifs_clm_ifs_avg[i] =
6615 				rtw89_phy_ccx_idx_to_us(rtwdev, bb,
6616 							env->ifs_clm_avg[i]);
6617 		}
6618 
6619 		res = rtw89_phy_ccx_idx_to_us(rtwdev, bb, env->ifs_clm_cca[i]);
6620 		res += env->ifs_clm_his[i] >> 1;
6621 		if (env->ifs_clm_his[i])
6622 			res /= env->ifs_clm_his[i];
6623 		else
6624 			res = 0;
6625 		env->ifs_clm_cca_avg[i] = res;
6626 	}
6627 
6628 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6629 		    "IFS-CLM ratio {Tx, EDCCA_exclu_cca} = {%d, %d}\n",
6630 		    env->ifs_clm_tx_ratio, env->ifs_clm_edcca_excl_cca_ratio);
6631 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6632 		    "IFS-CLM FA ratio {CCK, OFDM} = {%d, %d}\n",
6633 		    env->ifs_clm_cck_fa_ratio, env->ifs_clm_ofdm_fa_ratio);
6634 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6635 		    "IFS-CLM FA permil {CCK, OFDM} = {%d, %d}\n",
6636 		    env->ifs_clm_cck_fa_permil, env->ifs_clm_ofdm_fa_permil);
6637 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6638 		    "IFS-CLM CCA_exclu_FA ratio {CCK, OFDM} = {%d, %d}\n",
6639 		    env->ifs_clm_cck_cca_excl_fa_ratio,
6640 		    env->ifs_clm_ofdm_cca_excl_fa_ratio);
6641 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6642 		    "Time:[his, ifs_avg(us), cca_avg(us)]\n");
6643 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++)
6644 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "T%d:[%d, %d, %d]\n",
6645 			    i + 1, env->ifs_clm_his[i], env->ifs_clm_ifs_avg[i],
6646 			    env->ifs_clm_cca_avg[i]);
6647 }
6648 
6649 static u8 rtw89_nhm_weighted_avg(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
6650 {
6651 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6652 	u8 nhm_weight[RTW89_NHM_RPT_NUM];
6653 	u32 nhm_weighted_sum = 0;
6654 	u8 weight_zero;
6655 	u8 i;
6656 
6657 	if (env->nhm_sum == 0)
6658 		return 0;
6659 
6660 	weight_zero = clamp_t(u16, env->nhm_th[0] - RTW89_NHM_WEIGHT_OFFSET, 0, U8_MAX);
6661 
6662 	for (i = 0; i < RTW89_NHM_RPT_NUM; i++) {
6663 		if (i == 0)
6664 			nhm_weight[i] = weight_zero;
6665 		else if (i == (RTW89_NHM_RPT_NUM - 1))
6666 			nhm_weight[i] = env->nhm_th[i - 1] + RTW89_NHM_WEIGHT_OFFSET;
6667 		else
6668 			nhm_weight[i] = (env->nhm_th[i - 1] + env->nhm_th[i]) / 2;
6669 	}
6670 
6671 	if (rtwdev->chip->chip_id == RTL8852A || rtwdev->chip->chip_id == RTL8852B ||
6672 	    rtwdev->chip->chip_id == RTL8852C) {
6673 		if (env->nhm_th[RTW89_NHM_TH_NUM - 1] == RTW89_NHM_WA_TH) {
6674 			nhm_weight[RTW89_NHM_RPT_NUM - 1] =
6675 				env->nhm_th[RTW89_NHM_TH_NUM - 2] +
6676 				RTW89_NHM_WEIGHT_OFFSET;
6677 			nhm_weight[RTW89_NHM_RPT_NUM - 2] =
6678 				nhm_weight[RTW89_NHM_RPT_NUM - 1];
6679 		}
6680 
6681 		env->nhm_result[0] += env->nhm_result[RTW89_NHM_RPT_NUM - 1];
6682 		env->nhm_result[RTW89_NHM_RPT_NUM - 1] = 0;
6683 	}
6684 
6685 	for (i = 0; i < RTW89_NHM_RPT_NUM; i++)
6686 		nhm_weighted_sum += env->nhm_result[i] * nhm_weight[i];
6687 
6688 	return (nhm_weighted_sum / env->nhm_sum) >> RTW89_NHM_TH_FACTOR;
6689 }
6690 
6691 static void __rtw89_phy_nhm_get_result(struct rtw89_dev *rtwdev,
6692 				       struct rtw89_bb_ctx *bb, enum rtw89_band hw_band,
6693 				       u16 ch_hw_value)
6694 {
6695 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6696 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6697 	const struct rtw89_chip_info *chip = rtwdev->chip;
6698 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6699 	struct ieee80211_supported_band *sband;
6700 	const struct rtw89_reg_def *nhm_rpt;
6701 	enum nl80211_band band;
6702 	u32 sum = 0;
6703 	u8 chan_idx;
6704 	u8 nhm_pwr;
6705 	u8 i;
6706 
6707 	if (!rtw89_phy_read32_idx(rtwdev, ccx->nhm, ccx->nhm_ready, bb->phy_idx)) {
6708 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,  "[NHM] Get NHM report Fail\n");
6709 		return;
6710 	}
6711 
6712 	for (i = 0; i < RTW89_NHM_RPT_NUM; i++) {
6713 		nhm_rpt = &(*chip->nhm_report)[i];
6714 
6715 		env->nhm_result[i] =
6716 			rtw89_phy_read32_idx(rtwdev, nhm_rpt->addr,
6717 					     nhm_rpt->mask, bb->phy_idx);
6718 		sum += env->nhm_result[i];
6719 	}
6720 	env->nhm_sum = sum;
6721 	nhm_pwr = rtw89_nhm_weighted_avg(rtwdev, bb);
6722 
6723 	if (!ch_hw_value)
6724 		return;
6725 
6726 	band = rtw89_hw_to_nl80211_band(hw_band);
6727 	sband = rtwdev->hw->wiphy->bands[band];
6728 	if (!sband)
6729 		return;
6730 
6731 	for (chan_idx = 0; chan_idx < sband->n_channels; chan_idx++) {
6732 		struct ieee80211_channel *channel;
6733 		struct rtw89_nhm_report *rpt;
6734 		struct list_head *nhm_list;
6735 
6736 		channel = &sband->channels[chan_idx];
6737 		if (channel->hw_value != ch_hw_value)
6738 			continue;
6739 
6740 		rpt = &env->nhm_his[hw_band][chan_idx];
6741 		nhm_list = &env->nhm_rpt_list;
6742 
6743 		rpt->channel = channel;
6744 		rpt->noise = nhm_pwr;
6745 
6746 		if (list_empty(&rpt->list))
6747 			list_add_tail(&rpt->list, nhm_list);
6748 
6749 		return;
6750 	}
6751 
6752 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "[NHM] channel not found\n");
6753 }
6754 
6755 void rtw89_phy_nhm_get_result(struct rtw89_dev *rtwdev, enum rtw89_band hw_band,
6756 			      u16 ch_hw_value)
6757 {
6758 	const struct rtw89_chip_info *chip = rtwdev->chip;
6759 	struct rtw89_bb_ctx *bb;
6760 
6761 	if (!chip->support_noise)
6762 		return;
6763 
6764 	rtw89_for_each_active_bb(rtwdev, bb)
6765 		__rtw89_phy_nhm_get_result(rtwdev, bb, hw_band, ch_hw_value);
6766 }
6767 
6768 static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev,
6769 					 struct rtw89_bb_ctx *bb)
6770 {
6771 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6772 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6773 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6774 	u8 i = 0;
6775 
6776 	if (rtw89_phy_read32_idx(rtwdev, ccx->ifs_total_addr,
6777 				 ccx->ifs_cnt_done_mask, bb->phy_idx) == 0) {
6778 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6779 			    "Get IFS_CLM report Fail\n");
6780 		return false;
6781 	}
6782 
6783 	env->ifs_clm_tx =
6784 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_clm_tx_cnt_addr,
6785 				     ccx->ifs_clm_tx_cnt_msk, bb->phy_idx);
6786 	env->ifs_clm_edcca_excl_cca =
6787 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_clm_tx_cnt_addr,
6788 				     ccx->ifs_clm_edcca_excl_cca_fa_mask, bb->phy_idx);
6789 	env->ifs_clm_cckcca_excl_fa =
6790 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_clm_cca_addr,
6791 				     ccx->ifs_clm_cckcca_excl_fa_mask, bb->phy_idx);
6792 	env->ifs_clm_ofdmcca_excl_fa =
6793 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_clm_cca_addr,
6794 				     ccx->ifs_clm_ofdmcca_excl_fa_mask, bb->phy_idx);
6795 	env->ifs_clm_cckfa =
6796 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_clm_fa_addr,
6797 				     ccx->ifs_clm_cck_fa_mask, bb->phy_idx);
6798 	env->ifs_clm_ofdmfa =
6799 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_clm_fa_addr,
6800 				     ccx->ifs_clm_ofdm_fa_mask, bb->phy_idx);
6801 
6802 	env->ifs_clm_his[0] =
6803 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr,
6804 				     ccx->ifs_t1_his_mask, bb->phy_idx);
6805 	env->ifs_clm_his[1] =
6806 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr,
6807 				     ccx->ifs_t2_his_mask, bb->phy_idx);
6808 
6809 	env->ifs_clm_his[2] =
6810 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr2,
6811 				     ccx->ifs_t3_his_mask, bb->phy_idx);
6812 	env->ifs_clm_his[3] =
6813 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr2,
6814 				     ccx->ifs_t4_his_mask, bb->phy_idx);
6815 
6816 	env->ifs_clm_avg[0] =
6817 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_avg_l_addr,
6818 				     ccx->ifs_t1_avg_mask, bb->phy_idx);
6819 	env->ifs_clm_avg[1] =
6820 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_avg_l_addr,
6821 				     ccx->ifs_t2_avg_mask, bb->phy_idx);
6822 	env->ifs_clm_avg[2] =
6823 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_avg_h_addr,
6824 				     ccx->ifs_t3_avg_mask, bb->phy_idx);
6825 	env->ifs_clm_avg[3] =
6826 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_avg_h_addr,
6827 				     ccx->ifs_t4_avg_mask, bb->phy_idx);
6828 
6829 	env->ifs_clm_cca[0] =
6830 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_cca_l_addr,
6831 				     ccx->ifs_t1_cca_mask, bb->phy_idx);
6832 	env->ifs_clm_cca[1] =
6833 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_cca_l_addr,
6834 				     ccx->ifs_t2_cca_mask, bb->phy_idx);
6835 	env->ifs_clm_cca[2] =
6836 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_cca_h_addr,
6837 				     ccx->ifs_t3_cca_mask, bb->phy_idx);
6838 	env->ifs_clm_cca[3] =
6839 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_cca_h_addr,
6840 				     ccx->ifs_t4_cca_mask, bb->phy_idx);
6841 
6842 	env->ifs_clm_total_ifs =
6843 		rtw89_phy_read32_idx(rtwdev, ccx->ifs_total_addr,
6844 				     ccx->ifs_total_mask, bb->phy_idx);
6845 
6846 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "IFS-CLM total_ifs = %d\n",
6847 		    env->ifs_clm_total_ifs);
6848 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6849 		    "{Tx, EDCCA_exclu_cca} = {%d, %d}\n",
6850 		    env->ifs_clm_tx, env->ifs_clm_edcca_excl_cca);
6851 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6852 		    "IFS-CLM FA{CCK, OFDM} = {%d, %d}\n",
6853 		    env->ifs_clm_cckfa, env->ifs_clm_ofdmfa);
6854 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6855 		    "IFS-CLM CCA_exclu_FA{CCK, OFDM} = {%d, %d}\n",
6856 		    env->ifs_clm_cckcca_excl_fa, env->ifs_clm_ofdmcca_excl_fa);
6857 
6858 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "Time:[his, avg, cca]\n");
6859 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++)
6860 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6861 			    "T%d:[%d, %d, %d]\n", i + 1, env->ifs_clm_his[i],
6862 			    env->ifs_clm_avg[i], env->ifs_clm_cca[i]);
6863 
6864 	rtw89_phy_ifs_clm_get_utility(rtwdev, bb);
6865 
6866 	return true;
6867 }
6868 
6869 static bool rtw89_phy_edcca_clm_get_result(struct rtw89_dev *rtwdev,
6870 					   struct rtw89_bb_ctx *bb)
6871 {
6872 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6873 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6874 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6875 	u32 val;
6876 
6877 	val = rtw89_phy_read32_idx(rtwdev, ccx->edcca_clm_rdy,
6878 				   ccx->edcca_clm_rdy_mask, bb->phy_idx);
6879 	if (!val) {
6880 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6881 			    "Get EDCCA_CLM report Fail\n");
6882 		return false;
6883 	}
6884 
6885 	val = rtw89_phy_read32_idx(rtwdev, ccx->edcca_clm_cnt,
6886 				   ccx->edcca_clm_cnt_mask, bb->phy_idx);
6887 	env->edcca_clm_ratio = rtw89_phy_ccx_get_report(rtwdev, bb, val, PERCENT);
6888 
6889 	return true;
6890 }
6891 
6892 static void rtw89_phy_nhm_th_update(struct rtw89_dev *rtwdev,
6893 				    struct rtw89_bb_ctx *bb)
6894 {
6895 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6896 	static const u8 nhm_th_11k[RTW89_NHM_RPT_NUM] = {
6897 		18, 21, 24, 27, 30, 35, 40, 45, 50, 55, 60, 0
6898 	};
6899 	const struct rtw89_chip_info *chip = rtwdev->chip;
6900 	const struct rtw89_reg_def *nhm_th;
6901 	u8 i;
6902 
6903 	for (i = 0; i < RTW89_NHM_RPT_NUM; i++)
6904 		env->nhm_th[i] = nhm_th_11k[i] << RTW89_NHM_TH_FACTOR;
6905 
6906 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
6907 	    chip->chip_id == RTL8852C)
6908 		env->nhm_th[RTW89_NHM_TH_NUM - 1] = RTW89_NHM_WA_TH;
6909 
6910 	for (i = 0; i < RTW89_NHM_TH_NUM; i++) {
6911 		nhm_th = &(*chip->nhm_th)[i];
6912 
6913 		rtw89_phy_write32_idx(rtwdev, nhm_th->addr, nhm_th->mask,
6914 				      env->nhm_th[i], bb->phy_idx);
6915 	}
6916 }
6917 
6918 static int rtw89_phy_nhm_set(struct rtw89_dev *rtwdev,
6919 			     struct rtw89_bb_ctx *bb,
6920 			     struct rtw89_ccx_para_info *para)
6921 {
6922 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6923 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6924 	const struct rtw89_ccx_regs *ccx = phy->ccx;
6925 	u32 unit_idx = 0;
6926 	u32 period = 0;
6927 
6928 	if (para->mntr_time == 0) {
6929 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6930 			    "[NHM] MNTR_TIME is 0\n");
6931 		return -EINVAL;
6932 	}
6933 
6934 	if (rtw89_phy_ccx_racing_ctrl(rtwdev, bb, para->rac_lv))
6935 		return -EINVAL;
6936 
6937 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
6938 		    "[NHM]nhm_incld_cca=%d, mntr_time=%d ms\n",
6939 		    para->nhm_incld_cca, para->mntr_time);
6940 
6941 	if (para->mntr_time != env->nhm_mntr_time) {
6942 		rtw89_phy_ccx_ms_to_period_unit(rtwdev, para->mntr_time,
6943 						&period, &unit_idx);
6944 		rtw89_phy_write32_idx(rtwdev, ccx->nhm_config,
6945 				      ccx->nhm_period_mask, period, bb->phy_idx);
6946 		rtw89_phy_write32_idx(rtwdev, ccx->nhm_config,
6947 				      ccx->nhm_unit_mask, period, bb->phy_idx);
6948 
6949 		env->nhm_mntr_time = para->mntr_time;
6950 		env->ccx_period = period;
6951 		env->ccx_unit_idx = unit_idx;
6952 	}
6953 
6954 	if (para->nhm_incld_cca != env->nhm_include_cca) {
6955 		rtw89_phy_write32_idx(rtwdev, ccx->nhm_config,
6956 				      ccx->nhm_include_cca_mask, para->nhm_incld_cca,
6957 				      bb->phy_idx);
6958 
6959 		env->nhm_include_cca = para->nhm_incld_cca;
6960 	}
6961 
6962 	rtw89_phy_nhm_th_update(rtwdev, bb);
6963 
6964 	return 0;
6965 }
6966 
6967 static void __rtw89_phy_nhm_trigger(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
6968 {
6969 	struct rtw89_ccx_para_info para = {
6970 		.mntr_time = RTW89_NHM_MNTR_TIME,
6971 		.rac_lv = RTW89_RAC_LV_1,
6972 		.nhm_incld_cca = true,
6973 	};
6974 
6975 	rtw89_phy_ccx_racing_release(rtwdev, bb);
6976 
6977 	rtw89_phy_nhm_set(rtwdev, bb, &para);
6978 	rtw89_phy_ccx_trigger(rtwdev, bb, RTW89_PHY_ENV_MON_NHM);
6979 }
6980 
6981 void rtw89_phy_nhm_trigger(struct rtw89_dev *rtwdev)
6982 {
6983 	const struct rtw89_chip_info *chip = rtwdev->chip;
6984 	struct rtw89_bb_ctx *bb;
6985 
6986 	if (!chip->support_noise)
6987 		return;
6988 
6989 	rtw89_for_each_active_bb(rtwdev, bb)
6990 		__rtw89_phy_nhm_trigger(rtwdev, bb);
6991 }
6992 
6993 static int rtw89_phy_ifs_clm_set(struct rtw89_dev *rtwdev,
6994 				 struct rtw89_bb_ctx *bb,
6995 				 struct rtw89_ccx_para_info *para)
6996 {
6997 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
6998 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
6999 	const struct rtw89_ccx_regs *ccx = phy->ccx;
7000 	u32 period = 0;
7001 	u32 unit_idx = 0;
7002 
7003 	if (para->mntr_time == 0) {
7004 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
7005 			    "[WARN] MNTR_TIME is 0\n");
7006 		return -EINVAL;
7007 	}
7008 
7009 	if (rtw89_phy_ccx_racing_ctrl(rtwdev, bb, para->rac_lv))
7010 		return -EINVAL;
7011 
7012 	if (para->mntr_time != env->ifs_clm_mntr_time) {
7013 		rtw89_phy_ccx_ms_to_period_unit(rtwdev, para->mntr_time,
7014 						&period, &unit_idx);
7015 		rtw89_phy_write32_idx(rtwdev, ccx->ifs_cnt_addr,
7016 				      ccx->ifs_clm_period_mask, period, bb->phy_idx);
7017 		rtw89_phy_write32_idx(rtwdev, ccx->ifs_cnt_addr,
7018 				      ccx->ifs_clm_cnt_unit_mask,
7019 				      unit_idx, bb->phy_idx);
7020 
7021 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
7022 			    "Update IFS-CLM time ((%d)) -> ((%d))\n",
7023 			    env->ifs_clm_mntr_time, para->mntr_time);
7024 
7025 		env->ifs_clm_mntr_time = para->mntr_time;
7026 		env->ccx_period = (u16)period;
7027 		env->ccx_unit_idx = (u8)unit_idx;
7028 	}
7029 
7030 	if (rtw89_phy_ifs_clm_th_update_check(rtwdev, bb, para)) {
7031 		env->ifs_clm_app = para->ifs_clm_app;
7032 		rtw89_phy_ifs_clm_set_th_reg(rtwdev, bb);
7033 	}
7034 
7035 	return 0;
7036 }
7037 
7038 static void __rtw89_phy_env_monitor_track(struct rtw89_dev *rtwdev,
7039 					  struct rtw89_bb_ctx *bb)
7040 {
7041 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
7042 	struct rtw89_ccx_para_info para = {};
7043 	u8 chk_result = RTW89_PHY_ENV_MON_CCX_FAIL;
7044 
7045 	env->ccx_watchdog_result = RTW89_PHY_ENV_MON_CCX_FAIL;
7046 	if (env->ccx_manual_ctrl) {
7047 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
7048 			    "CCX in manual ctrl\n");
7049 		return;
7050 	}
7051 
7052 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
7053 		    "BB-%d env_monitor track\n", bb->phy_idx);
7054 
7055 	/* only ifs_clm for now */
7056 	if (rtw89_phy_ifs_clm_get_result(rtwdev, bb))
7057 		env->ccx_watchdog_result |= RTW89_PHY_ENV_MON_IFS_CLM;
7058 
7059 	if (rtw89_phy_edcca_clm_get_result(rtwdev, bb))
7060 		env->ccx_watchdog_result |= RTW89_PHY_ENV_MON_EDCCA_CLM;
7061 
7062 	rtw89_phy_ccx_racing_release(rtwdev, bb);
7063 	para.mntr_time = 1900;
7064 	para.rac_lv = RTW89_RAC_LV_1;
7065 	para.ifs_clm_app = RTW89_IFS_CLM_BACKGROUND;
7066 
7067 	if (rtw89_phy_ifs_clm_set(rtwdev, bb, &para) == 0)
7068 		chk_result |= RTW89_PHY_ENV_MON_IFS_CLM;
7069 	if (chk_result)
7070 		rtw89_phy_ccx_trigger(rtwdev, bb, chk_result);
7071 
7072 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
7073 		    "get_result=0x%x, chk_result:0x%x\n",
7074 		    env->ccx_watchdog_result, chk_result);
7075 }
7076 
7077 void rtw89_phy_env_monitor_track(struct rtw89_dev *rtwdev)
7078 {
7079 	struct rtw89_bb_ctx *bb;
7080 
7081 	rtw89_for_each_active_bb(rtwdev, bb)
7082 		__rtw89_phy_env_monitor_track(rtwdev, bb);
7083 }
7084 
7085 static bool rtw89_physts_ie_page_valid(struct rtw89_dev *rtwdev,
7086 				       enum rtw89_phy_status_bitmap *ie_page)
7087 {
7088 	const struct rtw89_chip_info *chip = rtwdev->chip;
7089 
7090 	if (*ie_page >= RTW89_PHYSTS_BITMAP_NUM ||
7091 	    *ie_page == RTW89_RSVD_9)
7092 		return false;
7093 	else if (*ie_page > RTW89_RSVD_9 && *ie_page < RTW89_EHT_PKT)
7094 		*ie_page -= 1;
7095 
7096 	if (*ie_page == RTW89_EHT_PKT && chip->chip_gen == RTW89_CHIP_AX)
7097 		return false;
7098 
7099 	return true;
7100 }
7101 
7102 static u32 rtw89_phy_get_ie_bitmap_addr(struct rtw89_dev *rtwdev,
7103 					enum rtw89_phy_status_bitmap ie_page)
7104 {
7105 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
7106 	static const u8 ie_page_shift = 2;
7107 
7108 	if (ie_page == RTW89_EHT_PKT)
7109 		return phy->physt_bmp_eht;
7110 
7111 	return phy->physt_bmp_start + (ie_page << ie_page_shift);
7112 }
7113 
7114 static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev,
7115 				      enum rtw89_phy_status_bitmap ie_page,
7116 				      enum rtw89_phy_idx phy_idx)
7117 {
7118 	u32 addr;
7119 
7120 	if (!rtw89_physts_ie_page_valid(rtwdev, &ie_page))
7121 		return 0;
7122 
7123 	addr = rtw89_phy_get_ie_bitmap_addr(rtwdev, ie_page);
7124 
7125 	return rtw89_phy_read32_idx(rtwdev, addr, MASKDWORD, phy_idx);
7126 }
7127 
7128 static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev,
7129 				       enum rtw89_phy_status_bitmap ie_page,
7130 				       u32 val, enum rtw89_phy_idx phy_idx)
7131 {
7132 	const struct rtw89_chip_info *chip = rtwdev->chip;
7133 	u32 addr;
7134 
7135 	if (!rtw89_physts_ie_page_valid(rtwdev, &ie_page))
7136 		return;
7137 
7138 	if (chip->chip_id == RTL8852A)
7139 		val &= B_PHY_STS_BITMAP_MSK_52A;
7140 
7141 	addr = rtw89_phy_get_ie_bitmap_addr(rtwdev, ie_page);
7142 	rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx);
7143 }
7144 
7145 static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev,
7146 					    bool enable,
7147 					    enum rtw89_phy_idx phy_idx)
7148 {
7149 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
7150 	const struct rtw89_physts_regs *physts = phy->physts;
7151 
7152 	if (enable) {
7153 		rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr,
7154 					  physts->dis_trigger_fail_mask, phy_idx);
7155 		rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr,
7156 					  physts->dis_trigger_brk_mask, phy_idx);
7157 	} else {
7158 		rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr,
7159 					  physts->dis_trigger_fail_mask, phy_idx);
7160 		rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr,
7161 					  physts->dis_trigger_brk_mask, phy_idx);
7162 	}
7163 }
7164 
7165 static void rtw89_physts_enable_hdr_2(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
7166 {
7167 	const struct rtw89_chip_info *chip = rtwdev->chip;
7168 
7169 	if (chip->chip_gen == RTW89_CHIP_AX || chip->chip_id == RTL8922A)
7170 		return;
7171 
7172 	rtw89_phy_write32_idx_set(rtwdev, R_STS_HDR2_PARSING_BE4,
7173 				  B_STS_HDR2_PARSING_BE4, phy_idx);
7174 }
7175 
7176 static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev,
7177 					enum rtw89_phy_idx phy_idx)
7178 {
7179 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
7180 	const struct rtw89_chip_info *chip = rtwdev->chip;
7181 	u32 monitor_mode_mu_ies = 0;
7182 	u32 monitor_mode_su_ies = 0;
7183 	u32 val;
7184 	u8 i;
7185 
7186 	if (rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR) {
7187 		monitor_mode_mu_ies = BIT(RTW89_PHYSTS_IE09_FTR_0);
7188 		if (phy->physt_gen < 2)
7189 			monitor_mode_mu_ies |= BIT(RTW89_PHYSTS_IE10_FTR_PLCP_EXT);
7190 
7191 		monitor_mode_su_ies = BIT(RTW89_PHYSTS_IE09_FTR_0);
7192 	}
7193 
7194 	rtw89_physts_enable_fail_report(rtwdev, false, phy_idx);
7195 
7196 	/* enable hdr_2 for 8922D (PHYSTS_BE_GEN2 above) */
7197 	rtw89_physts_enable_hdr_2(rtwdev, phy_idx);
7198 
7199 	for (i = 0; i < RTW89_PHYSTS_BITMAP_NUM; i++) {
7200 		if (i == RTW89_RSVD_9 ||
7201 		    (i == RTW89_EHT_PKT && chip->chip_gen == RTW89_CHIP_AX))
7202 			continue;
7203 
7204 		val = rtw89_physts_get_ie_bitmap(rtwdev, i, phy_idx);
7205 		if (i == RTW89_HE_MU || i == RTW89_VHT_MU) {
7206 			val |= BIT(RTW89_PHYSTS_IE13_DL_MU_DEF);
7207 			val |= monitor_mode_mu_ies;
7208 		} else if (i == RTW89_TRIG_BASE_PPDU) {
7209 			val |= BIT(RTW89_PHYSTS_IE13_DL_MU_DEF) |
7210 			       BIT(RTW89_PHYSTS_IE01_CMN_OFDM);
7211 		} else if (i >= RTW89_CCK_PKT) {
7212 			val &= ~(GENMASK(RTW89_PHYSTS_IE07_CMN_EXT_PATH_D,
7213 					 RTW89_PHYSTS_IE04_CMN_EXT_PATH_A));
7214 
7215 			if (i == RTW89_CCK_PKT)
7216 				val |= BIT(RTW89_PHYSTS_IE01_CMN_OFDM);
7217 			else if (i >= RTW89_HT_PKT)
7218 				val |= BIT(RTW89_PHYSTS_IE20_DBG_OFDM_FD_USER_SEG_0);
7219 		}
7220 
7221 		if (i == RTW89_HE_PKT || i == RTW89_VHT_PKT)
7222 			val |= monitor_mode_su_ies;
7223 
7224 		rtw89_physts_set_ie_bitmap(rtwdev, i, val, phy_idx);
7225 	}
7226 }
7227 
7228 void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev)
7229 {
7230 	__rtw89_physts_parsing_init(rtwdev, RTW89_PHY_0);
7231 	if (rtwdev->dbcc_en)
7232 		__rtw89_physts_parsing_init(rtwdev, RTW89_PHY_1);
7233 }
7234 
7235 static void rtw89_phy_dig_read_gain_table(struct rtw89_dev *rtwdev,
7236 					  struct rtw89_bb_ctx *bb, int type)
7237 {
7238 	const struct rtw89_chip_info *chip = rtwdev->chip;
7239 	const struct rtw89_phy_dig_gain_cfg *cfg;
7240 	struct rtw89_dig_info *dig = &bb->dig;
7241 	const char *msg;
7242 	u8 i;
7243 	s8 gain_base;
7244 	s8 *gain_arr;
7245 	u32 tmp;
7246 
7247 	switch (type) {
7248 	case RTW89_DIG_GAIN_LNA_G:
7249 		gain_arr = dig->lna_gain_g;
7250 		gain_base = LNA0_GAIN;
7251 		cfg = chip->dig_table->cfg_lna_g;
7252 		msg = "lna_gain_g";
7253 		break;
7254 	case RTW89_DIG_GAIN_TIA_G:
7255 		gain_arr = dig->tia_gain_g;
7256 		gain_base = TIA0_GAIN_G;
7257 		cfg = chip->dig_table->cfg_tia_g;
7258 		msg = "tia_gain_g";
7259 		break;
7260 	case RTW89_DIG_GAIN_LNA_A:
7261 		gain_arr = dig->lna_gain_a;
7262 		gain_base = LNA0_GAIN;
7263 		cfg = chip->dig_table->cfg_lna_a;
7264 		msg = "lna_gain_a";
7265 		break;
7266 	case RTW89_DIG_GAIN_TIA_A:
7267 		gain_arr = dig->tia_gain_a;
7268 		gain_base = TIA0_GAIN_A;
7269 		cfg = chip->dig_table->cfg_tia_a;
7270 		msg = "tia_gain_a";
7271 		break;
7272 	default:
7273 		return;
7274 	}
7275 
7276 	for (i = 0; i < cfg->size; i++) {
7277 		tmp = rtw89_phy_read32_idx(rtwdev, cfg->table[i].addr,
7278 					   cfg->table[i].mask, bb->phy_idx);
7279 		tmp >>= DIG_GAIN_SHIFT;
7280 		gain_arr[i] = sign_extend32(tmp, U4_MAX_BIT) + gain_base;
7281 		gain_base += DIG_GAIN;
7282 
7283 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "%s[%d]=%d\n",
7284 			    msg, i, gain_arr[i]);
7285 	}
7286 }
7287 
7288 static void rtw89_phy_dig_update_gain_para(struct rtw89_dev *rtwdev,
7289 					   struct rtw89_bb_ctx *bb)
7290 {
7291 	struct rtw89_dig_info *dig = &bb->dig;
7292 	u32 tmp;
7293 	u8 i;
7294 
7295 	if (!rtwdev->hal.support_igi)
7296 		return;
7297 
7298 	tmp = rtw89_phy_read32_idx(rtwdev, R_PATH0_IB_PKPW,
7299 				   B_PATH0_IB_PKPW_MSK, bb->phy_idx);
7300 	dig->ib_pkpwr = sign_extend32(tmp >> DIG_GAIN_SHIFT, U8_MAX_BIT);
7301 	dig->ib_pbk = rtw89_phy_read32_idx(rtwdev, R_PATH0_IB_PBK,
7302 					   B_PATH0_IB_PBK_MSK, bb->phy_idx);
7303 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "ib_pkpwr=%d, ib_pbk=%d\n",
7304 		    dig->ib_pkpwr, dig->ib_pbk);
7305 
7306 	for (i = RTW89_DIG_GAIN_LNA_G; i < RTW89_DIG_GAIN_MAX; i++)
7307 		rtw89_phy_dig_read_gain_table(rtwdev, bb, i);
7308 }
7309 
7310 static const u8 rssi_nolink = 22;
7311 static const u8 igi_rssi_th[IGI_RSSI_TH_NUM] = {68, 84, 90, 98, 104};
7312 static const u16 fa_th_2g[FA_TH_NUM] = {22, 44, 66, 88};
7313 static const u16 fa_th_5g[FA_TH_NUM] = {4, 8, 12, 16};
7314 static const u16 fa_th_nolink[FA_TH_NUM] = {196, 352, 440, 528};
7315 
7316 static void rtw89_phy_dig_update_rssi_info(struct rtw89_dev *rtwdev,
7317 					   struct rtw89_bb_ctx *bb)
7318 {
7319 	struct rtw89_phy_ch_info *ch_info = &bb->ch_info;
7320 	struct rtw89_dig_info *dig = &bb->dig;
7321 	bool is_linked = rtwdev->total_sta_assoc > 0;
7322 
7323 	if (is_linked) {
7324 		dig->igi_rssi = ch_info->rssi_min >> 1;
7325 	} else {
7326 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "RSSI update : NO Link\n");
7327 		dig->igi_rssi = rssi_nolink;
7328 	}
7329 }
7330 
7331 static void rtw89_phy_dig_update_para(struct rtw89_dev *rtwdev,
7332 				      struct rtw89_bb_ctx *bb)
7333 {
7334 	struct rtw89_dig_info *dig = &bb->dig;
7335 	bool is_linked = rtwdev->total_sta_assoc > 0;
7336 	struct rtw89_entity_conf conf;
7337 	const struct rtw89_chan *chan;
7338 	const u16 *fa_th_src = NULL;
7339 
7340 	rtw89_entity_get_conf(rtwdev, &conf);
7341 	chan = conf.chans[bb->phy_idx];
7342 
7343 	switch (chan->band_type) {
7344 	case RTW89_BAND_2G:
7345 		dig->lna_gain = dig->lna_gain_g;
7346 		dig->tia_gain = dig->tia_gain_g;
7347 		fa_th_src = is_linked ? fa_th_2g : fa_th_nolink;
7348 		dig->force_gaincode_idx_en = false;
7349 		dig->dyn_pd_th_en = true;
7350 		break;
7351 	case RTW89_BAND_5G:
7352 	default:
7353 		dig->lna_gain = dig->lna_gain_a;
7354 		dig->tia_gain = dig->tia_gain_a;
7355 		fa_th_src = is_linked ? fa_th_5g : fa_th_nolink;
7356 		dig->force_gaincode_idx_en = true;
7357 		dig->dyn_pd_th_en = true;
7358 		break;
7359 	}
7360 	memcpy(dig->fa_th, fa_th_src, sizeof(dig->fa_th));
7361 	memcpy(dig->igi_rssi_th, igi_rssi_th, sizeof(dig->igi_rssi_th));
7362 }
7363 
7364 static const u8 pd_low_th_offset = 16, dynamic_igi_min = 0x20;
7365 static const u8 igi_max_performance_mode = 0x5a;
7366 static const u8 dynamic_pd_threshold_max;
7367 
7368 static void rtw89_phy_dig_para_reset(struct rtw89_dev *rtwdev,
7369 				     struct rtw89_bb_ctx *bb)
7370 {
7371 	struct rtw89_dig_info *dig = &bb->dig;
7372 
7373 	dig->cur_gaincode.lna_idx = LNA_IDX_MAX;
7374 	dig->cur_gaincode.tia_idx = TIA_IDX_MAX;
7375 	dig->cur_gaincode.rxb_idx = RXB_IDX_MAX;
7376 	dig->force_gaincode.lna_idx = LNA_IDX_MAX;
7377 	dig->force_gaincode.tia_idx = TIA_IDX_MAX;
7378 	dig->force_gaincode.rxb_idx = RXB_IDX_MAX;
7379 
7380 	dig->dyn_igi_max = igi_max_performance_mode;
7381 	dig->dyn_igi_min = dynamic_igi_min;
7382 	dig->dyn_pd_th_max = dynamic_pd_threshold_max;
7383 	dig->dyn_pd_max_cnt = 0;
7384 	dig->pd_low_th_ofst = pd_low_th_offset;
7385 	dig->is_linked_pre = false;
7386 }
7387 
7388 static void __rtw89_phy_dig_init(struct rtw89_dev *rtwdev,
7389 				 struct rtw89_bb_ctx *bb)
7390 {
7391 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "BB-%d dig_init\n", bb->phy_idx);
7392 
7393 	rtw89_phy_dig_update_gain_para(rtwdev, bb);
7394 	rtw89_phy_dig_reset(rtwdev, bb);
7395 }
7396 
7397 static void rtw89_phy_dig_init(struct rtw89_dev *rtwdev)
7398 {
7399 	struct rtw89_bb_ctx *bb;
7400 
7401 	rtw89_for_each_capab_bb(rtwdev, bb)
7402 		__rtw89_phy_dig_init(rtwdev, bb);
7403 }
7404 
7405 static u8 rtw89_phy_dig_lna_idx_by_rssi(struct rtw89_dev *rtwdev,
7406 					struct rtw89_bb_ctx *bb, u8 rssi)
7407 {
7408 	struct rtw89_dig_info *dig = &bb->dig;
7409 	u8 lna_idx;
7410 
7411 	if (rssi < dig->igi_rssi_th[0])
7412 		lna_idx = RTW89_DIG_GAIN_LNA_IDX6;
7413 	else if (rssi < dig->igi_rssi_th[1])
7414 		lna_idx = RTW89_DIG_GAIN_LNA_IDX5;
7415 	else if (rssi < dig->igi_rssi_th[2])
7416 		lna_idx = RTW89_DIG_GAIN_LNA_IDX4;
7417 	else if (rssi < dig->igi_rssi_th[3])
7418 		lna_idx = RTW89_DIG_GAIN_LNA_IDX3;
7419 	else if (rssi < dig->igi_rssi_th[4])
7420 		lna_idx = RTW89_DIG_GAIN_LNA_IDX2;
7421 	else
7422 		lna_idx = RTW89_DIG_GAIN_LNA_IDX1;
7423 
7424 	return lna_idx;
7425 }
7426 
7427 static u8 rtw89_phy_dig_tia_idx_by_rssi(struct rtw89_dev *rtwdev,
7428 					struct rtw89_bb_ctx *bb, u8 rssi)
7429 {
7430 	struct rtw89_dig_info *dig = &bb->dig;
7431 	u8 tia_idx;
7432 
7433 	if (rssi < dig->igi_rssi_th[0])
7434 		tia_idx = RTW89_DIG_GAIN_TIA_IDX1;
7435 	else
7436 		tia_idx = RTW89_DIG_GAIN_TIA_IDX0;
7437 
7438 	return tia_idx;
7439 }
7440 
7441 #define IB_PBK_BASE 110
7442 #define WB_RSSI_BASE 10
7443 static u8 rtw89_phy_dig_rxb_idx_by_rssi(struct rtw89_dev *rtwdev,
7444 					struct rtw89_bb_ctx *bb, u8 rssi,
7445 					struct rtw89_agc_gaincode_set *set)
7446 {
7447 	struct rtw89_dig_info *dig = &bb->dig;
7448 	s8 lna_gain = dig->lna_gain[set->lna_idx];
7449 	s8 tia_gain = dig->tia_gain[set->tia_idx];
7450 	s32 wb_rssi = rssi + lna_gain + tia_gain;
7451 	s32 rxb_idx_tmp = IB_PBK_BASE + WB_RSSI_BASE;
7452 	u8 rxb_idx;
7453 
7454 	rxb_idx_tmp += dig->ib_pkpwr - dig->ib_pbk - wb_rssi;
7455 	rxb_idx = clamp_t(s32, rxb_idx_tmp, RXB_IDX_MIN, RXB_IDX_MAX);
7456 
7457 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "wb_rssi=%03d, rxb_idx_tmp=%03d\n",
7458 		    wb_rssi, rxb_idx_tmp);
7459 
7460 	return rxb_idx;
7461 }
7462 
7463 static void rtw89_phy_dig_gaincode_by_rssi(struct rtw89_dev *rtwdev,
7464 					   struct rtw89_bb_ctx *bb, u8 rssi,
7465 					   struct rtw89_agc_gaincode_set *set)
7466 {
7467 	set->lna_idx = rtw89_phy_dig_lna_idx_by_rssi(rtwdev, bb, rssi);
7468 	set->tia_idx = rtw89_phy_dig_tia_idx_by_rssi(rtwdev, bb, rssi);
7469 	set->rxb_idx = rtw89_phy_dig_rxb_idx_by_rssi(rtwdev, bb, rssi, set);
7470 
7471 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
7472 		    "final_rssi=%03d, (lna,tia,rab)=(%d,%d,%02d)\n",
7473 		    rssi, set->lna_idx, set->tia_idx, set->rxb_idx);
7474 }
7475 
7476 #define IGI_OFFSET_MAX 25
7477 #define IGI_OFFSET_MUL 2
7478 static void rtw89_phy_dig_igi_offset_by_env(struct rtw89_dev *rtwdev,
7479 					    struct rtw89_bb_ctx *bb)
7480 {
7481 	struct rtw89_dig_info *dig = &bb->dig;
7482 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
7483 	enum rtw89_dig_noisy_level noisy_lv;
7484 	u8 igi_offset = dig->fa_rssi_ofst;
7485 	u16 fa_ratio = 0;
7486 
7487 	fa_ratio = env->ifs_clm_cck_fa_permil + env->ifs_clm_ofdm_fa_permil;
7488 
7489 	if (fa_ratio < dig->fa_th[0])
7490 		noisy_lv = RTW89_DIG_NOISY_LEVEL0;
7491 	else if (fa_ratio < dig->fa_th[1])
7492 		noisy_lv = RTW89_DIG_NOISY_LEVEL1;
7493 	else if (fa_ratio < dig->fa_th[2])
7494 		noisy_lv = RTW89_DIG_NOISY_LEVEL2;
7495 	else if (fa_ratio < dig->fa_th[3])
7496 		noisy_lv = RTW89_DIG_NOISY_LEVEL3;
7497 	else
7498 		noisy_lv = RTW89_DIG_NOISY_LEVEL_MAX;
7499 
7500 	if (noisy_lv == RTW89_DIG_NOISY_LEVEL0 && igi_offset < 2)
7501 		igi_offset = 0;
7502 	else
7503 		igi_offset += noisy_lv * IGI_OFFSET_MUL;
7504 
7505 	igi_offset = min_t(u8, igi_offset, IGI_OFFSET_MAX);
7506 	dig->fa_rssi_ofst = igi_offset;
7507 	dig->noisy_lv = noisy_lv;
7508 
7509 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
7510 		    "fa_th: [+6 (%d) +4 (%d) +2 (%d) 0 (%d) -2 ]\n",
7511 		    dig->fa_th[3], dig->fa_th[2], dig->fa_th[1], dig->fa_th[0]);
7512 
7513 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
7514 		    "fa(CCK,OFDM,ALL)=(%d,%d,%d)%%, noisy_lv=%d, ofst=%d\n",
7515 		    env->ifs_clm_cck_fa_permil, env->ifs_clm_ofdm_fa_permil,
7516 		    env->ifs_clm_cck_fa_permil + env->ifs_clm_ofdm_fa_permil,
7517 		    noisy_lv, igi_offset);
7518 }
7519 
7520 static void rtw89_phy_dig_set_lna_idx(struct rtw89_dev *rtwdev,
7521 				      struct rtw89_bb_ctx *bb, u8 lna_idx)
7522 {
7523 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
7524 
7525 	rtw89_phy_write32_idx(rtwdev, dig_regs->p0_lna_init.addr,
7526 			      dig_regs->p0_lna_init.mask, lna_idx, bb->phy_idx);
7527 	rtw89_phy_write32_idx(rtwdev, dig_regs->p1_lna_init.addr,
7528 			      dig_regs->p1_lna_init.mask, lna_idx, bb->phy_idx);
7529 }
7530 
7531 static void rtw89_phy_dig_set_tia_idx(struct rtw89_dev *rtwdev,
7532 				      struct rtw89_bb_ctx *bb, u8 tia_idx)
7533 {
7534 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
7535 
7536 	rtw89_phy_write32_idx(rtwdev, dig_regs->p0_tia_init.addr,
7537 			      dig_regs->p0_tia_init.mask, tia_idx, bb->phy_idx);
7538 	rtw89_phy_write32_idx(rtwdev, dig_regs->p1_tia_init.addr,
7539 			      dig_regs->p1_tia_init.mask, tia_idx, bb->phy_idx);
7540 }
7541 
7542 static void rtw89_phy_dig_set_rxb_idx(struct rtw89_dev *rtwdev,
7543 				      struct rtw89_bb_ctx *bb, u8 rxb_idx)
7544 {
7545 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
7546 
7547 	rtw89_phy_write32_idx(rtwdev, dig_regs->p0_rxb_init.addr,
7548 			      dig_regs->p0_rxb_init.mask, rxb_idx, bb->phy_idx);
7549 	rtw89_phy_write32_idx(rtwdev, dig_regs->p1_rxb_init.addr,
7550 			      dig_regs->p1_rxb_init.mask, rxb_idx, bb->phy_idx);
7551 }
7552 
7553 static void rtw89_phy_dig_set_igi_cr(struct rtw89_dev *rtwdev,
7554 				     struct rtw89_bb_ctx *bb,
7555 				     const struct rtw89_agc_gaincode_set set)
7556 {
7557 	if (!rtwdev->hal.support_igi)
7558 		return;
7559 
7560 	rtw89_phy_dig_set_lna_idx(rtwdev, bb, set.lna_idx);
7561 	rtw89_phy_dig_set_tia_idx(rtwdev, bb, set.tia_idx);
7562 	rtw89_phy_dig_set_rxb_idx(rtwdev, bb, set.rxb_idx);
7563 
7564 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "Set (lna,tia,rxb)=((%d,%d,%02d))\n",
7565 		    set.lna_idx, set.tia_idx, set.rxb_idx);
7566 }
7567 
7568 static void rtw89_phy_dig_sdagc_follow_pagc_config(struct rtw89_dev *rtwdev,
7569 						   struct rtw89_bb_ctx *bb,
7570 						   bool enable)
7571 {
7572 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
7573 
7574 	if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
7575 		return;
7576 
7577 	rtw89_phy_write32_idx(rtwdev, dig_regs->p0_p20_pagcugc_en.addr,
7578 			      dig_regs->p0_p20_pagcugc_en.mask, enable, bb->phy_idx);
7579 	rtw89_phy_write32_idx(rtwdev, dig_regs->p0_s20_pagcugc_en.addr,
7580 			      dig_regs->p0_s20_pagcugc_en.mask, enable, bb->phy_idx);
7581 	rtw89_phy_write32_idx(rtwdev, dig_regs->p1_p20_pagcugc_en.addr,
7582 			      dig_regs->p1_p20_pagcugc_en.mask, enable, bb->phy_idx);
7583 	rtw89_phy_write32_idx(rtwdev, dig_regs->p1_s20_pagcugc_en.addr,
7584 			      dig_regs->p1_s20_pagcugc_en.mask, enable, bb->phy_idx);
7585 
7586 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "sdagc_follow_pagc=%d\n", enable);
7587 }
7588 
7589 static void rtw89_phy_dig_config_igi(struct rtw89_dev *rtwdev,
7590 				     struct rtw89_bb_ctx *bb)
7591 {
7592 	struct rtw89_dig_info *dig = &bb->dig;
7593 
7594 	if (!rtwdev->hal.support_igi)
7595 		return;
7596 
7597 	if (dig->force_gaincode_idx_en) {
7598 		rtw89_phy_dig_set_igi_cr(rtwdev, bb, dig->force_gaincode);
7599 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
7600 			    "Force gaincode index enabled.\n");
7601 	} else {
7602 		rtw89_phy_dig_gaincode_by_rssi(rtwdev, bb, dig->igi_fa_rssi,
7603 					       &dig->cur_gaincode);
7604 		rtw89_phy_dig_set_igi_cr(rtwdev, bb, dig->cur_gaincode);
7605 	}
7606 }
7607 
7608 static u8 rtw89_phy_dig_cal_under_region(struct rtw89_dev *rtwdev,
7609 					 struct rtw89_bb_ctx *bb,
7610 					 const struct rtw89_chan *chan)
7611 {
7612 	enum rtw89_bandwidth cbw = chan->band_width;
7613 	struct rtw89_dig_info *dig = &bb->dig;
7614 	u8 under_region = dig->pd_low_th_ofst;
7615 
7616 	if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
7617 		under_region += PD_TH_SB_FLTR_CMP_VAL;
7618 
7619 	switch (cbw) {
7620 	case RTW89_CHANNEL_WIDTH_40:
7621 		under_region += PD_TH_BW40_CMP_VAL;
7622 		break;
7623 	case RTW89_CHANNEL_WIDTH_80:
7624 		under_region += PD_TH_BW80_CMP_VAL;
7625 		break;
7626 	case RTW89_CHANNEL_WIDTH_160:
7627 		under_region += PD_TH_BW160_CMP_VAL;
7628 		break;
7629 	case RTW89_CHANNEL_WIDTH_20:
7630 		fallthrough;
7631 	default:
7632 		under_region += PD_TH_BW20_CMP_VAL;
7633 		break;
7634 	}
7635 
7636 	return under_region;
7637 }
7638 
7639 static u32 __rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev,
7640 				     struct rtw89_bb_ctx *bb,
7641 				     u8 rssi, bool enable,
7642 				     const struct rtw89_chan *chan)
7643 {
7644 	struct rtw89_dig_info *dig = &bb->dig;
7645 	u8 ofdm_cca_th, under_region;
7646 	u8 final_rssi;
7647 	u32 pd_val;
7648 
7649 	under_region = rtw89_phy_dig_cal_under_region(rtwdev, bb, chan);
7650 	dig->dyn_pd_th_max = dig->igi_rssi;
7651 
7652 	final_rssi = min_t(u8, rssi, dig->igi_rssi);
7653 	ofdm_cca_th = clamp_t(u8, final_rssi, PD_TH_MIN_RSSI + under_region,
7654 			      PD_TH_MAX_RSSI + under_region);
7655 
7656 	if (enable) {
7657 		pd_val = (ofdm_cca_th - under_region - PD_TH_MIN_RSSI) >> 1;
7658 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
7659 			    "igi=%d, ofdm_ccaTH=%d, backoff=%d, PD_low=%d\n",
7660 			    final_rssi, ofdm_cca_th, under_region, pd_val);
7661 	} else {
7662 		pd_val = 0;
7663 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
7664 			    "Dynamic PD th disabled, Set PD_low_bd=0\n");
7665 	}
7666 
7667 	return pd_val;
7668 }
7669 
7670 static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev,
7671 				    struct rtw89_bb_ctx *bb,
7672 				    u8 rssi, bool enable)
7673 {
7674 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
7675 	struct rtw89_dig_info *dig = &bb->dig;
7676 	struct rtw89_hal *hal = &rtwdev->hal;
7677 	u8 final_rssi, under_region = dig->pd_low_th_ofst;
7678 	struct rtw89_entity_conf conf;
7679 	const struct rtw89_chan *chan;
7680 	s8 cck_cca_th;
7681 	u32 pd_val;
7682 
7683 	rtw89_entity_get_conf(rtwdev, &conf);
7684 	chan = conf.chans[bb->phy_idx];
7685 
7686 	if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD)) {
7687 		pd_val = hal->fixed_dig_pd_th;
7688 
7689 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
7690 			    "Fixed DIG: PD_low=%d\n", pd_val);
7691 	} else {
7692 		pd_val = __rtw89_phy_dig_dyn_pd_th(rtwdev, bb, rssi, enable, chan);
7693 	}
7694 	dig->bak_dig = pd_val;
7695 
7696 	rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
7697 			      dig_regs->pd_lower_bound_mask, pd_val, bb->phy_idx);
7698 	rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
7699 			      dig_regs->pd_spatial_reuse_en, enable, bb->phy_idx);
7700 
7701 	if (!hal->support_cckpd)
7702 		return;
7703 
7704 	if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD)) {
7705 		pd_val = hal->fixed_dig_cck_pd_th;
7706 
7707 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
7708 			    "Fixed DIG: cck_PD_low=((%d))dB\n", pd_val);
7709 	} else {
7710 		final_rssi = min_t(u8, rssi, dig->igi_rssi);
7711 		under_region = rtw89_phy_dig_cal_under_region(rtwdev, bb, chan);
7712 		cck_cca_th = max_t(s8, final_rssi - under_region, CCKPD_TH_MIN_RSSI);
7713 		pd_val = (u32)(cck_cca_th - IGI_RSSI_MAX);
7714 
7715 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
7716 			    "igi=%d, cck_ccaTH=%d, backoff=%d, cck_PD_low=((%d))dB\n",
7717 			    final_rssi, cck_cca_th, under_region, pd_val);
7718 	}
7719 
7720 	rtw89_phy_write32_idx(rtwdev, dig_regs->bmode_pd_reg,
7721 			      dig_regs->bmode_cca_rssi_limit_en, enable, bb->phy_idx);
7722 	rtw89_phy_write32_idx(rtwdev, dig_regs->bmode_pd_lower_bound_reg,
7723 			      dig_regs->bmode_rssi_nocca_low_th_mask, pd_val, bb->phy_idx);
7724 }
7725 
7726 void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
7727 {
7728 	struct rtw89_dig_info *dig = &bb->dig;
7729 
7730 	dig->bypass_dig = false;
7731 	rtw89_phy_dig_para_reset(rtwdev, bb);
7732 	rtw89_phy_dig_set_igi_cr(rtwdev, bb, dig->force_gaincode);
7733 	rtw89_phy_dig_dyn_pd_th(rtwdev, bb, rssi_nolink, false);
7734 	rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, bb, false);
7735 	rtw89_phy_dig_update_para(rtwdev, bb);
7736 }
7737 
7738 static void rtw89_phy_dig_diag(struct rtw89_dev *rtwdev,
7739 			       struct rtw89_bb_ctx *bb, bool is_linked)
7740 {
7741 #define RTW89_DIAG_BB_PD_MAX_PERIOD 5
7742 	struct rtw89_diag_bb *diag = &bb->diag;
7743 	struct rtw89_dig_info *dig = &bb->dig;
7744 
7745 	diag->diag_bb_bitmap &= ~BIT(RTW89_DIAG_BB_PD);
7746 
7747 	if (dig->dyn_igi_max != dig->igi_fa_rssi ||
7748 	    dig->noisy_lv < RTW89_DIG_NOISY_LEVEL_MAX) {
7749 		dig->dyn_pd_max_cnt = 0;
7750 		return;
7751 	}
7752 
7753 	if (++dig->dyn_pd_max_cnt < RTW89_DIAG_BB_PD_MAX_PERIOD || !is_linked)
7754 		return;
7755 
7756 	diag->diag_bb_bitmap |= BIT(RTW89_DIAG_BB_PD);
7757 	diag->diag_bb_cnt[RTW89_DIAG_BB_PD]++;
7758 }
7759 
7760 #define IGI_RSSI_MIN 10
7761 #define ABS_IGI_MIN 0xc
7762 static
7763 void rtw89_phy_cal_igi_fa_rssi(struct rtw89_dev *rtwdev,
7764 			       struct rtw89_bb_ctx *bb, bool is_linked)
7765 {
7766 	struct rtw89_dig_info *dig = &bb->dig;
7767 	u8 igi_min;
7768 
7769 	rtw89_phy_dig_igi_offset_by_env(rtwdev, bb);
7770 
7771 	igi_min = max_t(int, dig->igi_rssi - IGI_RSSI_MIN, 0);
7772 	dig->dyn_igi_max = min(igi_min + IGI_OFFSET_MAX, igi_max_performance_mode);
7773 	dig->dyn_igi_min = max(igi_min, ABS_IGI_MIN);
7774 
7775 	if (dig->dyn_igi_max >= dig->dyn_igi_min) {
7776 		dig->igi_fa_rssi += dig->fa_rssi_ofst;
7777 		dig->igi_fa_rssi = clamp(dig->igi_fa_rssi, dig->dyn_igi_min,
7778 					 dig->dyn_igi_max);
7779 	} else {
7780 		dig->igi_fa_rssi = dig->dyn_igi_max;
7781 	}
7782 
7783 	rtw89_phy_dig_diag(rtwdev, bb, is_linked);
7784 }
7785 
7786 struct rtw89_phy_iter_mcc_dig {
7787 	struct rtw89_vif_link *rtwvif_link;
7788 	bool has_sta;
7789 	u8 rssi_min;
7790 };
7791 
7792 static void rtw89_phy_set_mcc_dig(struct rtw89_dev *rtwdev,
7793 				  struct rtw89_vif_link *rtwvif_link,
7794 				  struct rtw89_bb_ctx *bb,
7795 				  u8 rssi_min, u8 mcc_role_idx,
7796 				  bool is_linked)
7797 {
7798 	struct rtw89_dig_info *dig = &bb->dig;
7799 	const struct rtw89_chan *chan;
7800 	u8 pd_val;
7801 
7802 	if (is_linked) {
7803 		dig->igi_rssi = rssi_min >> 1;
7804 		dig->igi_fa_rssi = dig->igi_rssi;
7805 	} else {
7806 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "RSSI update : NO Link\n");
7807 		dig->igi_rssi = rssi_nolink;
7808 		dig->igi_fa_rssi = dig->igi_rssi;
7809 	}
7810 
7811 	chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
7812 	rtw89_phy_cal_igi_fa_rssi(rtwdev, bb, is_linked);
7813 	pd_val = __rtw89_phy_dig_dyn_pd_th(rtwdev, bb, dig->igi_fa_rssi,
7814 					   is_linked, chan);
7815 	rtw89_fw_h2c_mcc_dig(rtwdev, rtwvif_link->chanctx_idx,
7816 			     mcc_role_idx, pd_val, true);
7817 
7818 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
7819 		    "MCC chanctx_idx %d chan %d rssi %d pd_val %d",
7820 		    rtwvif_link->chanctx_idx, chan->primary_channel,
7821 		    dig->igi_rssi, pd_val);
7822 }
7823 
7824 static void rtw89_phy_set_mcc_dig_iter(void *data, struct ieee80211_sta *sta)
7825 {
7826 	struct rtw89_phy_iter_mcc_dig *mcc_dig = (struct rtw89_phy_iter_mcc_dig *)data;
7827 	unsigned int link_id = mcc_dig->rtwvif_link->link_id;
7828 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
7829 	struct rtw89_sta_link *rtwsta_link;
7830 
7831 	if (rtwsta->rtwvif != mcc_dig->rtwvif_link->rtwvif)
7832 		return;
7833 
7834 	rtwsta_link = rtwsta->links[link_id];
7835 	if (!rtwsta_link)
7836 		return;
7837 
7838 	mcc_dig->has_sta = true;
7839 	if (ewma_rssi_read(&rtwsta_link->avg_rssi) < mcc_dig->rssi_min)
7840 		mcc_dig->rssi_min = ewma_rssi_read(&rtwsta_link->avg_rssi);
7841 }
7842 
7843 static void rtw89_phy_dig_mcc(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
7844 {
7845 	struct rtw89_phy_iter_mcc_dig mcc_dig;
7846 	struct rtw89_vif_link *rtwvif_link;
7847 	struct rtw89_mcc_links_info info;
7848 	int i;
7849 
7850 	rtw89_mcc_get_links(rtwdev, &info);
7851 	for (i = 0; i < ARRAY_SIZE(info.links); i++) {
7852 		rtwvif_link = info.links[i];
7853 		if (!rtwvif_link)
7854 			continue;
7855 
7856 		memset(&mcc_dig, 0, sizeof(mcc_dig));
7857 		mcc_dig.rtwvif_link = rtwvif_link;
7858 		mcc_dig.has_sta = false;
7859 		mcc_dig.rssi_min = U8_MAX;
7860 		ieee80211_iterate_stations_atomic(rtwdev->hw,
7861 						  rtw89_phy_set_mcc_dig_iter,
7862 						  &mcc_dig);
7863 
7864 		rtw89_phy_set_mcc_dig(rtwdev, rtwvif_link, bb,
7865 				      mcc_dig.rssi_min, i, mcc_dig.has_sta);
7866 	}
7867 }
7868 
7869 static void rtw89_phy_dig_ctrl(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb,
7870 			       bool pause_dig, bool restore)
7871 {
7872 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
7873 	struct rtw89_dig_info *dig = &bb->dig;
7874 	struct rtw89_hal *hal = &rtwdev->hal;
7875 	bool en_dig;
7876 	u32 pd_val;
7877 
7878 	if (dig->pause_dig == pause_dig)
7879 		return;
7880 
7881 	if (pause_dig) {
7882 		en_dig = false;
7883 		if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD))
7884 			pd_val = hal->fixed_dig_pd_th;
7885 		else
7886 			pd_val = 0;
7887 	} else {
7888 		en_dig = rtwdev->total_sta_assoc > 0;
7889 		if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DIG_PD))
7890 			pd_val = hal->fixed_dig_pd_th;
7891 		else
7892 			pd_val = restore ? dig->bak_dig : 0;
7893 	}
7894 
7895 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "%s <%s> PD_low=%d", __func__,
7896 		    pause_dig ? "suspend" : "resume", pd_val);
7897 
7898 	rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
7899 			      dig_regs->pd_lower_bound_mask, pd_val, bb->phy_idx);
7900 	rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
7901 			      dig_regs->pd_spatial_reuse_en, en_dig, bb->phy_idx);
7902 
7903 	dig->pause_dig = pause_dig;
7904 }
7905 
7906 void rtw89_phy_dig_suspend(struct rtw89_dev *rtwdev)
7907 {
7908 	struct rtw89_bb_ctx *bb;
7909 
7910 	rtw89_for_each_active_bb(rtwdev, bb)
7911 		rtw89_phy_dig_ctrl(rtwdev, bb, true, false);
7912 }
7913 
7914 void rtw89_phy_dig_resume(struct rtw89_dev *rtwdev, bool restore)
7915 {
7916 	struct rtw89_bb_ctx *bb;
7917 
7918 	rtw89_for_each_active_bb(rtwdev, bb)
7919 		rtw89_phy_dig_ctrl(rtwdev, bb, false, restore);
7920 }
7921 
7922 static void __rtw89_phy_dig(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
7923 {
7924 	struct rtw89_dig_info *dig = &bb->dig;
7925 	bool is_linked = rtwdev->total_sta_assoc > 0;
7926 	enum rtw89_entity_mode mode;
7927 
7928 	if (unlikely(dig->bypass_dig)) {
7929 		dig->bypass_dig = false;
7930 		return;
7931 	}
7932 
7933 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "BB-%d dig track\n", bb->phy_idx);
7934 
7935 	rtw89_phy_dig_update_rssi_info(rtwdev, bb);
7936 
7937 	mode = rtw89_get_entity_mode(rtwdev);
7938 	if (mode == RTW89_ENTITY_MODE_MCC) {
7939 		rtw89_phy_dig_mcc(rtwdev, bb);
7940 		return;
7941 	}
7942 
7943 	if (unlikely(dig->pause_dig))
7944 		return;
7945 
7946 	if (!dig->is_linked_pre && is_linked) {
7947 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "First connected\n");
7948 		rtw89_phy_dig_update_para(rtwdev, bb);
7949 		dig->igi_fa_rssi = dig->igi_rssi;
7950 	} else if (dig->is_linked_pre && !is_linked) {
7951 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "First disconnected\n");
7952 		rtw89_phy_dig_update_para(rtwdev, bb);
7953 		dig->igi_fa_rssi = dig->igi_rssi;
7954 	}
7955 	dig->is_linked_pre = is_linked;
7956 
7957 	rtw89_phy_cal_igi_fa_rssi(rtwdev, bb, is_linked);
7958 
7959 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
7960 		    "rssi=%03d, dyn_joint(max,min)=(%d,%d), final_rssi=%d\n",
7961 		    dig->igi_rssi, dig->dyn_igi_max, dig->dyn_igi_min,
7962 		    dig->igi_fa_rssi);
7963 
7964 	rtw89_phy_dig_config_igi(rtwdev, bb);
7965 
7966 	rtw89_phy_dig_dyn_pd_th(rtwdev, bb, dig->igi_fa_rssi, dig->dyn_pd_th_en);
7967 
7968 	if (dig->dyn_pd_th_en && dig->igi_fa_rssi > dig->dyn_pd_th_max)
7969 		rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, bb, true);
7970 	else
7971 		rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, bb, false);
7972 }
7973 
7974 void rtw89_phy_dig(struct rtw89_dev *rtwdev)
7975 {
7976 	struct rtw89_bb_ctx *bb;
7977 
7978 	rtw89_for_each_active_bb(rtwdev, bb)
7979 		__rtw89_phy_dig(rtwdev, bb);
7980 }
7981 
7982 static void __rtw89_phy_tx_path_div_sta_iter(struct rtw89_dev *rtwdev,
7983 					     struct rtw89_sta_link *rtwsta_link)
7984 {
7985 	struct rtw89_hal *hal = &rtwdev->hal;
7986 	u8 rssi_a, rssi_b;
7987 	u32 candidate;
7988 
7989 	rssi_a = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_A]);
7990 	rssi_b = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_B]);
7991 
7992 	if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH)
7993 		candidate = RF_A;
7994 	else if (rssi_b > rssi_a + RTW89_TX_DIV_RSSI_RAW_TH)
7995 		candidate = RF_B;
7996 	else
7997 		return;
7998 
7999 	if (hal->antenna_tx == candidate)
8000 		return;
8001 
8002 	hal->antenna_tx = candidate;
8003 	rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta_link);
8004 
8005 	if (hal->antenna_tx == RF_A) {
8006 		rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12);
8007 		rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x11);
8008 	} else if (hal->antenna_tx == RF_B) {
8009 		rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x11);
8010 		rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x12);
8011 	}
8012 }
8013 
8014 static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
8015 {
8016 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
8017 	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
8018 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
8019 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
8020 	struct rtw89_vif_link *rtwvif_link;
8021 	struct rtw89_sta_link *rtwsta_link;
8022 	unsigned int link_id;
8023 	bool *done = data;
8024 
8025 	if (WARN(ieee80211_vif_is_mld(vif), "MLD mix path_div\n"))
8026 		return;
8027 
8028 	if (sta->tdls)
8029 		return;
8030 
8031 	if (*done)
8032 		return;
8033 
8034 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
8035 		rtwvif_link = rtwsta_link->rtwvif_link;
8036 		if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION)
8037 			continue;
8038 
8039 		*done = true;
8040 		__rtw89_phy_tx_path_div_sta_iter(rtwdev, rtwsta_link);
8041 		return;
8042 	}
8043 }
8044 
8045 void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
8046 {
8047 	struct rtw89_hal *hal = &rtwdev->hal;
8048 	bool done = false;
8049 
8050 	if (!hal->tx_path_diversity)
8051 		return;
8052 
8053 	ieee80211_iterate_stations_atomic(rtwdev->hw,
8054 					  rtw89_phy_tx_path_div_sta_iter,
8055 					  &done);
8056 }
8057 
8058 #define ANTDIV_MAIN 0
8059 #define ANTDIV_AUX 1
8060 
8061 static void rtw89_phy_antdiv_set_ant(struct rtw89_dev *rtwdev)
8062 {
8063 	struct rtw89_hal *hal = &rtwdev->hal;
8064 	u8 default_ant, optional_ant;
8065 
8066 	if (!hal->ant_diversity || hal->antenna_tx == 0)
8067 		return;
8068 
8069 	if (hal->antenna_tx == RF_B) {
8070 		default_ant = ANTDIV_AUX;
8071 		optional_ant = ANTDIV_MAIN;
8072 	} else {
8073 		default_ant = ANTDIV_MAIN;
8074 		optional_ant = ANTDIV_AUX;
8075 	}
8076 
8077 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_CGCS_CTRL,
8078 			      default_ant, RTW89_PHY_0);
8079 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ORI,
8080 			      default_ant, RTW89_PHY_0);
8081 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ALT,
8082 			      optional_ant, RTW89_PHY_0);
8083 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_TX_ORI,
8084 			      default_ant, RTW89_PHY_0);
8085 }
8086 
8087 static void rtw89_phy_swap_hal_antenna(struct rtw89_dev *rtwdev)
8088 {
8089 	struct rtw89_hal *hal = &rtwdev->hal;
8090 
8091 	hal->antenna_rx = hal->antenna_rx == RF_A ? RF_B : RF_A;
8092 	hal->antenna_tx = hal->antenna_rx;
8093 }
8094 
8095 static void rtw89_phy_antdiv_decision_state(struct rtw89_dev *rtwdev)
8096 {
8097 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
8098 	struct rtw89_hal *hal = &rtwdev->hal;
8099 	bool no_change = false;
8100 	u8 main_rssi, aux_rssi;
8101 	u8 main_evm, aux_evm;
8102 	u32 candidate;
8103 
8104 	antdiv->get_stats = false;
8105 	antdiv->training_count = 0;
8106 
8107 	main_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->main_stats);
8108 	main_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->main_stats);
8109 	aux_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->aux_stats);
8110 	aux_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->aux_stats);
8111 
8112 	if (main_evm > aux_evm + ANTDIV_EVM_DIFF_TH)
8113 		candidate = RF_A;
8114 	else if (aux_evm > main_evm + ANTDIV_EVM_DIFF_TH)
8115 		candidate = RF_B;
8116 	else if (main_rssi > aux_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
8117 		candidate = RF_A;
8118 	else if (aux_rssi > main_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
8119 		candidate = RF_B;
8120 	else
8121 		no_change = true;
8122 
8123 	if (no_change) {
8124 		/* swap back from training antenna to original */
8125 		rtw89_phy_swap_hal_antenna(rtwdev);
8126 		return;
8127 	}
8128 
8129 	hal->antenna_tx = candidate;
8130 	hal->antenna_rx = candidate;
8131 }
8132 
8133 static void rtw89_phy_antdiv_training_state(struct rtw89_dev *rtwdev)
8134 {
8135 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
8136 	u64 state_period;
8137 
8138 	if (antdiv->training_count % 2 == 0) {
8139 		if (antdiv->training_count == 0)
8140 			rtw89_phy_antdiv_sts_reset(rtwdev);
8141 
8142 		antdiv->get_stats = true;
8143 		state_period = msecs_to_jiffies(ANTDIV_TRAINNING_INTVL);
8144 	} else {
8145 		antdiv->get_stats = false;
8146 		state_period = msecs_to_jiffies(ANTDIV_DELAY);
8147 
8148 		rtw89_phy_swap_hal_antenna(rtwdev);
8149 		rtw89_phy_antdiv_set_ant(rtwdev);
8150 	}
8151 
8152 	antdiv->training_count++;
8153 	wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->antdiv_work,
8154 				 state_period);
8155 }
8156 
8157 void rtw89_phy_antdiv_work(struct wiphy *wiphy, struct wiphy_work *work)
8158 {
8159 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8160 						antdiv_work.work);
8161 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
8162 
8163 	lockdep_assert_wiphy(wiphy);
8164 
8165 	if (antdiv->training_count <= ANTDIV_TRAINNING_CNT) {
8166 		rtw89_phy_antdiv_training_state(rtwdev);
8167 	} else {
8168 		rtw89_phy_antdiv_decision_state(rtwdev);
8169 		rtw89_phy_antdiv_set_ant(rtwdev);
8170 	}
8171 }
8172 
8173 void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev)
8174 {
8175 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
8176 	struct rtw89_hal *hal = &rtwdev->hal;
8177 	u8 rssi, rssi_pre;
8178 
8179 	if (!hal->ant_diversity || hal->ant_diversity_fixed)
8180 		return;
8181 
8182 	rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->target_stats);
8183 	rssi_pre = antdiv->rssi_pre;
8184 	antdiv->rssi_pre = rssi;
8185 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
8186 
8187 	if (abs((int)rssi - (int)rssi_pre) < ANTDIV_RSSI_DIFF_TH)
8188 		return;
8189 
8190 	antdiv->training_count = 0;
8191 	wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->antdiv_work, 0);
8192 }
8193 
8194 static void __rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev,
8195 					 struct rtw89_bb_ctx *bb)
8196 {
8197 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
8198 		    "BB-%d env_monitor init\n", bb->phy_idx);
8199 
8200 	rtw89_phy_ccx_top_setting_init(rtwdev, bb);
8201 	rtw89_phy_ifs_clm_setting_init(rtwdev, bb);
8202 }
8203 
8204 static void rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev)
8205 {
8206 	struct rtw89_bb_ctx *bb;
8207 
8208 	rtw89_for_each_capab_bb(rtwdev, bb)
8209 		__rtw89_phy_env_monitor_init(rtwdev, bb);
8210 }
8211 
8212 static void rtw89_phy_diag_init(struct rtw89_dev *rtwdev)
8213 {
8214 	struct rtw89_bb_ctx *bb;
8215 
8216 	rtw89_for_each_capab_bb(rtwdev, bb)
8217 		memset(&bb->diag, 0, sizeof(bb->diag));
8218 }
8219 
8220 static void __rtw89_phy_edcca_init(struct rtw89_dev *rtwdev,
8221 				   struct rtw89_bb_ctx *bb)
8222 {
8223 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
8224 	struct rtw89_edcca_bak *edcca_bak = &bb->edcca_bak;
8225 
8226 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA, "BB-%d edcca init\n", bb->phy_idx);
8227 
8228 	memset(edcca_bak, 0, sizeof(*edcca_bak));
8229 
8230 	if (rtwdev->chip->chip_id == RTL8922A && rtwdev->hal.cv == CHIP_CAV) {
8231 		rtw89_phy_set_phy_regs(rtwdev, R_TXGATING, B_TXGATING_EN, 0);
8232 		rtw89_phy_set_phy_regs(rtwdev, R_CTLTOP, B_CTLTOP_VAL, 2);
8233 		rtw89_phy_set_phy_regs(rtwdev, R_CTLTOP, B_CTLTOP_ON, 1);
8234 		rtw89_phy_set_phy_regs(rtwdev, R_SPOOF_CG, B_SPOOF_CG_EN, 0);
8235 		rtw89_phy_set_phy_regs(rtwdev, R_DFS_FFT_CG, B_DFS_CG_EN, 0);
8236 		rtw89_phy_set_phy_regs(rtwdev, R_DFS_FFT_CG, B_DFS_FFT_EN, 0);
8237 		rtw89_phy_set_phy_regs(rtwdev, R_SEGSND, B_SEGSND_EN, 0);
8238 		rtw89_phy_set_phy_regs(rtwdev, R_SEGSND, B_SEGSND_EN, 1);
8239 		rtw89_phy_set_phy_regs(rtwdev, R_DFS_FFT_CG, B_DFS_FFT_EN, 1);
8240 	}
8241 
8242 	rtw89_phy_write32_idx(rtwdev, edcca_regs->tx_collision_t2r_st,
8243 			      edcca_regs->tx_collision_t2r_st_mask, 0x29, bb->phy_idx);
8244 }
8245 
8246 static void rtw89_phy_edcca_init(struct rtw89_dev *rtwdev)
8247 {
8248 	struct rtw89_bb_ctx *bb;
8249 
8250 	rtw89_for_each_capab_bb(rtwdev, bb)
8251 		__rtw89_phy_edcca_init(rtwdev, bb);
8252 }
8253 
8254 void rtw89_phy_dm_init(struct rtw89_dev *rtwdev)
8255 {
8256 	rtw89_phy_stat_init(rtwdev);
8257 
8258 	rtw89_chip_bb_sethw(rtwdev);
8259 
8260 	rtw89_phy_diag_init(rtwdev);
8261 	rtw89_phy_env_monitor_init(rtwdev);
8262 	rtw89_phy_nhm_setting_init(rtwdev);
8263 	rtw89_physts_parsing_init(rtwdev);
8264 	rtw89_phy_dig_init(rtwdev);
8265 	rtw89_phy_cfo_init(rtwdev);
8266 	rtw89_phy_bb_wrap_init(rtwdev);
8267 	rtw89_phy_edcca_init(rtwdev);
8268 	rtw89_phy_ch_info_init(rtwdev);
8269 	rtw89_phy_ul_tb_info_init(rtwdev);
8270 	rtw89_phy_antdiv_init(rtwdev);
8271 	rtw89_chip_rfe_gpio(rtwdev);
8272 	rtw89_phy_antdiv_set_ant(rtwdev);
8273 
8274 	rtw89_chip_rfk_hw_init(rtwdev);
8275 	rtw89_phy_init_rf_nctl(rtwdev);
8276 	rtw89_chip_rfk_init(rtwdev);
8277 	rtw89_chip_set_txpwr_ctrl(rtwdev);
8278 	rtw89_chip_power_trim(rtwdev);
8279 	rtw89_chip_cfg_txrx_path(rtwdev);
8280 }
8281 
8282 void rtw89_phy_dm_reinit(struct rtw89_dev *rtwdev)
8283 {
8284 	rtw89_phy_env_monitor_init(rtwdev);
8285 	rtw89_physts_parsing_init(rtwdev);
8286 }
8287 
8288 static void __rtw89_phy_dm_init_data(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
8289 {
8290 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
8291 	const struct rtw89_chip_info *chip = rtwdev->chip;
8292 	struct ieee80211_supported_band *sband;
8293 	enum rtw89_band hw_band;
8294 	enum nl80211_band band;
8295 	u8 idx;
8296 
8297 	if (!chip->support_noise)
8298 		return;
8299 
8300 	for (band = 0; band < NUM_NL80211_BANDS; band++) {
8301 		sband = rtwdev->hw->wiphy->bands[band];
8302 		if (!sband)
8303 			continue;
8304 
8305 		hw_band = rtw89_nl80211_to_hw_band(band);
8306 		env->nhm_his[hw_band] =
8307 			devm_kcalloc(rtwdev->dev, sband->n_channels,
8308 				     sizeof(*env->nhm_his[0]), GFP_KERNEL);
8309 
8310 		for (idx = 0; idx < sband->n_channels; idx++)
8311 			INIT_LIST_HEAD(&env->nhm_his[hw_band][idx].list);
8312 
8313 		INIT_LIST_HEAD(&env->nhm_rpt_list);
8314 	}
8315 }
8316 
8317 void rtw89_phy_dm_init_data(struct rtw89_dev *rtwdev)
8318 {
8319 	struct rtw89_bb_ctx *bb;
8320 
8321 	rtw89_for_each_capab_bb(rtwdev, bb)
8322 		__rtw89_phy_dm_init_data(rtwdev, bb);
8323 }
8324 
8325 void __rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, u8 bss_color, u16 aid,
8326 			       enum rtw89_phy_idx phy_idx)
8327 {
8328 	const struct rtw89_chip_info *chip = rtwdev->chip;
8329 	const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld;
8330 
8331 	rtw89_phy_write32_idx(rtwdev, bss_clr_vld->addr, bss_clr_vld->mask, 0x1,
8332 			      phy_idx);
8333 	rtw89_phy_write32_idx(rtwdev, chip->bss_clr_map_reg, B_BSS_CLR_MAP_TGT,
8334 			      bss_color, phy_idx);
8335 	rtw89_phy_write32_idx(rtwdev, chip->bss_clr_map_reg, B_BSS_CLR_MAP_STAID,
8336 			      aid, phy_idx);
8337 }
8338 
8339 void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev,
8340 			     struct rtw89_vif_link *rtwvif_link)
8341 {
8342 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
8343 	enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
8344 	struct ieee80211_bss_conf *bss_conf;
8345 	u8 bss_color;
8346 
8347 	rcu_read_lock();
8348 
8349 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
8350 	if (!bss_conf->he_support || !vif->cfg.assoc) {
8351 		rcu_read_unlock();
8352 		return;
8353 	}
8354 
8355 	bss_color = bss_conf->he_bss_color.color;
8356 
8357 	rcu_read_unlock();
8358 
8359 	__rtw89_phy_set_bss_color(rtwdev, bss_color, vif->cfg.aid, phy_idx);
8360 }
8361 
8362 static bool rfk_chan_validate_desc(const struct rtw89_rfk_chan_desc *desc)
8363 {
8364 	return desc->ch != 0;
8365 }
8366 
8367 static bool rfk_chan_is_equivalent(const struct rtw89_rfk_chan_desc *desc,
8368 				   const struct rtw89_chan *chan)
8369 {
8370 	if (!rfk_chan_validate_desc(desc))
8371 		return false;
8372 
8373 	if (desc->ch != chan->channel)
8374 		return false;
8375 
8376 	if (desc->has_band && desc->band != chan->band_type)
8377 		return false;
8378 
8379 	if (desc->has_bw && desc->bw != chan->band_width)
8380 		return false;
8381 
8382 	return true;
8383 }
8384 
8385 struct rfk_chan_iter_data {
8386 	const struct rtw89_rfk_chan_desc desc;
8387 	unsigned int found;
8388 };
8389 
8390 static int rfk_chan_iter_search(const struct rtw89_chan *chan, void *data)
8391 {
8392 	struct rfk_chan_iter_data *iter_data = data;
8393 
8394 	if (rfk_chan_is_equivalent(&iter_data->desc, chan))
8395 		iter_data->found++;
8396 
8397 	return 0;
8398 }
8399 
8400 u8 rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev,
8401 			 const struct rtw89_rfk_chan_desc *desc, u8 desc_nr,
8402 			 const struct rtw89_chan *target_chan)
8403 {
8404 	int sel = -1;
8405 	u8 i;
8406 
8407 	for (i = 0; i < desc_nr; i++) {
8408 		struct rfk_chan_iter_data iter_data = {
8409 			.desc = desc[i],
8410 		};
8411 
8412 		if (rfk_chan_is_equivalent(&desc[i], target_chan))
8413 			return i;
8414 
8415 		rtw89_iterate_entity_chan(rtwdev, rfk_chan_iter_search, &iter_data);
8416 		if (!iter_data.found && sel == -1)
8417 			sel = i;
8418 	}
8419 
8420 	if (sel == -1) {
8421 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
8422 			    "no idle rfk entry; force replace the first\n");
8423 		sel = 0;
8424 	}
8425 
8426 	return sel;
8427 }
8428 EXPORT_SYMBOL(rtw89_rfk_chan_lookup);
8429 
8430 static void
8431 _rfk_write_rf(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
8432 {
8433 	rtw89_write_rf(rtwdev, def->path, def->addr, def->mask, def->data);
8434 }
8435 
8436 static void
8437 _rfk_write32_mask(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
8438 {
8439 	rtw89_phy_write32_mask(rtwdev, def->addr, def->mask, def->data);
8440 }
8441 
8442 static void
8443 _rfk_write32_set(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
8444 {
8445 	rtw89_phy_write32_set(rtwdev, def->addr, def->mask);
8446 }
8447 
8448 static void
8449 _rfk_write32_clr(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
8450 {
8451 	rtw89_phy_write32_clr(rtwdev, def->addr, def->mask);
8452 }
8453 
8454 static void
8455 _rfk_delay(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
8456 {
8457 	udelay(def->data);
8458 }
8459 
8460 static void
8461 (*_rfk_handler[])(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def) = {
8462 	[RTW89_RFK_F_WRF] = _rfk_write_rf,
8463 	[RTW89_RFK_F_WM] = _rfk_write32_mask,
8464 	[RTW89_RFK_F_WS] = _rfk_write32_set,
8465 	[RTW89_RFK_F_WC] = _rfk_write32_clr,
8466 	[RTW89_RFK_F_DELAY] = _rfk_delay,
8467 };
8468 
8469 static_assert(ARRAY_SIZE(_rfk_handler) == RTW89_RFK_F_NUM);
8470 
8471 void
8472 rtw89_rfk_parser(struct rtw89_dev *rtwdev, const struct rtw89_rfk_tbl *tbl)
8473 {
8474 	const struct rtw89_reg5_def *p = tbl->defs;
8475 	const struct rtw89_reg5_def *end = tbl->defs + tbl->size;
8476 
8477 	for (; p < end; p++)
8478 		_rfk_handler[p->flag](rtwdev, p);
8479 }
8480 EXPORT_SYMBOL(rtw89_rfk_parser);
8481 
8482 #define RTW89_TSSI_FAST_MODE_NUM 4
8483 
8484 static const struct rtw89_reg_def rtw89_tssi_fastmode_regs_flat[RTW89_TSSI_FAST_MODE_NUM] = {
8485 	{0xD934, 0xff0000},
8486 	{0xD934, 0xff000000},
8487 	{0xD938, 0xff},
8488 	{0xD934, 0xff00},
8489 };
8490 
8491 static const struct rtw89_reg_def rtw89_tssi_fastmode_regs_level[RTW89_TSSI_FAST_MODE_NUM] = {
8492 	{0xD930, 0xff0000},
8493 	{0xD930, 0xff000000},
8494 	{0xD934, 0xff},
8495 	{0xD930, 0xff00},
8496 };
8497 
8498 static
8499 void rtw89_phy_tssi_ctrl_set_fast_mode_cfg(struct rtw89_dev *rtwdev,
8500 					   enum rtw89_mac_idx mac_idx,
8501 					   enum rtw89_tssi_bandedge_cfg bandedge_cfg,
8502 					   u32 val)
8503 {
8504 	const struct rtw89_reg_def *regs;
8505 	u32 reg;
8506 	int i;
8507 
8508 	if (bandedge_cfg == RTW89_TSSI_BANDEDGE_FLAT)
8509 		regs = rtw89_tssi_fastmode_regs_flat;
8510 	else
8511 		regs = rtw89_tssi_fastmode_regs_level;
8512 
8513 	for (i = 0; i < RTW89_TSSI_FAST_MODE_NUM; i++) {
8514 		reg = rtw89_mac_reg_by_idx(rtwdev, regs[i].addr, mac_idx);
8515 		rtw89_write32_mask(rtwdev, reg, regs[i].mask, val);
8516 	}
8517 }
8518 
8519 static const struct rtw89_reg_def rtw89_tssi_bandedge_regs_flat[RTW89_TSSI_SBW_NUM] = {
8520 	{0xD91C, 0xff000000},
8521 	{0xD920, 0xff},
8522 	{0xD920, 0xff00},
8523 	{0xD920, 0xff0000},
8524 	{0xD920, 0xff000000},
8525 	{0xD924, 0xff},
8526 	{0xD924, 0xff00},
8527 	{0xD914, 0xff000000},
8528 	{0xD918, 0xff},
8529 	{0xD918, 0xff00},
8530 	{0xD918, 0xff0000},
8531 	{0xD918, 0xff000000},
8532 	{0xD91C, 0xff},
8533 	{0xD91C, 0xff00},
8534 	{0xD91C, 0xff0000},
8535 };
8536 
8537 static const struct rtw89_reg_def rtw89_tssi_bandedge_regs_level[RTW89_TSSI_SBW_NUM] = {
8538 	{0xD910, 0xff},
8539 	{0xD910, 0xff00},
8540 	{0xD910, 0xff0000},
8541 	{0xD910, 0xff000000},
8542 	{0xD914, 0xff},
8543 	{0xD914, 0xff00},
8544 	{0xD914, 0xff0000},
8545 	{0xD908, 0xff},
8546 	{0xD908, 0xff00},
8547 	{0xD908, 0xff0000},
8548 	{0xD908, 0xff000000},
8549 	{0xD90C, 0xff},
8550 	{0xD90C, 0xff00},
8551 	{0xD90C, 0xff0000},
8552 	{0xD90C, 0xff000000},
8553 };
8554 
8555 void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
8556 					  enum rtw89_mac_idx mac_idx,
8557 					  enum rtw89_tssi_bandedge_cfg bandedge_cfg)
8558 {
8559 	const struct rtw89_chip_info *chip = rtwdev->chip;
8560 	const struct rtw89_reg_def *regs;
8561 	const u32 *data;
8562 	u32 reg;
8563 	int i;
8564 
8565 	if (bandedge_cfg >= RTW89_TSSI_CFG_NUM)
8566 		return;
8567 
8568 	if (bandedge_cfg == RTW89_TSSI_BANDEDGE_FLAT)
8569 		regs = rtw89_tssi_bandedge_regs_flat;
8570 	else
8571 		regs = rtw89_tssi_bandedge_regs_level;
8572 
8573 	data = chip->tssi_dbw_table->data[bandedge_cfg];
8574 
8575 	for (i = 0; i < RTW89_TSSI_SBW_NUM; i++) {
8576 		reg = rtw89_mac_reg_by_idx(rtwdev, regs[i].addr, mac_idx);
8577 		rtw89_write32_mask(rtwdev, reg, regs[i].mask, data[i]);
8578 	}
8579 
8580 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BANDEDGE_CFG, mac_idx);
8581 	rtw89_write32_mask(rtwdev, reg, B_AX_BANDEDGE_CFG_IDX_MASK, bandedge_cfg);
8582 
8583 	rtw89_phy_tssi_ctrl_set_fast_mode_cfg(rtwdev, mac_idx, bandedge_cfg,
8584 					      data[RTW89_TSSI_SBW20]);
8585 }
8586 EXPORT_SYMBOL(rtw89_phy_tssi_ctrl_set_bandedge_cfg);
8587 
8588 static
8589 const u8 rtw89_ch_base_table[16] = {1, 0xff,
8590 				    36, 100, 132, 149, 0xff,
8591 				    1, 33, 65, 97, 129, 161, 193, 225, 0xff};
8592 #define RTW89_CH_BASE_IDX_2G		0
8593 #define RTW89_CH_BASE_IDX_5G_FIRST	2
8594 #define RTW89_CH_BASE_IDX_5G_LAST	5
8595 #define RTW89_CH_BASE_IDX_6G_FIRST	7
8596 #define RTW89_CH_BASE_IDX_6G_LAST	14
8597 
8598 #define RTW89_CH_BASE_IDX_MASK		GENMASK(7, 4)
8599 #define RTW89_CH_OFFSET_MASK		GENMASK(3, 0)
8600 
8601 u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band)
8602 {
8603 	u8 chan_idx;
8604 	u8 last, first;
8605 	u8 idx;
8606 
8607 	switch (band) {
8608 	case RTW89_BAND_2G:
8609 		chan_idx = FIELD_PREP(RTW89_CH_BASE_IDX_MASK, RTW89_CH_BASE_IDX_2G) |
8610 			   FIELD_PREP(RTW89_CH_OFFSET_MASK, central_ch);
8611 		return chan_idx;
8612 	case RTW89_BAND_5G:
8613 		first = RTW89_CH_BASE_IDX_5G_FIRST;
8614 		last = RTW89_CH_BASE_IDX_5G_LAST;
8615 		break;
8616 	case RTW89_BAND_6G:
8617 		first = RTW89_CH_BASE_IDX_6G_FIRST;
8618 		last = RTW89_CH_BASE_IDX_6G_LAST;
8619 		break;
8620 	default:
8621 		rtw89_warn(rtwdev, "Unsupported band %d\n", band);
8622 		return 0;
8623 	}
8624 
8625 	for (idx = last; idx >= first; idx--)
8626 		if (central_ch >= rtw89_ch_base_table[idx])
8627 			break;
8628 
8629 	if (idx < first) {
8630 		rtw89_warn(rtwdev, "Unknown band %d channel %d\n", band, central_ch);
8631 		return 0;
8632 	}
8633 
8634 	chan_idx = FIELD_PREP(RTW89_CH_BASE_IDX_MASK, idx) |
8635 		   FIELD_PREP(RTW89_CH_OFFSET_MASK,
8636 			      (central_ch - rtw89_ch_base_table[idx]) >> 1);
8637 	return chan_idx;
8638 }
8639 EXPORT_SYMBOL(rtw89_encode_chan_idx);
8640 
8641 void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
8642 			   u8 *ch, enum nl80211_band *band)
8643 {
8644 	u8 idx, offset;
8645 
8646 	idx = FIELD_GET(RTW89_CH_BASE_IDX_MASK, chan_idx);
8647 	offset = FIELD_GET(RTW89_CH_OFFSET_MASK, chan_idx);
8648 
8649 	if (idx == RTW89_CH_BASE_IDX_2G) {
8650 		*band = NL80211_BAND_2GHZ;
8651 		*ch = offset;
8652 		return;
8653 	}
8654 
8655 	*band = idx <= RTW89_CH_BASE_IDX_5G_LAST ? NL80211_BAND_5GHZ : NL80211_BAND_6GHZ;
8656 	*ch = rtw89_ch_base_table[idx] + (offset << 1);
8657 }
8658 EXPORT_SYMBOL(rtw89_decode_chan_idx);
8659 
8660 void rtw89_phy_config_edcca(struct rtw89_dev *rtwdev,
8661 			    struct rtw89_bb_ctx *bb, bool scan)
8662 {
8663 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
8664 	struct rtw89_edcca_bak *edcca_bak = &bb->edcca_bak;
8665 
8666 	if (scan) {
8667 		edcca_bak->a =
8668 			rtw89_phy_read32_idx(rtwdev, edcca_regs->edcca_level,
8669 					     edcca_regs->edcca_mask, bb->phy_idx);
8670 		edcca_bak->p =
8671 			rtw89_phy_read32_idx(rtwdev, edcca_regs->edcca_level,
8672 					     edcca_regs->edcca_p_mask, bb->phy_idx);
8673 		edcca_bak->ppdu =
8674 			rtw89_phy_read32_idx(rtwdev, edcca_regs->ppdu_level,
8675 					     edcca_regs->ppdu_mask, bb->phy_idx);
8676 
8677 		rtw89_phy_write32_idx(rtwdev, edcca_regs->edcca_level,
8678 				      edcca_regs->edcca_mask, EDCCA_MAX, bb->phy_idx);
8679 		rtw89_phy_write32_idx(rtwdev, edcca_regs->edcca_level,
8680 				      edcca_regs->edcca_p_mask, EDCCA_MAX, bb->phy_idx);
8681 		rtw89_phy_write32_idx(rtwdev, edcca_regs->ppdu_level,
8682 				      edcca_regs->ppdu_mask, EDCCA_MAX, bb->phy_idx);
8683 	} else {
8684 		rtw89_phy_write32_idx(rtwdev, edcca_regs->edcca_level,
8685 				      edcca_regs->edcca_mask,
8686 				      edcca_bak->a, bb->phy_idx);
8687 		rtw89_phy_write32_idx(rtwdev, edcca_regs->edcca_level,
8688 				      edcca_regs->edcca_p_mask,
8689 				      edcca_bak->p, bb->phy_idx);
8690 		rtw89_phy_write32_idx(rtwdev, edcca_regs->ppdu_level,
8691 				      edcca_regs->ppdu_mask,
8692 				      edcca_bak->ppdu, bb->phy_idx);
8693 	}
8694 }
8695 
8696 static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
8697 {
8698 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
8699 	const struct rtw89_edcca_p_regs *edcca_p_regs;
8700 	bool flag_fb, flag_p20, flag_s20, flag_s40, flag_s80;
8701 	s8 pwdb_fb, pwdb_p20, pwdb_s20, pwdb_s40, pwdb_s80;
8702 	u8 path, per20_bitmap = 0;
8703 	u8 pwdb_sel = 5;
8704 	u8 pwdb[8];
8705 	u32 tmp;
8706 
8707 	if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_EDCCA))
8708 		return;
8709 
8710 	if (bb->phy_idx == RTW89_PHY_1)
8711 		edcca_p_regs = &edcca_regs->p[RTW89_PHY_1];
8712 	else
8713 		edcca_p_regs = &edcca_regs->p[RTW89_PHY_0];
8714 
8715 	rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
8716 			       edcca_p_regs->rpt_sel_mask, 0);
8717 	if (rtwdev->chip->chip_id == RTL8922A || rtwdev->chip->chip_id == RTL8922D) {
8718 		rtw89_phy_write32_idx(rtwdev, edcca_regs->rpt_sel_be,
8719 				      edcca_regs->rpt_sel_be_mask, 0, bb->phy_idx);
8720 		per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_p_regs->rpt_a,
8721 						     MASKBYTE0);
8722 	}
8723 	tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b);
8724 	path = u32_get_bits(tmp, B_EDCCA_RPT_B_PATH_MASK);
8725 	flag_s80 = u32_get_bits(tmp, B_EDCCA_RPT_B_S80);
8726 	flag_s40 = u32_get_bits(tmp, B_EDCCA_RPT_B_S40);
8727 	flag_s20 = u32_get_bits(tmp, B_EDCCA_RPT_B_S20);
8728 	flag_p20 = u32_get_bits(tmp, B_EDCCA_RPT_B_P20);
8729 	flag_fb = u32_get_bits(tmp, B_EDCCA_RPT_B_FB);
8730 	pwdb_s20 = u32_get_bits(tmp, MASKBYTE1);
8731 	pwdb_p20 = u32_get_bits(tmp, MASKBYTE2);
8732 	pwdb_fb = u32_get_bits(tmp, MASKBYTE3);
8733 
8734 	if (rtwdev->chip->chip_id == RTL8922D)
8735 		pwdb_sel = 2;
8736 
8737 	rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
8738 			       edcca_p_regs->rpt_sel_mask, pwdb_sel);
8739 	tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b);
8740 	pwdb_s80 = u32_get_bits(tmp, MASKBYTE1);
8741 	pwdb_s40 = u32_get_bits(tmp, MASKBYTE2);
8742 
8743 	if (rtwdev->chip->chip_id == RTL8922A || rtwdev->chip->chip_id == RTL8922D) {
8744 		rtw89_phy_write32_idx(rtwdev, edcca_regs->rpt_sel_be,
8745 				      edcca_regs->rpt_sel_be_mask, 4, bb->phy_idx);
8746 		tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b);
8747 		pwdb[0] = u32_get_bits(tmp, MASKBYTE3);
8748 		pwdb[1] = u32_get_bits(tmp, MASKBYTE2);
8749 		pwdb[2] = u32_get_bits(tmp, MASKBYTE1);
8750 		pwdb[3] = u32_get_bits(tmp, MASKBYTE0);
8751 
8752 		rtw89_phy_write32_idx(rtwdev, edcca_regs->rpt_sel_be,
8753 				      edcca_regs->rpt_sel_be_mask, 5, bb->phy_idx);
8754 		tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b);
8755 		pwdb[4] = u32_get_bits(tmp, MASKBYTE3);
8756 		pwdb[5] = u32_get_bits(tmp, MASKBYTE2);
8757 		pwdb[6] = u32_get_bits(tmp, MASKBYTE1);
8758 		pwdb[7] = u32_get_bits(tmp, MASKBYTE0);
8759 	} else {
8760 		rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
8761 				       edcca_p_regs->rpt_sel_mask, 0);
8762 		tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_a);
8763 		pwdb[0] = u32_get_bits(tmp, MASKBYTE3);
8764 		pwdb[1] = u32_get_bits(tmp, MASKBYTE2);
8765 
8766 		rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
8767 				       edcca_p_regs->rpt_sel_mask, 5);
8768 		tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_a);
8769 		pwdb[2] = u32_get_bits(tmp, MASKBYTE3);
8770 		pwdb[3] = u32_get_bits(tmp, MASKBYTE2);
8771 
8772 		rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
8773 				       edcca_p_regs->rpt_sel_mask, 2);
8774 		tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_a);
8775 		pwdb[4] = u32_get_bits(tmp, MASKBYTE3);
8776 		pwdb[5] = u32_get_bits(tmp, MASKBYTE2);
8777 
8778 		rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel,
8779 				       edcca_p_regs->rpt_sel_mask, 3);
8780 		tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_a);
8781 		pwdb[6] = u32_get_bits(tmp, MASKBYTE3);
8782 		pwdb[7] = u32_get_bits(tmp, MASKBYTE2);
8783 	}
8784 
8785 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
8786 		    "[EDCCA]: edcca_bitmap = %04x\n", per20_bitmap);
8787 
8788 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
8789 		    "[EDCCA]: pwdb per20{0,1,2,3,4,5,6,7} = {%d,%d,%d,%d,%d,%d,%d,%d}(dBm)\n",
8790 		    pwdb[0], pwdb[1], pwdb[2], pwdb[3], pwdb[4], pwdb[5],
8791 		    pwdb[6], pwdb[7]);
8792 
8793 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
8794 		    "[EDCCA]: path=%d, flag {FB,p20,s20,s40,s80} = {%d,%d,%d,%d,%d}\n",
8795 		    path, flag_fb, flag_p20, flag_s20, flag_s40, flag_s80);
8796 
8797 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
8798 		    "[EDCCA]: pwdb {FB,p20,s20,s40,s80} = {%d,%d,%d,%d,%d}(dBm)\n",
8799 		    pwdb_fb, pwdb_p20, pwdb_s20, pwdb_s40, pwdb_s80);
8800 }
8801 
8802 static u8 rtw89_phy_edcca_get_thre_by_rssi(struct rtw89_dev *rtwdev,
8803 					   struct rtw89_bb_ctx *bb)
8804 {
8805 	struct rtw89_phy_ch_info *ch_info = &bb->ch_info;
8806 	bool is_linked = rtwdev->total_sta_assoc > 0;
8807 	u8 rssi_min = ch_info->rssi_min >> 1;
8808 	u8 edcca_thre;
8809 
8810 	if (!is_linked) {
8811 		edcca_thre = EDCCA_MAX;
8812 	} else {
8813 		edcca_thre = rssi_min - RSSI_UNIT_CONVER + EDCCA_UNIT_CONVER -
8814 			     EDCCA_TH_REF;
8815 		edcca_thre = max_t(u8, edcca_thre, EDCCA_TH_L2H_LB);
8816 	}
8817 
8818 	return edcca_thre;
8819 }
8820 
8821 void rtw89_phy_edcca_thre_calc(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
8822 {
8823 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
8824 	struct rtw89_edcca_bak *edcca_bak = &bb->edcca_bak;
8825 	u8 th;
8826 
8827 	th = rtw89_phy_edcca_get_thre_by_rssi(rtwdev, bb);
8828 	if (th == edcca_bak->th_old)
8829 		return;
8830 
8831 	edcca_bak->th_old = th;
8832 
8833 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
8834 		    "[EDCCA]: Normal Mode, EDCCA_th = %d\n", th);
8835 
8836 	rtw89_phy_write32_idx(rtwdev, edcca_regs->edcca_level,
8837 			      edcca_regs->edcca_mask, th, bb->phy_idx);
8838 	rtw89_phy_write32_idx(rtwdev, edcca_regs->edcca_level,
8839 			      edcca_regs->edcca_p_mask, th, bb->phy_idx);
8840 	rtw89_phy_write32_idx(rtwdev, edcca_regs->ppdu_level,
8841 			      edcca_regs->ppdu_mask, th, bb->phy_idx);
8842 }
8843 
8844 static void rtw89_phy_edcca_diag(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
8845 {
8846 #define RTW89_DIAG_BB_EDCCA_RATIO_TH 50
8847 #define RTW89_DIAG_BB_EDCCA_TX_TH 10
8848 	struct rtw89_env_monitor_info *env = &bb->env_monitor;
8849 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
8850 	struct rtw89_diag_bb *diag = &bb->diag;
8851 
8852 	diag->diag_bb_bitmap &= ~BIT(RTW89_DIAG_BB_EDCCA);
8853 
8854 	if (stats->tx_throughput <= RTW89_DIAG_BB_EDCCA_TX_TH ||
8855 	    env->edcca_clm_ratio <= RTW89_DIAG_BB_EDCCA_RATIO_TH)
8856 		return;
8857 
8858 	diag->diag_bb_bitmap |= BIT(RTW89_DIAG_BB_EDCCA);
8859 	diag->diag_bb_cnt[RTW89_DIAG_BB_EDCCA]++;
8860 }
8861 
8862 static
8863 void __rtw89_phy_edcca_track(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
8864 {
8865 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA, "BB-%d edcca track\n", bb->phy_idx);
8866 
8867 	rtw89_phy_edcca_thre_calc(rtwdev, bb);
8868 	rtw89_phy_edcca_log(rtwdev, bb);
8869 	rtw89_phy_edcca_diag(rtwdev, bb);
8870 }
8871 
8872 void rtw89_phy_edcca_track(struct rtw89_dev *rtwdev)
8873 {
8874 	struct rtw89_hal *hal = &rtwdev->hal;
8875 	struct rtw89_bb_ctx *bb;
8876 
8877 	if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DYNAMIC_EDCCA))
8878 		return;
8879 
8880 	rtw89_for_each_active_bb(rtwdev, bb)
8881 		__rtw89_phy_edcca_track(rtwdev, bb);
8882 }
8883 
8884 enum rtw89_rf_path_bit rtw89_phy_get_kpath(struct rtw89_dev *rtwdev,
8885 					   enum rtw89_phy_idx phy_idx)
8886 {
8887 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
8888 		    "[RFK] kpath dbcc_en: 0x%x, mode=0x%x, PHY%d\n",
8889 		    rtwdev->dbcc_en, rtwdev->mlo_dbcc_mode, phy_idx);
8890 
8891 	switch (rtwdev->mlo_dbcc_mode) {
8892 	case MLO_1_PLUS_1_1RF:
8893 		if (phy_idx == RTW89_PHY_0)
8894 			return RF_A;
8895 		else
8896 			return RF_B;
8897 	case MLO_1_PLUS_1_2RF:
8898 		if (phy_idx == RTW89_PHY_0)
8899 			return RF_A;
8900 		else
8901 			return RF_D;
8902 	case MLO_0_PLUS_2_1RF:
8903 	case MLO_2_PLUS_0_1RF:
8904 		/* for both PHY 0/1 */
8905 		return RF_AB;
8906 	case MLO_0_PLUS_2_2RF:
8907 	case MLO_2_PLUS_0_2RF:
8908 	case MLO_2_PLUS_2_2RF:
8909 	default:
8910 		if (phy_idx == RTW89_PHY_0)
8911 			return RF_AB;
8912 		else
8913 			return RF_CD;
8914 	}
8915 }
8916 EXPORT_SYMBOL(rtw89_phy_get_kpath);
8917 
8918 enum rtw89_rf_path rtw89_phy_get_syn_sel(struct rtw89_dev *rtwdev,
8919 					 enum rtw89_phy_idx phy_idx)
8920 {
8921 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
8922 		    "[RFK] kpath dbcc_en: 0x%x, mode=0x%x, PHY%d\n",
8923 		    rtwdev->dbcc_en, rtwdev->mlo_dbcc_mode, phy_idx);
8924 
8925 	switch (rtwdev->mlo_dbcc_mode) {
8926 	case MLO_1_PLUS_1_1RF:
8927 		if (phy_idx == RTW89_PHY_0)
8928 			return RF_PATH_A;
8929 		else
8930 			return RF_PATH_B;
8931 	case MLO_1_PLUS_1_2RF:
8932 		if (phy_idx == RTW89_PHY_0)
8933 			return RF_PATH_A;
8934 		else
8935 			return RF_PATH_D;
8936 	case MLO_0_PLUS_2_1RF:
8937 	case MLO_2_PLUS_0_1RF:
8938 		if (phy_idx == RTW89_PHY_0)
8939 			return RF_PATH_A;
8940 		else
8941 			return RF_PATH_B;
8942 	case MLO_0_PLUS_2_2RF:
8943 	case MLO_2_PLUS_0_2RF:
8944 	case MLO_2_PLUS_2_2RF:
8945 	default:
8946 		if (phy_idx == RTW89_PHY_0)
8947 			return RF_PATH_A;
8948 		else
8949 			return RF_PATH_C;
8950 	}
8951 }
8952 EXPORT_SYMBOL(rtw89_phy_get_syn_sel);
8953 
8954 static const struct rtw89_ccx_regs rtw89_ccx_regs_ax = {
8955 	.setting_addr = R_CCX,
8956 	.edcca_opt_mask = B_CCX_EDCCA_OPT_MSK,
8957 	.measurement_trig_mask = B_MEASUREMENT_TRIG_MSK,
8958 	.trig_opt_mask = B_CCX_TRIG_OPT_MSK,
8959 	.en_mask = B_CCX_EN_MSK,
8960 	.ifs_cnt_addr = R_IFS_COUNTER,
8961 	.ifs_clm_period_mask = B_IFS_CLM_PERIOD_MSK,
8962 	.ifs_clm_cnt_unit_mask = B_IFS_CLM_COUNTER_UNIT_MSK,
8963 	.ifs_clm_cnt_clear_mask = B_IFS_COUNTER_CLR_MSK,
8964 	.ifs_collect_en_mask = B_IFS_COLLECT_EN,
8965 	.ifs_t1_addr = R_IFS_T1,
8966 	.ifs_t1_th_h_mask = B_IFS_T1_TH_HIGH_MSK,
8967 	.ifs_t1_en_mask = B_IFS_T1_EN_MSK,
8968 	.ifs_t1_th_l_mask = B_IFS_T1_TH_LOW_MSK,
8969 	.ifs_t2_addr = R_IFS_T2,
8970 	.ifs_t2_th_h_mask = B_IFS_T2_TH_HIGH_MSK,
8971 	.ifs_t2_en_mask = B_IFS_T2_EN_MSK,
8972 	.ifs_t2_th_l_mask = B_IFS_T2_TH_LOW_MSK,
8973 	.ifs_t3_addr = R_IFS_T3,
8974 	.ifs_t3_th_h_mask = B_IFS_T3_TH_HIGH_MSK,
8975 	.ifs_t3_en_mask = B_IFS_T3_EN_MSK,
8976 	.ifs_t3_th_l_mask = B_IFS_T3_TH_LOW_MSK,
8977 	.ifs_t4_addr = R_IFS_T4,
8978 	.ifs_t4_th_h_mask = B_IFS_T4_TH_HIGH_MSK,
8979 	.ifs_t4_en_mask = B_IFS_T4_EN_MSK,
8980 	.ifs_t4_th_l_mask = B_IFS_T4_TH_LOW_MSK,
8981 	.ifs_clm_tx_cnt_addr = R_IFS_CLM_TX_CNT,
8982 	.ifs_clm_edcca_excl_cca_fa_mask = B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK,
8983 	.ifs_clm_tx_cnt_msk = B_IFS_CLM_TX_CNT_MSK,
8984 	.ifs_clm_cca_addr = R_IFS_CLM_CCA,
8985 	.ifs_clm_ofdmcca_excl_fa_mask = B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK,
8986 	.ifs_clm_cckcca_excl_fa_mask = B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK,
8987 	.ifs_clm_fa_addr = R_IFS_CLM_FA,
8988 	.ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK,
8989 	.ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK,
8990 	.ifs_his_addr = R_IFS_HIS,
8991 	.ifs_his_addr2 = R_IFS_HIS,
8992 	.ifs_t4_his_mask = B_IFS_T4_HIS_MSK,
8993 	.ifs_t3_his_mask = B_IFS_T3_HIS_MSK,
8994 	.ifs_t2_his_mask = B_IFS_T2_HIS_MSK,
8995 	.ifs_t1_his_mask = B_IFS_T1_HIS_MSK,
8996 	.ifs_avg_l_addr = R_IFS_AVG_L,
8997 	.ifs_t2_avg_mask = B_IFS_T2_AVG_MSK,
8998 	.ifs_t1_avg_mask = B_IFS_T1_AVG_MSK,
8999 	.ifs_avg_h_addr = R_IFS_AVG_H,
9000 	.ifs_t4_avg_mask = B_IFS_T4_AVG_MSK,
9001 	.ifs_t3_avg_mask = B_IFS_T3_AVG_MSK,
9002 	.ifs_cca_l_addr = R_IFS_CCA_L,
9003 	.ifs_t2_cca_mask = B_IFS_T2_CCA_MSK,
9004 	.ifs_t1_cca_mask = B_IFS_T1_CCA_MSK,
9005 	.ifs_cca_h_addr = R_IFS_CCA_H,
9006 	.ifs_t4_cca_mask = B_IFS_T4_CCA_MSK,
9007 	.ifs_t3_cca_mask = B_IFS_T3_CCA_MSK,
9008 	.ifs_total_addr = R_IFSCNT,
9009 	.ifs_cnt_done_mask = B_IFSCNT_DONE_MSK,
9010 	.ifs_total_mask = B_IFSCNT_TOTAL_CNT_MSK,
9011 	.nhm = R_NHM_AX,
9012 	.nhm_ready = B_NHM_READY_MSK,
9013 	.nhm_config = R_NHM_CFG,
9014 	.nhm_period_mask = B_NHM_PERIOD_MSK,
9015 	.nhm_unit_mask = B_NHM_COUNTER_MSK,
9016 	.nhm_include_cca_mask = B_NHM_INCLUDE_CCA_MSK,
9017 	.nhm_en_mask = B_NHM_EN_MSK,
9018 	.nhm_method = R_NHM_TH9,
9019 	.nhm_pwr_method_msk = B_NHM_PWDB_METHOD_MSK,
9020 	.edcca_clm_rdy = R_CLM_EDCCA_RDY,
9021 	.edcca_clm_rdy_mask = B_CLM_EDCCA_RDY,
9022 	.edcca_clm_cnt = R_CLM_EDCCA_RESULT,
9023 	.edcca_clm_cnt_mask = B_CLM_EDCCA_RESULT,
9024 };
9025 
9026 static const u32 rtw89_txinfo_reg_ax[] = {
9027 	R_TX_INFO_0_0_COMB,
9028 	R_TX_INFO_0_1_COMB,
9029 	R_TX_INFO_1_0_COMB,
9030 	R_TX_INFO_1_1_COMB
9031 };
9032 
9033 static const u32 rtw89_tx_common_ctrl_reg_ax[] = {
9034 	R_TX_COMMON_CTRL_0_0_COMB,
9035 	R_TX_COMMON_CTRL_0_1_COMB
9036 };
9037 
9038 static const struct rtw89_reg_def rtw89_txpwr_ax[] = {
9039 	{.addr = R_PATH0_TXPWR, .mask = B_PATH0_TXPWR},
9040 	{.addr = R_PATH1_TXPWR, .mask = B_PATH1_TXPWR}
9041 };
9042 
9043 static const struct rtw89_physts_regs rtw89_physts_regs_ax = {
9044 	.setting_addr = R_PLCP_HISTOGRAM,
9045 	.dis_trigger_fail_mask = B_STS_DIS_TRIG_BY_FAIL,
9046 	.dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK,
9047 	.mac_phy_intf_sel = {R_INTF_R_INTF_RPT_SEL, B_INTF_R_INTF_RPT_SEL},
9048 	.txpwr = rtw89_txpwr_ax,
9049 	.tx_info = RTW89_REGS_DEF(rtw89_txinfo_reg_ax),
9050 	.tx_common_ctrl = RTW89_REGS_DEF(rtw89_tx_common_ctrl_reg_ax),
9051 };
9052 
9053 static const struct rtw89_cfo_regs rtw89_cfo_regs_ax = {
9054 	.comp = R_DCFO_WEIGHT,
9055 	.weighting_mask = B_DCFO_WEIGHT_MSK,
9056 	.comp_seg0 = R_DCFO_OPT,
9057 	.valid_0_mask = B_DCFO_OPT_EN,
9058 };
9059 
9060 const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
9061 	.cr_base = 0x10000,
9062 	.physt_bmp_start = R_PHY_STS_BITMAP_ADDR_START,
9063 	.physt_bmp_eht = 0xfc,
9064 	.physt_ie_len = {16, 32, 24, 24, 8, 8, 8, 8, VAR_LEN, 8, VAR_LEN, 176, VAR_LEN,
9065 			 VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, VAR_LEN, 16, 24, VAR_LEN,
9066 			 VAR_LEN, VAR_LEN, 0, 24, 24, 24, 24, 32, 32, 32, 32},
9067 	.physt_gen = 0,
9068 	.ccx = &rtw89_ccx_regs_ax,
9069 	.physts = &rtw89_physts_regs_ax,
9070 	.cfo = &rtw89_cfo_regs_ax,
9071 	.bb_wrap = NULL,
9072 	.nctl = NULL,
9073 	.phy0_phy1_offset = rtw89_phy0_phy1_offset_ax,
9074 	.config_bb_gain = rtw89_phy_config_bb_gain_ax,
9075 	.preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_ax,
9076 	.bb_wrap_init = NULL,
9077 	.ch_info_init = NULL,
9078 
9079 	.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_ax,
9080 	.set_txpwr_offset = rtw89_phy_set_txpwr_offset_ax,
9081 	.set_txpwr_limit = rtw89_phy_set_txpwr_limit_ax,
9082 	.set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_ax,
9083 };
9084 EXPORT_SYMBOL(rtw89_phy_gen_ax);
9085