xref: /freebsd/sys/contrib/dev/rtw89/phy.c (revision 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75)
18e93258fSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
28e93258fSBjoern A. Zeeb /* Copyright(c) 2019-2020  Realtek Corporation
38e93258fSBjoern A. Zeeb  */
48e93258fSBjoern A. Zeeb 
5*6d67aabdSBjoern A. Zeeb #include "chan.h"
6e2340276SBjoern A. Zeeb #include "coex.h"
78e93258fSBjoern A. Zeeb #include "debug.h"
88e93258fSBjoern A. Zeeb #include "fw.h"
98e93258fSBjoern A. Zeeb #include "mac.h"
108e93258fSBjoern A. Zeeb #include "phy.h"
118e93258fSBjoern A. Zeeb #include "ps.h"
128e93258fSBjoern A. Zeeb #include "reg.h"
138e93258fSBjoern A. Zeeb #include "sar.h"
14e2340276SBjoern A. Zeeb #include "txrx.h"
15e2340276SBjoern A. Zeeb #include "util.h"
168e93258fSBjoern A. Zeeb 
17*6d67aabdSBjoern A. Zeeb static u32 rtw89_phy0_phy1_offset(struct rtw89_dev *rtwdev, u32 addr)
18*6d67aabdSBjoern A. Zeeb {
19*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
20*6d67aabdSBjoern A. Zeeb 
21*6d67aabdSBjoern A. Zeeb 	return phy->phy0_phy1_offset(rtwdev, addr);
22*6d67aabdSBjoern A. Zeeb }
23*6d67aabdSBjoern A. Zeeb 
248e93258fSBjoern A. Zeeb static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev,
258e93258fSBjoern A. Zeeb 			     const struct rtw89_ra_report *report)
268e93258fSBjoern A. Zeeb {
278e93258fSBjoern A. Zeeb 	u32 bit_rate = report->bit_rate;
288e93258fSBjoern A. Zeeb 
298e93258fSBjoern A. Zeeb 	/* lower than ofdm, do not aggregate */
308e93258fSBjoern A. Zeeb 	if (bit_rate < 550)
318e93258fSBjoern A. Zeeb 		return 1;
328e93258fSBjoern A. Zeeb 
338e93258fSBjoern A. Zeeb 	/* avoid AMSDU for legacy rate */
348e93258fSBjoern A. Zeeb 	if (report->might_fallback_legacy)
358e93258fSBjoern A. Zeeb 		return 1;
368e93258fSBjoern A. Zeeb 
378e93258fSBjoern A. Zeeb 	/* lower than 20M vht 2ss mcs8, make it small */
388e93258fSBjoern A. Zeeb 	if (bit_rate < 1800)
398e93258fSBjoern A. Zeeb 		return 1200;
408e93258fSBjoern A. Zeeb 
418e93258fSBjoern A. Zeeb 	/* lower than 40M vht 2ss mcs9, make it medium */
428e93258fSBjoern A. Zeeb 	if (bit_rate < 4000)
438e93258fSBjoern A. Zeeb 		return 2600;
448e93258fSBjoern A. Zeeb 
458e93258fSBjoern A. Zeeb 	/* not yet 80M vht 2ss mcs8/9, make it twice regular packet size */
468e93258fSBjoern A. Zeeb 	if (bit_rate < 7000)
478e93258fSBjoern A. Zeeb 		return 3500;
488e93258fSBjoern A. Zeeb 
498e93258fSBjoern A. Zeeb 	return rtwdev->chip->max_amsdu_limit;
508e93258fSBjoern A. Zeeb }
518e93258fSBjoern A. Zeeb 
528e93258fSBjoern A. Zeeb static u64 get_mcs_ra_mask(u16 mcs_map, u8 highest_mcs, u8 gap)
538e93258fSBjoern A. Zeeb {
548e93258fSBjoern A. Zeeb 	u64 ra_mask = 0;
558e93258fSBjoern A. Zeeb 	u8 mcs_cap;
568e93258fSBjoern A. Zeeb 	int i, nss;
578e93258fSBjoern A. Zeeb 
588e93258fSBjoern A. Zeeb 	for (i = 0, nss = 12; i < 4; i++, mcs_map >>= 2, nss += 12) {
598e93258fSBjoern A. Zeeb 		mcs_cap = mcs_map & 0x3;
608e93258fSBjoern A. Zeeb 		switch (mcs_cap) {
618e93258fSBjoern A. Zeeb 		case 2:
628e93258fSBjoern A. Zeeb 			ra_mask |= GENMASK_ULL(highest_mcs, 0) << nss;
638e93258fSBjoern A. Zeeb 			break;
648e93258fSBjoern A. Zeeb 		case 1:
658e93258fSBjoern A. Zeeb 			ra_mask |= GENMASK_ULL(highest_mcs - gap, 0) << nss;
668e93258fSBjoern A. Zeeb 			break;
678e93258fSBjoern A. Zeeb 		case 0:
688e93258fSBjoern A. Zeeb 			ra_mask |= GENMASK_ULL(highest_mcs - gap * 2, 0) << nss;
698e93258fSBjoern A. Zeeb 			break;
708e93258fSBjoern A. Zeeb 		default:
718e93258fSBjoern A. Zeeb 			break;
728e93258fSBjoern A. Zeeb 		}
738e93258fSBjoern A. Zeeb 	}
748e93258fSBjoern A. Zeeb 
758e93258fSBjoern A. Zeeb 	return ra_mask;
768e93258fSBjoern A. Zeeb }
778e93258fSBjoern A. Zeeb 
788e93258fSBjoern A. Zeeb static u64 get_he_ra_mask(struct ieee80211_sta *sta)
798e93258fSBjoern A. Zeeb {
808e93258fSBjoern A. Zeeb 	struct ieee80211_sta_he_cap cap = sta->deflink.he_cap;
818e93258fSBjoern A. Zeeb 	u16 mcs_map;
828e93258fSBjoern A. Zeeb 
838e93258fSBjoern A. Zeeb 	switch (sta->deflink.bandwidth) {
848e93258fSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_160:
858e93258fSBjoern A. Zeeb 		if (cap.he_cap_elem.phy_cap_info[0] &
868e93258fSBjoern A. Zeeb 		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
878e93258fSBjoern A. Zeeb 			mcs_map = le16_to_cpu(cap.he_mcs_nss_supp.rx_mcs_80p80);
888e93258fSBjoern A. Zeeb 		else
898e93258fSBjoern A. Zeeb 			mcs_map = le16_to_cpu(cap.he_mcs_nss_supp.rx_mcs_160);
908e93258fSBjoern A. Zeeb 		break;
918e93258fSBjoern A. Zeeb 	default:
928e93258fSBjoern A. Zeeb 		mcs_map = le16_to_cpu(cap.he_mcs_nss_supp.rx_mcs_80);
938e93258fSBjoern A. Zeeb 	}
948e93258fSBjoern A. Zeeb 
958e93258fSBjoern A. Zeeb 	/* MCS11, MCS9, MCS7 */
968e93258fSBjoern A. Zeeb 	return get_mcs_ra_mask(mcs_map, 11, 2);
978e93258fSBjoern A. Zeeb }
988e93258fSBjoern A. Zeeb 
99*6d67aabdSBjoern A. Zeeb static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss)
100*6d67aabdSBjoern A. Zeeb {
101*6d67aabdSBjoern A. Zeeb 	u64 nss_mcs_shift;
102*6d67aabdSBjoern A. Zeeb 	u64 nss_mcs_val;
103*6d67aabdSBjoern A. Zeeb 	u64 mask = 0;
104*6d67aabdSBjoern A. Zeeb 	int i, j;
105*6d67aabdSBjoern A. Zeeb 	u8 nss;
106*6d67aabdSBjoern A. Zeeb 
107*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < n_nss; i++) {
108*6d67aabdSBjoern A. Zeeb 		nss = u8_get_bits(max_nss[i], IEEE80211_EHT_MCS_NSS_RX);
109*6d67aabdSBjoern A. Zeeb 		if (!nss)
110*6d67aabdSBjoern A. Zeeb 			continue;
111*6d67aabdSBjoern A. Zeeb 
112*6d67aabdSBjoern A. Zeeb 		nss_mcs_val = GENMASK_ULL(start_mcs + i * 2, 0);
113*6d67aabdSBjoern A. Zeeb 
114*6d67aabdSBjoern A. Zeeb 		for (j = 0, nss_mcs_shift = 12; j < nss; j++, nss_mcs_shift += 16)
115*6d67aabdSBjoern A. Zeeb 			mask |= nss_mcs_val << nss_mcs_shift;
116*6d67aabdSBjoern A. Zeeb 	}
117*6d67aabdSBjoern A. Zeeb 
118*6d67aabdSBjoern A. Zeeb 	return mask;
119*6d67aabdSBjoern A. Zeeb }
120*6d67aabdSBjoern A. Zeeb 
121*6d67aabdSBjoern A. Zeeb static u64 get_eht_ra_mask(struct ieee80211_sta *sta)
122*6d67aabdSBjoern A. Zeeb {
123*6d67aabdSBjoern A. Zeeb 	struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
124*6d67aabdSBjoern A. Zeeb 	struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz;
125*6d67aabdSBjoern A. Zeeb 	struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss;
126*6d67aabdSBjoern A. Zeeb 	u8 *he_phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info;
127*6d67aabdSBjoern A. Zeeb 
128*6d67aabdSBjoern A. Zeeb 	switch (sta->deflink.bandwidth) {
129*6d67aabdSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_320:
130*6d67aabdSBjoern A. Zeeb 		mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320;
131*6d67aabdSBjoern A. Zeeb 		/* MCS 9, 11, 13 */
132*6d67aabdSBjoern A. Zeeb 		return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
133*6d67aabdSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_160:
134*6d67aabdSBjoern A. Zeeb 		mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._160;
135*6d67aabdSBjoern A. Zeeb 		/* MCS 9, 11, 13 */
136*6d67aabdSBjoern A. Zeeb 		return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
137*6d67aabdSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_20:
138*6d67aabdSBjoern A. Zeeb 		if (!(he_phy_cap[0] &
139*6d67aabdSBjoern A. Zeeb 		      IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) {
140*6d67aabdSBjoern A. Zeeb 			mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz;
141*6d67aabdSBjoern A. Zeeb 			/* MCS 7, 9, 11, 13 */
142*6d67aabdSBjoern A. Zeeb 			return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4);
143*6d67aabdSBjoern A. Zeeb 		}
144*6d67aabdSBjoern A. Zeeb 		fallthrough;
145*6d67aabdSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_80:
146*6d67aabdSBjoern A. Zeeb 	default:
147*6d67aabdSBjoern A. Zeeb 		mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._80;
148*6d67aabdSBjoern A. Zeeb 		/* MCS 9, 11, 13 */
149*6d67aabdSBjoern A. Zeeb 		return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3);
150*6d67aabdSBjoern A. Zeeb 	}
151*6d67aabdSBjoern A. Zeeb }
152*6d67aabdSBjoern A. Zeeb 
1538e93258fSBjoern A. Zeeb #define RA_FLOOR_TABLE_SIZE	7
1548e93258fSBjoern A. Zeeb #define RA_FLOOR_UP_GAP		3
1558e93258fSBjoern A. Zeeb static u64 rtw89_phy_ra_mask_rssi(struct rtw89_dev *rtwdev, u8 rssi,
1568e93258fSBjoern A. Zeeb 				  u8 ratr_state)
1578e93258fSBjoern A. Zeeb {
1588e93258fSBjoern A. Zeeb 	u8 rssi_lv_t[RA_FLOOR_TABLE_SIZE] = {30, 44, 48, 52, 56, 60, 100};
1598e93258fSBjoern A. Zeeb 	u8 rssi_lv = 0;
1608e93258fSBjoern A. Zeeb 	u8 i;
1618e93258fSBjoern A. Zeeb 
1628e93258fSBjoern A. Zeeb 	rssi >>= 1;
1638e93258fSBjoern A. Zeeb 	for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) {
1648e93258fSBjoern A. Zeeb 		if (i >= ratr_state)
1658e93258fSBjoern A. Zeeb 			rssi_lv_t[i] += RA_FLOOR_UP_GAP;
1668e93258fSBjoern A. Zeeb 		if (rssi < rssi_lv_t[i]) {
1678e93258fSBjoern A. Zeeb 			rssi_lv = i;
1688e93258fSBjoern A. Zeeb 			break;
1698e93258fSBjoern A. Zeeb 		}
1708e93258fSBjoern A. Zeeb 	}
1718e93258fSBjoern A. Zeeb 	if (rssi_lv == 0)
1728e93258fSBjoern A. Zeeb 		return 0xffffffffffffffffULL;
1738e93258fSBjoern A. Zeeb 	else if (rssi_lv == 1)
1748e93258fSBjoern A. Zeeb 		return 0xfffffffffffffff0ULL;
1758e93258fSBjoern A. Zeeb 	else if (rssi_lv == 2)
1768e93258fSBjoern A. Zeeb 		return 0xffffffffffffefe0ULL;
1778e93258fSBjoern A. Zeeb 	else if (rssi_lv == 3)
1788e93258fSBjoern A. Zeeb 		return 0xffffffffffffcfc0ULL;
1798e93258fSBjoern A. Zeeb 	else if (rssi_lv == 4)
1808e93258fSBjoern A. Zeeb 		return 0xffffffffffff8f80ULL;
1818e93258fSBjoern A. Zeeb 	else if (rssi_lv >= 5)
1828e93258fSBjoern A. Zeeb 		return 0xffffffffffff0f00ULL;
1838e93258fSBjoern A. Zeeb 
1848e93258fSBjoern A. Zeeb 	return 0xffffffffffffffffULL;
1858e93258fSBjoern A. Zeeb }
1868e93258fSBjoern A. Zeeb 
1878e93258fSBjoern A. Zeeb static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak)
1888e93258fSBjoern A. Zeeb {
1898e93258fSBjoern A. Zeeb 	if ((ra_mask & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES)) == 0)
1908e93258fSBjoern A. Zeeb 		ra_mask |= (ra_mask_bak & ~(RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES));
1918e93258fSBjoern A. Zeeb 
1928e93258fSBjoern A. Zeeb 	if (ra_mask == 0)
1938e93258fSBjoern A. Zeeb 		ra_mask |= (ra_mask_bak & (RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES));
1948e93258fSBjoern A. Zeeb 
1958e93258fSBjoern A. Zeeb 	return ra_mask;
1968e93258fSBjoern A. Zeeb }
1978e93258fSBjoern A. Zeeb 
198*6d67aabdSBjoern A. Zeeb static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
199*6d67aabdSBjoern A. Zeeb 				 const struct rtw89_chan *chan)
2008e93258fSBjoern A. Zeeb {
2018e93258fSBjoern A. Zeeb 	struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
2028e93258fSBjoern A. Zeeb 	struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
2038e93258fSBjoern A. Zeeb 	enum nl80211_band band;
2048e93258fSBjoern A. Zeeb 	u64 cfg_mask;
2058e93258fSBjoern A. Zeeb 
2068e93258fSBjoern A. Zeeb 	if (!rtwsta->use_cfg_mask)
2078e93258fSBjoern A. Zeeb 		return -1;
2088e93258fSBjoern A. Zeeb 
2098e93258fSBjoern A. Zeeb 	switch (chan->band_type) {
2108e93258fSBjoern A. Zeeb 	case RTW89_BAND_2G:
2118e93258fSBjoern A. Zeeb 		band = NL80211_BAND_2GHZ;
2128e93258fSBjoern A. Zeeb 		cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_2GHZ].legacy,
2138e93258fSBjoern A. Zeeb 					   RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES);
2148e93258fSBjoern A. Zeeb 		break;
2158e93258fSBjoern A. Zeeb 	case RTW89_BAND_5G:
2168e93258fSBjoern A. Zeeb 		band = NL80211_BAND_5GHZ;
2178e93258fSBjoern A. Zeeb 		cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_5GHZ].legacy,
2188e93258fSBjoern A. Zeeb 					   RA_MASK_OFDM_RATES);
2198e93258fSBjoern A. Zeeb 		break;
2208e93258fSBjoern A. Zeeb 	case RTW89_BAND_6G:
2218e93258fSBjoern A. Zeeb 		band = NL80211_BAND_6GHZ;
2228e93258fSBjoern A. Zeeb 		cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_6GHZ].legacy,
2238e93258fSBjoern A. Zeeb 					   RA_MASK_OFDM_RATES);
2248e93258fSBjoern A. Zeeb 		break;
2258e93258fSBjoern A. Zeeb 	default:
2268e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "unhandled band type %d\n", chan->band_type);
2278e93258fSBjoern A. Zeeb 		return -1;
2288e93258fSBjoern A. Zeeb 	}
2298e93258fSBjoern A. Zeeb 
2308e93258fSBjoern A. Zeeb 	if (sta->deflink.he_cap.has_he) {
2318e93258fSBjoern A. Zeeb 		cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[0],
2328e93258fSBjoern A. Zeeb 					    RA_MASK_HE_1SS_RATES);
2338e93258fSBjoern A. Zeeb 		cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[1],
2348e93258fSBjoern A. Zeeb 					    RA_MASK_HE_2SS_RATES);
2358e93258fSBjoern A. Zeeb 	} else if (sta->deflink.vht_cap.vht_supported) {
2368e93258fSBjoern A. Zeeb 		cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0],
2378e93258fSBjoern A. Zeeb 					    RA_MASK_VHT_1SS_RATES);
2388e93258fSBjoern A. Zeeb 		cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1],
2398e93258fSBjoern A. Zeeb 					    RA_MASK_VHT_2SS_RATES);
2408e93258fSBjoern A. Zeeb 	} else if (sta->deflink.ht_cap.ht_supported) {
2418e93258fSBjoern A. Zeeb 		cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0],
2428e93258fSBjoern A. Zeeb 					    RA_MASK_HT_1SS_RATES);
2438e93258fSBjoern A. Zeeb 		cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1],
2448e93258fSBjoern A. Zeeb 					    RA_MASK_HT_2SS_RATES);
2458e93258fSBjoern A. Zeeb 	}
2468e93258fSBjoern A. Zeeb 
2478e93258fSBjoern A. Zeeb 	return cfg_mask;
2488e93258fSBjoern A. Zeeb }
2498e93258fSBjoern A. Zeeb 
2508e93258fSBjoern A. Zeeb static const u64
2518e93258fSBjoern A. Zeeb rtw89_ra_mask_ht_rates[4] = {RA_MASK_HT_1SS_RATES, RA_MASK_HT_2SS_RATES,
2528e93258fSBjoern A. Zeeb 			     RA_MASK_HT_3SS_RATES, RA_MASK_HT_4SS_RATES};
2538e93258fSBjoern A. Zeeb static const u64
2548e93258fSBjoern A. Zeeb rtw89_ra_mask_vht_rates[4] = {RA_MASK_VHT_1SS_RATES, RA_MASK_VHT_2SS_RATES,
2558e93258fSBjoern A. Zeeb 			      RA_MASK_VHT_3SS_RATES, RA_MASK_VHT_4SS_RATES};
2568e93258fSBjoern A. Zeeb static const u64
2578e93258fSBjoern A. Zeeb rtw89_ra_mask_he_rates[4] = {RA_MASK_HE_1SS_RATES, RA_MASK_HE_2SS_RATES,
2588e93258fSBjoern A. Zeeb 			     RA_MASK_HE_3SS_RATES, RA_MASK_HE_4SS_RATES};
259*6d67aabdSBjoern A. Zeeb static const u64
260*6d67aabdSBjoern A. Zeeb rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES,
261*6d67aabdSBjoern A. Zeeb 			      RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES};
2628e93258fSBjoern A. Zeeb 
263e2340276SBjoern A. Zeeb static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
264e2340276SBjoern A. Zeeb 				struct rtw89_sta *rtwsta,
265*6d67aabdSBjoern A. Zeeb 				const struct rtw89_chan *chan,
266e2340276SBjoern A. Zeeb 				bool *fix_giltf_en, u8 *fix_giltf)
267e2340276SBjoern A. Zeeb {
268e2340276SBjoern A. Zeeb 	struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
269e2340276SBjoern A. Zeeb 	u8 band = chan->band_type;
270e2340276SBjoern A. Zeeb 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
271e2340276SBjoern A. Zeeb 	u8 he_gi = mask->control[nl_band].he_gi;
272e2340276SBjoern A. Zeeb 	u8 he_ltf = mask->control[nl_band].he_ltf;
273e2340276SBjoern A. Zeeb 
274e2340276SBjoern A. Zeeb 	if (!rtwsta->use_cfg_mask)
275e2340276SBjoern A. Zeeb 		return;
276e2340276SBjoern A. Zeeb 
277e2340276SBjoern A. Zeeb 	if (he_ltf == 2 && he_gi == 2) {
278e2340276SBjoern A. Zeeb 		*fix_giltf = RTW89_GILTF_LGI_4XHE32;
279e2340276SBjoern A. Zeeb 	} else if (he_ltf == 2 && he_gi == 0) {
280e2340276SBjoern A. Zeeb 		*fix_giltf = RTW89_GILTF_SGI_4XHE08;
281e2340276SBjoern A. Zeeb 	} else if (he_ltf == 1 && he_gi == 1) {
282e2340276SBjoern A. Zeeb 		*fix_giltf = RTW89_GILTF_2XHE16;
283e2340276SBjoern A. Zeeb 	} else if (he_ltf == 1 && he_gi == 0) {
284e2340276SBjoern A. Zeeb 		*fix_giltf = RTW89_GILTF_2XHE08;
285e2340276SBjoern A. Zeeb 	} else if (he_ltf == 0 && he_gi == 1) {
286e2340276SBjoern A. Zeeb 		*fix_giltf = RTW89_GILTF_1XHE16;
287e2340276SBjoern A. Zeeb 	} else if (he_ltf == 0 && he_gi == 0) {
288e2340276SBjoern A. Zeeb 		*fix_giltf = RTW89_GILTF_1XHE08;
289e2340276SBjoern A. Zeeb 	} else {
290e2340276SBjoern A. Zeeb 		*fix_giltf_en = false;
291e2340276SBjoern A. Zeeb 		return;
292e2340276SBjoern A. Zeeb 	}
293e2340276SBjoern A. Zeeb 
294e2340276SBjoern A. Zeeb 	*fix_giltf_en = true;
295e2340276SBjoern A. Zeeb }
296e2340276SBjoern A. Zeeb 
2978e93258fSBjoern A. Zeeb static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
2988e93258fSBjoern A. Zeeb 				    struct ieee80211_sta *sta, bool csi)
2998e93258fSBjoern A. Zeeb {
3008e93258fSBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
3018e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
3028e93258fSBjoern A. Zeeb 	struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
3038e93258fSBjoern A. Zeeb 	struct rtw89_ra_info *ra = &rtwsta->ra;
304*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
305*6d67aabdSBjoern A. Zeeb 						       rtwvif->sub_entity_idx);
306e2340276SBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif);
3078e93258fSBjoern A. Zeeb 	const u64 *high_rate_masks = rtw89_ra_mask_ht_rates;
3088e93258fSBjoern A. Zeeb 	u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi);
3098e93258fSBjoern A. Zeeb 	u64 ra_mask = 0;
3108e93258fSBjoern A. Zeeb 	u64 ra_mask_bak;
3118e93258fSBjoern A. Zeeb 	u8 mode = 0;
3128e93258fSBjoern A. Zeeb 	u8 csi_mode = RTW89_RA_RPT_MODE_LEGACY;
3138e93258fSBjoern A. Zeeb 	u8 bw_mode = 0;
3148e93258fSBjoern A. Zeeb 	u8 stbc_en = 0;
3158e93258fSBjoern A. Zeeb 	u8 ldpc_en = 0;
316e2340276SBjoern A. Zeeb 	u8 fix_giltf = 0;
3178e93258fSBjoern A. Zeeb 	u8 i;
3188e93258fSBjoern A. Zeeb 	bool sgi = false;
319e2340276SBjoern A. Zeeb 	bool fix_giltf_en = false;
3208e93258fSBjoern A. Zeeb 
3218e93258fSBjoern A. Zeeb 	memset(ra, 0, sizeof(*ra));
3228e93258fSBjoern A. Zeeb 	/* Set the ra mask from sta's capability */
323*6d67aabdSBjoern A. Zeeb 	if (sta->deflink.eht_cap.has_eht) {
324*6d67aabdSBjoern A. Zeeb 		mode |= RTW89_RA_MODE_EHT;
325*6d67aabdSBjoern A. Zeeb 		ra_mask |= get_eht_ra_mask(sta);
326*6d67aabdSBjoern A. Zeeb 		high_rate_masks = rtw89_ra_mask_eht_rates;
327*6d67aabdSBjoern A. Zeeb 	} else if (sta->deflink.he_cap.has_he) {
3288e93258fSBjoern A. Zeeb 		mode |= RTW89_RA_MODE_HE;
3298e93258fSBjoern A. Zeeb 		csi_mode = RTW89_RA_RPT_MODE_HE;
3308e93258fSBjoern A. Zeeb 		ra_mask |= get_he_ra_mask(sta);
3318e93258fSBjoern A. Zeeb 		high_rate_masks = rtw89_ra_mask_he_rates;
3328e93258fSBjoern A. Zeeb 		if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[2] &
3338e93258fSBjoern A. Zeeb 		    IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
3348e93258fSBjoern A. Zeeb 			stbc_en = 1;
3358e93258fSBjoern A. Zeeb 		if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] &
3368e93258fSBjoern A. Zeeb 		    IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
3378e93258fSBjoern A. Zeeb 			ldpc_en = 1;
338*6d67aabdSBjoern A. Zeeb 		rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, chan, &fix_giltf_en, &fix_giltf);
3398e93258fSBjoern A. Zeeb 	} else if (sta->deflink.vht_cap.vht_supported) {
3408e93258fSBjoern A. Zeeb 		u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
3418e93258fSBjoern A. Zeeb 
3428e93258fSBjoern A. Zeeb 		mode |= RTW89_RA_MODE_VHT;
3438e93258fSBjoern A. Zeeb 		csi_mode = RTW89_RA_RPT_MODE_VHT;
3448e93258fSBjoern A. Zeeb 		/* MCS9, MCS8, MCS7 */
3458e93258fSBjoern A. Zeeb 		ra_mask |= get_mcs_ra_mask(mcs_map, 9, 1);
3468e93258fSBjoern A. Zeeb 		high_rate_masks = rtw89_ra_mask_vht_rates;
3478e93258fSBjoern A. Zeeb 		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
3488e93258fSBjoern A. Zeeb 			stbc_en = 1;
3498e93258fSBjoern A. Zeeb 		if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
3508e93258fSBjoern A. Zeeb 			ldpc_en = 1;
3518e93258fSBjoern A. Zeeb 	} else if (sta->deflink.ht_cap.ht_supported) {
3528e93258fSBjoern A. Zeeb 		mode |= RTW89_RA_MODE_HT;
3538e93258fSBjoern A. Zeeb 		csi_mode = RTW89_RA_RPT_MODE_HT;
3548e93258fSBjoern A. Zeeb 		ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 48) |
3558e93258fSBjoern A. Zeeb 			   ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 36) |
3568e93258fSBjoern A. Zeeb 			   (sta->deflink.ht_cap.mcs.rx_mask[1] << 24) |
3578e93258fSBjoern A. Zeeb 			   (sta->deflink.ht_cap.mcs.rx_mask[0] << 12);
3588e93258fSBjoern A. Zeeb 		high_rate_masks = rtw89_ra_mask_ht_rates;
3598e93258fSBjoern A. Zeeb 		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
3608e93258fSBjoern A. Zeeb 			stbc_en = 1;
3618e93258fSBjoern A. Zeeb 		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
3628e93258fSBjoern A. Zeeb 			ldpc_en = 1;
3638e93258fSBjoern A. Zeeb 	}
3648e93258fSBjoern A. Zeeb 
3658e93258fSBjoern A. Zeeb 	switch (chan->band_type) {
3668e93258fSBjoern A. Zeeb 	case RTW89_BAND_2G:
3678e93258fSBjoern A. Zeeb 		ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ];
368e2340276SBjoern A. Zeeb 		if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xf)
3698e93258fSBjoern A. Zeeb 			mode |= RTW89_RA_MODE_CCK;
370e2340276SBjoern A. Zeeb 		if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xff0)
371e2340276SBjoern A. Zeeb 			mode |= RTW89_RA_MODE_OFDM;
3728e93258fSBjoern A. Zeeb 		break;
3738e93258fSBjoern A. Zeeb 	case RTW89_BAND_5G:
3748e93258fSBjoern A. Zeeb 		ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4;
3758e93258fSBjoern A. Zeeb 		mode |= RTW89_RA_MODE_OFDM;
3768e93258fSBjoern A. Zeeb 		break;
3778e93258fSBjoern A. Zeeb 	case RTW89_BAND_6G:
3788e93258fSBjoern A. Zeeb 		ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_6GHZ] << 4;
3798e93258fSBjoern A. Zeeb 		mode |= RTW89_RA_MODE_OFDM;
3808e93258fSBjoern A. Zeeb 		break;
3818e93258fSBjoern A. Zeeb 	default:
3828e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "Unknown band type\n");
3838e93258fSBjoern A. Zeeb 		break;
3848e93258fSBjoern A. Zeeb 	}
3858e93258fSBjoern A. Zeeb 
3868e93258fSBjoern A. Zeeb 	ra_mask_bak = ra_mask;
3878e93258fSBjoern A. Zeeb 
3888e93258fSBjoern A. Zeeb 	if (mode >= RTW89_RA_MODE_HT) {
3898e93258fSBjoern A. Zeeb 		u64 mask = 0;
3908e93258fSBjoern A. Zeeb 		for (i = 0; i < rtwdev->hal.tx_nss; i++)
3918e93258fSBjoern A. Zeeb 			mask |= high_rate_masks[i];
3928e93258fSBjoern A. Zeeb 		if (mode & RTW89_RA_MODE_OFDM)
3938e93258fSBjoern A. Zeeb 			mask |= RA_MASK_SUBOFDM_RATES;
3948e93258fSBjoern A. Zeeb 		if (mode & RTW89_RA_MODE_CCK)
3958e93258fSBjoern A. Zeeb 			mask |= RA_MASK_SUBCCK_RATES;
3968e93258fSBjoern A. Zeeb 		ra_mask &= mask;
3978e93258fSBjoern A. Zeeb 	} else if (mode & RTW89_RA_MODE_OFDM) {
3988e93258fSBjoern A. Zeeb 		ra_mask &= (RA_MASK_OFDM_RATES | RA_MASK_SUBCCK_RATES);
3998e93258fSBjoern A. Zeeb 	}
4008e93258fSBjoern A. Zeeb 
4018e93258fSBjoern A. Zeeb 	if (mode != RTW89_RA_MODE_CCK)
4028e93258fSBjoern A. Zeeb 		ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0);
4038e93258fSBjoern A. Zeeb 
4048e93258fSBjoern A. Zeeb 	ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak);
405*6d67aabdSBjoern A. Zeeb 	ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan);
4068e93258fSBjoern A. Zeeb 
4078e93258fSBjoern A. Zeeb 	switch (sta->deflink.bandwidth) {
4088e93258fSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_160:
4098e93258fSBjoern A. Zeeb 		bw_mode = RTW89_CHANNEL_WIDTH_160;
4108e93258fSBjoern A. Zeeb 		sgi = sta->deflink.vht_cap.vht_supported &&
4118e93258fSBjoern A. Zeeb 		      (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160);
4128e93258fSBjoern A. Zeeb 		break;
4138e93258fSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_80:
4148e93258fSBjoern A. Zeeb 		bw_mode = RTW89_CHANNEL_WIDTH_80;
4158e93258fSBjoern A. Zeeb 		sgi = sta->deflink.vht_cap.vht_supported &&
4168e93258fSBjoern A. Zeeb 		      (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
4178e93258fSBjoern A. Zeeb 		break;
4188e93258fSBjoern A. Zeeb 	case IEEE80211_STA_RX_BW_40:
4198e93258fSBjoern A. Zeeb 		bw_mode = RTW89_CHANNEL_WIDTH_40;
4208e93258fSBjoern A. Zeeb 		sgi = sta->deflink.ht_cap.ht_supported &&
4218e93258fSBjoern A. Zeeb 		      (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
4228e93258fSBjoern A. Zeeb 		break;
4238e93258fSBjoern A. Zeeb 	default:
4248e93258fSBjoern A. Zeeb 		bw_mode = RTW89_CHANNEL_WIDTH_20;
4258e93258fSBjoern A. Zeeb 		sgi = sta->deflink.ht_cap.ht_supported &&
4268e93258fSBjoern A. Zeeb 		      (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
4278e93258fSBjoern A. Zeeb 		break;
4288e93258fSBjoern A. Zeeb 	}
4298e93258fSBjoern A. Zeeb 
4308e93258fSBjoern A. Zeeb 	if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] &
4318e93258fSBjoern A. Zeeb 	    IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM)
4328e93258fSBjoern A. Zeeb 		ra->dcm_cap = 1;
4338e93258fSBjoern A. Zeeb 
434e2340276SBjoern A. Zeeb 	if (rate_pattern->enable && !vif->p2p) {
435*6d67aabdSBjoern A. Zeeb 		ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan);
4368e93258fSBjoern A. Zeeb 		ra_mask &= rate_pattern->ra_mask;
4378e93258fSBjoern A. Zeeb 		mode = rate_pattern->ra_mode;
4388e93258fSBjoern A. Zeeb 	}
4398e93258fSBjoern A. Zeeb 
4408e93258fSBjoern A. Zeeb 	ra->bw_cap = bw_mode;
441e2340276SBjoern A. Zeeb 	ra->er_cap = rtwsta->er_cap;
4428e93258fSBjoern A. Zeeb 	ra->mode_ctrl = mode;
4438e93258fSBjoern A. Zeeb 	ra->macid = rtwsta->mac_id;
4448e93258fSBjoern A. Zeeb 	ra->stbc_cap = stbc_en;
4458e93258fSBjoern A. Zeeb 	ra->ldpc_cap = ldpc_en;
4468e93258fSBjoern A. Zeeb 	ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
4478e93258fSBjoern A. Zeeb 	ra->en_sgi = sgi;
4488e93258fSBjoern A. Zeeb 	ra->ra_mask = ra_mask;
449e2340276SBjoern A. Zeeb 	ra->fix_giltf_en = fix_giltf_en;
450e2340276SBjoern A. Zeeb 	ra->fix_giltf = fix_giltf;
4518e93258fSBjoern A. Zeeb 
4528e93258fSBjoern A. Zeeb 	if (!csi)
4538e93258fSBjoern A. Zeeb 		return;
4548e93258fSBjoern A. Zeeb 
4558e93258fSBjoern A. Zeeb 	ra->fixed_csi_rate_en = false;
4568e93258fSBjoern A. Zeeb 	ra->ra_csi_rate_en = true;
4578e93258fSBjoern A. Zeeb 	ra->cr_tbl_sel = false;
4588e93258fSBjoern A. Zeeb 	ra->band_num = rtwvif->phy_idx;
4598e93258fSBjoern A. Zeeb 	ra->csi_bw = bw_mode;
4608e93258fSBjoern A. Zeeb 	ra->csi_gi_ltf = RTW89_GILTF_LGI_4XHE32;
4618e93258fSBjoern A. Zeeb 	ra->csi_mcs_ss_idx = 5;
4628e93258fSBjoern A. Zeeb 	ra->csi_mode = csi_mode;
4638e93258fSBjoern A. Zeeb }
4648e93258fSBjoern A. Zeeb 
4658e93258fSBjoern A. Zeeb void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
4668e93258fSBjoern A. Zeeb 			     u32 changed)
4678e93258fSBjoern A. Zeeb {
4688e93258fSBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
4698e93258fSBjoern A. Zeeb 	struct rtw89_ra_info *ra = &rtwsta->ra;
4708e93258fSBjoern A. Zeeb 
4718e93258fSBjoern A. Zeeb 	rtw89_phy_ra_sta_update(rtwdev, sta, false);
4728e93258fSBjoern A. Zeeb 
4738e93258fSBjoern A. Zeeb 	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED)
4748e93258fSBjoern A. Zeeb 		ra->upd_mask = 1;
4758e93258fSBjoern A. Zeeb 	if (changed & (IEEE80211_RC_BW_CHANGED | IEEE80211_RC_NSS_CHANGED))
4768e93258fSBjoern A. Zeeb 		ra->upd_bw_nss_mask = 1;
4778e93258fSBjoern A. Zeeb 
4788e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RA,
4798e93258fSBjoern A. Zeeb 		    "ra updat: macid = %d, bw = %d, nss = %d, gi = %d %d",
4808e93258fSBjoern A. Zeeb 		    ra->macid,
4818e93258fSBjoern A. Zeeb 		    ra->bw_cap,
4828e93258fSBjoern A. Zeeb 		    ra->ss_num,
4838e93258fSBjoern A. Zeeb 		    ra->en_sgi,
4848e93258fSBjoern A. Zeeb 		    ra->giltf);
4858e93258fSBjoern A. Zeeb 
4868e93258fSBjoern A. Zeeb 	rtw89_fw_h2c_ra(rtwdev, ra, false);
4878e93258fSBjoern A. Zeeb }
4888e93258fSBjoern A. Zeeb 
4898e93258fSBjoern A. Zeeb static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next,
4908e93258fSBjoern A. Zeeb 				 u16 rate_base, u64 ra_mask, u8 ra_mode,
4918e93258fSBjoern A. Zeeb 				 u32 rate_ctrl, u32 ctrl_skip, bool force)
4928e93258fSBjoern A. Zeeb {
4938e93258fSBjoern A. Zeeb 	u8 n, c;
4948e93258fSBjoern A. Zeeb 
4958e93258fSBjoern A. Zeeb 	if (rate_ctrl == ctrl_skip)
4968e93258fSBjoern A. Zeeb 		return true;
4978e93258fSBjoern A. Zeeb 
4988e93258fSBjoern A. Zeeb 	n = hweight32(rate_ctrl);
4998e93258fSBjoern A. Zeeb 	if (n == 0)
5008e93258fSBjoern A. Zeeb 		return true;
5018e93258fSBjoern A. Zeeb 
5028e93258fSBjoern A. Zeeb 	if (force && n != 1)
5038e93258fSBjoern A. Zeeb 		return false;
5048e93258fSBjoern A. Zeeb 
5058e93258fSBjoern A. Zeeb 	if (next->enable)
5068e93258fSBjoern A. Zeeb 		return false;
5078e93258fSBjoern A. Zeeb 
5088e93258fSBjoern A. Zeeb 	c = __fls(rate_ctrl);
5098e93258fSBjoern A. Zeeb 	next->rate = rate_base + c;
5108e93258fSBjoern A. Zeeb 	next->ra_mode = ra_mode;
5118e93258fSBjoern A. Zeeb 	next->ra_mask = ra_mask;
5128e93258fSBjoern A. Zeeb 	next->enable = true;
5138e93258fSBjoern A. Zeeb 
5148e93258fSBjoern A. Zeeb 	return true;
5158e93258fSBjoern A. Zeeb }
5168e93258fSBjoern A. Zeeb 
517e2340276SBjoern A. Zeeb #define RTW89_HW_RATE_BY_CHIP_GEN(rate) \
518e2340276SBjoern A. Zeeb 	{ \
519e2340276SBjoern A. Zeeb 		[RTW89_CHIP_AX] = RTW89_HW_RATE_ ## rate, \
520e2340276SBjoern A. Zeeb 		[RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \
521e2340276SBjoern A. Zeeb 	}
522e2340276SBjoern A. Zeeb 
5238e93258fSBjoern A. Zeeb void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
5248e93258fSBjoern A. Zeeb 				struct ieee80211_vif *vif,
5258e93258fSBjoern A. Zeeb 				const struct cfg80211_bitrate_mask *mask)
5268e93258fSBjoern A. Zeeb {
5278e93258fSBjoern A. Zeeb 	struct ieee80211_supported_band *sband;
5288e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
5298e93258fSBjoern A. Zeeb 	struct rtw89_phy_rate_pattern next_pattern = {0};
530*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
531*6d67aabdSBjoern A. Zeeb 						       rtwvif->sub_entity_idx);
532e2340276SBjoern A. Zeeb 	static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = {
533e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0),
534e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0),
535e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS3_MCS0),
536e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS4_MCS0),
537e2340276SBjoern A. Zeeb 	};
538e2340276SBjoern A. Zeeb 	static const u16 hw_rate_vht[][RTW89_CHIP_GEN_NUM] = {
539e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS1_MCS0),
540e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS2_MCS0),
541e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS3_MCS0),
542e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS4_MCS0),
543e2340276SBjoern A. Zeeb 	};
544e2340276SBjoern A. Zeeb 	static const u16 hw_rate_ht[][RTW89_CHIP_GEN_NUM] = {
545e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(MCS0),
546e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(MCS8),
547e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(MCS16),
548e2340276SBjoern A. Zeeb 		RTW89_HW_RATE_BY_CHIP_GEN(MCS24),
549e2340276SBjoern A. Zeeb 	};
5508e93258fSBjoern A. Zeeb 	u8 band = chan->band_type;
5518e93258fSBjoern A. Zeeb 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
552e2340276SBjoern A. Zeeb 	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
5538e93258fSBjoern A. Zeeb 	u8 tx_nss = rtwdev->hal.tx_nss;
5548e93258fSBjoern A. Zeeb 	u8 i;
5558e93258fSBjoern A. Zeeb 
5568e93258fSBjoern A. Zeeb 	for (i = 0; i < tx_nss; i++)
557e2340276SBjoern A. Zeeb 		if (!__check_rate_pattern(&next_pattern, hw_rate_he[i][chip_gen],
5588e93258fSBjoern A. Zeeb 					  RA_MASK_HE_RATES, RTW89_RA_MODE_HE,
5598e93258fSBjoern A. Zeeb 					  mask->control[nl_band].he_mcs[i],
5608e93258fSBjoern A. Zeeb 					  0, true))
5618e93258fSBjoern A. Zeeb 			goto out;
5628e93258fSBjoern A. Zeeb 
5638e93258fSBjoern A. Zeeb 	for (i = 0; i < tx_nss; i++)
564e2340276SBjoern A. Zeeb 		if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i][chip_gen],
5658e93258fSBjoern A. Zeeb 					  RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT,
5668e93258fSBjoern A. Zeeb 					  mask->control[nl_band].vht_mcs[i],
5678e93258fSBjoern A. Zeeb 					  0, true))
5688e93258fSBjoern A. Zeeb 			goto out;
5698e93258fSBjoern A. Zeeb 
5708e93258fSBjoern A. Zeeb 	for (i = 0; i < tx_nss; i++)
571e2340276SBjoern A. Zeeb 		if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i][chip_gen],
5728e93258fSBjoern A. Zeeb 					  RA_MASK_HT_RATES, RTW89_RA_MODE_HT,
5738e93258fSBjoern A. Zeeb 					  mask->control[nl_band].ht_mcs[i],
5748e93258fSBjoern A. Zeeb 					  0, true))
5758e93258fSBjoern A. Zeeb 			goto out;
5768e93258fSBjoern A. Zeeb 
5778e93258fSBjoern A. Zeeb 	/* lagacy cannot be empty for nl80211_parse_tx_bitrate_mask, and
5788e93258fSBjoern A. Zeeb 	 * require at least one basic rate for ieee80211_set_bitrate_mask,
5798e93258fSBjoern A. Zeeb 	 * so the decision just depends on if all bitrates are set or not.
5808e93258fSBjoern A. Zeeb 	 */
5818e93258fSBjoern A. Zeeb 	sband = rtwdev->hw->wiphy->bands[nl_band];
5828e93258fSBjoern A. Zeeb 	if (band == RTW89_BAND_2G) {
5838e93258fSBjoern A. Zeeb 		if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_CCK1,
5848e93258fSBjoern A. Zeeb 					  RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES,
5858e93258fSBjoern A. Zeeb 					  RTW89_RA_MODE_CCK | RTW89_RA_MODE_OFDM,
5868e93258fSBjoern A. Zeeb 					  mask->control[nl_band].legacy,
5878e93258fSBjoern A. Zeeb 					  BIT(sband->n_bitrates) - 1, false))
5888e93258fSBjoern A. Zeeb 			goto out;
5898e93258fSBjoern A. Zeeb 	} else {
5908e93258fSBjoern A. Zeeb 		if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_OFDM6,
5918e93258fSBjoern A. Zeeb 					  RA_MASK_OFDM_RATES, RTW89_RA_MODE_OFDM,
5928e93258fSBjoern A. Zeeb 					  mask->control[nl_band].legacy,
5938e93258fSBjoern A. Zeeb 					  BIT(sband->n_bitrates) - 1, false))
5948e93258fSBjoern A. Zeeb 			goto out;
5958e93258fSBjoern A. Zeeb 	}
5968e93258fSBjoern A. Zeeb 
5978e93258fSBjoern A. Zeeb 	if (!next_pattern.enable)
5988e93258fSBjoern A. Zeeb 		goto out;
5998e93258fSBjoern A. Zeeb 
6008e93258fSBjoern A. Zeeb 	rtwvif->rate_pattern = next_pattern;
6018e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RA,
6028e93258fSBjoern A. Zeeb #if defined(__linux__)
6038e93258fSBjoern A. Zeeb 		    "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n",
6048e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__)
6058e93258fSBjoern A. Zeeb 		    "configure pattern: rate 0x%x, mask 0x%jx, mode 0x%x\n",
6068e93258fSBjoern A. Zeeb #endif
6078e93258fSBjoern A. Zeeb 		    next_pattern.rate,
6088e93258fSBjoern A. Zeeb #if defined(__FreeBSD__)
6098e93258fSBjoern A. Zeeb 		    (uintmax_t)
6108e93258fSBjoern A. Zeeb #endif
6118e93258fSBjoern A. Zeeb 		    next_pattern.ra_mask,
6128e93258fSBjoern A. Zeeb 		    next_pattern.ra_mode);
6138e93258fSBjoern A. Zeeb 	return;
6148e93258fSBjoern A. Zeeb 
6158e93258fSBjoern A. Zeeb out:
6168e93258fSBjoern A. Zeeb 	rtwvif->rate_pattern.enable = false;
6178e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n");
6188e93258fSBjoern A. Zeeb }
6198e93258fSBjoern A. Zeeb 
6208e93258fSBjoern A. Zeeb static void rtw89_phy_ra_updata_sta_iter(void *data, struct ieee80211_sta *sta)
6218e93258fSBjoern A. Zeeb {
6228e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
6238e93258fSBjoern A. Zeeb 
6248e93258fSBjoern A. Zeeb 	rtw89_phy_ra_updata_sta(rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
6258e93258fSBjoern A. Zeeb }
6268e93258fSBjoern A. Zeeb 
6278e93258fSBjoern A. Zeeb void rtw89_phy_ra_update(struct rtw89_dev *rtwdev)
6288e93258fSBjoern A. Zeeb {
6298e93258fSBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
6308e93258fSBjoern A. Zeeb 					  rtw89_phy_ra_updata_sta_iter,
6318e93258fSBjoern A. Zeeb 					  rtwdev);
6328e93258fSBjoern A. Zeeb }
6338e93258fSBjoern A. Zeeb 
6348e93258fSBjoern A. Zeeb void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta)
6358e93258fSBjoern A. Zeeb {
6368e93258fSBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
6378e93258fSBjoern A. Zeeb 	struct rtw89_ra_info *ra = &rtwsta->ra;
6388e93258fSBjoern A. Zeeb 	u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
6398e93258fSBjoern A. Zeeb 	bool csi = rtw89_sta_has_beamformer_cap(sta);
6408e93258fSBjoern A. Zeeb 
6418e93258fSBjoern A. Zeeb 	rtw89_phy_ra_sta_update(rtwdev, sta, csi);
6428e93258fSBjoern A. Zeeb 
6438e93258fSBjoern A. Zeeb 	if (rssi > 40)
6448e93258fSBjoern A. Zeeb 		ra->init_rate_lv = 1;
6458e93258fSBjoern A. Zeeb 	else if (rssi > 20)
6468e93258fSBjoern A. Zeeb 		ra->init_rate_lv = 2;
6478e93258fSBjoern A. Zeeb 	else if (rssi > 1)
6488e93258fSBjoern A. Zeeb 		ra->init_rate_lv = 3;
6498e93258fSBjoern A. Zeeb 	else
6508e93258fSBjoern A. Zeeb 		ra->init_rate_lv = 0;
6518e93258fSBjoern A. Zeeb 	ra->upd_all = 1;
6528e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RA,
6538e93258fSBjoern A. Zeeb 		    "ra assoc: macid = %d, mode = %d, bw = %d, nss = %d, lv = %d",
6548e93258fSBjoern A. Zeeb 		    ra->macid,
6558e93258fSBjoern A. Zeeb 		    ra->mode_ctrl,
6568e93258fSBjoern A. Zeeb 		    ra->bw_cap,
6578e93258fSBjoern A. Zeeb 		    ra->ss_num,
6588e93258fSBjoern A. Zeeb 		    ra->init_rate_lv);
6598e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RA,
6608e93258fSBjoern A. Zeeb 		    "ra assoc: dcm = %d, er = %d, ldpc = %d, stbc = %d, gi = %d %d",
6618e93258fSBjoern A. Zeeb 		    ra->dcm_cap,
6628e93258fSBjoern A. Zeeb 		    ra->er_cap,
6638e93258fSBjoern A. Zeeb 		    ra->ldpc_cap,
6648e93258fSBjoern A. Zeeb 		    ra->stbc_cap,
6658e93258fSBjoern A. Zeeb 		    ra->en_sgi,
6668e93258fSBjoern A. Zeeb 		    ra->giltf);
6678e93258fSBjoern A. Zeeb 
6688e93258fSBjoern A. Zeeb 	rtw89_fw_h2c_ra(rtwdev, ra, csi);
6698e93258fSBjoern A. Zeeb }
6708e93258fSBjoern A. Zeeb 
6718e93258fSBjoern A. Zeeb u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
6728e93258fSBjoern A. Zeeb 		      const struct rtw89_chan *chan,
6738e93258fSBjoern A. Zeeb 		      enum rtw89_bandwidth dbw)
6748e93258fSBjoern A. Zeeb {
6758e93258fSBjoern A. Zeeb 	enum rtw89_bandwidth cbw = chan->band_width;
6768e93258fSBjoern A. Zeeb 	u8 pri_ch = chan->primary_channel;
6778e93258fSBjoern A. Zeeb 	u8 central_ch = chan->channel;
6788e93258fSBjoern A. Zeeb 	u8 txsc_idx = 0;
6798e93258fSBjoern A. Zeeb 	u8 tmp = 0;
6808e93258fSBjoern A. Zeeb 
6818e93258fSBjoern A. Zeeb 	if (cbw == dbw || cbw == RTW89_CHANNEL_WIDTH_20)
6828e93258fSBjoern A. Zeeb 		return txsc_idx;
6838e93258fSBjoern A. Zeeb 
6848e93258fSBjoern A. Zeeb 	switch (cbw) {
6858e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_40:
6868e93258fSBjoern A. Zeeb 		txsc_idx = pri_ch > central_ch ? 1 : 2;
6878e93258fSBjoern A. Zeeb 		break;
6888e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_80:
6898e93258fSBjoern A. Zeeb 		if (dbw == RTW89_CHANNEL_WIDTH_20) {
6908e93258fSBjoern A. Zeeb 			if (pri_ch > central_ch)
6918e93258fSBjoern A. Zeeb 				txsc_idx = (pri_ch - central_ch) >> 1;
6928e93258fSBjoern A. Zeeb 			else
6938e93258fSBjoern A. Zeeb 				txsc_idx = ((central_ch - pri_ch) >> 1) + 1;
6948e93258fSBjoern A. Zeeb 		} else {
6958e93258fSBjoern A. Zeeb 			txsc_idx = pri_ch > central_ch ? 9 : 10;
6968e93258fSBjoern A. Zeeb 		}
6978e93258fSBjoern A. Zeeb 		break;
6988e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_160:
6998e93258fSBjoern A. Zeeb 		if (pri_ch > central_ch)
7008e93258fSBjoern A. Zeeb 			tmp = (pri_ch - central_ch) >> 1;
7018e93258fSBjoern A. Zeeb 		else
7028e93258fSBjoern A. Zeeb 			tmp = ((central_ch - pri_ch) >> 1) + 1;
7038e93258fSBjoern A. Zeeb 
7048e93258fSBjoern A. Zeeb 		if (dbw == RTW89_CHANNEL_WIDTH_20) {
7058e93258fSBjoern A. Zeeb 			txsc_idx = tmp;
7068e93258fSBjoern A. Zeeb 		} else if (dbw == RTW89_CHANNEL_WIDTH_40) {
7078e93258fSBjoern A. Zeeb 			if (tmp == 1 || tmp == 3)
7088e93258fSBjoern A. Zeeb 				txsc_idx = 9;
7098e93258fSBjoern A. Zeeb 			else if (tmp == 5 || tmp == 7)
7108e93258fSBjoern A. Zeeb 				txsc_idx = 11;
7118e93258fSBjoern A. Zeeb 			else if (tmp == 2 || tmp == 4)
7128e93258fSBjoern A. Zeeb 				txsc_idx = 10;
7138e93258fSBjoern A. Zeeb 			else if (tmp == 6 || tmp == 8)
7148e93258fSBjoern A. Zeeb 				txsc_idx = 12;
7158e93258fSBjoern A. Zeeb 			else
7168e93258fSBjoern A. Zeeb 				return 0xff;
7178e93258fSBjoern A. Zeeb 		} else {
7188e93258fSBjoern A. Zeeb 			txsc_idx = pri_ch > central_ch ? 13 : 14;
7198e93258fSBjoern A. Zeeb 		}
7208e93258fSBjoern A. Zeeb 		break;
7218e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_80_80:
7228e93258fSBjoern A. Zeeb 		if (dbw == RTW89_CHANNEL_WIDTH_20) {
7238e93258fSBjoern A. Zeeb 			if (pri_ch > central_ch)
7248e93258fSBjoern A. Zeeb 				txsc_idx = (10 - (pri_ch - central_ch)) >> 1;
7258e93258fSBjoern A. Zeeb 			else
7268e93258fSBjoern A. Zeeb 				txsc_idx = ((central_ch - pri_ch) >> 1) + 5;
7278e93258fSBjoern A. Zeeb 		} else if (dbw == RTW89_CHANNEL_WIDTH_40) {
7288e93258fSBjoern A. Zeeb 			txsc_idx = pri_ch > central_ch ? 10 : 12;
7298e93258fSBjoern A. Zeeb 		} else {
7308e93258fSBjoern A. Zeeb 			txsc_idx = 14;
7318e93258fSBjoern A. Zeeb 		}
7328e93258fSBjoern A. Zeeb 		break;
7338e93258fSBjoern A. Zeeb 	default:
7348e93258fSBjoern A. Zeeb 		break;
7358e93258fSBjoern A. Zeeb 	}
7368e93258fSBjoern A. Zeeb 
7378e93258fSBjoern A. Zeeb 	return txsc_idx;
7388e93258fSBjoern A. Zeeb }
7398e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_get_txsc);
7408e93258fSBjoern A. Zeeb 
741*6d67aabdSBjoern A. Zeeb u8 rtw89_phy_get_txsb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
742*6d67aabdSBjoern A. Zeeb 		      enum rtw89_bandwidth dbw)
743*6d67aabdSBjoern A. Zeeb {
744*6d67aabdSBjoern A. Zeeb 	enum rtw89_bandwidth cbw = chan->band_width;
745*6d67aabdSBjoern A. Zeeb 	u8 pri_ch = chan->primary_channel;
746*6d67aabdSBjoern A. Zeeb 	u8 central_ch = chan->channel;
747*6d67aabdSBjoern A. Zeeb 	u8 txsb_idx = 0;
748*6d67aabdSBjoern A. Zeeb 
749*6d67aabdSBjoern A. Zeeb 	if (cbw == dbw || cbw == RTW89_CHANNEL_WIDTH_20)
750*6d67aabdSBjoern A. Zeeb 		return txsb_idx;
751*6d67aabdSBjoern A. Zeeb 
752*6d67aabdSBjoern A. Zeeb 	switch (cbw) {
753*6d67aabdSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_40:
754*6d67aabdSBjoern A. Zeeb 		txsb_idx = pri_ch > central_ch ? 1 : 0;
755*6d67aabdSBjoern A. Zeeb 		break;
756*6d67aabdSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_80:
757*6d67aabdSBjoern A. Zeeb 		if (dbw == RTW89_CHANNEL_WIDTH_20)
758*6d67aabdSBjoern A. Zeeb 			txsb_idx = (pri_ch - central_ch + 6) / 4;
759*6d67aabdSBjoern A. Zeeb 		else
760*6d67aabdSBjoern A. Zeeb 			txsb_idx = pri_ch > central_ch ? 1 : 0;
761*6d67aabdSBjoern A. Zeeb 		break;
762*6d67aabdSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_160:
763*6d67aabdSBjoern A. Zeeb 		if (dbw == RTW89_CHANNEL_WIDTH_20)
764*6d67aabdSBjoern A. Zeeb 			txsb_idx = (pri_ch - central_ch + 14) / 4;
765*6d67aabdSBjoern A. Zeeb 		else if (dbw == RTW89_CHANNEL_WIDTH_40)
766*6d67aabdSBjoern A. Zeeb 			txsb_idx = (pri_ch - central_ch + 12) / 8;
767*6d67aabdSBjoern A. Zeeb 		else
768*6d67aabdSBjoern A. Zeeb 			txsb_idx = pri_ch > central_ch ? 1 : 0;
769*6d67aabdSBjoern A. Zeeb 		break;
770*6d67aabdSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_320:
771*6d67aabdSBjoern A. Zeeb 		if (dbw == RTW89_CHANNEL_WIDTH_20)
772*6d67aabdSBjoern A. Zeeb 			txsb_idx = (pri_ch - central_ch + 30) / 4;
773*6d67aabdSBjoern A. Zeeb 		else if (dbw == RTW89_CHANNEL_WIDTH_40)
774*6d67aabdSBjoern A. Zeeb 			txsb_idx = (pri_ch - central_ch + 28) / 8;
775*6d67aabdSBjoern A. Zeeb 		else if (dbw == RTW89_CHANNEL_WIDTH_80)
776*6d67aabdSBjoern A. Zeeb 			txsb_idx = (pri_ch - central_ch + 24) / 16;
777*6d67aabdSBjoern A. Zeeb 		else
778*6d67aabdSBjoern A. Zeeb 			txsb_idx = pri_ch > central_ch ? 1 : 0;
779*6d67aabdSBjoern A. Zeeb 		break;
780*6d67aabdSBjoern A. Zeeb 	default:
781*6d67aabdSBjoern A. Zeeb 		break;
782*6d67aabdSBjoern A. Zeeb 	}
783*6d67aabdSBjoern A. Zeeb 
784*6d67aabdSBjoern A. Zeeb 	return txsb_idx;
785*6d67aabdSBjoern A. Zeeb }
786*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_get_txsb);
787*6d67aabdSBjoern A. Zeeb 
7888e93258fSBjoern A. Zeeb static bool rtw89_phy_check_swsi_busy(struct rtw89_dev *rtwdev)
7898e93258fSBjoern A. Zeeb {
7908e93258fSBjoern A. Zeeb 	return !!rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, B_SWSI_W_BUSY_V1) ||
7918e93258fSBjoern A. Zeeb 	       !!rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, B_SWSI_R_BUSY_V1);
7928e93258fSBjoern A. Zeeb }
7938e93258fSBjoern A. Zeeb 
7948e93258fSBjoern A. Zeeb u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
7958e93258fSBjoern A. Zeeb 		      u32 addr, u32 mask)
7968e93258fSBjoern A. Zeeb {
7978e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
7988e93258fSBjoern A. Zeeb 	const u32 *base_addr = chip->rf_base_addr;
7998e93258fSBjoern A. Zeeb 	u32 val, direct_addr;
8008e93258fSBjoern A. Zeeb 
8018e93258fSBjoern A. Zeeb 	if (rf_path >= rtwdev->chip->rf_path_num) {
8028e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
8038e93258fSBjoern A. Zeeb 		return INV_RF_DATA;
8048e93258fSBjoern A. Zeeb 	}
8058e93258fSBjoern A. Zeeb 
8068e93258fSBjoern A. Zeeb 	addr &= 0xff;
8078e93258fSBjoern A. Zeeb 	direct_addr = base_addr[rf_path] + (addr << 2);
8088e93258fSBjoern A. Zeeb 	mask &= RFREG_MASK;
8098e93258fSBjoern A. Zeeb 
8108e93258fSBjoern A. Zeeb 	val = rtw89_phy_read32_mask(rtwdev, direct_addr, mask);
8118e93258fSBjoern A. Zeeb 
8128e93258fSBjoern A. Zeeb 	return val;
8138e93258fSBjoern A. Zeeb }
8148e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_read_rf);
8158e93258fSBjoern A. Zeeb 
8168e93258fSBjoern A. Zeeb static u32 rtw89_phy_read_rf_a(struct rtw89_dev *rtwdev,
8178e93258fSBjoern A. Zeeb 			       enum rtw89_rf_path rf_path, u32 addr, u32 mask)
8188e93258fSBjoern A. Zeeb {
8198e93258fSBjoern A. Zeeb 	bool busy;
8208e93258fSBjoern A. Zeeb 	bool done;
8218e93258fSBjoern A. Zeeb 	u32 val;
8228e93258fSBjoern A. Zeeb 	int ret;
8238e93258fSBjoern A. Zeeb 
8248e93258fSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_phy_check_swsi_busy, busy, !busy,
8258e93258fSBjoern A. Zeeb 				       1, 30, false, rtwdev);
8268e93258fSBjoern A. Zeeb 	if (ret) {
8278e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "read rf busy swsi\n");
8288e93258fSBjoern A. Zeeb 		return INV_RF_DATA;
8298e93258fSBjoern A. Zeeb 	}
8308e93258fSBjoern A. Zeeb 
8318e93258fSBjoern A. Zeeb 	mask &= RFREG_MASK;
8328e93258fSBjoern A. Zeeb 
8338e93258fSBjoern A. Zeeb 	val = FIELD_PREP(B_SWSI_READ_ADDR_PATH_V1, rf_path) |
8348e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_SWSI_READ_ADDR_ADDR_V1, addr);
8358e93258fSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, R_SWSI_READ_ADDR_V1, B_SWSI_READ_ADDR_V1, val);
8368e93258fSBjoern A. Zeeb 	udelay(2);
8378e93258fSBjoern A. Zeeb 
8388e93258fSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done, 1,
8398e93258fSBjoern A. Zeeb 				       30, false, rtwdev, R_SWSI_V1,
8408e93258fSBjoern A. Zeeb 				       B_SWSI_R_DATA_DONE_V1);
8418e93258fSBjoern A. Zeeb 	if (ret) {
8428e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "read swsi busy\n");
8438e93258fSBjoern A. Zeeb 		return INV_RF_DATA;
8448e93258fSBjoern A. Zeeb 	}
8458e93258fSBjoern A. Zeeb 
8468e93258fSBjoern A. Zeeb 	return rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, mask);
8478e93258fSBjoern A. Zeeb }
8488e93258fSBjoern A. Zeeb 
8498e93258fSBjoern A. Zeeb u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
8508e93258fSBjoern A. Zeeb 			 u32 addr, u32 mask)
8518e93258fSBjoern A. Zeeb {
8528e93258fSBjoern A. Zeeb 	bool ad_sel = FIELD_GET(RTW89_RF_ADDR_ADSEL_MASK, addr);
8538e93258fSBjoern A. Zeeb 
8548e93258fSBjoern A. Zeeb 	if (rf_path >= rtwdev->chip->rf_path_num) {
8558e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
8568e93258fSBjoern A. Zeeb 		return INV_RF_DATA;
8578e93258fSBjoern A. Zeeb 	}
8588e93258fSBjoern A. Zeeb 
8598e93258fSBjoern A. Zeeb 	if (ad_sel)
8608e93258fSBjoern A. Zeeb 		return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
8618e93258fSBjoern A. Zeeb 	else
8628e93258fSBjoern A. Zeeb 		return rtw89_phy_read_rf_a(rtwdev, rf_path, addr, mask);
8638e93258fSBjoern A. Zeeb }
8648e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_read_rf_v1);
8658e93258fSBjoern A. Zeeb 
866*6d67aabdSBjoern A. Zeeb static u32 rtw89_phy_read_full_rf_v2_a(struct rtw89_dev *rtwdev,
867*6d67aabdSBjoern A. Zeeb 				       enum rtw89_rf_path rf_path, u32 addr)
868*6d67aabdSBjoern A. Zeeb {
869*6d67aabdSBjoern A. Zeeb 	static const u16 r_addr_ofst[2] = {0x2C24, 0x2D24};
870*6d67aabdSBjoern A. Zeeb 	static const u16 addr_ofst[2] = {0x2ADC, 0x2BDC};
871*6d67aabdSBjoern A. Zeeb 	bool busy, done;
872*6d67aabdSBjoern A. Zeeb 	int ret;
873*6d67aabdSBjoern A. Zeeb 	u32 val;
874*6d67aabdSBjoern A. Zeeb 
875*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_CTL_MASK, 0x1);
876*6d67aabdSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
877*6d67aabdSBjoern A. Zeeb 				       1, 3800, false,
878*6d67aabdSBjoern A. Zeeb 				       rtwdev, r_addr_ofst[rf_path], B_HWSI_VAL_BUSY);
879*6d67aabdSBjoern A. Zeeb 	if (ret) {
880*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "poll HWSI is busy\n");
881*6d67aabdSBjoern A. Zeeb 		return INV_RF_DATA;
882*6d67aabdSBjoern A. Zeeb 	}
883*6d67aabdSBjoern A. Zeeb 
884*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_MASK, addr);
885*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_RD, 0x1);
886*6d67aabdSBjoern A. Zeeb 	udelay(2);
887*6d67aabdSBjoern A. Zeeb 
888*6d67aabdSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done,
889*6d67aabdSBjoern A. Zeeb 				       1, 3800, false,
890*6d67aabdSBjoern A. Zeeb 				       rtwdev, r_addr_ofst[rf_path], B_HWSI_VAL_RDONE);
891*6d67aabdSBjoern A. Zeeb 	if (ret) {
892*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "read HWSI is busy\n");
893*6d67aabdSBjoern A. Zeeb 		val = INV_RF_DATA;
894*6d67aabdSBjoern A. Zeeb 		goto out;
895*6d67aabdSBjoern A. Zeeb 	}
896*6d67aabdSBjoern A. Zeeb 
897*6d67aabdSBjoern A. Zeeb 	val = rtw89_phy_read32_mask(rtwdev, r_addr_ofst[rf_path], RFREG_MASK);
898*6d67aabdSBjoern A. Zeeb out:
899*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, addr_ofst[rf_path], B_HWSI_ADD_POLL_MASK, 0);
900*6d67aabdSBjoern A. Zeeb 
901*6d67aabdSBjoern A. Zeeb 	return val;
902*6d67aabdSBjoern A. Zeeb }
903*6d67aabdSBjoern A. Zeeb 
904*6d67aabdSBjoern A. Zeeb static u32 rtw89_phy_read_rf_v2_a(struct rtw89_dev *rtwdev,
905*6d67aabdSBjoern A. Zeeb 				  enum rtw89_rf_path rf_path, u32 addr, u32 mask)
906*6d67aabdSBjoern A. Zeeb {
907*6d67aabdSBjoern A. Zeeb 	u32 val;
908*6d67aabdSBjoern A. Zeeb 
909*6d67aabdSBjoern A. Zeeb 	val = rtw89_phy_read_full_rf_v2_a(rtwdev, rf_path, addr);
910*6d67aabdSBjoern A. Zeeb 
911*6d67aabdSBjoern A. Zeeb 	return (val & mask) >> __ffs(mask);
912*6d67aabdSBjoern A. Zeeb }
913*6d67aabdSBjoern A. Zeeb 
914*6d67aabdSBjoern A. Zeeb u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
915*6d67aabdSBjoern A. Zeeb 			 u32 addr, u32 mask)
916*6d67aabdSBjoern A. Zeeb {
917*6d67aabdSBjoern A. Zeeb 	bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
918*6d67aabdSBjoern A. Zeeb 
919*6d67aabdSBjoern A. Zeeb 	if (rf_path >= rtwdev->chip->rf_path_num) {
920*6d67aabdSBjoern A. Zeeb 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
921*6d67aabdSBjoern A. Zeeb 		return INV_RF_DATA;
922*6d67aabdSBjoern A. Zeeb 	}
923*6d67aabdSBjoern A. Zeeb 
924*6d67aabdSBjoern A. Zeeb 	if (ad_sel)
925*6d67aabdSBjoern A. Zeeb 		return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask);
926*6d67aabdSBjoern A. Zeeb 	else
927*6d67aabdSBjoern A. Zeeb 		return rtw89_phy_read_rf_v2_a(rtwdev, rf_path, addr, mask);
928*6d67aabdSBjoern A. Zeeb }
929*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_read_rf_v2);
930*6d67aabdSBjoern A. Zeeb 
9318e93258fSBjoern A. Zeeb bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
9328e93258fSBjoern A. Zeeb 			u32 addr, u32 mask, u32 data)
9338e93258fSBjoern A. Zeeb {
9348e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
9358e93258fSBjoern A. Zeeb 	const u32 *base_addr = chip->rf_base_addr;
9368e93258fSBjoern A. Zeeb 	u32 direct_addr;
9378e93258fSBjoern A. Zeeb 
9388e93258fSBjoern A. Zeeb 	if (rf_path >= rtwdev->chip->rf_path_num) {
9398e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
9408e93258fSBjoern A. Zeeb 		return false;
9418e93258fSBjoern A. Zeeb 	}
9428e93258fSBjoern A. Zeeb 
9438e93258fSBjoern A. Zeeb 	addr &= 0xff;
9448e93258fSBjoern A. Zeeb 	direct_addr = base_addr[rf_path] + (addr << 2);
9458e93258fSBjoern A. Zeeb 	mask &= RFREG_MASK;
9468e93258fSBjoern A. Zeeb 
9478e93258fSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, direct_addr, mask, data);
9488e93258fSBjoern A. Zeeb 
9498e93258fSBjoern A. Zeeb 	/* delay to ensure writing properly */
9508e93258fSBjoern A. Zeeb 	udelay(1);
9518e93258fSBjoern A. Zeeb 
9528e93258fSBjoern A. Zeeb 	return true;
9538e93258fSBjoern A. Zeeb }
9548e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_write_rf);
9558e93258fSBjoern A. Zeeb 
9568e93258fSBjoern A. Zeeb static bool rtw89_phy_write_rf_a(struct rtw89_dev *rtwdev,
9578e93258fSBjoern A. Zeeb 				 enum rtw89_rf_path rf_path, u32 addr, u32 mask,
9588e93258fSBjoern A. Zeeb 				 u32 data)
9598e93258fSBjoern A. Zeeb {
9608e93258fSBjoern A. Zeeb 	u8 bit_shift;
9618e93258fSBjoern A. Zeeb 	u32 val;
9628e93258fSBjoern A. Zeeb 	bool busy, b_msk_en = false;
9638e93258fSBjoern A. Zeeb 	int ret;
9648e93258fSBjoern A. Zeeb 
9658e93258fSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_phy_check_swsi_busy, busy, !busy,
9668e93258fSBjoern A. Zeeb 				       1, 30, false, rtwdev);
9678e93258fSBjoern A. Zeeb 	if (ret) {
9688e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "write rf busy swsi\n");
9698e93258fSBjoern A. Zeeb 		return false;
9708e93258fSBjoern A. Zeeb 	}
9718e93258fSBjoern A. Zeeb 
9728e93258fSBjoern A. Zeeb 	data &= RFREG_MASK;
9738e93258fSBjoern A. Zeeb 	mask &= RFREG_MASK;
9748e93258fSBjoern A. Zeeb 
9758e93258fSBjoern A. Zeeb 	if (mask != RFREG_MASK) {
9768e93258fSBjoern A. Zeeb 		b_msk_en = true;
9778e93258fSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, R_SWSI_BIT_MASK_V1, RFREG_MASK,
9788e93258fSBjoern A. Zeeb 				       mask);
9798e93258fSBjoern A. Zeeb 		bit_shift = __ffs(mask);
9808e93258fSBjoern A. Zeeb 		data = (data << bit_shift) & RFREG_MASK;
9818e93258fSBjoern A. Zeeb 	}
9828e93258fSBjoern A. Zeeb 
9838e93258fSBjoern A. Zeeb 	val = FIELD_PREP(B_SWSI_DATA_BIT_MASK_EN_V1, b_msk_en) |
9848e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_SWSI_DATA_PATH_V1, rf_path) |
9858e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_SWSI_DATA_ADDR_V1, addr) |
9868e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_SWSI_DATA_VAL_V1, data);
9878e93258fSBjoern A. Zeeb 
9888e93258fSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, R_SWSI_DATA_V1, MASKDWORD, val);
9898e93258fSBjoern A. Zeeb 
9908e93258fSBjoern A. Zeeb 	return true;
9918e93258fSBjoern A. Zeeb }
9928e93258fSBjoern A. Zeeb 
9938e93258fSBjoern A. Zeeb bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
9948e93258fSBjoern A. Zeeb 			   u32 addr, u32 mask, u32 data)
9958e93258fSBjoern A. Zeeb {
9968e93258fSBjoern A. Zeeb 	bool ad_sel = FIELD_GET(RTW89_RF_ADDR_ADSEL_MASK, addr);
9978e93258fSBjoern A. Zeeb 
9988e93258fSBjoern A. Zeeb 	if (rf_path >= rtwdev->chip->rf_path_num) {
9998e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
10008e93258fSBjoern A. Zeeb 		return false;
10018e93258fSBjoern A. Zeeb 	}
10028e93258fSBjoern A. Zeeb 
10038e93258fSBjoern A. Zeeb 	if (ad_sel)
10048e93258fSBjoern A. Zeeb 		return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
10058e93258fSBjoern A. Zeeb 	else
10068e93258fSBjoern A. Zeeb 		return rtw89_phy_write_rf_a(rtwdev, rf_path, addr, mask, data);
10078e93258fSBjoern A. Zeeb }
10088e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_write_rf_v1);
10098e93258fSBjoern A. Zeeb 
1010*6d67aabdSBjoern A. Zeeb static
1011*6d67aabdSBjoern A. Zeeb bool rtw89_phy_write_full_rf_v2_a(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1012*6d67aabdSBjoern A. Zeeb 				  u32 addr, u32 data)
1013*6d67aabdSBjoern A. Zeeb {
1014*6d67aabdSBjoern A. Zeeb 	static const u32 addr_is_idle[2] = {0x2C24, 0x2D24};
1015*6d67aabdSBjoern A. Zeeb 	static const u32 addr_ofst[2] = {0x2AE0, 0x2BE0};
1016*6d67aabdSBjoern A. Zeeb 	bool busy;
1017*6d67aabdSBjoern A. Zeeb 	u32 val;
1018*6d67aabdSBjoern A. Zeeb 	int ret;
1019*6d67aabdSBjoern A. Zeeb 
1020*6d67aabdSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy,
1021*6d67aabdSBjoern A. Zeeb 				       1, 3800, false,
1022*6d67aabdSBjoern A. Zeeb 				       rtwdev, addr_is_idle[rf_path], BIT(29));
1023*6d67aabdSBjoern A. Zeeb 	if (ret) {
1024*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "[%s] HWSI is busy\n", __func__);
1025*6d67aabdSBjoern A. Zeeb 		return false;
1026*6d67aabdSBjoern A. Zeeb 	}
1027*6d67aabdSBjoern A. Zeeb 
1028*6d67aabdSBjoern A. Zeeb 	val = u32_encode_bits(addr, B_HWSI_DATA_ADDR) |
1029*6d67aabdSBjoern A. Zeeb 	      u32_encode_bits(data, B_HWSI_DATA_VAL);
1030*6d67aabdSBjoern A. Zeeb 
1031*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32(rtwdev, addr_ofst[rf_path], val);
1032*6d67aabdSBjoern A. Zeeb 
1033*6d67aabdSBjoern A. Zeeb 	return true;
1034*6d67aabdSBjoern A. Zeeb }
1035*6d67aabdSBjoern A. Zeeb 
1036*6d67aabdSBjoern A. Zeeb static
1037*6d67aabdSBjoern A. Zeeb bool rtw89_phy_write_rf_a_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1038*6d67aabdSBjoern A. Zeeb 			     u32 addr, u32 mask, u32 data)
1039*6d67aabdSBjoern A. Zeeb {
1040*6d67aabdSBjoern A. Zeeb 	u32 val;
1041*6d67aabdSBjoern A. Zeeb 
1042*6d67aabdSBjoern A. Zeeb 	if (mask == RFREG_MASK) {
1043*6d67aabdSBjoern A. Zeeb 		val = data;
1044*6d67aabdSBjoern A. Zeeb 	} else {
1045*6d67aabdSBjoern A. Zeeb 		val = rtw89_phy_read_full_rf_v2_a(rtwdev, rf_path, addr);
1046*6d67aabdSBjoern A. Zeeb 		val &= ~mask;
1047*6d67aabdSBjoern A. Zeeb 		val |= (data << __ffs(mask)) & mask;
1048*6d67aabdSBjoern A. Zeeb 	}
1049*6d67aabdSBjoern A. Zeeb 
1050*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_write_full_rf_v2_a(rtwdev, rf_path, addr, val);
1051*6d67aabdSBjoern A. Zeeb }
1052*6d67aabdSBjoern A. Zeeb 
1053*6d67aabdSBjoern A. Zeeb bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
1054*6d67aabdSBjoern A. Zeeb 			   u32 addr, u32 mask, u32 data)
1055*6d67aabdSBjoern A. Zeeb {
1056*6d67aabdSBjoern A. Zeeb 	bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK);
1057*6d67aabdSBjoern A. Zeeb 
1058*6d67aabdSBjoern A. Zeeb 	if (rf_path >= rtwdev->chip->rf_path_num) {
1059*6d67aabdSBjoern A. Zeeb 		rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
1060*6d67aabdSBjoern A. Zeeb 		return INV_RF_DATA;
1061*6d67aabdSBjoern A. Zeeb 	}
1062*6d67aabdSBjoern A. Zeeb 
1063*6d67aabdSBjoern A. Zeeb 	if (ad_sel)
1064*6d67aabdSBjoern A. Zeeb 		return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data);
1065*6d67aabdSBjoern A. Zeeb 	else
1066*6d67aabdSBjoern A. Zeeb 		return rtw89_phy_write_rf_a_v2(rtwdev, rf_path, addr, mask, data);
1067*6d67aabdSBjoern A. Zeeb }
1068*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_write_rf_v2);
1069*6d67aabdSBjoern A. Zeeb 
1070e2340276SBjoern A. Zeeb static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev)
1071e2340276SBjoern A. Zeeb {
1072e2340276SBjoern A. Zeeb 	return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1;
1073e2340276SBjoern A. Zeeb }
1074e2340276SBjoern A. Zeeb 
10758e93258fSBjoern A. Zeeb static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev,
10768e93258fSBjoern A. Zeeb 			       enum rtw89_phy_idx phy_idx)
10778e93258fSBjoern A. Zeeb {
10788e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
10798e93258fSBjoern A. Zeeb 
10808e93258fSBjoern A. Zeeb 	chip->ops->bb_reset(rtwdev, phy_idx);
10818e93258fSBjoern A. Zeeb }
10828e93258fSBjoern A. Zeeb 
10838e93258fSBjoern A. Zeeb static void rtw89_phy_config_bb_reg(struct rtw89_dev *rtwdev,
10848e93258fSBjoern A. Zeeb 				    const struct rtw89_reg2_def *reg,
10858e93258fSBjoern A. Zeeb 				    enum rtw89_rf_path rf_path,
10868e93258fSBjoern A. Zeeb 				    void *extra_data)
10878e93258fSBjoern A. Zeeb {
1088*6d67aabdSBjoern A. Zeeb 	u32 addr;
1089*6d67aabdSBjoern A. Zeeb 
1090*6d67aabdSBjoern A. Zeeb 	if (reg->addr == 0xfe) {
10918e93258fSBjoern A. Zeeb 		mdelay(50);
1092*6d67aabdSBjoern A. Zeeb 	} else if (reg->addr == 0xfd) {
10938e93258fSBjoern A. Zeeb 		mdelay(5);
1094*6d67aabdSBjoern A. Zeeb 	} else if (reg->addr == 0xfc) {
10958e93258fSBjoern A. Zeeb 		mdelay(1);
1096*6d67aabdSBjoern A. Zeeb 	} else if (reg->addr == 0xfb) {
10978e93258fSBjoern A. Zeeb 		udelay(50);
1098*6d67aabdSBjoern A. Zeeb 	} else if (reg->addr == 0xfa) {
10998e93258fSBjoern A. Zeeb 		udelay(5);
1100*6d67aabdSBjoern A. Zeeb 	} else if (reg->addr == 0xf9) {
11018e93258fSBjoern A. Zeeb 		udelay(1);
1102*6d67aabdSBjoern A. Zeeb 	} else if (reg->data == BYPASS_CR_DATA) {
1103*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "Bypass CR 0x%x\n", reg->addr);
1104*6d67aabdSBjoern A. Zeeb 	} else {
1105*6d67aabdSBjoern A. Zeeb 		addr = reg->addr;
1106*6d67aabdSBjoern A. Zeeb 
1107*6d67aabdSBjoern A. Zeeb 		if ((uintptr_t)extra_data == RTW89_PHY_1)
1108*6d67aabdSBjoern A. Zeeb 			addr += rtw89_phy0_phy1_offset(rtwdev, reg->addr);
1109*6d67aabdSBjoern A. Zeeb 
1110*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32(rtwdev, addr, reg->data);
1111*6d67aabdSBjoern A. Zeeb 	}
11128e93258fSBjoern A. Zeeb }
11138e93258fSBjoern A. Zeeb 
11148e93258fSBjoern A. Zeeb union rtw89_phy_bb_gain_arg {
11158e93258fSBjoern A. Zeeb 	u32 addr;
11168e93258fSBjoern A. Zeeb 	struct {
11178e93258fSBjoern A. Zeeb 		union {
11188e93258fSBjoern A. Zeeb 			u8 type;
11198e93258fSBjoern A. Zeeb 			struct {
11208e93258fSBjoern A. Zeeb 				u8 rxsc_start:4;
11218e93258fSBjoern A. Zeeb 				u8 bw:4;
11228e93258fSBjoern A. Zeeb 			};
11238e93258fSBjoern A. Zeeb 		};
11248e93258fSBjoern A. Zeeb 		u8 path;
11258e93258fSBjoern A. Zeeb 		u8 gain_band;
11268e93258fSBjoern A. Zeeb 		u8 cfg_type;
11278e93258fSBjoern A. Zeeb 	};
11288e93258fSBjoern A. Zeeb } __packed;
11298e93258fSBjoern A. Zeeb 
11308e93258fSBjoern A. Zeeb static void
11318e93258fSBjoern A. Zeeb rtw89_phy_cfg_bb_gain_error(struct rtw89_dev *rtwdev,
11328e93258fSBjoern A. Zeeb 			    union rtw89_phy_bb_gain_arg arg, u32 data)
11338e93258fSBjoern A. Zeeb {
1134*6d67aabdSBjoern A. Zeeb 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
11358e93258fSBjoern A. Zeeb 	u8 type = arg.type;
11368e93258fSBjoern A. Zeeb 	u8 path = arg.path;
11378e93258fSBjoern A. Zeeb 	u8 gband = arg.gain_band;
11388e93258fSBjoern A. Zeeb 	int i;
11398e93258fSBjoern A. Zeeb 
11408e93258fSBjoern A. Zeeb 	switch (type) {
11418e93258fSBjoern A. Zeeb 	case 0:
11428e93258fSBjoern A. Zeeb 		for (i = 0; i < 4; i++, data >>= 8)
11438e93258fSBjoern A. Zeeb 			gain->lna_gain[gband][path][i] = data & 0xff;
11448e93258fSBjoern A. Zeeb 		break;
11458e93258fSBjoern A. Zeeb 	case 1:
11468e93258fSBjoern A. Zeeb 		for (i = 4; i < 7; i++, data >>= 8)
11478e93258fSBjoern A. Zeeb 			gain->lna_gain[gband][path][i] = data & 0xff;
11488e93258fSBjoern A. Zeeb 		break;
11498e93258fSBjoern A. Zeeb 	case 2:
11508e93258fSBjoern A. Zeeb 		for (i = 0; i < 2; i++, data >>= 8)
11518e93258fSBjoern A. Zeeb 			gain->tia_gain[gband][path][i] = data & 0xff;
11528e93258fSBjoern A. Zeeb 		break;
11538e93258fSBjoern A. Zeeb 	default:
11548e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev,
11558e93258fSBjoern A. Zeeb 			   "bb gain error {0x%x:0x%x} with unknown type: %d\n",
11568e93258fSBjoern A. Zeeb 			   arg.addr, data, type);
11578e93258fSBjoern A. Zeeb 		break;
11588e93258fSBjoern A. Zeeb 	}
11598e93258fSBjoern A. Zeeb }
11608e93258fSBjoern A. Zeeb 
11618e93258fSBjoern A. Zeeb enum rtw89_phy_bb_rxsc_start_idx {
11628e93258fSBjoern A. Zeeb 	RTW89_BB_RXSC_START_IDX_FULL = 0,
11638e93258fSBjoern A. Zeeb 	RTW89_BB_RXSC_START_IDX_20 = 1,
11648e93258fSBjoern A. Zeeb 	RTW89_BB_RXSC_START_IDX_20_1 = 5,
11658e93258fSBjoern A. Zeeb 	RTW89_BB_RXSC_START_IDX_40 = 9,
11668e93258fSBjoern A. Zeeb 	RTW89_BB_RXSC_START_IDX_80 = 13,
11678e93258fSBjoern A. Zeeb };
11688e93258fSBjoern A. Zeeb 
11698e93258fSBjoern A. Zeeb static void
11708e93258fSBjoern A. Zeeb rtw89_phy_cfg_bb_rpl_ofst(struct rtw89_dev *rtwdev,
11718e93258fSBjoern A. Zeeb 			  union rtw89_phy_bb_gain_arg arg, u32 data)
11728e93258fSBjoern A. Zeeb {
1173*6d67aabdSBjoern A. Zeeb 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
11748e93258fSBjoern A. Zeeb 	u8 rxsc_start = arg.rxsc_start;
11758e93258fSBjoern A. Zeeb 	u8 bw = arg.bw;
11768e93258fSBjoern A. Zeeb 	u8 path = arg.path;
11778e93258fSBjoern A. Zeeb 	u8 gband = arg.gain_band;
11788e93258fSBjoern A. Zeeb 	u8 rxsc;
11798e93258fSBjoern A. Zeeb 	s8 ofst;
11808e93258fSBjoern A. Zeeb 	int i;
11818e93258fSBjoern A. Zeeb 
11828e93258fSBjoern A. Zeeb 	switch (bw) {
11838e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_20:
11848e93258fSBjoern A. Zeeb 		gain->rpl_ofst_20[gband][path] = (s8)data;
11858e93258fSBjoern A. Zeeb 		break;
11868e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_40:
11878e93258fSBjoern A. Zeeb 		if (rxsc_start == RTW89_BB_RXSC_START_IDX_FULL) {
11888e93258fSBjoern A. Zeeb 			gain->rpl_ofst_40[gband][path][0] = (s8)data;
11898e93258fSBjoern A. Zeeb 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20) {
11908e93258fSBjoern A. Zeeb 			for (i = 0; i < 2; i++, data >>= 8) {
11918e93258fSBjoern A. Zeeb 				rxsc = RTW89_BB_RXSC_START_IDX_20 + i;
11928e93258fSBjoern A. Zeeb 				ofst = (s8)(data & 0xff);
11938e93258fSBjoern A. Zeeb 				gain->rpl_ofst_40[gband][path][rxsc] = ofst;
11948e93258fSBjoern A. Zeeb 			}
11958e93258fSBjoern A. Zeeb 		}
11968e93258fSBjoern A. Zeeb 		break;
11978e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_80:
11988e93258fSBjoern A. Zeeb 		if (rxsc_start == RTW89_BB_RXSC_START_IDX_FULL) {
11998e93258fSBjoern A. Zeeb 			gain->rpl_ofst_80[gband][path][0] = (s8)data;
12008e93258fSBjoern A. Zeeb 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20) {
12018e93258fSBjoern A. Zeeb 			for (i = 0; i < 4; i++, data >>= 8) {
12028e93258fSBjoern A. Zeeb 				rxsc = RTW89_BB_RXSC_START_IDX_20 + i;
12038e93258fSBjoern A. Zeeb 				ofst = (s8)(data & 0xff);
12048e93258fSBjoern A. Zeeb 				gain->rpl_ofst_80[gband][path][rxsc] = ofst;
12058e93258fSBjoern A. Zeeb 			}
12068e93258fSBjoern A. Zeeb 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_40) {
12078e93258fSBjoern A. Zeeb 			for (i = 0; i < 2; i++, data >>= 8) {
12088e93258fSBjoern A. Zeeb 				rxsc = RTW89_BB_RXSC_START_IDX_40 + i;
12098e93258fSBjoern A. Zeeb 				ofst = (s8)(data & 0xff);
12108e93258fSBjoern A. Zeeb 				gain->rpl_ofst_80[gband][path][rxsc] = ofst;
12118e93258fSBjoern A. Zeeb 			}
12128e93258fSBjoern A. Zeeb 		}
12138e93258fSBjoern A. Zeeb 		break;
12148e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_160:
12158e93258fSBjoern A. Zeeb 		if (rxsc_start == RTW89_BB_RXSC_START_IDX_FULL) {
12168e93258fSBjoern A. Zeeb 			gain->rpl_ofst_160[gband][path][0] = (s8)data;
12178e93258fSBjoern A. Zeeb 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20) {
12188e93258fSBjoern A. Zeeb 			for (i = 0; i < 4; i++, data >>= 8) {
12198e93258fSBjoern A. Zeeb 				rxsc = RTW89_BB_RXSC_START_IDX_20 + i;
12208e93258fSBjoern A. Zeeb 				ofst = (s8)(data & 0xff);
12218e93258fSBjoern A. Zeeb 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
12228e93258fSBjoern A. Zeeb 			}
12238e93258fSBjoern A. Zeeb 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_20_1) {
12248e93258fSBjoern A. Zeeb 			for (i = 0; i < 4; i++, data >>= 8) {
12258e93258fSBjoern A. Zeeb 				rxsc = RTW89_BB_RXSC_START_IDX_20_1 + i;
12268e93258fSBjoern A. Zeeb 				ofst = (s8)(data & 0xff);
12278e93258fSBjoern A. Zeeb 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
12288e93258fSBjoern A. Zeeb 			}
12298e93258fSBjoern A. Zeeb 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_40) {
12308e93258fSBjoern A. Zeeb 			for (i = 0; i < 4; i++, data >>= 8) {
12318e93258fSBjoern A. Zeeb 				rxsc = RTW89_BB_RXSC_START_IDX_40 + i;
12328e93258fSBjoern A. Zeeb 				ofst = (s8)(data & 0xff);
12338e93258fSBjoern A. Zeeb 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
12348e93258fSBjoern A. Zeeb 			}
12358e93258fSBjoern A. Zeeb 		} else if (rxsc_start == RTW89_BB_RXSC_START_IDX_80) {
12368e93258fSBjoern A. Zeeb 			for (i = 0; i < 2; i++, data >>= 8) {
12378e93258fSBjoern A. Zeeb 				rxsc = RTW89_BB_RXSC_START_IDX_80 + i;
12388e93258fSBjoern A. Zeeb 				ofst = (s8)(data & 0xff);
12398e93258fSBjoern A. Zeeb 				gain->rpl_ofst_160[gband][path][rxsc] = ofst;
12408e93258fSBjoern A. Zeeb 			}
12418e93258fSBjoern A. Zeeb 		}
12428e93258fSBjoern A. Zeeb 		break;
12438e93258fSBjoern A. Zeeb 	default:
12448e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev,
12458e93258fSBjoern A. Zeeb 			   "bb rpl ofst {0x%x:0x%x} with unknown bw: %d\n",
12468e93258fSBjoern A. Zeeb 			   arg.addr, data, bw);
12478e93258fSBjoern A. Zeeb 		break;
12488e93258fSBjoern A. Zeeb 	}
12498e93258fSBjoern A. Zeeb }
12508e93258fSBjoern A. Zeeb 
12518e93258fSBjoern A. Zeeb static void
12528e93258fSBjoern A. Zeeb rtw89_phy_cfg_bb_gain_bypass(struct rtw89_dev *rtwdev,
12538e93258fSBjoern A. Zeeb 			     union rtw89_phy_bb_gain_arg arg, u32 data)
12548e93258fSBjoern A. Zeeb {
1255*6d67aabdSBjoern A. Zeeb 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
12568e93258fSBjoern A. Zeeb 	u8 type = arg.type;
12578e93258fSBjoern A. Zeeb 	u8 path = arg.path;
12588e93258fSBjoern A. Zeeb 	u8 gband = arg.gain_band;
12598e93258fSBjoern A. Zeeb 	int i;
12608e93258fSBjoern A. Zeeb 
12618e93258fSBjoern A. Zeeb 	switch (type) {
12628e93258fSBjoern A. Zeeb 	case 0:
12638e93258fSBjoern A. Zeeb 		for (i = 0; i < 4; i++, data >>= 8)
12648e93258fSBjoern A. Zeeb 			gain->lna_gain_bypass[gband][path][i] = data & 0xff;
12658e93258fSBjoern A. Zeeb 		break;
12668e93258fSBjoern A. Zeeb 	case 1:
12678e93258fSBjoern A. Zeeb 		for (i = 4; i < 7; i++, data >>= 8)
12688e93258fSBjoern A. Zeeb 			gain->lna_gain_bypass[gband][path][i] = data & 0xff;
12698e93258fSBjoern A. Zeeb 		break;
12708e93258fSBjoern A. Zeeb 	default:
12718e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev,
12728e93258fSBjoern A. Zeeb 			   "bb gain bypass {0x%x:0x%x} with unknown type: %d\n",
12738e93258fSBjoern A. Zeeb 			   arg.addr, data, type);
12748e93258fSBjoern A. Zeeb 		break;
12758e93258fSBjoern A. Zeeb 	}
12768e93258fSBjoern A. Zeeb }
12778e93258fSBjoern A. Zeeb 
12788e93258fSBjoern A. Zeeb static void
12798e93258fSBjoern A. Zeeb rtw89_phy_cfg_bb_gain_op1db(struct rtw89_dev *rtwdev,
12808e93258fSBjoern A. Zeeb 			    union rtw89_phy_bb_gain_arg arg, u32 data)
12818e93258fSBjoern A. Zeeb {
1282*6d67aabdSBjoern A. Zeeb 	struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax;
12838e93258fSBjoern A. Zeeb 	u8 type = arg.type;
12848e93258fSBjoern A. Zeeb 	u8 path = arg.path;
12858e93258fSBjoern A. Zeeb 	u8 gband = arg.gain_band;
12868e93258fSBjoern A. Zeeb 	int i;
12878e93258fSBjoern A. Zeeb 
12888e93258fSBjoern A. Zeeb 	switch (type) {
12898e93258fSBjoern A. Zeeb 	case 0:
12908e93258fSBjoern A. Zeeb 		for (i = 0; i < 4; i++, data >>= 8)
12918e93258fSBjoern A. Zeeb 			gain->lna_op1db[gband][path][i] = data & 0xff;
12928e93258fSBjoern A. Zeeb 		break;
12938e93258fSBjoern A. Zeeb 	case 1:
12948e93258fSBjoern A. Zeeb 		for (i = 4; i < 7; i++, data >>= 8)
12958e93258fSBjoern A. Zeeb 			gain->lna_op1db[gband][path][i] = data & 0xff;
12968e93258fSBjoern A. Zeeb 		break;
12978e93258fSBjoern A. Zeeb 	case 2:
12988e93258fSBjoern A. Zeeb 		for (i = 0; i < 4; i++, data >>= 8)
12998e93258fSBjoern A. Zeeb 			gain->tia_lna_op1db[gband][path][i] = data & 0xff;
13008e93258fSBjoern A. Zeeb 		break;
13018e93258fSBjoern A. Zeeb 	case 3:
13028e93258fSBjoern A. Zeeb 		for (i = 4; i < 8; i++, data >>= 8)
13038e93258fSBjoern A. Zeeb 			gain->tia_lna_op1db[gband][path][i] = data & 0xff;
13048e93258fSBjoern A. Zeeb 		break;
13058e93258fSBjoern A. Zeeb 	default:
13068e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev,
13078e93258fSBjoern A. Zeeb 			   "bb gain op1db {0x%x:0x%x} with unknown type: %d\n",
13088e93258fSBjoern A. Zeeb 			   arg.addr, data, type);
13098e93258fSBjoern A. Zeeb 		break;
13108e93258fSBjoern A. Zeeb 	}
13118e93258fSBjoern A. Zeeb }
13128e93258fSBjoern A. Zeeb 
1313*6d67aabdSBjoern A. Zeeb static void rtw89_phy_config_bb_gain_ax(struct rtw89_dev *rtwdev,
13148e93258fSBjoern A. Zeeb 					const struct rtw89_reg2_def *reg,
13158e93258fSBjoern A. Zeeb 					enum rtw89_rf_path rf_path,
13168e93258fSBjoern A. Zeeb 					void *extra_data)
13178e93258fSBjoern A. Zeeb {
13188e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
13198e93258fSBjoern A. Zeeb 	union rtw89_phy_bb_gain_arg arg = { .addr = reg->addr };
1320e2340276SBjoern A. Zeeb 	struct rtw89_efuse *efuse = &rtwdev->efuse;
13218e93258fSBjoern A. Zeeb 
13228e93258fSBjoern A. Zeeb 	if (arg.gain_band >= RTW89_BB_GAIN_BAND_NR)
13238e93258fSBjoern A. Zeeb 		return;
13248e93258fSBjoern A. Zeeb 
13258e93258fSBjoern A. Zeeb 	if (arg.path >= chip->rf_path_num)
13268e93258fSBjoern A. Zeeb 		return;
13278e93258fSBjoern A. Zeeb 
13288e93258fSBjoern A. Zeeb 	if (arg.addr >= 0xf9 && arg.addr <= 0xfe) {
13298e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "bb gain table with flow ctrl\n");
13308e93258fSBjoern A. Zeeb 		return;
13318e93258fSBjoern A. Zeeb 	}
13328e93258fSBjoern A. Zeeb 
13338e93258fSBjoern A. Zeeb 	switch (arg.cfg_type) {
13348e93258fSBjoern A. Zeeb 	case 0:
13358e93258fSBjoern A. Zeeb 		rtw89_phy_cfg_bb_gain_error(rtwdev, arg, reg->data);
13368e93258fSBjoern A. Zeeb 		break;
13378e93258fSBjoern A. Zeeb 	case 1:
13388e93258fSBjoern A. Zeeb 		rtw89_phy_cfg_bb_rpl_ofst(rtwdev, arg, reg->data);
13398e93258fSBjoern A. Zeeb 		break;
13408e93258fSBjoern A. Zeeb 	case 2:
13418e93258fSBjoern A. Zeeb 		rtw89_phy_cfg_bb_gain_bypass(rtwdev, arg, reg->data);
13428e93258fSBjoern A. Zeeb 		break;
13438e93258fSBjoern A. Zeeb 	case 3:
13448e93258fSBjoern A. Zeeb 		rtw89_phy_cfg_bb_gain_op1db(rtwdev, arg, reg->data);
13458e93258fSBjoern A. Zeeb 		break;
1346e2340276SBjoern A. Zeeb 	case 4:
1347e2340276SBjoern A. Zeeb 		/* This cfg_type is only used by rfe_type >= 50 with eFEM */
1348e2340276SBjoern A. Zeeb 		if (efuse->rfe_type < 50)
1349e2340276SBjoern A. Zeeb 			break;
1350e2340276SBjoern A. Zeeb 		fallthrough;
13518e93258fSBjoern A. Zeeb 	default:
13528e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev,
13538e93258fSBjoern A. Zeeb 			   "bb gain {0x%x:0x%x} with unknown cfg type: %d\n",
13548e93258fSBjoern A. Zeeb 			   arg.addr, reg->data, arg.cfg_type);
13558e93258fSBjoern A. Zeeb 		break;
13568e93258fSBjoern A. Zeeb 	}
13578e93258fSBjoern A. Zeeb }
13588e93258fSBjoern A. Zeeb 
13598e93258fSBjoern A. Zeeb static void
13608e93258fSBjoern A. Zeeb rtw89_phy_cofig_rf_reg_store(struct rtw89_dev *rtwdev,
13618e93258fSBjoern A. Zeeb 			     const struct rtw89_reg2_def *reg,
13628e93258fSBjoern A. Zeeb 			     enum rtw89_rf_path rf_path,
13638e93258fSBjoern A. Zeeb 			     struct rtw89_fw_h2c_rf_reg_info *info)
13648e93258fSBjoern A. Zeeb {
13658e93258fSBjoern A. Zeeb 	u16 idx = info->curr_idx % RTW89_H2C_RF_PAGE_SIZE;
13668e93258fSBjoern A. Zeeb 	u8 page = info->curr_idx / RTW89_H2C_RF_PAGE_SIZE;
13678e93258fSBjoern A. Zeeb 
13688e93258fSBjoern A. Zeeb 	if (page >= RTW89_H2C_RF_PAGE_NUM) {
13698e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "RF parameters exceed size. path=%d, idx=%d",
13708e93258fSBjoern A. Zeeb 			   rf_path, info->curr_idx);
13718e93258fSBjoern A. Zeeb 		return;
13728e93258fSBjoern A. Zeeb 	}
13738e93258fSBjoern A. Zeeb 
13748e93258fSBjoern A. Zeeb 	info->rtw89_phy_config_rf_h2c[page][idx] =
13758e93258fSBjoern A. Zeeb 		cpu_to_le32((reg->addr << 20) | reg->data);
13768e93258fSBjoern A. Zeeb 	info->curr_idx++;
13778e93258fSBjoern A. Zeeb }
13788e93258fSBjoern A. Zeeb 
13798e93258fSBjoern A. Zeeb static int rtw89_phy_config_rf_reg_fw(struct rtw89_dev *rtwdev,
13808e93258fSBjoern A. Zeeb 				      struct rtw89_fw_h2c_rf_reg_info *info)
13818e93258fSBjoern A. Zeeb {
13828e93258fSBjoern A. Zeeb 	u16 remain = info->curr_idx;
13838e93258fSBjoern A. Zeeb 	u16 len = 0;
13848e93258fSBjoern A. Zeeb 	u8 i;
13858e93258fSBjoern A. Zeeb 	int ret = 0;
13868e93258fSBjoern A. Zeeb 
13878e93258fSBjoern A. Zeeb 	if (remain > RTW89_H2C_RF_PAGE_NUM * RTW89_H2C_RF_PAGE_SIZE) {
13888e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev,
13898e93258fSBjoern A. Zeeb 			   "rf reg h2c total len %d larger than %d\n",
13908e93258fSBjoern A. Zeeb 			   remain, RTW89_H2C_RF_PAGE_NUM * RTW89_H2C_RF_PAGE_SIZE);
13918e93258fSBjoern A. Zeeb 		ret = -EINVAL;
13928e93258fSBjoern A. Zeeb 		goto out;
13938e93258fSBjoern A. Zeeb 	}
13948e93258fSBjoern A. Zeeb 
13958e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_H2C_RF_PAGE_NUM && remain; i++, remain -= len) {
13968e93258fSBjoern A. Zeeb 		len = remain > RTW89_H2C_RF_PAGE_SIZE ? RTW89_H2C_RF_PAGE_SIZE : remain;
13978e93258fSBjoern A. Zeeb 		ret = rtw89_fw_h2c_rf_reg(rtwdev, info, len * 4, i);
13988e93258fSBjoern A. Zeeb 		if (ret)
13998e93258fSBjoern A. Zeeb 			goto out;
14008e93258fSBjoern A. Zeeb 	}
14018e93258fSBjoern A. Zeeb out:
14028e93258fSBjoern A. Zeeb 	info->curr_idx = 0;
14038e93258fSBjoern A. Zeeb 
14048e93258fSBjoern A. Zeeb 	return ret;
14058e93258fSBjoern A. Zeeb }
14068e93258fSBjoern A. Zeeb 
1407e2340276SBjoern A. Zeeb static void rtw89_phy_config_rf_reg_noio(struct rtw89_dev *rtwdev,
1408e2340276SBjoern A. Zeeb 					 const struct rtw89_reg2_def *reg,
1409e2340276SBjoern A. Zeeb 					 enum rtw89_rf_path rf_path,
1410e2340276SBjoern A. Zeeb 					 void *extra_data)
1411e2340276SBjoern A. Zeeb {
1412e2340276SBjoern A. Zeeb 	u32 addr = reg->addr;
1413e2340276SBjoern A. Zeeb 
1414e2340276SBjoern A. Zeeb 	if (addr == 0xfe || addr == 0xfd || addr == 0xfc || addr == 0xfb ||
1415e2340276SBjoern A. Zeeb 	    addr == 0xfa || addr == 0xf9)
1416e2340276SBjoern A. Zeeb 		return;
1417e2340276SBjoern A. Zeeb 
1418e2340276SBjoern A. Zeeb 	if (rtw89_chip_rf_v1(rtwdev) && addr < 0x100)
1419e2340276SBjoern A. Zeeb 		return;
1420e2340276SBjoern A. Zeeb 
1421e2340276SBjoern A. Zeeb 	rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path,
1422e2340276SBjoern A. Zeeb 				     (struct rtw89_fw_h2c_rf_reg_info *)extra_data);
1423e2340276SBjoern A. Zeeb }
1424e2340276SBjoern A. Zeeb 
14258e93258fSBjoern A. Zeeb static void rtw89_phy_config_rf_reg(struct rtw89_dev *rtwdev,
14268e93258fSBjoern A. Zeeb 				    const struct rtw89_reg2_def *reg,
14278e93258fSBjoern A. Zeeb 				    enum rtw89_rf_path rf_path,
14288e93258fSBjoern A. Zeeb 				    void *extra_data)
14298e93258fSBjoern A. Zeeb {
14308e93258fSBjoern A. Zeeb 	if (reg->addr == 0xfe) {
14318e93258fSBjoern A. Zeeb 		mdelay(50);
14328e93258fSBjoern A. Zeeb 	} else if (reg->addr == 0xfd) {
14338e93258fSBjoern A. Zeeb 		mdelay(5);
14348e93258fSBjoern A. Zeeb 	} else if (reg->addr == 0xfc) {
14358e93258fSBjoern A. Zeeb 		mdelay(1);
14368e93258fSBjoern A. Zeeb 	} else if (reg->addr == 0xfb) {
14378e93258fSBjoern A. Zeeb 		udelay(50);
14388e93258fSBjoern A. Zeeb 	} else if (reg->addr == 0xfa) {
14398e93258fSBjoern A. Zeeb 		udelay(5);
14408e93258fSBjoern A. Zeeb 	} else if (reg->addr == 0xf9) {
14418e93258fSBjoern A. Zeeb 		udelay(1);
14428e93258fSBjoern A. Zeeb 	} else {
14438e93258fSBjoern A. Zeeb 		rtw89_write_rf(rtwdev, rf_path, reg->addr, 0xfffff, reg->data);
14448e93258fSBjoern A. Zeeb 		rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path,
14458e93258fSBjoern A. Zeeb 					     (struct rtw89_fw_h2c_rf_reg_info *)extra_data);
14468e93258fSBjoern A. Zeeb 	}
14478e93258fSBjoern A. Zeeb }
14488e93258fSBjoern A. Zeeb 
14498e93258fSBjoern A. Zeeb void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
14508e93258fSBjoern A. Zeeb 				const struct rtw89_reg2_def *reg,
14518e93258fSBjoern A. Zeeb 				enum rtw89_rf_path rf_path,
14528e93258fSBjoern A. Zeeb 				void *extra_data)
14538e93258fSBjoern A. Zeeb {
14548e93258fSBjoern A. Zeeb 	rtw89_write_rf(rtwdev, rf_path, reg->addr, RFREG_MASK, reg->data);
14558e93258fSBjoern A. Zeeb 
14568e93258fSBjoern A. Zeeb 	if (reg->addr < 0x100)
14578e93258fSBjoern A. Zeeb 		return;
14588e93258fSBjoern A. Zeeb 
14598e93258fSBjoern A. Zeeb 	rtw89_phy_cofig_rf_reg_store(rtwdev, reg, rf_path,
14608e93258fSBjoern A. Zeeb 				     (struct rtw89_fw_h2c_rf_reg_info *)extra_data);
14618e93258fSBjoern A. Zeeb }
14628e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_config_rf_reg_v1);
14638e93258fSBjoern A. Zeeb 
14648e93258fSBjoern A. Zeeb static int rtw89_phy_sel_headline(struct rtw89_dev *rtwdev,
14658e93258fSBjoern A. Zeeb 				  const struct rtw89_phy_table *table,
14668e93258fSBjoern A. Zeeb 				  u32 *headline_size, u32 *headline_idx,
14678e93258fSBjoern A. Zeeb 				  u8 rfe, u8 cv)
14688e93258fSBjoern A. Zeeb {
14698e93258fSBjoern A. Zeeb 	const struct rtw89_reg2_def *reg;
14708e93258fSBjoern A. Zeeb 	u32 headline;
14718e93258fSBjoern A. Zeeb 	u32 compare, target;
14728e93258fSBjoern A. Zeeb 	u8 rfe_para, cv_para;
14738e93258fSBjoern A. Zeeb 	u8 cv_max = 0;
14748e93258fSBjoern A. Zeeb 	bool case_matched = false;
14758e93258fSBjoern A. Zeeb 	u32 i;
14768e93258fSBjoern A. Zeeb 
14778e93258fSBjoern A. Zeeb 	for (i = 0; i < table->n_regs; i++) {
14788e93258fSBjoern A. Zeeb 		reg = &table->regs[i];
14798e93258fSBjoern A. Zeeb 		headline = get_phy_headline(reg->addr);
14808e93258fSBjoern A. Zeeb 		if (headline != PHY_HEADLINE_VALID)
14818e93258fSBjoern A. Zeeb 			break;
14828e93258fSBjoern A. Zeeb 	}
14838e93258fSBjoern A. Zeeb 	*headline_size = i;
14848e93258fSBjoern A. Zeeb 	if (*headline_size == 0)
14858e93258fSBjoern A. Zeeb 		return 0;
14868e93258fSBjoern A. Zeeb 
14878e93258fSBjoern A. Zeeb 	/* case 1: RFE match, CV match */
14888e93258fSBjoern A. Zeeb 	compare = get_phy_compare(rfe, cv);
14898e93258fSBjoern A. Zeeb 	for (i = 0; i < *headline_size; i++) {
14908e93258fSBjoern A. Zeeb 		reg = &table->regs[i];
14918e93258fSBjoern A. Zeeb 		target = get_phy_target(reg->addr);
14928e93258fSBjoern A. Zeeb 		if (target == compare) {
14938e93258fSBjoern A. Zeeb 			*headline_idx = i;
14948e93258fSBjoern A. Zeeb 			return 0;
14958e93258fSBjoern A. Zeeb 		}
14968e93258fSBjoern A. Zeeb 	}
14978e93258fSBjoern A. Zeeb 
14988e93258fSBjoern A. Zeeb 	/* case 2: RFE match, CV don't care */
14998e93258fSBjoern A. Zeeb 	compare = get_phy_compare(rfe, PHY_COND_DONT_CARE);
15008e93258fSBjoern A. Zeeb 	for (i = 0; i < *headline_size; i++) {
15018e93258fSBjoern A. Zeeb 		reg = &table->regs[i];
15028e93258fSBjoern A. Zeeb 		target = get_phy_target(reg->addr);
15038e93258fSBjoern A. Zeeb 		if (target == compare) {
15048e93258fSBjoern A. Zeeb 			*headline_idx = i;
15058e93258fSBjoern A. Zeeb 			return 0;
15068e93258fSBjoern A. Zeeb 		}
15078e93258fSBjoern A. Zeeb 	}
15088e93258fSBjoern A. Zeeb 
15098e93258fSBjoern A. Zeeb 	/* case 3: RFE match, CV max in table */
15108e93258fSBjoern A. Zeeb 	for (i = 0; i < *headline_size; i++) {
15118e93258fSBjoern A. Zeeb 		reg = &table->regs[i];
15128e93258fSBjoern A. Zeeb 		rfe_para = get_phy_cond_rfe(reg->addr);
15138e93258fSBjoern A. Zeeb 		cv_para = get_phy_cond_cv(reg->addr);
15148e93258fSBjoern A. Zeeb 		if (rfe_para == rfe) {
15158e93258fSBjoern A. Zeeb 			if (cv_para >= cv_max) {
15168e93258fSBjoern A. Zeeb 				cv_max = cv_para;
15178e93258fSBjoern A. Zeeb 				*headline_idx = i;
15188e93258fSBjoern A. Zeeb 				case_matched = true;
15198e93258fSBjoern A. Zeeb 			}
15208e93258fSBjoern A. Zeeb 		}
15218e93258fSBjoern A. Zeeb 	}
15228e93258fSBjoern A. Zeeb 
15238e93258fSBjoern A. Zeeb 	if (case_matched)
15248e93258fSBjoern A. Zeeb 		return 0;
15258e93258fSBjoern A. Zeeb 
15268e93258fSBjoern A. Zeeb 	/* case 4: RFE don't care, CV max in table */
15278e93258fSBjoern A. Zeeb 	for (i = 0; i < *headline_size; i++) {
15288e93258fSBjoern A. Zeeb 		reg = &table->regs[i];
15298e93258fSBjoern A. Zeeb 		rfe_para = get_phy_cond_rfe(reg->addr);
15308e93258fSBjoern A. Zeeb 		cv_para = get_phy_cond_cv(reg->addr);
15318e93258fSBjoern A. Zeeb 		if (rfe_para == PHY_COND_DONT_CARE) {
15328e93258fSBjoern A. Zeeb 			if (cv_para >= cv_max) {
15338e93258fSBjoern A. Zeeb 				cv_max = cv_para;
15348e93258fSBjoern A. Zeeb 				*headline_idx = i;
15358e93258fSBjoern A. Zeeb 				case_matched = true;
15368e93258fSBjoern A. Zeeb 			}
15378e93258fSBjoern A. Zeeb 		}
15388e93258fSBjoern A. Zeeb 	}
15398e93258fSBjoern A. Zeeb 
15408e93258fSBjoern A. Zeeb 	if (case_matched)
15418e93258fSBjoern A. Zeeb 		return 0;
15428e93258fSBjoern A. Zeeb 
15438e93258fSBjoern A. Zeeb 	return -EINVAL;
15448e93258fSBjoern A. Zeeb }
15458e93258fSBjoern A. Zeeb 
15468e93258fSBjoern A. Zeeb static void rtw89_phy_init_reg(struct rtw89_dev *rtwdev,
15478e93258fSBjoern A. Zeeb 			       const struct rtw89_phy_table *table,
15488e93258fSBjoern A. Zeeb 			       void (*config)(struct rtw89_dev *rtwdev,
15498e93258fSBjoern A. Zeeb 					      const struct rtw89_reg2_def *reg,
15508e93258fSBjoern A. Zeeb 					      enum rtw89_rf_path rf_path,
15518e93258fSBjoern A. Zeeb 					      void *data),
15528e93258fSBjoern A. Zeeb 			       void *extra_data)
15538e93258fSBjoern A. Zeeb {
15548e93258fSBjoern A. Zeeb 	const struct rtw89_reg2_def *reg;
15558e93258fSBjoern A. Zeeb 	enum rtw89_rf_path rf_path = table->rf_path;
15568e93258fSBjoern A. Zeeb 	u8 rfe = rtwdev->efuse.rfe_type;
15578e93258fSBjoern A. Zeeb 	u8 cv = rtwdev->hal.cv;
15588e93258fSBjoern A. Zeeb 	u32 i;
15598e93258fSBjoern A. Zeeb 	u32 headline_size = 0, headline_idx = 0;
15608e93258fSBjoern A. Zeeb 	u32 target = 0, cfg_target;
15618e93258fSBjoern A. Zeeb 	u8 cond;
15628e93258fSBjoern A. Zeeb 	bool is_matched = true;
15638e93258fSBjoern A. Zeeb 	bool target_found = false;
15648e93258fSBjoern A. Zeeb 	int ret;
15658e93258fSBjoern A. Zeeb 
15668e93258fSBjoern A. Zeeb 	ret = rtw89_phy_sel_headline(rtwdev, table, &headline_size,
15678e93258fSBjoern A. Zeeb 				     &headline_idx, rfe, cv);
15688e93258fSBjoern A. Zeeb 	if (ret) {
15698e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "invalid PHY package: %d/%d\n", rfe, cv);
15708e93258fSBjoern A. Zeeb 		return;
15718e93258fSBjoern A. Zeeb 	}
15728e93258fSBjoern A. Zeeb 
15738e93258fSBjoern A. Zeeb 	cfg_target = get_phy_target(table->regs[headline_idx].addr);
15748e93258fSBjoern A. Zeeb 	for (i = headline_size; i < table->n_regs; i++) {
15758e93258fSBjoern A. Zeeb 		reg = &table->regs[i];
15768e93258fSBjoern A. Zeeb 		cond = get_phy_cond(reg->addr);
15778e93258fSBjoern A. Zeeb 		switch (cond) {
15788e93258fSBjoern A. Zeeb 		case PHY_COND_BRANCH_IF:
15798e93258fSBjoern A. Zeeb 		case PHY_COND_BRANCH_ELIF:
15808e93258fSBjoern A. Zeeb 			target = get_phy_target(reg->addr);
15818e93258fSBjoern A. Zeeb 			break;
15828e93258fSBjoern A. Zeeb 		case PHY_COND_BRANCH_ELSE:
15838e93258fSBjoern A. Zeeb 			is_matched = false;
15848e93258fSBjoern A. Zeeb 			if (!target_found) {
15858e93258fSBjoern A. Zeeb 				rtw89_warn(rtwdev, "failed to load CR %x/%x\n",
15868e93258fSBjoern A. Zeeb 					   reg->addr, reg->data);
15878e93258fSBjoern A. Zeeb 				return;
15888e93258fSBjoern A. Zeeb 			}
15898e93258fSBjoern A. Zeeb 			break;
15908e93258fSBjoern A. Zeeb 		case PHY_COND_BRANCH_END:
15918e93258fSBjoern A. Zeeb 			is_matched = true;
15928e93258fSBjoern A. Zeeb 			target_found = false;
15938e93258fSBjoern A. Zeeb 			break;
15948e93258fSBjoern A. Zeeb 		case PHY_COND_CHECK:
15958e93258fSBjoern A. Zeeb 			if (target_found) {
15968e93258fSBjoern A. Zeeb 				is_matched = false;
15978e93258fSBjoern A. Zeeb 				break;
15988e93258fSBjoern A. Zeeb 			}
15998e93258fSBjoern A. Zeeb 
16008e93258fSBjoern A. Zeeb 			if (target == cfg_target) {
16018e93258fSBjoern A. Zeeb 				is_matched = true;
16028e93258fSBjoern A. Zeeb 				target_found = true;
16038e93258fSBjoern A. Zeeb 			} else {
16048e93258fSBjoern A. Zeeb 				is_matched = false;
16058e93258fSBjoern A. Zeeb 				target_found = false;
16068e93258fSBjoern A. Zeeb 			}
16078e93258fSBjoern A. Zeeb 			break;
16088e93258fSBjoern A. Zeeb 		default:
16098e93258fSBjoern A. Zeeb 			if (is_matched)
16108e93258fSBjoern A. Zeeb 				config(rtwdev, reg, rf_path, extra_data);
16118e93258fSBjoern A. Zeeb 			break;
16128e93258fSBjoern A. Zeeb 		}
16138e93258fSBjoern A. Zeeb 	}
16148e93258fSBjoern A. Zeeb }
16158e93258fSBjoern A. Zeeb 
16168e93258fSBjoern A. Zeeb void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev)
16178e93258fSBjoern A. Zeeb {
1618e2340276SBjoern A. Zeeb 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
16198e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
1620e2340276SBjoern A. Zeeb 	const struct rtw89_phy_table *bb_table;
1621e2340276SBjoern A. Zeeb 	const struct rtw89_phy_table *bb_gain_table;
16228e93258fSBjoern A. Zeeb 
1623e2340276SBjoern A. Zeeb 	bb_table = elm_info->bb_tbl ? elm_info->bb_tbl : chip->bb_table;
16248e93258fSBjoern A. Zeeb 	rtw89_phy_init_reg(rtwdev, bb_table, rtw89_phy_config_bb_reg, NULL);
1625*6d67aabdSBjoern A. Zeeb 	if (rtwdev->dbcc_en)
1626*6d67aabdSBjoern A. Zeeb 		rtw89_phy_init_reg(rtwdev, bb_table, rtw89_phy_config_bb_reg,
1627*6d67aabdSBjoern A. Zeeb 				   (void *)RTW89_PHY_1);
16288e93258fSBjoern A. Zeeb 	rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0);
1629e2340276SBjoern A. Zeeb 
1630e2340276SBjoern A. Zeeb 	bb_gain_table = elm_info->bb_gain ? elm_info->bb_gain : chip->bb_gain_table;
16318e93258fSBjoern A. Zeeb 	if (bb_gain_table)
16328e93258fSBjoern A. Zeeb 		rtw89_phy_init_reg(rtwdev, bb_gain_table,
1633*6d67aabdSBjoern A. Zeeb 				   chip->phy_def->config_bb_gain, NULL);
16348e93258fSBjoern A. Zeeb 	rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0);
16358e93258fSBjoern A. Zeeb }
16368e93258fSBjoern A. Zeeb 
16378e93258fSBjoern A. Zeeb static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev)
16388e93258fSBjoern A. Zeeb {
16398e93258fSBjoern A. Zeeb 	rtw89_phy_write32(rtwdev, 0x8080, 0x4);
16408e93258fSBjoern A. Zeeb 	udelay(1);
16418e93258fSBjoern A. Zeeb 	return rtw89_phy_read32(rtwdev, 0x8080);
16428e93258fSBjoern A. Zeeb }
16438e93258fSBjoern A. Zeeb 
1644e2340276SBjoern A. Zeeb void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio)
16458e93258fSBjoern A. Zeeb {
16468e93258fSBjoern A. Zeeb 	void (*config)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg,
16478e93258fSBjoern A. Zeeb 		       enum rtw89_rf_path rf_path, void *data);
1648e2340276SBjoern A. Zeeb 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
16498e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
16508e93258fSBjoern A. Zeeb 	const struct rtw89_phy_table *rf_table;
16518e93258fSBjoern A. Zeeb 	struct rtw89_fw_h2c_rf_reg_info *rf_reg_info;
16528e93258fSBjoern A. Zeeb 	u8 path;
16538e93258fSBjoern A. Zeeb 
16548e93258fSBjoern A. Zeeb 	rf_reg_info = kzalloc(sizeof(*rf_reg_info), GFP_KERNEL);
16558e93258fSBjoern A. Zeeb 	if (!rf_reg_info)
16568e93258fSBjoern A. Zeeb 		return;
16578e93258fSBjoern A. Zeeb 
16588e93258fSBjoern A. Zeeb 	for (path = RF_PATH_A; path < chip->rf_path_num; path++) {
1659e2340276SBjoern A. Zeeb 		rf_table = elm_info->rf_radio[path] ?
1660e2340276SBjoern A. Zeeb 			   elm_info->rf_radio[path] : chip->rf_table[path];
16618e93258fSBjoern A. Zeeb 		rf_reg_info->rf_path = rf_table->rf_path;
1662e2340276SBjoern A. Zeeb 		if (noio)
1663e2340276SBjoern A. Zeeb 			config = rtw89_phy_config_rf_reg_noio;
1664e2340276SBjoern A. Zeeb 		else
1665e2340276SBjoern A. Zeeb 			config = rf_table->config ? rf_table->config :
1666e2340276SBjoern A. Zeeb 				 rtw89_phy_config_rf_reg;
16678e93258fSBjoern A. Zeeb 		rtw89_phy_init_reg(rtwdev, rf_table, config, (void *)rf_reg_info);
16688e93258fSBjoern A. Zeeb 		if (rtw89_phy_config_rf_reg_fw(rtwdev, rf_reg_info))
16698e93258fSBjoern A. Zeeb 			rtw89_warn(rtwdev, "rf path %d reg h2c config failed\n",
16708e93258fSBjoern A. Zeeb 				   rf_reg_info->rf_path);
16718e93258fSBjoern A. Zeeb 	}
16728e93258fSBjoern A. Zeeb 	kfree(rf_reg_info);
16738e93258fSBjoern A. Zeeb }
16748e93258fSBjoern A. Zeeb 
1675*6d67aabdSBjoern A. Zeeb static void rtw89_phy_preinit_rf_nctl_ax(struct rtw89_dev *rtwdev)
16768e93258fSBjoern A. Zeeb {
16778e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
16788e93258fSBjoern A. Zeeb 	u32 val;
16798e93258fSBjoern A. Zeeb 	int ret;
16808e93258fSBjoern A. Zeeb 
16818e93258fSBjoern A. Zeeb 	/* IQK/DPK clock & reset */
1682e2340276SBjoern A. Zeeb 	rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x3);
1683e2340276SBjoern A. Zeeb 	rtw89_phy_write32_set(rtwdev, R_GNT_BT_WGT_EN, 0x1);
1684e2340276SBjoern A. Zeeb 	rtw89_phy_write32_set(rtwdev, R_P0_PATH_RST, 0x8000000);
1685e2340276SBjoern A. Zeeb 	if (chip->chip_id != RTL8851B)
1686e2340276SBjoern A. Zeeb 		rtw89_phy_write32_set(rtwdev, R_P1_PATH_RST, 0x8000000);
1687*6d67aabdSBjoern A. Zeeb 	if (chip->chip_id == RTL8852B || chip->chip_id == RTL8852BT)
1688e2340276SBjoern A. Zeeb 		rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, 0x2);
16898e93258fSBjoern A. Zeeb 
16908e93258fSBjoern A. Zeeb 	/* check 0x8080 */
1691e2340276SBjoern A. Zeeb 	rtw89_phy_write32(rtwdev, R_NCTL_CFG, 0x8);
16928e93258fSBjoern A. Zeeb 
16938e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_phy_nctl_poll, val, val == 0x4, 10,
16948e93258fSBjoern A. Zeeb 				1000, false, rtwdev);
16958e93258fSBjoern A. Zeeb 	if (ret)
1696118d0ff5SBjoern A. Zeeb #if defined(__linux__)
16978e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "failed to poll nctl block\n");
1698118d0ff5SBjoern A. Zeeb #elif defined(__FreeBSD__)
1699118d0ff5SBjoern A. Zeeb 		rtw89_err(rtwdev, "failed to poll nctl block: ret %d val %#06x\n", ret, val);
1700118d0ff5SBjoern A. Zeeb #endif
1701*6d67aabdSBjoern A. Zeeb }
1702*6d67aabdSBjoern A. Zeeb 
1703*6d67aabdSBjoern A. Zeeb static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev)
1704*6d67aabdSBjoern A. Zeeb {
1705*6d67aabdSBjoern A. Zeeb 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
1706*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
1707*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_table *nctl_table;
1708*6d67aabdSBjoern A. Zeeb 
1709*6d67aabdSBjoern A. Zeeb 	rtw89_phy_preinit_rf_nctl(rtwdev);
17108e93258fSBjoern A. Zeeb 
1711e2340276SBjoern A. Zeeb 	nctl_table = elm_info->rf_nctl ? elm_info->rf_nctl : chip->nctl_table;
17128e93258fSBjoern A. Zeeb 	rtw89_phy_init_reg(rtwdev, nctl_table, rtw89_phy_config_bb_reg, NULL);
1713e2340276SBjoern A. Zeeb 
1714e2340276SBjoern A. Zeeb 	if (chip->nctl_post_table)
1715e2340276SBjoern A. Zeeb 		rtw89_rfk_parser(rtwdev, chip->nctl_post_table);
17168e93258fSBjoern A. Zeeb }
17178e93258fSBjoern A. Zeeb 
1718*6d67aabdSBjoern A. Zeeb static u32 rtw89_phy0_phy1_offset_ax(struct rtw89_dev *rtwdev, u32 addr)
17198e93258fSBjoern A. Zeeb {
17208e93258fSBjoern A. Zeeb 	u32 phy_page = addr >> 8;
17218e93258fSBjoern A. Zeeb 	u32 ofst = 0;
17228e93258fSBjoern A. Zeeb 
17238e93258fSBjoern A. Zeeb 	switch (phy_page) {
17248e93258fSBjoern A. Zeeb 	case 0x6:
17258e93258fSBjoern A. Zeeb 	case 0x7:
17268e93258fSBjoern A. Zeeb 	case 0x8:
17278e93258fSBjoern A. Zeeb 	case 0x9:
17288e93258fSBjoern A. Zeeb 	case 0xa:
17298e93258fSBjoern A. Zeeb 	case 0xb:
17308e93258fSBjoern A. Zeeb 	case 0xc:
17318e93258fSBjoern A. Zeeb 	case 0xd:
17328e93258fSBjoern A. Zeeb 	case 0x19:
17338e93258fSBjoern A. Zeeb 	case 0x1a:
17348e93258fSBjoern A. Zeeb 	case 0x1b:
17358e93258fSBjoern A. Zeeb 		ofst = 0x2000;
17368e93258fSBjoern A. Zeeb 		break;
17378e93258fSBjoern A. Zeeb 	default:
17388e93258fSBjoern A. Zeeb 		/* warning case */
17398e93258fSBjoern A. Zeeb 		ofst = 0;
17408e93258fSBjoern A. Zeeb 		break;
17418e93258fSBjoern A. Zeeb 	}
17428e93258fSBjoern A. Zeeb 
17438e93258fSBjoern A. Zeeb 	if (phy_page >= 0x40 && phy_page <= 0x4f)
17448e93258fSBjoern A. Zeeb 		ofst = 0x2000;
17458e93258fSBjoern A. Zeeb 
17468e93258fSBjoern A. Zeeb 	return ofst;
17478e93258fSBjoern A. Zeeb }
17488e93258fSBjoern A. Zeeb 
17498e93258fSBjoern A. Zeeb void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
17508e93258fSBjoern A. Zeeb 			   u32 data, enum rtw89_phy_idx phy_idx)
17518e93258fSBjoern A. Zeeb {
17528e93258fSBjoern A. Zeeb 	if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
17538e93258fSBjoern A. Zeeb 		addr += rtw89_phy0_phy1_offset(rtwdev, addr);
17548e93258fSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, addr, mask, data);
17558e93258fSBjoern A. Zeeb }
17568e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_write32_idx);
17578e93258fSBjoern A. Zeeb 
1758e2340276SBjoern A. Zeeb u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
1759e2340276SBjoern A. Zeeb 			 enum rtw89_phy_idx phy_idx)
1760e2340276SBjoern A. Zeeb {
1761e2340276SBjoern A. Zeeb 	if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1)
1762e2340276SBjoern A. Zeeb 		addr += rtw89_phy0_phy1_offset(rtwdev, addr);
1763e2340276SBjoern A. Zeeb 	return rtw89_phy_read32_mask(rtwdev, addr, mask);
1764e2340276SBjoern A. Zeeb }
1765e2340276SBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_read32_idx);
1766e2340276SBjoern A. Zeeb 
17678e93258fSBjoern A. Zeeb void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
17688e93258fSBjoern A. Zeeb 			    u32 val)
17698e93258fSBjoern A. Zeeb {
17708e93258fSBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_0);
17718e93258fSBjoern A. Zeeb 
17728e93258fSBjoern A. Zeeb 	if (!rtwdev->dbcc_en)
17738e93258fSBjoern A. Zeeb 		return;
17748e93258fSBjoern A. Zeeb 
17758e93258fSBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_1);
17768e93258fSBjoern A. Zeeb }
1777*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_set_phy_regs);
17788e93258fSBjoern A. Zeeb 
17798e93258fSBjoern A. Zeeb void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
17808e93258fSBjoern A. Zeeb 			      const struct rtw89_phy_reg3_tbl *tbl)
17818e93258fSBjoern A. Zeeb {
17828e93258fSBjoern A. Zeeb 	const struct rtw89_reg3_def *reg3;
17838e93258fSBjoern A. Zeeb 	int i;
17848e93258fSBjoern A. Zeeb 
17858e93258fSBjoern A. Zeeb 	for (i = 0; i < tbl->size; i++) {
17868e93258fSBjoern A. Zeeb 		reg3 = &tbl->reg3[i];
17878e93258fSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, reg3->addr, reg3->mask, reg3->data);
17888e93258fSBjoern A. Zeeb 	}
17898e93258fSBjoern A. Zeeb }
17908e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl);
17918e93258fSBjoern A. Zeeb 
1792*6d67aabdSBjoern A. Zeeb static const u8 rtw89_rs_idx_num_ax[] = {
1793e2340276SBjoern A. Zeeb 	[RTW89_RS_CCK] = RTW89_RATE_CCK_NUM,
1794e2340276SBjoern A. Zeeb 	[RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM,
1795*6d67aabdSBjoern A. Zeeb 	[RTW89_RS_MCS] = RTW89_RATE_MCS_NUM_AX,
1796e2340276SBjoern A. Zeeb 	[RTW89_RS_HEDCM] = RTW89_RATE_HEDCM_NUM,
1797*6d67aabdSBjoern A. Zeeb 	[RTW89_RS_OFFSET] = RTW89_RATE_OFFSET_NUM_AX,
17988e93258fSBjoern A. Zeeb };
17998e93258fSBjoern A. Zeeb 
1800*6d67aabdSBjoern A. Zeeb static const u8 rtw89_rs_nss_num_ax[] = {
18018e93258fSBjoern A. Zeeb 	[RTW89_RS_CCK] = 1,
18028e93258fSBjoern A. Zeeb 	[RTW89_RS_OFDM] = 1,
1803e2340276SBjoern A. Zeeb 	[RTW89_RS_MCS] = RTW89_NSS_NUM,
1804e2340276SBjoern A. Zeeb 	[RTW89_RS_HEDCM] = RTW89_NSS_HEDCM_NUM,
18058e93258fSBjoern A. Zeeb 	[RTW89_RS_OFFSET] = 1,
18068e93258fSBjoern A. Zeeb };
18078e93258fSBjoern A. Zeeb 
1808*6d67aabdSBjoern A. Zeeb s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
1809*6d67aabdSBjoern A. Zeeb 			   struct rtw89_txpwr_byrate *head,
1810*6d67aabdSBjoern A. Zeeb 			   const struct rtw89_rate_desc *desc)
1811*6d67aabdSBjoern A. Zeeb {
1812*6d67aabdSBjoern A. Zeeb 	switch (desc->rs) {
1813*6d67aabdSBjoern A. Zeeb 	case RTW89_RS_CCK:
1814*6d67aabdSBjoern A. Zeeb 		return &head->cck[desc->idx];
1815*6d67aabdSBjoern A. Zeeb 	case RTW89_RS_OFDM:
1816*6d67aabdSBjoern A. Zeeb 		return &head->ofdm[desc->idx];
1817*6d67aabdSBjoern A. Zeeb 	case RTW89_RS_MCS:
1818*6d67aabdSBjoern A. Zeeb 		return &head->mcs[desc->ofdma][desc->nss][desc->idx];
1819*6d67aabdSBjoern A. Zeeb 	case RTW89_RS_HEDCM:
1820*6d67aabdSBjoern A. Zeeb 		return &head->hedcm[desc->ofdma][desc->nss][desc->idx];
1821*6d67aabdSBjoern A. Zeeb 	case RTW89_RS_OFFSET:
1822*6d67aabdSBjoern A. Zeeb 		return &head->offset[desc->idx];
1823*6d67aabdSBjoern A. Zeeb 	default:
1824*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "unrecognized byr rs: %d\n", desc->rs);
1825*6d67aabdSBjoern A. Zeeb 		return &head->trap;
1826*6d67aabdSBjoern A. Zeeb 	}
1827*6d67aabdSBjoern A. Zeeb }
18288e93258fSBjoern A. Zeeb 
18298e93258fSBjoern A. Zeeb void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
18308e93258fSBjoern A. Zeeb 				 const struct rtw89_txpwr_table *tbl)
18318e93258fSBjoern A. Zeeb {
18328e93258fSBjoern A. Zeeb 	const struct rtw89_txpwr_byrate_cfg *cfg = tbl->data;
18338e93258fSBjoern A. Zeeb 	const struct rtw89_txpwr_byrate_cfg *end = cfg + tbl->size;
1834*6d67aabdSBjoern A. Zeeb 	struct rtw89_txpwr_byrate *byr_head;
1835*6d67aabdSBjoern A. Zeeb 	struct rtw89_rate_desc desc = {};
18368e93258fSBjoern A. Zeeb 	s8 *byr;
18378e93258fSBjoern A. Zeeb 	u32 data;
1838*6d67aabdSBjoern A. Zeeb 	u8 i;
18398e93258fSBjoern A. Zeeb 
18408e93258fSBjoern A. Zeeb 	for (; cfg < end; cfg++) {
1841*6d67aabdSBjoern A. Zeeb 		byr_head = &rtwdev->byr[cfg->band][0];
1842*6d67aabdSBjoern A. Zeeb 		desc.rs = cfg->rs;
1843*6d67aabdSBjoern A. Zeeb 		desc.nss = cfg->nss;
18448e93258fSBjoern A. Zeeb 		data = cfg->data;
18458e93258fSBjoern A. Zeeb 
18468e93258fSBjoern A. Zeeb 		for (i = 0; i < cfg->len; i++, data >>= 8) {
1847*6d67aabdSBjoern A. Zeeb 			desc.idx = cfg->shf + i;
1848*6d67aabdSBjoern A. Zeeb 			byr = rtw89_phy_raw_byr_seek(rtwdev, byr_head, &desc);
1849*6d67aabdSBjoern A. Zeeb 			*byr = data & 0xff;
18508e93258fSBjoern A. Zeeb 		}
18518e93258fSBjoern A. Zeeb 	}
18528e93258fSBjoern A. Zeeb }
18538e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_load_txpwr_byrate);
18548e93258fSBjoern A. Zeeb 
1855*6d67aabdSBjoern A. Zeeb static s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf)
1856*6d67aabdSBjoern A. Zeeb {
1857*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
18588e93258fSBjoern A. Zeeb 
1859*6d67aabdSBjoern A. Zeeb 	return txpwr_rf >> (chip->txpwr_factor_rf - chip->txpwr_factor_mac);
1860*6d67aabdSBjoern A. Zeeb }
1861*6d67aabdSBjoern A. Zeeb 
1862*6d67aabdSBjoern A. Zeeb static s8 rtw89_phy_txpwr_dbm_to_mac(struct rtw89_dev *rtwdev, s8 dbm)
1863*6d67aabdSBjoern A. Zeeb {
1864*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
1865*6d67aabdSBjoern A. Zeeb 
1866*6d67aabdSBjoern A. Zeeb 	return clamp_t(s16, dbm << chip->txpwr_factor_mac, -64, 63);
1867*6d67aabdSBjoern A. Zeeb }
1868*6d67aabdSBjoern A. Zeeb 
1869*6d67aabdSBjoern A. Zeeb static s8 rtw89_phy_txpwr_dbm_without_tolerance(s8 dbm)
1870*6d67aabdSBjoern A. Zeeb {
1871*6d67aabdSBjoern A. Zeeb 	const u8 tssi_deviation_point = 0;
1872*6d67aabdSBjoern A. Zeeb 	const u8 tssi_max_deviation = 2;
1873*6d67aabdSBjoern A. Zeeb 
1874*6d67aabdSBjoern A. Zeeb 	if (dbm <= tssi_deviation_point)
1875*6d67aabdSBjoern A. Zeeb 		dbm -= tssi_max_deviation;
1876*6d67aabdSBjoern A. Zeeb 
1877*6d67aabdSBjoern A. Zeeb 	return dbm;
1878*6d67aabdSBjoern A. Zeeb }
1879*6d67aabdSBjoern A. Zeeb 
1880*6d67aabdSBjoern A. Zeeb static s8 rtw89_phy_get_tpe_constraint(struct rtw89_dev *rtwdev, u8 band)
1881*6d67aabdSBjoern A. Zeeb {
1882*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
1883*6d67aabdSBjoern A. Zeeb 	const struct rtw89_reg_6ghz_tpe *tpe = &regulatory->reg_6ghz_tpe;
1884*6d67aabdSBjoern A. Zeeb 	s8 cstr = S8_MAX;
1885*6d67aabdSBjoern A. Zeeb 
1886*6d67aabdSBjoern A. Zeeb 	if (band == RTW89_BAND_6G && tpe->valid)
1887*6d67aabdSBjoern A. Zeeb 		cstr = rtw89_phy_txpwr_dbm_without_tolerance(tpe->constraint);
1888*6d67aabdSBjoern A. Zeeb 
1889*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_txpwr_dbm_to_mac(rtwdev, cstr);
1890*6d67aabdSBjoern A. Zeeb }
1891*6d67aabdSBjoern A. Zeeb 
1892*6d67aabdSBjoern A. Zeeb s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band, u8 bw,
18938e93258fSBjoern A. Zeeb 			       const struct rtw89_rate_desc *rate_desc)
18948e93258fSBjoern A. Zeeb {
1895*6d67aabdSBjoern A. Zeeb 	struct rtw89_txpwr_byrate *byr_head;
18968e93258fSBjoern A. Zeeb 	s8 *byr;
18978e93258fSBjoern A. Zeeb 
18988e93258fSBjoern A. Zeeb 	if (rate_desc->rs == RTW89_RS_CCK)
18998e93258fSBjoern A. Zeeb 		band = RTW89_BAND_2G;
19008e93258fSBjoern A. Zeeb 
1901*6d67aabdSBjoern A. Zeeb 	byr_head = &rtwdev->byr[band][bw];
1902*6d67aabdSBjoern A. Zeeb 	byr = rtw89_phy_raw_byr_seek(rtwdev, byr_head, rate_desc);
19038e93258fSBjoern A. Zeeb 
1904*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_txpwr_rf_to_mac(rtwdev, *byr);
19058e93258fSBjoern A. Zeeb }
19068e93258fSBjoern A. Zeeb 
19078e93258fSBjoern A. Zeeb static u8 rtw89_channel_6g_to_idx(struct rtw89_dev *rtwdev, u8 channel_6g)
19088e93258fSBjoern A. Zeeb {
19098e93258fSBjoern A. Zeeb 	switch (channel_6g) {
19108e93258fSBjoern A. Zeeb 	case 1 ... 29:
19118e93258fSBjoern A. Zeeb 		return (channel_6g - 1) / 2;
19128e93258fSBjoern A. Zeeb 	case 33 ... 61:
19138e93258fSBjoern A. Zeeb 		return (channel_6g - 3) / 2;
19148e93258fSBjoern A. Zeeb 	case 65 ... 93:
19158e93258fSBjoern A. Zeeb 		return (channel_6g - 5) / 2;
19168e93258fSBjoern A. Zeeb 	case 97 ... 125:
19178e93258fSBjoern A. Zeeb 		return (channel_6g - 7) / 2;
19188e93258fSBjoern A. Zeeb 	case 129 ... 157:
19198e93258fSBjoern A. Zeeb 		return (channel_6g - 9) / 2;
19208e93258fSBjoern A. Zeeb 	case 161 ... 189:
19218e93258fSBjoern A. Zeeb 		return (channel_6g - 11) / 2;
19228e93258fSBjoern A. Zeeb 	case 193 ... 221:
19238e93258fSBjoern A. Zeeb 		return (channel_6g - 13) / 2;
19248e93258fSBjoern A. Zeeb 	case 225 ... 253:
19258e93258fSBjoern A. Zeeb 		return (channel_6g - 15) / 2;
19268e93258fSBjoern A. Zeeb 	default:
19278e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "unknown 6g channel: %d\n", channel_6g);
19288e93258fSBjoern A. Zeeb 		return 0;
19298e93258fSBjoern A. Zeeb 	}
19308e93258fSBjoern A. Zeeb }
19318e93258fSBjoern A. Zeeb 
19328e93258fSBjoern A. Zeeb static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel)
19338e93258fSBjoern A. Zeeb {
19348e93258fSBjoern A. Zeeb 	if (band == RTW89_BAND_6G)
19358e93258fSBjoern A. Zeeb 		return rtw89_channel_6g_to_idx(rtwdev, channel);
19368e93258fSBjoern A. Zeeb 
19378e93258fSBjoern A. Zeeb 	switch (channel) {
19388e93258fSBjoern A. Zeeb 	case 1 ... 14:
19398e93258fSBjoern A. Zeeb 		return channel - 1;
19408e93258fSBjoern A. Zeeb 	case 36 ... 64:
19418e93258fSBjoern A. Zeeb 		return (channel - 36) / 2;
19428e93258fSBjoern A. Zeeb 	case 100 ... 144:
19438e93258fSBjoern A. Zeeb 		return ((channel - 100) / 2) + 15;
19448e93258fSBjoern A. Zeeb 	case 149 ... 177:
19458e93258fSBjoern A. Zeeb 		return ((channel - 149) / 2) + 38;
19468e93258fSBjoern A. Zeeb 	default:
19478e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "unknown channel: %d\n", channel);
19488e93258fSBjoern A. Zeeb 		return 0;
19498e93258fSBjoern A. Zeeb 	}
19508e93258fSBjoern A. Zeeb }
19518e93258fSBjoern A. Zeeb 
19528e93258fSBjoern A. Zeeb s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
19538e93258fSBjoern A. Zeeb 			      u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
19548e93258fSBjoern A. Zeeb {
1955e2340276SBjoern A. Zeeb 	const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
1956e2340276SBjoern A. Zeeb 	const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
1957e2340276SBjoern A. Zeeb 	const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
1958e2340276SBjoern A. Zeeb 	const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
1959e2340276SBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
1960*6d67aabdSBjoern A. Zeeb 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
1961*6d67aabdSBjoern A. Zeeb 	u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
19628e93258fSBjoern A. Zeeb 	u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
19638e93258fSBjoern A. Zeeb 	u8 regd = rtw89_regd_get(rtwdev, band);
1964e2340276SBjoern A. Zeeb 	u8 reg6 = regulatory->reg_6ghz_power;
19658e93258fSBjoern A. Zeeb 	s8 lmt = 0, sar;
1966*6d67aabdSBjoern A. Zeeb 	s8 cstr;
19678e93258fSBjoern A. Zeeb 
19688e93258fSBjoern A. Zeeb 	switch (band) {
19698e93258fSBjoern A. Zeeb 	case RTW89_BAND_2G:
1970e2340276SBjoern A. Zeeb 		lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
1971e2340276SBjoern A. Zeeb 		if (lmt)
1972e2340276SBjoern A. Zeeb 			break;
1973e2340276SBjoern A. Zeeb 
1974e2340276SBjoern A. Zeeb 		lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
19758e93258fSBjoern A. Zeeb 		break;
19768e93258fSBjoern A. Zeeb 	case RTW89_BAND_5G:
1977e2340276SBjoern A. Zeeb 		lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
1978e2340276SBjoern A. Zeeb 		if (lmt)
1979e2340276SBjoern A. Zeeb 			break;
1980e2340276SBjoern A. Zeeb 
1981e2340276SBjoern A. Zeeb 		lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
19828e93258fSBjoern A. Zeeb 		break;
19838e93258fSBjoern A. Zeeb 	case RTW89_BAND_6G:
1984e2340276SBjoern A. Zeeb 		lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
1985e2340276SBjoern A. Zeeb 		if (lmt)
1986e2340276SBjoern A. Zeeb 			break;
1987e2340276SBjoern A. Zeeb 
1988e2340276SBjoern A. Zeeb 		lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW]
1989e2340276SBjoern A. Zeeb 				       [RTW89_REG_6GHZ_POWER_DFLT]
1990e2340276SBjoern A. Zeeb 				       [ch_idx];
19918e93258fSBjoern A. Zeeb 		break;
19928e93258fSBjoern A. Zeeb 	default:
19938e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "unknown band type: %d\n", band);
19948e93258fSBjoern A. Zeeb 		return 0;
19958e93258fSBjoern A. Zeeb 	}
19968e93258fSBjoern A. Zeeb 
1997*6d67aabdSBjoern A. Zeeb 	lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt);
1998*6d67aabdSBjoern A. Zeeb 	sar = rtw89_query_sar(rtwdev, freq);
1999*6d67aabdSBjoern A. Zeeb 	cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
20008e93258fSBjoern A. Zeeb 
2001*6d67aabdSBjoern A. Zeeb 	return min3(lmt, sar, cstr);
20028e93258fSBjoern A. Zeeb }
20038e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_read_txpwr_limit);
20048e93258fSBjoern A. Zeeb 
20058e93258fSBjoern A. Zeeb #define __fill_txpwr_limit_nonbf_bf(ptr, band, bw, ntx, rs, ch)		\
20068e93258fSBjoern A. Zeeb 	do {								\
20078e93258fSBjoern A. Zeeb 		u8 __i;							\
20088e93258fSBjoern A. Zeeb 		for (__i = 0; __i < RTW89_BF_NUM; __i++)		\
20098e93258fSBjoern A. Zeeb 			ptr[__i] = rtw89_phy_read_txpwr_limit(rtwdev,	\
20108e93258fSBjoern A. Zeeb 							      band,	\
20118e93258fSBjoern A. Zeeb 							      bw, ntx,	\
20128e93258fSBjoern A. Zeeb 							      rs, __i,	\
20138e93258fSBjoern A. Zeeb 							      (ch));	\
20148e93258fSBjoern A. Zeeb 	} while (0)
20158e93258fSBjoern A. Zeeb 
2016*6d67aabdSBjoern A. Zeeb static void rtw89_phy_fill_txpwr_limit_20m_ax(struct rtw89_dev *rtwdev,
2017*6d67aabdSBjoern A. Zeeb 					      struct rtw89_txpwr_limit_ax *lmt,
20188e93258fSBjoern A. Zeeb 					      u8 band, u8 ntx, u8 ch)
20198e93258fSBjoern A. Zeeb {
20208e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
20218e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_CCK, ch);
20228e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
20238e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_CCK, ch);
20248e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
20258e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_OFDM, ch);
20268e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
20278e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
20288e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch);
20298e93258fSBjoern A. Zeeb }
20308e93258fSBjoern A. Zeeb 
2031*6d67aabdSBjoern A. Zeeb static void rtw89_phy_fill_txpwr_limit_40m_ax(struct rtw89_dev *rtwdev,
2032*6d67aabdSBjoern A. Zeeb 					      struct rtw89_txpwr_limit_ax *lmt,
20338e93258fSBjoern A. Zeeb 					      u8 band, u8 ntx, u8 ch, u8 pri_ch)
20348e93258fSBjoern A. Zeeb {
20358e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
20368e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_CCK, ch - 2);
20378e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
20388e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_CCK, ch);
20398e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
20408e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_OFDM, pri_ch);
20418e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
20428e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
20438e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 2);
20448e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
20458e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
20468e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 2);
20478e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
20488e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_40,
20498e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch);
20508e93258fSBjoern A. Zeeb }
20518e93258fSBjoern A. Zeeb 
2052*6d67aabdSBjoern A. Zeeb static void rtw89_phy_fill_txpwr_limit_80m_ax(struct rtw89_dev *rtwdev,
2053*6d67aabdSBjoern A. Zeeb 					      struct rtw89_txpwr_limit_ax *lmt,
20548e93258fSBjoern A. Zeeb 					      u8 band, u8 ntx, u8 ch, u8 pri_ch)
20558e93258fSBjoern A. Zeeb {
20568e93258fSBjoern A. Zeeb 	s8 val_0p5_n[RTW89_BF_NUM];
20578e93258fSBjoern A. Zeeb 	s8 val_0p5_p[RTW89_BF_NUM];
20588e93258fSBjoern A. Zeeb 	u8 i;
20598e93258fSBjoern A. Zeeb 
20608e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
20618e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_OFDM, pri_ch);
20628e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
20638e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
20648e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 6);
20658e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
20668e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
20678e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 2);
20688e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
20698e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
20708e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 2);
20718e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
20728e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
20738e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 6);
20748e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
20758e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_40,
20768e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 4);
20778e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
20788e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_40,
20798e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 4);
20808e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
20818e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_80,
20828e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch);
20838e93258fSBjoern A. Zeeb 
20848e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
20858e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 4);
20868e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
20878e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 4);
20888e93258fSBjoern A. Zeeb 
20898e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_BF_NUM; i++)
20908e93258fSBjoern A. Zeeb 		lmt->mcs_40m_0p5[i] = min_t(s8, val_0p5_n[i], val_0p5_p[i]);
20918e93258fSBjoern A. Zeeb }
20928e93258fSBjoern A. Zeeb 
2093*6d67aabdSBjoern A. Zeeb static void rtw89_phy_fill_txpwr_limit_160m_ax(struct rtw89_dev *rtwdev,
2094*6d67aabdSBjoern A. Zeeb 					       struct rtw89_txpwr_limit_ax *lmt,
20958e93258fSBjoern A. Zeeb 					       u8 band, u8 ntx, u8 ch, u8 pri_ch)
20968e93258fSBjoern A. Zeeb {
20978e93258fSBjoern A. Zeeb 	s8 val_0p5_n[RTW89_BF_NUM];
20988e93258fSBjoern A. Zeeb 	s8 val_0p5_p[RTW89_BF_NUM];
20998e93258fSBjoern A. Zeeb 	s8 val_2p5_n[RTW89_BF_NUM];
21008e93258fSBjoern A. Zeeb 	s8 val_2p5_p[RTW89_BF_NUM];
21018e93258fSBjoern A. Zeeb 	u8 i;
21028e93258fSBjoern A. Zeeb 
21038e93258fSBjoern A. Zeeb 	/* fill ofdm section */
21048e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
21058e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_OFDM, pri_ch);
21068e93258fSBjoern A. Zeeb 
21078e93258fSBjoern A. Zeeb 	/* fill mcs 20m section */
21088e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
21098e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21108e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 14);
21118e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
21128e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21138e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 10);
21148e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
21158e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21168e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 6);
21178e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
21188e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21198e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 2);
21208e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[4], band,
21218e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21228e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 2);
21238e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[5], band,
21248e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21258e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 6);
21268e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[6], band,
21278e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21288e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 10);
21298e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[7], band,
21308e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_20,
21318e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 14);
21328e93258fSBjoern A. Zeeb 
21338e93258fSBjoern A. Zeeb 	/* fill mcs 40m section */
21348e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
21358e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_40,
21368e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 12);
21378e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
21388e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_40,
21398e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 4);
21408e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[2], band,
21418e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_40,
21428e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 4);
21438e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[3], band,
21448e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_40,
21458e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 12);
21468e93258fSBjoern A. Zeeb 
21478e93258fSBjoern A. Zeeb 	/* fill mcs 80m section */
21488e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
21498e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_80,
21508e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 8);
21518e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[1], band,
21528e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_80,
21538e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 8);
21548e93258fSBjoern A. Zeeb 
21558e93258fSBjoern A. Zeeb 	/* fill mcs 160m section */
21568e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(lmt->mcs_160m, band,
21578e93258fSBjoern A. Zeeb 				    RTW89_CHANNEL_WIDTH_160,
21588e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch);
21598e93258fSBjoern A. Zeeb 
21608e93258fSBjoern A. Zeeb 	/* fill mcs 40m 0p5 section */
21618e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
21628e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 4);
21638e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
21648e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 4);
21658e93258fSBjoern A. Zeeb 
21668e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_BF_NUM; i++)
21678e93258fSBjoern A. Zeeb 		lmt->mcs_40m_0p5[i] = min_t(s8, val_0p5_n[i], val_0p5_p[i]);
21688e93258fSBjoern A. Zeeb 
21698e93258fSBjoern A. Zeeb 	/* fill mcs 40m 2p5 section */
21708e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(val_2p5_n, band, RTW89_CHANNEL_WIDTH_40,
21718e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch - 8);
21728e93258fSBjoern A. Zeeb 	__fill_txpwr_limit_nonbf_bf(val_2p5_p, band, RTW89_CHANNEL_WIDTH_40,
21738e93258fSBjoern A. Zeeb 				    ntx, RTW89_RS_MCS, ch + 8);
21748e93258fSBjoern A. Zeeb 
21758e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_BF_NUM; i++)
21768e93258fSBjoern A. Zeeb 		lmt->mcs_40m_2p5[i] = min_t(s8, val_2p5_n[i], val_2p5_p[i]);
21778e93258fSBjoern A. Zeeb }
21788e93258fSBjoern A. Zeeb 
2179e2340276SBjoern A. Zeeb static
2180*6d67aabdSBjoern A. Zeeb void rtw89_phy_fill_txpwr_limit_ax(struct rtw89_dev *rtwdev,
21818e93258fSBjoern A. Zeeb 				   const struct rtw89_chan *chan,
2182*6d67aabdSBjoern A. Zeeb 				   struct rtw89_txpwr_limit_ax *lmt,
21838e93258fSBjoern A. Zeeb 				   u8 ntx)
21848e93258fSBjoern A. Zeeb {
21858e93258fSBjoern A. Zeeb 	u8 band = chan->band_type;
21868e93258fSBjoern A. Zeeb 	u8 pri_ch = chan->primary_channel;
21878e93258fSBjoern A. Zeeb 	u8 ch = chan->channel;
21888e93258fSBjoern A. Zeeb 	u8 bw = chan->band_width;
21898e93258fSBjoern A. Zeeb 
21908e93258fSBjoern A. Zeeb 	memset(lmt, 0, sizeof(*lmt));
21918e93258fSBjoern A. Zeeb 
21928e93258fSBjoern A. Zeeb 	switch (bw) {
21938e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_20:
2194*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_20m_ax(rtwdev, lmt, band, ntx, ch);
21958e93258fSBjoern A. Zeeb 		break;
21968e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_40:
2197*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_40m_ax(rtwdev, lmt, band, ntx, ch,
21988e93258fSBjoern A. Zeeb 						  pri_ch);
21998e93258fSBjoern A. Zeeb 		break;
22008e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_80:
2201*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_80m_ax(rtwdev, lmt, band, ntx, ch,
22028e93258fSBjoern A. Zeeb 						  pri_ch);
22038e93258fSBjoern A. Zeeb 		break;
22048e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_160:
2205*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_160m_ax(rtwdev, lmt, band, ntx, ch,
22068e93258fSBjoern A. Zeeb 						   pri_ch);
22078e93258fSBjoern A. Zeeb 		break;
22088e93258fSBjoern A. Zeeb 	}
22098e93258fSBjoern A. Zeeb }
22108e93258fSBjoern A. Zeeb 
2211*6d67aabdSBjoern A. Zeeb s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
22128e93258fSBjoern A. Zeeb 				 u8 ru, u8 ntx, u8 ch)
22138e93258fSBjoern A. Zeeb {
2214e2340276SBjoern A. Zeeb 	const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
2215e2340276SBjoern A. Zeeb 	const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
2216e2340276SBjoern A. Zeeb 	const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
2217e2340276SBjoern A. Zeeb 	const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
2218e2340276SBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
2219*6d67aabdSBjoern A. Zeeb 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
2220*6d67aabdSBjoern A. Zeeb 	u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
22218e93258fSBjoern A. Zeeb 	u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
22228e93258fSBjoern A. Zeeb 	u8 regd = rtw89_regd_get(rtwdev, band);
2223e2340276SBjoern A. Zeeb 	u8 reg6 = regulatory->reg_6ghz_power;
22248e93258fSBjoern A. Zeeb 	s8 lmt_ru = 0, sar;
2225*6d67aabdSBjoern A. Zeeb 	s8 cstr;
22268e93258fSBjoern A. Zeeb 
22278e93258fSBjoern A. Zeeb 	switch (band) {
22288e93258fSBjoern A. Zeeb 	case RTW89_BAND_2G:
2229e2340276SBjoern A. Zeeb 		lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
2230e2340276SBjoern A. Zeeb 		if (lmt_ru)
2231e2340276SBjoern A. Zeeb 			break;
2232e2340276SBjoern A. Zeeb 
2233e2340276SBjoern A. Zeeb 		lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
22348e93258fSBjoern A. Zeeb 		break;
22358e93258fSBjoern A. Zeeb 	case RTW89_BAND_5G:
2236e2340276SBjoern A. Zeeb 		lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
2237e2340276SBjoern A. Zeeb 		if (lmt_ru)
2238e2340276SBjoern A. Zeeb 			break;
2239e2340276SBjoern A. Zeeb 
2240e2340276SBjoern A. Zeeb 		lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
22418e93258fSBjoern A. Zeeb 		break;
22428e93258fSBjoern A. Zeeb 	case RTW89_BAND_6G:
2243e2340276SBjoern A. Zeeb 		lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
2244e2340276SBjoern A. Zeeb 		if (lmt_ru)
2245e2340276SBjoern A. Zeeb 			break;
2246e2340276SBjoern A. Zeeb 
2247e2340276SBjoern A. Zeeb 		lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW]
2248e2340276SBjoern A. Zeeb 					     [RTW89_REG_6GHZ_POWER_DFLT]
2249e2340276SBjoern A. Zeeb 					     [ch_idx];
22508e93258fSBjoern A. Zeeb 		break;
22518e93258fSBjoern A. Zeeb 	default:
22528e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "unknown band type: %d\n", band);
22538e93258fSBjoern A. Zeeb 		return 0;
22548e93258fSBjoern A. Zeeb 	}
22558e93258fSBjoern A. Zeeb 
2256*6d67aabdSBjoern A. Zeeb 	lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt_ru);
2257*6d67aabdSBjoern A. Zeeb 	sar = rtw89_query_sar(rtwdev, freq);
2258*6d67aabdSBjoern A. Zeeb 	cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
22598e93258fSBjoern A. Zeeb 
2260*6d67aabdSBjoern A. Zeeb 	return min3(lmt_ru, sar, cstr);
22618e93258fSBjoern A. Zeeb }
22628e93258fSBjoern A. Zeeb 
22638e93258fSBjoern A. Zeeb static void
2264*6d67aabdSBjoern A. Zeeb rtw89_phy_fill_txpwr_limit_ru_20m_ax(struct rtw89_dev *rtwdev,
2265*6d67aabdSBjoern A. Zeeb 				     struct rtw89_txpwr_limit_ru_ax *lmt_ru,
22668e93258fSBjoern A. Zeeb 				     u8 band, u8 ntx, u8 ch)
22678e93258fSBjoern A. Zeeb {
22688e93258fSBjoern A. Zeeb 	lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22698e93258fSBjoern A. Zeeb 							RTW89_RU26,
22708e93258fSBjoern A. Zeeb 							ntx, ch);
22718e93258fSBjoern A. Zeeb 	lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22728e93258fSBjoern A. Zeeb 							RTW89_RU52,
22738e93258fSBjoern A. Zeeb 							ntx, ch);
22748e93258fSBjoern A. Zeeb 	lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22758e93258fSBjoern A. Zeeb 							 RTW89_RU106,
22768e93258fSBjoern A. Zeeb 							 ntx, ch);
22778e93258fSBjoern A. Zeeb }
22788e93258fSBjoern A. Zeeb 
22798e93258fSBjoern A. Zeeb static void
2280*6d67aabdSBjoern A. Zeeb rtw89_phy_fill_txpwr_limit_ru_40m_ax(struct rtw89_dev *rtwdev,
2281*6d67aabdSBjoern A. Zeeb 				     struct rtw89_txpwr_limit_ru_ax *lmt_ru,
22828e93258fSBjoern A. Zeeb 				     u8 band, u8 ntx, u8 ch)
22838e93258fSBjoern A. Zeeb {
22848e93258fSBjoern A. Zeeb 	lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22858e93258fSBjoern A. Zeeb 							RTW89_RU26,
22868e93258fSBjoern A. Zeeb 							ntx, ch - 2);
22878e93258fSBjoern A. Zeeb 	lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22888e93258fSBjoern A. Zeeb 							RTW89_RU26,
22898e93258fSBjoern A. Zeeb 							ntx, ch + 2);
22908e93258fSBjoern A. Zeeb 	lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22918e93258fSBjoern A. Zeeb 							RTW89_RU52,
22928e93258fSBjoern A. Zeeb 							ntx, ch - 2);
22938e93258fSBjoern A. Zeeb 	lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22948e93258fSBjoern A. Zeeb 							RTW89_RU52,
22958e93258fSBjoern A. Zeeb 							ntx, ch + 2);
22968e93258fSBjoern A. Zeeb 	lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
22978e93258fSBjoern A. Zeeb 							 RTW89_RU106,
22988e93258fSBjoern A. Zeeb 							 ntx, ch - 2);
22998e93258fSBjoern A. Zeeb 	lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23008e93258fSBjoern A. Zeeb 							 RTW89_RU106,
23018e93258fSBjoern A. Zeeb 							 ntx, ch + 2);
23028e93258fSBjoern A. Zeeb }
23038e93258fSBjoern A. Zeeb 
23048e93258fSBjoern A. Zeeb static void
2305*6d67aabdSBjoern A. Zeeb rtw89_phy_fill_txpwr_limit_ru_80m_ax(struct rtw89_dev *rtwdev,
2306*6d67aabdSBjoern A. Zeeb 				     struct rtw89_txpwr_limit_ru_ax *lmt_ru,
23078e93258fSBjoern A. Zeeb 				     u8 band, u8 ntx, u8 ch)
23088e93258fSBjoern A. Zeeb {
23098e93258fSBjoern A. Zeeb 	lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23108e93258fSBjoern A. Zeeb 							RTW89_RU26,
23118e93258fSBjoern A. Zeeb 							ntx, ch - 6);
23128e93258fSBjoern A. Zeeb 	lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23138e93258fSBjoern A. Zeeb 							RTW89_RU26,
23148e93258fSBjoern A. Zeeb 							ntx, ch - 2);
23158e93258fSBjoern A. Zeeb 	lmt_ru->ru26[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23168e93258fSBjoern A. Zeeb 							RTW89_RU26,
23178e93258fSBjoern A. Zeeb 							ntx, ch + 2);
23188e93258fSBjoern A. Zeeb 	lmt_ru->ru26[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23198e93258fSBjoern A. Zeeb 							RTW89_RU26,
23208e93258fSBjoern A. Zeeb 							ntx, ch + 6);
23218e93258fSBjoern A. Zeeb 	lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23228e93258fSBjoern A. Zeeb 							RTW89_RU52,
23238e93258fSBjoern A. Zeeb 							ntx, ch - 6);
23248e93258fSBjoern A. Zeeb 	lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23258e93258fSBjoern A. Zeeb 							RTW89_RU52,
23268e93258fSBjoern A. Zeeb 							ntx, ch - 2);
23278e93258fSBjoern A. Zeeb 	lmt_ru->ru52[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23288e93258fSBjoern A. Zeeb 							RTW89_RU52,
23298e93258fSBjoern A. Zeeb 							ntx, ch + 2);
23308e93258fSBjoern A. Zeeb 	lmt_ru->ru52[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23318e93258fSBjoern A. Zeeb 							RTW89_RU52,
23328e93258fSBjoern A. Zeeb 							ntx, ch + 6);
23338e93258fSBjoern A. Zeeb 	lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23348e93258fSBjoern A. Zeeb 							 RTW89_RU106,
23358e93258fSBjoern A. Zeeb 							 ntx, ch - 6);
23368e93258fSBjoern A. Zeeb 	lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23378e93258fSBjoern A. Zeeb 							 RTW89_RU106,
23388e93258fSBjoern A. Zeeb 							 ntx, ch - 2);
23398e93258fSBjoern A. Zeeb 	lmt_ru->ru106[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23408e93258fSBjoern A. Zeeb 							 RTW89_RU106,
23418e93258fSBjoern A. Zeeb 							 ntx, ch + 2);
23428e93258fSBjoern A. Zeeb 	lmt_ru->ru106[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23438e93258fSBjoern A. Zeeb 							 RTW89_RU106,
23448e93258fSBjoern A. Zeeb 							 ntx, ch + 6);
23458e93258fSBjoern A. Zeeb }
23468e93258fSBjoern A. Zeeb 
23478e93258fSBjoern A. Zeeb static void
2348*6d67aabdSBjoern A. Zeeb rtw89_phy_fill_txpwr_limit_ru_160m_ax(struct rtw89_dev *rtwdev,
2349*6d67aabdSBjoern A. Zeeb 				      struct rtw89_txpwr_limit_ru_ax *lmt_ru,
23508e93258fSBjoern A. Zeeb 				      u8 band, u8 ntx, u8 ch)
23518e93258fSBjoern A. Zeeb {
23528e93258fSBjoern A. Zeeb 	static const int ofst[] = { -14, -10, -6, -2, 2, 6, 10, 14 };
23538e93258fSBjoern A. Zeeb 	int i;
23548e93258fSBjoern A. Zeeb 
23558e93258fSBjoern A. Zeeb #if defined(__linux__)
2356*6d67aabdSBjoern A. Zeeb 	static_assert(ARRAY_SIZE(ofst) == RTW89_RU_SEC_NUM_AX);
23578e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__)
2358*6d67aabdSBjoern A. Zeeb 	rtw89_static_assert(ARRAY_SIZE(ofst) == RTW89_RU_SEC_NUM_AX);
23598e93258fSBjoern A. Zeeb #endif
2360*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < RTW89_RU_SEC_NUM_AX; i++) {
23618e93258fSBjoern A. Zeeb 		lmt_ru->ru26[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23628e93258fSBjoern A. Zeeb 								RTW89_RU26,
23638e93258fSBjoern A. Zeeb 								ntx,
23648e93258fSBjoern A. Zeeb 								ch + ofst[i]);
23658e93258fSBjoern A. Zeeb 		lmt_ru->ru52[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23668e93258fSBjoern A. Zeeb 								RTW89_RU52,
23678e93258fSBjoern A. Zeeb 								ntx,
23688e93258fSBjoern A. Zeeb 								ch + ofst[i]);
23698e93258fSBjoern A. Zeeb 		lmt_ru->ru106[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
23708e93258fSBjoern A. Zeeb 								 RTW89_RU106,
23718e93258fSBjoern A. Zeeb 								 ntx,
23728e93258fSBjoern A. Zeeb 								 ch + ofst[i]);
23738e93258fSBjoern A. Zeeb 	}
23748e93258fSBjoern A. Zeeb }
23758e93258fSBjoern A. Zeeb 
2376e2340276SBjoern A. Zeeb static
2377*6d67aabdSBjoern A. Zeeb void rtw89_phy_fill_txpwr_limit_ru_ax(struct rtw89_dev *rtwdev,
23788e93258fSBjoern A. Zeeb 				      const struct rtw89_chan *chan,
2379*6d67aabdSBjoern A. Zeeb 				      struct rtw89_txpwr_limit_ru_ax *lmt_ru,
23808e93258fSBjoern A. Zeeb 				      u8 ntx)
23818e93258fSBjoern A. Zeeb {
23828e93258fSBjoern A. Zeeb 	u8 band = chan->band_type;
23838e93258fSBjoern A. Zeeb 	u8 ch = chan->channel;
23848e93258fSBjoern A. Zeeb 	u8 bw = chan->band_width;
23858e93258fSBjoern A. Zeeb 
23868e93258fSBjoern A. Zeeb 	memset(lmt_ru, 0, sizeof(*lmt_ru));
23878e93258fSBjoern A. Zeeb 
23888e93258fSBjoern A. Zeeb 	switch (bw) {
23898e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_20:
2390*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_ru_20m_ax(rtwdev, lmt_ru, band, ntx,
23918e93258fSBjoern A. Zeeb 						     ch);
23928e93258fSBjoern A. Zeeb 		break;
23938e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_40:
2394*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_ru_40m_ax(rtwdev, lmt_ru, band, ntx,
23958e93258fSBjoern A. Zeeb 						     ch);
23968e93258fSBjoern A. Zeeb 		break;
23978e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_80:
2398*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_ru_80m_ax(rtwdev, lmt_ru, band, ntx,
23998e93258fSBjoern A. Zeeb 						     ch);
24008e93258fSBjoern A. Zeeb 		break;
24018e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_160:
2402*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_ru_160m_ax(rtwdev, lmt_ru, band, ntx,
24038e93258fSBjoern A. Zeeb 						      ch);
24048e93258fSBjoern A. Zeeb 		break;
24058e93258fSBjoern A. Zeeb 	}
24068e93258fSBjoern A. Zeeb }
2407e2340276SBjoern A. Zeeb 
2408*6d67aabdSBjoern A. Zeeb static void rtw89_phy_set_txpwr_byrate_ax(struct rtw89_dev *rtwdev,
2409e2340276SBjoern A. Zeeb 					  const struct rtw89_chan *chan,
2410e2340276SBjoern A. Zeeb 					  enum rtw89_phy_idx phy_idx)
2411e2340276SBjoern A. Zeeb {
2412e2340276SBjoern A. Zeeb 	u8 max_nss_num = rtwdev->chip->rf_path_num;
2413e2340276SBjoern A. Zeeb 	static const u8 rs[] = {
2414e2340276SBjoern A. Zeeb 		RTW89_RS_CCK,
2415e2340276SBjoern A. Zeeb 		RTW89_RS_OFDM,
2416e2340276SBjoern A. Zeeb 		RTW89_RS_MCS,
2417e2340276SBjoern A. Zeeb 		RTW89_RS_HEDCM,
2418e2340276SBjoern A. Zeeb 	};
2419*6d67aabdSBjoern A. Zeeb 	struct rtw89_rate_desc cur = {};
2420e2340276SBjoern A. Zeeb 	u8 band = chan->band_type;
2421e2340276SBjoern A. Zeeb 	u8 ch = chan->channel;
2422e2340276SBjoern A. Zeeb 	u32 addr, val;
2423e2340276SBjoern A. Zeeb 	s8 v[4] = {};
2424e2340276SBjoern A. Zeeb 	u8 i;
2425e2340276SBjoern A. Zeeb 
2426e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2427e2340276SBjoern A. Zeeb 		    "[TXPWR] set txpwr byrate with ch=%d\n", ch);
2428e2340276SBjoern A. Zeeb 
2429*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_CCK] % 4);
2430*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_OFDM] % 4);
2431*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_MCS] % 4);
2432*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(rtw89_rs_idx_num_ax[RTW89_RS_HEDCM] % 4);
2433e2340276SBjoern A. Zeeb 
2434e2340276SBjoern A. Zeeb 	addr = R_AX_PWR_BY_RATE;
2435e2340276SBjoern A. Zeeb 	for (cur.nss = 0; cur.nss < max_nss_num; cur.nss++) {
2436e2340276SBjoern A. Zeeb 		for (i = 0; i < ARRAY_SIZE(rs); i++) {
2437*6d67aabdSBjoern A. Zeeb 			if (cur.nss >= rtw89_rs_nss_num_ax[rs[i]])
2438e2340276SBjoern A. Zeeb 				continue;
2439e2340276SBjoern A. Zeeb 
2440e2340276SBjoern A. Zeeb 			cur.rs = rs[i];
2441*6d67aabdSBjoern A. Zeeb 			for (cur.idx = 0; cur.idx < rtw89_rs_idx_num_ax[rs[i]];
2442e2340276SBjoern A. Zeeb 			     cur.idx++) {
2443e2340276SBjoern A. Zeeb 				v[cur.idx % 4] =
2444e2340276SBjoern A. Zeeb 					rtw89_phy_read_txpwr_byrate(rtwdev,
2445*6d67aabdSBjoern A. Zeeb 								    band, 0,
2446e2340276SBjoern A. Zeeb 								    &cur);
2447e2340276SBjoern A. Zeeb 
2448e2340276SBjoern A. Zeeb 				if ((cur.idx + 1) % 4)
2449e2340276SBjoern A. Zeeb 					continue;
2450e2340276SBjoern A. Zeeb 
2451e2340276SBjoern A. Zeeb 				val = FIELD_PREP(GENMASK(7, 0), v[0]) |
2452e2340276SBjoern A. Zeeb 				      FIELD_PREP(GENMASK(15, 8), v[1]) |
2453e2340276SBjoern A. Zeeb 				      FIELD_PREP(GENMASK(23, 16), v[2]) |
2454e2340276SBjoern A. Zeeb 				      FIELD_PREP(GENMASK(31, 24), v[3]);
2455e2340276SBjoern A. Zeeb 
2456e2340276SBjoern A. Zeeb 				rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr,
2457e2340276SBjoern A. Zeeb 							val);
2458e2340276SBjoern A. Zeeb 				addr += 4;
2459e2340276SBjoern A. Zeeb 			}
2460e2340276SBjoern A. Zeeb 		}
2461e2340276SBjoern A. Zeeb 	}
2462e2340276SBjoern A. Zeeb }
2463e2340276SBjoern A. Zeeb 
2464*6d67aabdSBjoern A. Zeeb static
2465*6d67aabdSBjoern A. Zeeb void rtw89_phy_set_txpwr_offset_ax(struct rtw89_dev *rtwdev,
2466e2340276SBjoern A. Zeeb 				   const struct rtw89_chan *chan,
2467e2340276SBjoern A. Zeeb 				   enum rtw89_phy_idx phy_idx)
2468e2340276SBjoern A. Zeeb {
2469e2340276SBjoern A. Zeeb 	struct rtw89_rate_desc desc = {
2470e2340276SBjoern A. Zeeb 		.nss = RTW89_NSS_1,
2471e2340276SBjoern A. Zeeb 		.rs = RTW89_RS_OFFSET,
2472e2340276SBjoern A. Zeeb 	};
2473e2340276SBjoern A. Zeeb 	u8 band = chan->band_type;
2474*6d67aabdSBjoern A. Zeeb 	s8 v[RTW89_RATE_OFFSET_NUM_AX] = {};
2475e2340276SBjoern A. Zeeb 	u32 val;
2476e2340276SBjoern A. Zeeb 
2477e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
2478e2340276SBjoern A. Zeeb 
2479*6d67aabdSBjoern A. Zeeb 	for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_NUM_AX; desc.idx++)
2480*6d67aabdSBjoern A. Zeeb 		v[desc.idx] = rtw89_phy_read_txpwr_byrate(rtwdev, band, 0, &desc);
2481e2340276SBjoern A. Zeeb 
2482*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(RTW89_RATE_OFFSET_NUM_AX != 5);
2483e2340276SBjoern A. Zeeb 	val = FIELD_PREP(GENMASK(3, 0), v[0]) |
2484e2340276SBjoern A. Zeeb 	      FIELD_PREP(GENMASK(7, 4), v[1]) |
2485e2340276SBjoern A. Zeeb 	      FIELD_PREP(GENMASK(11, 8), v[2]) |
2486e2340276SBjoern A. Zeeb 	      FIELD_PREP(GENMASK(15, 12), v[3]) |
2487e2340276SBjoern A. Zeeb 	      FIELD_PREP(GENMASK(19, 16), v[4]);
2488e2340276SBjoern A. Zeeb 
2489e2340276SBjoern A. Zeeb 	rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_OFST_CTRL,
2490e2340276SBjoern A. Zeeb 				     GENMASK(19, 0), val);
2491e2340276SBjoern A. Zeeb }
2492e2340276SBjoern A. Zeeb 
2493*6d67aabdSBjoern A. Zeeb static void rtw89_phy_set_txpwr_limit_ax(struct rtw89_dev *rtwdev,
2494e2340276SBjoern A. Zeeb 					 const struct rtw89_chan *chan,
2495e2340276SBjoern A. Zeeb 					 enum rtw89_phy_idx phy_idx)
2496e2340276SBjoern A. Zeeb {
2497e2340276SBjoern A. Zeeb 	u8 max_ntx_num = rtwdev->chip->rf_path_num;
2498*6d67aabdSBjoern A. Zeeb 	struct rtw89_txpwr_limit_ax lmt;
2499e2340276SBjoern A. Zeeb 	u8 ch = chan->channel;
2500e2340276SBjoern A. Zeeb 	u8 bw = chan->band_width;
2501e2340276SBjoern A. Zeeb 	const s8 *ptr;
2502e2340276SBjoern A. Zeeb 	u32 addr, val;
2503e2340276SBjoern A. Zeeb 	u8 i, j;
2504e2340276SBjoern A. Zeeb 
2505e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2506e2340276SBjoern A. Zeeb 		    "[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
2507e2340276SBjoern A. Zeeb 
2508*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ax) !=
2509*6d67aabdSBjoern A. Zeeb 		     RTW89_TXPWR_LMT_PAGE_SIZE_AX);
2510e2340276SBjoern A. Zeeb 
2511e2340276SBjoern A. Zeeb 	addr = R_AX_PWR_LMT;
2512e2340276SBjoern A. Zeeb 	for (i = 0; i < max_ntx_num; i++) {
2513*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_ax(rtwdev, chan, &lmt, i);
2514e2340276SBjoern A. Zeeb 
2515e2340276SBjoern A. Zeeb 		ptr = (s8 *)&lmt;
2516*6d67aabdSBjoern A. Zeeb 		for (j = 0; j < RTW89_TXPWR_LMT_PAGE_SIZE_AX;
2517e2340276SBjoern A. Zeeb 		     j += 4, addr += 4, ptr += 4) {
2518e2340276SBjoern A. Zeeb 			val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
2519e2340276SBjoern A. Zeeb 			      FIELD_PREP(GENMASK(15, 8), ptr[1]) |
2520e2340276SBjoern A. Zeeb 			      FIELD_PREP(GENMASK(23, 16), ptr[2]) |
2521e2340276SBjoern A. Zeeb 			      FIELD_PREP(GENMASK(31, 24), ptr[3]);
2522e2340276SBjoern A. Zeeb 
2523e2340276SBjoern A. Zeeb 			rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
2524e2340276SBjoern A. Zeeb 		}
2525e2340276SBjoern A. Zeeb 	}
2526e2340276SBjoern A. Zeeb }
2527e2340276SBjoern A. Zeeb 
2528*6d67aabdSBjoern A. Zeeb static void rtw89_phy_set_txpwr_limit_ru_ax(struct rtw89_dev *rtwdev,
2529e2340276SBjoern A. Zeeb 					    const struct rtw89_chan *chan,
2530e2340276SBjoern A. Zeeb 					    enum rtw89_phy_idx phy_idx)
2531e2340276SBjoern A. Zeeb {
2532e2340276SBjoern A. Zeeb 	u8 max_ntx_num = rtwdev->chip->rf_path_num;
2533*6d67aabdSBjoern A. Zeeb 	struct rtw89_txpwr_limit_ru_ax lmt_ru;
2534e2340276SBjoern A. Zeeb 	u8 ch = chan->channel;
2535e2340276SBjoern A. Zeeb 	u8 bw = chan->band_width;
2536e2340276SBjoern A. Zeeb 	const s8 *ptr;
2537e2340276SBjoern A. Zeeb 	u32 addr, val;
2538e2340276SBjoern A. Zeeb 	u8 i, j;
2539e2340276SBjoern A. Zeeb 
2540e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2541e2340276SBjoern A. Zeeb 		    "[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
2542e2340276SBjoern A. Zeeb 
2543*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(sizeof(struct rtw89_txpwr_limit_ru_ax) !=
2544*6d67aabdSBjoern A. Zeeb 		     RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX);
2545e2340276SBjoern A. Zeeb 
2546e2340276SBjoern A. Zeeb 	addr = R_AX_PWR_RU_LMT;
2547e2340276SBjoern A. Zeeb 	for (i = 0; i < max_ntx_num; i++) {
2548*6d67aabdSBjoern A. Zeeb 		rtw89_phy_fill_txpwr_limit_ru_ax(rtwdev, chan, &lmt_ru, i);
2549e2340276SBjoern A. Zeeb 
2550e2340276SBjoern A. Zeeb 		ptr = (s8 *)&lmt_ru;
2551*6d67aabdSBjoern A. Zeeb 		for (j = 0; j < RTW89_TXPWR_LMT_RU_PAGE_SIZE_AX;
2552e2340276SBjoern A. Zeeb 		     j += 4, addr += 4, ptr += 4) {
2553e2340276SBjoern A. Zeeb 			val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
2554e2340276SBjoern A. Zeeb 			      FIELD_PREP(GENMASK(15, 8), ptr[1]) |
2555e2340276SBjoern A. Zeeb 			      FIELD_PREP(GENMASK(23, 16), ptr[2]) |
2556e2340276SBjoern A. Zeeb 			      FIELD_PREP(GENMASK(31, 24), ptr[3]);
2557e2340276SBjoern A. Zeeb 
2558e2340276SBjoern A. Zeeb 			rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
2559e2340276SBjoern A. Zeeb 		}
2560e2340276SBjoern A. Zeeb 	}
2561e2340276SBjoern A. Zeeb }
25628e93258fSBjoern A. Zeeb 
25638e93258fSBjoern A. Zeeb struct rtw89_phy_iter_ra_data {
25648e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev;
25658e93258fSBjoern A. Zeeb 	struct sk_buff *c2h;
25668e93258fSBjoern A. Zeeb };
25678e93258fSBjoern A. Zeeb 
25688e93258fSBjoern A. Zeeb static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
25698e93258fSBjoern A. Zeeb {
25708e93258fSBjoern A. Zeeb 	struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data;
25718e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = ra_data->rtwdev;
25728e93258fSBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
2573e2340276SBjoern A. Zeeb 	const struct rtw89_c2h_ra_rpt *c2h =
2574e2340276SBjoern A. Zeeb 		(const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data;
25758e93258fSBjoern A. Zeeb 	struct rtw89_ra_report *ra_report = &rtwsta->ra_report;
2576e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
2577e2340276SBjoern A. Zeeb 	bool format_v1 = chip->chip_gen == RTW89_CHIP_BE;
25788e93258fSBjoern A. Zeeb 	u8 mode, rate, bw, giltf, mac_id;
25798e93258fSBjoern A. Zeeb 	u16 legacy_bitrate;
25808e93258fSBjoern A. Zeeb 	bool valid;
25818e93258fSBjoern A. Zeeb 	u8 mcs = 0;
2582e2340276SBjoern A. Zeeb 	u8 t;
25838e93258fSBjoern A. Zeeb 
2584e2340276SBjoern A. Zeeb 	mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID);
25858e93258fSBjoern A. Zeeb 	if (mac_id != rtwsta->mac_id)
25868e93258fSBjoern A. Zeeb 		return;
25878e93258fSBjoern A. Zeeb 
2588e2340276SBjoern A. Zeeb 	rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS);
2589e2340276SBjoern A. Zeeb 	bw = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW);
2590e2340276SBjoern A. Zeeb 	giltf = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_GILTF);
2591e2340276SBjoern A. Zeeb 	mode = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL);
2592e2340276SBjoern A. Zeeb 
2593e2340276SBjoern A. Zeeb 	if (format_v1) {
2594e2340276SBjoern A. Zeeb 		t = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MCSNSS_B7);
2595e2340276SBjoern A. Zeeb 		rate |= u8_encode_bits(t, BIT(7));
2596e2340276SBjoern A. Zeeb 		t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW_B2);
2597e2340276SBjoern A. Zeeb 		bw |= u8_encode_bits(t, BIT(2));
2598e2340276SBjoern A. Zeeb 		t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL_B2);
2599e2340276SBjoern A. Zeeb 		mode |= u8_encode_bits(t, BIT(2));
2600e2340276SBjoern A. Zeeb 	}
26018e93258fSBjoern A. Zeeb 
26028e93258fSBjoern A. Zeeb 	if (mode == RTW89_RA_RPT_MODE_LEGACY) {
26038e93258fSBjoern A. Zeeb 		valid = rtw89_ra_report_to_bitrate(rtwdev, rate, &legacy_bitrate);
26048e93258fSBjoern A. Zeeb 		if (!valid)
26058e93258fSBjoern A. Zeeb 			return;
26068e93258fSBjoern A. Zeeb 	}
26078e93258fSBjoern A. Zeeb 
26088e93258fSBjoern A. Zeeb 	memset(&ra_report->txrate, 0, sizeof(ra_report->txrate));
26098e93258fSBjoern A. Zeeb 
26108e93258fSBjoern A. Zeeb 	switch (mode) {
26118e93258fSBjoern A. Zeeb 	case RTW89_RA_RPT_MODE_LEGACY:
26128e93258fSBjoern A. Zeeb 		ra_report->txrate.legacy = legacy_bitrate;
26138e93258fSBjoern A. Zeeb 		break;
26148e93258fSBjoern A. Zeeb 	case RTW89_RA_RPT_MODE_HT:
26158e93258fSBjoern A. Zeeb 		ra_report->txrate.flags |= RATE_INFO_FLAGS_MCS;
26168e93258fSBjoern A. Zeeb 		if (RTW89_CHK_FW_FEATURE(OLD_HT_RA_FORMAT, &rtwdev->fw))
26178e93258fSBjoern A. Zeeb 			rate = RTW89_MK_HT_RATE(FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate),
26188e93258fSBjoern A. Zeeb 						FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate));
26198e93258fSBjoern A. Zeeb 		else
26208e93258fSBjoern A. Zeeb 			rate = FIELD_GET(RTW89_RA_RATE_MASK_HT_MCS, rate);
26218e93258fSBjoern A. Zeeb 		ra_report->txrate.mcs = rate;
26228e93258fSBjoern A. Zeeb 		if (giltf)
26238e93258fSBjoern A. Zeeb 			ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
26248e93258fSBjoern A. Zeeb 		mcs = ra_report->txrate.mcs & 0x07;
26258e93258fSBjoern A. Zeeb 		break;
26268e93258fSBjoern A. Zeeb 	case RTW89_RA_RPT_MODE_VHT:
26278e93258fSBjoern A. Zeeb 		ra_report->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
2628e2340276SBjoern A. Zeeb 		ra_report->txrate.mcs = format_v1 ?
2629e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) :
2630e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS);
2631e2340276SBjoern A. Zeeb 		ra_report->txrate.nss = format_v1 ?
2632e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 :
2633e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1;
26348e93258fSBjoern A. Zeeb 		if (giltf)
26358e93258fSBjoern A. Zeeb 			ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
26368e93258fSBjoern A. Zeeb 		mcs = ra_report->txrate.mcs;
26378e93258fSBjoern A. Zeeb 		break;
26388e93258fSBjoern A. Zeeb 	case RTW89_RA_RPT_MODE_HE:
26398e93258fSBjoern A. Zeeb 		ra_report->txrate.flags |= RATE_INFO_FLAGS_HE_MCS;
2640e2340276SBjoern A. Zeeb 		ra_report->txrate.mcs = format_v1 ?
2641e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) :
2642e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS);
2643e2340276SBjoern A. Zeeb 		ra_report->txrate.nss  = format_v1 ?
2644e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 :
2645e2340276SBjoern A. Zeeb 			u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1;
26468e93258fSBjoern A. Zeeb 		if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08)
26478e93258fSBjoern A. Zeeb 			ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_0_8;
26488e93258fSBjoern A. Zeeb 		else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16)
26498e93258fSBjoern A. Zeeb 			ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_1_6;
26508e93258fSBjoern A. Zeeb 		else
26518e93258fSBjoern A. Zeeb 			ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_3_2;
26528e93258fSBjoern A. Zeeb 		mcs = ra_report->txrate.mcs;
26538e93258fSBjoern A. Zeeb 		break;
2654*6d67aabdSBjoern A. Zeeb 	case RTW89_RA_RPT_MODE_EHT:
2655*6d67aabdSBjoern A. Zeeb 		ra_report->txrate.flags |= RATE_INFO_FLAGS_EHT_MCS;
2656*6d67aabdSBjoern A. Zeeb 		ra_report->txrate.mcs = u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1);
2657*6d67aabdSBjoern A. Zeeb 		ra_report->txrate.nss = u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1;
2658*6d67aabdSBjoern A. Zeeb 		if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08)
2659*6d67aabdSBjoern A. Zeeb 			ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_0_8;
2660*6d67aabdSBjoern A. Zeeb 		else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16)
2661*6d67aabdSBjoern A. Zeeb 			ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_1_6;
2662*6d67aabdSBjoern A. Zeeb 		else
2663*6d67aabdSBjoern A. Zeeb 			ra_report->txrate.eht_gi = NL80211_RATE_INFO_EHT_GI_3_2;
2664*6d67aabdSBjoern A. Zeeb 		mcs = ra_report->txrate.mcs;
2665*6d67aabdSBjoern A. Zeeb 		break;
26668e93258fSBjoern A. Zeeb 	}
26678e93258fSBjoern A. Zeeb 
26688e93258fSBjoern A. Zeeb 	ra_report->txrate.bw = rtw89_hw_to_rate_info_bw(bw);
26698e93258fSBjoern A. Zeeb 	ra_report->bit_rate = cfg80211_calculate_bitrate(&ra_report->txrate);
2670e2340276SBjoern A. Zeeb 	ra_report->hw_rate = format_v1 ?
2671e2340276SBjoern A. Zeeb 			     u16_encode_bits(mode, RTW89_HW_RATE_V1_MASK_MOD) |
2672e2340276SBjoern A. Zeeb 			     u16_encode_bits(rate, RTW89_HW_RATE_V1_MASK_VAL) :
2673e2340276SBjoern A. Zeeb 			     u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) |
2674e2340276SBjoern A. Zeeb 			     u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL);
26758e93258fSBjoern A. Zeeb 	ra_report->might_fallback_legacy = mcs <= 2;
2676e2340276SBjoern A. Zeeb 	sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
2677e2340276SBjoern A. Zeeb 	rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1;
26788e93258fSBjoern A. Zeeb }
26798e93258fSBjoern A. Zeeb 
26808e93258fSBjoern A. Zeeb static void
26818e93258fSBjoern A. Zeeb rtw89_phy_c2h_ra_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
26828e93258fSBjoern A. Zeeb {
26838e93258fSBjoern A. Zeeb 	struct rtw89_phy_iter_ra_data ra_data;
26848e93258fSBjoern A. Zeeb 
26858e93258fSBjoern A. Zeeb 	ra_data.rtwdev = rtwdev;
26868e93258fSBjoern A. Zeeb 	ra_data.c2h = c2h;
26878e93258fSBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
26888e93258fSBjoern A. Zeeb 					  rtw89_phy_c2h_ra_rpt_iter,
26898e93258fSBjoern A. Zeeb 					  &ra_data);
26908e93258fSBjoern A. Zeeb }
26918e93258fSBjoern A. Zeeb 
26928e93258fSBjoern A. Zeeb static
26938e93258fSBjoern A. Zeeb void (* const rtw89_phy_c2h_ra_handler[])(struct rtw89_dev *rtwdev,
26948e93258fSBjoern A. Zeeb 					  struct sk_buff *c2h, u32 len) = {
26958e93258fSBjoern A. Zeeb 	[RTW89_PHY_C2H_FUNC_STS_RPT] = rtw89_phy_c2h_ra_rpt,
26968e93258fSBjoern A. Zeeb 	[RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT] = NULL,
26978e93258fSBjoern A. Zeeb 	[RTW89_PHY_C2H_FUNC_TXSTS] = NULL,
26988e93258fSBjoern A. Zeeb };
26998e93258fSBjoern A. Zeeb 
2700*6d67aabdSBjoern A. Zeeb static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev,
2701*6d67aabdSBjoern A. Zeeb 				      enum rtw89_phy_c2h_rfk_log_func func,
2702*6d67aabdSBjoern A. Zeeb 				      void *content, u16 len)
2703*6d67aabdSBjoern A. Zeeb {
2704*6d67aabdSBjoern A. Zeeb 	struct rtw89_c2h_rf_txgapk_rpt_log *txgapk;
2705*6d67aabdSBjoern A. Zeeb 	struct rtw89_c2h_rf_rxdck_rpt_log *rxdck;
2706*6d67aabdSBjoern A. Zeeb 	struct rtw89_c2h_rf_dack_rpt_log *dack;
2707*6d67aabdSBjoern A. Zeeb 	struct rtw89_c2h_rf_dpk_rpt_log *dpk;
2708*6d67aabdSBjoern A. Zeeb 
2709*6d67aabdSBjoern A. Zeeb 	switch (func) {
2710*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK:
2711*6d67aabdSBjoern A. Zeeb 		if (len != sizeof(*dpk))
2712*6d67aabdSBjoern A. Zeeb 			goto out;
2713*6d67aabdSBjoern A. Zeeb 
2714*6d67aabdSBjoern A. Zeeb 		dpk = content;
2715*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
2716*6d67aabdSBjoern A. Zeeb 			    "DPK ver:%d idx:%2ph band:%2ph bw:%2ph ch:%2ph path:%2ph\n",
2717*6d67aabdSBjoern A. Zeeb 			    dpk->ver, dpk->idx, dpk->band, dpk->bw, dpk->ch, dpk->path_ok);
2718*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
2719*6d67aabdSBjoern A. Zeeb 			    "DPK txagc:%2ph ther:%2ph gs:%2ph dc_i:%4ph dc_q:%4ph\n",
2720*6d67aabdSBjoern A. Zeeb 			    dpk->txagc, dpk->ther, dpk->gs, dpk->dc_i, dpk->dc_q);
2721*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
2722*6d67aabdSBjoern A. Zeeb 			    "DPK corr_v:%2ph corr_i:%2ph to:%2ph ov:%2ph\n",
2723*6d67aabdSBjoern A. Zeeb 			    dpk->corr_val, dpk->corr_idx, dpk->is_timeout, dpk->rxbb_ov);
2724*6d67aabdSBjoern A. Zeeb 		return;
2725*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_LOG_FUNC_DACK:
2726*6d67aabdSBjoern A. Zeeb 		if (len != sizeof(*dack))
2727*6d67aabdSBjoern A. Zeeb 			goto out;
2728*6d67aabdSBjoern A. Zeeb 
2729*6d67aabdSBjoern A. Zeeb 		dack = content;
2730*6d67aabdSBjoern A. Zeeb 
2731*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ver=0x%x 0x%x\n",
2732*6d67aabdSBjoern A. Zeeb 			    dack->fwdack_ver, dack->fwdack_rpt_ver);
2733*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK ic = [0x%x, 0x%x]\n",
2734*6d67aabdSBjoern A. Zeeb 			    dack->cdack_d[0][0][0], dack->cdack_d[0][0][1]);
2735*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK qc = [0x%x, 0x%x]\n",
2736*6d67aabdSBjoern A. Zeeb 			    dack->cdack_d[0][1][0], dack->cdack_d[0][1][1]);
2737*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 CDACK ic = [0x%x, 0x%x]\n",
2738*6d67aabdSBjoern A. Zeeb 			    dack->cdack_d[1][0][0], dack->cdack_d[1][0][1]);
2739*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 CDACK qc = [0x%x, 0x%x]\n",
2740*6d67aabdSBjoern A. Zeeb 			    dack->cdack_d[1][1][0], dack->cdack_d[1][1][1]);
2741*6d67aabdSBjoern A. Zeeb 
2742*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = [0x%x, 0x%x]\n",
2743*6d67aabdSBjoern A. Zeeb 			    dack->addck2_d[0][0][0], dack->addck2_d[0][0][1]);
2744*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK qc = [0x%x, 0x%x]\n",
2745*6d67aabdSBjoern A. Zeeb 			    dack->addck2_d[0][1][0], dack->addck2_d[0][1][1]);
2746*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK ic = [0x%x, 0x%x]\n",
2747*6d67aabdSBjoern A. Zeeb 			    dack->addck2_d[1][0][0], dack->addck2_d[1][0][1]);
2748*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK qc = [0x%x, 0x%x]\n",
2749*6d67aabdSBjoern A. Zeeb 			    dack->addck2_d[1][1][0], dack->addck2_d[1][1][1]);
2750*6d67aabdSBjoern A. Zeeb 
2751*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_GAINK ic = 0x%x, qc = 0x%x\n",
2752*6d67aabdSBjoern A. Zeeb 			    dack->adgaink_d[0][0], dack->adgaink_d[0][1]);
2753*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_GAINK ic = 0x%x, qc = 0x%x\n",
2754*6d67aabdSBjoern A. Zeeb 			    dack->adgaink_d[1][0], dack->adgaink_d[1][1]);
2755*6d67aabdSBjoern A. Zeeb 
2756*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DAC_DCK ic = 0x%x, qc = 0x%x\n",
2757*6d67aabdSBjoern A. Zeeb 			    dack->dadck_d[0][0], dack->dadck_d[0][1]);
2758*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 DAC_DCK ic = 0x%x, qc = 0x%x\n",
2759*6d67aabdSBjoern A. Zeeb 			    dack->dadck_d[1][0], dack->dadck_d[1][1]);
2760*6d67aabdSBjoern A. Zeeb 
2761*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask iqc = 0x%x\n",
2762*6d67aabdSBjoern A. Zeeb 			    dack->biask_d[0][0]);
2763*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 biask iqc = 0x%x\n",
2764*6d67aabdSBjoern A. Zeeb 			    dack->biask_d[1][0]);
2765*6d67aabdSBjoern A. Zeeb 
2766*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic: %*ph\n",
2767*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(dack->msbk_d[0][0]), dack->msbk_d[0][0]);
2768*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc: %*ph\n",
2769*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(dack->msbk_d[0][1]), dack->msbk_d[0][1]);
2770*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic: %*ph\n",
2771*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(dack->msbk_d[1][0]), dack->msbk_d[1][0]);
2772*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc: %*ph\n",
2773*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(dack->msbk_d[1][1]), dack->msbk_d[1][1]);
2774*6d67aabdSBjoern A. Zeeb 		return;
2775*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK:
2776*6d67aabdSBjoern A. Zeeb 		if (len != sizeof(*rxdck))
2777*6d67aabdSBjoern A. Zeeb 			goto out;
2778*6d67aabdSBjoern A. Zeeb 
2779*6d67aabdSBjoern A. Zeeb 		rxdck = content;
2780*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
2781*6d67aabdSBjoern A. Zeeb 			    "RXDCK ver:%d band:%2ph bw:%2ph ch:%2ph to:%2ph\n",
2782*6d67aabdSBjoern A. Zeeb 			    rxdck->ver, rxdck->band, rxdck->bw, rxdck->ch,
2783*6d67aabdSBjoern A. Zeeb 			    rxdck->timeout);
2784*6d67aabdSBjoern A. Zeeb 		return;
2785*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK:
2786*6d67aabdSBjoern A. Zeeb 		if (len != sizeof(*txgapk))
2787*6d67aabdSBjoern A. Zeeb 			goto out;
2788*6d67aabdSBjoern A. Zeeb 
2789*6d67aabdSBjoern A. Zeeb 		txgapk = content;
2790*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
2791*6d67aabdSBjoern A. Zeeb 			    "[TXGAPK]rpt r0x8010[0]=0x%x, r0x8010[1]=0x%x\n",
2792*6d67aabdSBjoern A. Zeeb 			    le32_to_cpu(txgapk->r0x8010[0]),
2793*6d67aabdSBjoern A. Zeeb 			    le32_to_cpu(txgapk->r0x8010[1]));
2794*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt chk_id = %d\n",
2795*6d67aabdSBjoern A. Zeeb 			    txgapk->chk_id);
2796*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt chk_cnt = %d\n",
2797*6d67aabdSBjoern A. Zeeb 			    le32_to_cpu(txgapk->chk_cnt));
2798*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt ver = 0x%x\n",
2799*6d67aabdSBjoern A. Zeeb 			    txgapk->ver);
2800*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt rsv1 = %d\n",
2801*6d67aabdSBjoern A. Zeeb 			    txgapk->rsv1);
2802*6d67aabdSBjoern A. Zeeb 
2803*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt track_d[0] = %*ph\n",
2804*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(txgapk->track_d[0]), txgapk->track_d[0]);
2805*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt power_d[0] = %*ph\n",
2806*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(txgapk->power_d[0]), txgapk->power_d[0]);
2807*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt track_d[1] = %*ph\n",
2808*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(txgapk->track_d[1]), txgapk->track_d[1]);
2809*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt power_d[1] = %*ph\n",
2810*6d67aabdSBjoern A. Zeeb 			    (int)sizeof(txgapk->power_d[1]), txgapk->power_d[1]);
2811*6d67aabdSBjoern A. Zeeb 		return;
2812*6d67aabdSBjoern A. Zeeb 	default:
2813*6d67aabdSBjoern A. Zeeb 		break;
2814*6d67aabdSBjoern A. Zeeb 	}
2815*6d67aabdSBjoern A. Zeeb 
2816*6d67aabdSBjoern A. Zeeb out:
2817*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
2818*6d67aabdSBjoern A. Zeeb 		    "unexpected RFK func %d report log with length %d\n", func, len);
2819*6d67aabdSBjoern A. Zeeb }
2820*6d67aabdSBjoern A. Zeeb 
2821*6d67aabdSBjoern A. Zeeb static bool rtw89_phy_c2h_rfk_run_log(struct rtw89_dev *rtwdev,
2822*6d67aabdSBjoern A. Zeeb 				      enum rtw89_phy_c2h_rfk_log_func func,
2823*6d67aabdSBjoern A. Zeeb 				      void *content, u16 len)
2824*6d67aabdSBjoern A. Zeeb {
2825*6d67aabdSBjoern A. Zeeb 	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
2826*6d67aabdSBjoern A. Zeeb 	const struct rtw89_c2h_rf_run_log *log = content;
2827*6d67aabdSBjoern A. Zeeb 	const struct rtw89_fw_element_hdr *elm;
2828*6d67aabdSBjoern A. Zeeb 	u32 fmt_idx;
2829*6d67aabdSBjoern A. Zeeb 	u16 offset;
2830*6d67aabdSBjoern A. Zeeb 
2831*6d67aabdSBjoern A. Zeeb 	if (sizeof(*log) != len)
2832*6d67aabdSBjoern A. Zeeb 		return false;
2833*6d67aabdSBjoern A. Zeeb 
2834*6d67aabdSBjoern A. Zeeb 	if (!elm_info->rfk_log_fmt)
2835*6d67aabdSBjoern A. Zeeb 		return false;
2836*6d67aabdSBjoern A. Zeeb 
2837*6d67aabdSBjoern A. Zeeb 	elm = elm_info->rfk_log_fmt->elm[func];
2838*6d67aabdSBjoern A. Zeeb 	fmt_idx = le32_to_cpu(log->fmt_idx);
2839*6d67aabdSBjoern A. Zeeb 	if (!elm || fmt_idx >= elm->u.rfk_log_fmt.nr)
2840*6d67aabdSBjoern A. Zeeb 		return false;
2841*6d67aabdSBjoern A. Zeeb 
2842*6d67aabdSBjoern A. Zeeb 	offset = le16_to_cpu(elm->u.rfk_log_fmt.offset[fmt_idx]);
2843*6d67aabdSBjoern A. Zeeb 	if (offset == 0)
2844*6d67aabdSBjoern A. Zeeb 		return false;
2845*6d67aabdSBjoern A. Zeeb 
2846*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK, &elm->u.common.contents[offset],
2847*6d67aabdSBjoern A. Zeeb 		    le32_to_cpu(log->arg[0]), le32_to_cpu(log->arg[1]),
2848*6d67aabdSBjoern A. Zeeb 		    le32_to_cpu(log->arg[2]), le32_to_cpu(log->arg[3]));
2849*6d67aabdSBjoern A. Zeeb 
2850*6d67aabdSBjoern A. Zeeb 	return true;
2851*6d67aabdSBjoern A. Zeeb }
2852*6d67aabdSBjoern A. Zeeb 
2853*6d67aabdSBjoern A. Zeeb static void rtw89_phy_c2h_rfk_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
2854*6d67aabdSBjoern A. Zeeb 				  u32 len, enum rtw89_phy_c2h_rfk_log_func func,
2855*6d67aabdSBjoern A. Zeeb 				  const char *rfk_name)
2856*6d67aabdSBjoern A. Zeeb {
2857*6d67aabdSBjoern A. Zeeb 	struct rtw89_c2h_hdr *c2h_hdr = (struct rtw89_c2h_hdr *)c2h->data;
2858*6d67aabdSBjoern A. Zeeb 	struct rtw89_c2h_rf_log_hdr *log_hdr;
2859*6d67aabdSBjoern A. Zeeb #if defined(__linux__)
2860*6d67aabdSBjoern A. Zeeb 	void *log_ptr = c2h_hdr;
2861*6d67aabdSBjoern A. Zeeb #elif defined(__FreeBSD__)
2862*6d67aabdSBjoern A. Zeeb 	u8 *log_ptr = (void *)c2h_hdr;
2863*6d67aabdSBjoern A. Zeeb #endif
2864*6d67aabdSBjoern A. Zeeb 	u16 content_len;
2865*6d67aabdSBjoern A. Zeeb 	u16 chunk_len;
2866*6d67aabdSBjoern A. Zeeb 	bool handled;
2867*6d67aabdSBjoern A. Zeeb 
2868*6d67aabdSBjoern A. Zeeb 	if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK))
2869*6d67aabdSBjoern A. Zeeb 		return;
2870*6d67aabdSBjoern A. Zeeb 
2871*6d67aabdSBjoern A. Zeeb 	log_ptr += sizeof(*c2h_hdr);
2872*6d67aabdSBjoern A. Zeeb 	len -= sizeof(*c2h_hdr);
2873*6d67aabdSBjoern A. Zeeb 
2874*6d67aabdSBjoern A. Zeeb 	while (len > sizeof(*log_hdr)) {
2875*6d67aabdSBjoern A. Zeeb #if defined(__linux__)
2876*6d67aabdSBjoern A. Zeeb 		log_hdr = log_ptr;
2877*6d67aabdSBjoern A. Zeeb #elif defined(__FreeBSD__)
2878*6d67aabdSBjoern A. Zeeb 		log_hdr = (void *)log_ptr;
2879*6d67aabdSBjoern A. Zeeb #endif
2880*6d67aabdSBjoern A. Zeeb 		content_len = le16_to_cpu(log_hdr->len);
2881*6d67aabdSBjoern A. Zeeb 		chunk_len = content_len + sizeof(*log_hdr);
2882*6d67aabdSBjoern A. Zeeb 
2883*6d67aabdSBjoern A. Zeeb 		if (chunk_len > len)
2884*6d67aabdSBjoern A. Zeeb 			break;
2885*6d67aabdSBjoern A. Zeeb 
2886*6d67aabdSBjoern A. Zeeb 		switch (log_hdr->type) {
2887*6d67aabdSBjoern A. Zeeb 		case RTW89_RF_RUN_LOG:
2888*6d67aabdSBjoern A. Zeeb 			handled = rtw89_phy_c2h_rfk_run_log(rtwdev, func,
2889*6d67aabdSBjoern A. Zeeb 							    log_hdr->content, content_len);
2890*6d67aabdSBjoern A. Zeeb 			if (handled)
2891*6d67aabdSBjoern A. Zeeb 				break;
2892*6d67aabdSBjoern A. Zeeb 
2893*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_RFK, "%s run: %*ph\n",
2894*6d67aabdSBjoern A. Zeeb 				    rfk_name, content_len, log_hdr->content);
2895*6d67aabdSBjoern A. Zeeb 			break;
2896*6d67aabdSBjoern A. Zeeb 		case RTW89_RF_RPT_LOG:
2897*6d67aabdSBjoern A. Zeeb 			rtw89_phy_c2h_rfk_rpt_log(rtwdev, func,
2898*6d67aabdSBjoern A. Zeeb 						  log_hdr->content, content_len);
2899*6d67aabdSBjoern A. Zeeb 			break;
2900*6d67aabdSBjoern A. Zeeb 		default:
2901*6d67aabdSBjoern A. Zeeb 			return;
2902*6d67aabdSBjoern A. Zeeb 		}
2903*6d67aabdSBjoern A. Zeeb 
2904*6d67aabdSBjoern A. Zeeb 		log_ptr += chunk_len;
2905*6d67aabdSBjoern A. Zeeb 		len -= chunk_len;
2906*6d67aabdSBjoern A. Zeeb 	}
2907*6d67aabdSBjoern A. Zeeb }
2908*6d67aabdSBjoern A. Zeeb 
2909*6d67aabdSBjoern A. Zeeb static void
2910*6d67aabdSBjoern A. Zeeb rtw89_phy_c2h_rfk_log_iqk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
2911*6d67aabdSBjoern A. Zeeb {
2912*6d67aabdSBjoern A. Zeeb 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
2913*6d67aabdSBjoern A. Zeeb 			      RTW89_PHY_C2H_RFK_LOG_FUNC_IQK, "IQK");
2914*6d67aabdSBjoern A. Zeeb }
2915*6d67aabdSBjoern A. Zeeb 
2916*6d67aabdSBjoern A. Zeeb static void
2917*6d67aabdSBjoern A. Zeeb rtw89_phy_c2h_rfk_log_dpk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
2918*6d67aabdSBjoern A. Zeeb {
2919*6d67aabdSBjoern A. Zeeb 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
2920*6d67aabdSBjoern A. Zeeb 			      RTW89_PHY_C2H_RFK_LOG_FUNC_DPK, "DPK");
2921*6d67aabdSBjoern A. Zeeb }
2922*6d67aabdSBjoern A. Zeeb 
2923*6d67aabdSBjoern A. Zeeb static void
2924*6d67aabdSBjoern A. Zeeb rtw89_phy_c2h_rfk_log_dack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
2925*6d67aabdSBjoern A. Zeeb {
2926*6d67aabdSBjoern A. Zeeb 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
2927*6d67aabdSBjoern A. Zeeb 			      RTW89_PHY_C2H_RFK_LOG_FUNC_DACK, "DACK");
2928*6d67aabdSBjoern A. Zeeb }
2929*6d67aabdSBjoern A. Zeeb 
2930*6d67aabdSBjoern A. Zeeb static void
2931*6d67aabdSBjoern A. Zeeb rtw89_phy_c2h_rfk_log_rxdck(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
2932*6d67aabdSBjoern A. Zeeb {
2933*6d67aabdSBjoern A. Zeeb 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
2934*6d67aabdSBjoern A. Zeeb 			      RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK, "RX_DCK");
2935*6d67aabdSBjoern A. Zeeb }
2936*6d67aabdSBjoern A. Zeeb 
2937*6d67aabdSBjoern A. Zeeb static void
2938*6d67aabdSBjoern A. Zeeb rtw89_phy_c2h_rfk_log_tssi(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
2939*6d67aabdSBjoern A. Zeeb {
2940*6d67aabdSBjoern A. Zeeb 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
2941*6d67aabdSBjoern A. Zeeb 			      RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI, "TSSI");
2942*6d67aabdSBjoern A. Zeeb }
2943*6d67aabdSBjoern A. Zeeb 
2944*6d67aabdSBjoern A. Zeeb static void
2945*6d67aabdSBjoern A. Zeeb rtw89_phy_c2h_rfk_log_txgapk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
2946*6d67aabdSBjoern A. Zeeb {
2947*6d67aabdSBjoern A. Zeeb 	rtw89_phy_c2h_rfk_log(rtwdev, c2h, len,
2948*6d67aabdSBjoern A. Zeeb 			      RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK, "TXGAPK");
2949*6d67aabdSBjoern A. Zeeb }
2950*6d67aabdSBjoern A. Zeeb 
2951*6d67aabdSBjoern A. Zeeb static
2952*6d67aabdSBjoern A. Zeeb void (* const rtw89_phy_c2h_rfk_log_handler[])(struct rtw89_dev *rtwdev,
2953*6d67aabdSBjoern A. Zeeb 					       struct sk_buff *c2h, u32 len) = {
2954*6d67aabdSBjoern A. Zeeb 	[RTW89_PHY_C2H_RFK_LOG_FUNC_IQK] = rtw89_phy_c2h_rfk_log_iqk,
2955*6d67aabdSBjoern A. Zeeb 	[RTW89_PHY_C2H_RFK_LOG_FUNC_DPK] = rtw89_phy_c2h_rfk_log_dpk,
2956*6d67aabdSBjoern A. Zeeb 	[RTW89_PHY_C2H_RFK_LOG_FUNC_DACK] = rtw89_phy_c2h_rfk_log_dack,
2957*6d67aabdSBjoern A. Zeeb 	[RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK] = rtw89_phy_c2h_rfk_log_rxdck,
2958*6d67aabdSBjoern A. Zeeb 	[RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI] = rtw89_phy_c2h_rfk_log_tssi,
2959*6d67aabdSBjoern A. Zeeb 	[RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK] = rtw89_phy_c2h_rfk_log_txgapk,
2960*6d67aabdSBjoern A. Zeeb };
2961*6d67aabdSBjoern A. Zeeb 
2962*6d67aabdSBjoern A. Zeeb static
2963*6d67aabdSBjoern A. Zeeb void rtw89_phy_rfk_report_prep(struct rtw89_dev *rtwdev)
2964*6d67aabdSBjoern A. Zeeb {
2965*6d67aabdSBjoern A. Zeeb 	struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
2966*6d67aabdSBjoern A. Zeeb 
2967*6d67aabdSBjoern A. Zeeb 	wait->state = RTW89_RFK_STATE_START;
2968*6d67aabdSBjoern A. Zeeb 	wait->start_time = ktime_get();
2969*6d67aabdSBjoern A. Zeeb 	reinit_completion(&wait->completion);
2970*6d67aabdSBjoern A. Zeeb }
2971*6d67aabdSBjoern A. Zeeb 
2972*6d67aabdSBjoern A. Zeeb static
2973*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_report_wait(struct rtw89_dev *rtwdev, const char *rfk_name,
2974*6d67aabdSBjoern A. Zeeb 			      unsigned int ms)
2975*6d67aabdSBjoern A. Zeeb {
2976*6d67aabdSBjoern A. Zeeb 	struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
2977*6d67aabdSBjoern A. Zeeb 	unsigned long time_left;
2978*6d67aabdSBjoern A. Zeeb 
2979*6d67aabdSBjoern A. Zeeb 	/* Since we can't receive C2H event during SER, use a fixed delay. */
2980*6d67aabdSBjoern A. Zeeb 	if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) {
2981*6d67aabdSBjoern A. Zeeb 		fsleep(1000 * ms / 2);
2982*6d67aabdSBjoern A. Zeeb 		goto out;
2983*6d67aabdSBjoern A. Zeeb 	}
2984*6d67aabdSBjoern A. Zeeb 
2985*6d67aabdSBjoern A. Zeeb 	time_left = wait_for_completion_timeout(&wait->completion,
2986*6d67aabdSBjoern A. Zeeb 						msecs_to_jiffies(ms));
2987*6d67aabdSBjoern A. Zeeb 	if (time_left == 0) {
2988*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "failed to wait RF %s\n", rfk_name);
2989*6d67aabdSBjoern A. Zeeb 		return -ETIMEDOUT;
2990*6d67aabdSBjoern A. Zeeb 	} else if (wait->state != RTW89_RFK_STATE_OK) {
2991*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "failed to do RF %s result from state %d\n",
2992*6d67aabdSBjoern A. Zeeb 			   rfk_name, wait->state);
2993*6d67aabdSBjoern A. Zeeb 		return -EFAULT;
2994*6d67aabdSBjoern A. Zeeb 	}
2995*6d67aabdSBjoern A. Zeeb 
2996*6d67aabdSBjoern A. Zeeb out:
2997*6d67aabdSBjoern A. Zeeb #if defined(__linux__)
2998*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK, "RF %s takes %lld ms to complete\n",
2999*6d67aabdSBjoern A. Zeeb 		    rfk_name, ktime_ms_delta(ktime_get(), wait->start_time));
3000*6d67aabdSBjoern A. Zeeb #elif defined(__FreeBSD__)
3001*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK, "RF %s takes %jd ms to complete\n",
3002*6d67aabdSBjoern A. Zeeb 		    rfk_name, ktime_ms_delta(ktime_get(), (intmax_t)wait->start_time));
3003*6d67aabdSBjoern A. Zeeb #endif
3004*6d67aabdSBjoern A. Zeeb 
3005*6d67aabdSBjoern A. Zeeb 	return 0;
3006*6d67aabdSBjoern A. Zeeb }
3007*6d67aabdSBjoern A. Zeeb 
3008*6d67aabdSBjoern A. Zeeb static void
3009*6d67aabdSBjoern A. Zeeb rtw89_phy_c2h_rfk_report_state(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
3010*6d67aabdSBjoern A. Zeeb {
3011*6d67aabdSBjoern A. Zeeb 	const struct rtw89_c2h_rfk_report *report =
3012*6d67aabdSBjoern A. Zeeb 		(const struct rtw89_c2h_rfk_report *)c2h->data;
3013*6d67aabdSBjoern A. Zeeb 	struct rtw89_rfk_wait_info *wait = &rtwdev->rfk_wait;
3014*6d67aabdSBjoern A. Zeeb 
3015*6d67aabdSBjoern A. Zeeb 	wait->state = report->state;
3016*6d67aabdSBjoern A. Zeeb 	wait->version = report->version;
3017*6d67aabdSBjoern A. Zeeb 
3018*6d67aabdSBjoern A. Zeeb 	complete(&wait->completion);
3019*6d67aabdSBjoern A. Zeeb 
3020*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
3021*6d67aabdSBjoern A. Zeeb 		    "RFK report state %d with version %d (%*ph)\n",
3022*6d67aabdSBjoern A. Zeeb 		    wait->state, wait->version,
3023*6d67aabdSBjoern A. Zeeb 		    (int)(len - sizeof(report->hdr)), &report->state);
3024*6d67aabdSBjoern A. Zeeb }
3025*6d67aabdSBjoern A. Zeeb 
3026*6d67aabdSBjoern A. Zeeb static
3027*6d67aabdSBjoern A. Zeeb void (* const rtw89_phy_c2h_rfk_report_handler[])(struct rtw89_dev *rtwdev,
3028*6d67aabdSBjoern A. Zeeb 						  struct sk_buff *c2h, u32 len) = {
3029*6d67aabdSBjoern A. Zeeb 	[RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE] = rtw89_phy_c2h_rfk_report_state,
3030*6d67aabdSBjoern A. Zeeb };
3031*6d67aabdSBjoern A. Zeeb 
3032*6d67aabdSBjoern A. Zeeb bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
3033*6d67aabdSBjoern A. Zeeb {
3034*6d67aabdSBjoern A. Zeeb 	switch (class) {
3035*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_LOG:
3036*6d67aabdSBjoern A. Zeeb 		switch (func) {
3037*6d67aabdSBjoern A. Zeeb 		case RTW89_PHY_C2H_RFK_LOG_FUNC_IQK:
3038*6d67aabdSBjoern A. Zeeb 		case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK:
3039*6d67aabdSBjoern A. Zeeb 		case RTW89_PHY_C2H_RFK_LOG_FUNC_DACK:
3040*6d67aabdSBjoern A. Zeeb 		case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK:
3041*6d67aabdSBjoern A. Zeeb 		case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI:
3042*6d67aabdSBjoern A. Zeeb 		case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK:
3043*6d67aabdSBjoern A. Zeeb 			return true;
3044*6d67aabdSBjoern A. Zeeb 		default:
3045*6d67aabdSBjoern A. Zeeb 			return false;
3046*6d67aabdSBjoern A. Zeeb 		}
3047*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_REPORT:
3048*6d67aabdSBjoern A. Zeeb 		switch (func) {
3049*6d67aabdSBjoern A. Zeeb 		case RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE:
3050*6d67aabdSBjoern A. Zeeb 			return true;
3051*6d67aabdSBjoern A. Zeeb 		default:
3052*6d67aabdSBjoern A. Zeeb 			return false;
3053*6d67aabdSBjoern A. Zeeb 		}
3054*6d67aabdSBjoern A. Zeeb 	default:
3055*6d67aabdSBjoern A. Zeeb 		return false;
3056*6d67aabdSBjoern A. Zeeb 	}
3057*6d67aabdSBjoern A. Zeeb }
3058*6d67aabdSBjoern A. Zeeb 
30598e93258fSBjoern A. Zeeb void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
30608e93258fSBjoern A. Zeeb 			  u32 len, u8 class, u8 func)
30618e93258fSBjoern A. Zeeb {
30628e93258fSBjoern A. Zeeb 	void (*handler)(struct rtw89_dev *rtwdev,
30638e93258fSBjoern A. Zeeb 			struct sk_buff *c2h, u32 len) = NULL;
30648e93258fSBjoern A. Zeeb 
30658e93258fSBjoern A. Zeeb 	switch (class) {
30668e93258fSBjoern A. Zeeb 	case RTW89_PHY_C2H_CLASS_RA:
30678e93258fSBjoern A. Zeeb 		if (func < RTW89_PHY_C2H_FUNC_RA_MAX)
30688e93258fSBjoern A. Zeeb 			handler = rtw89_phy_c2h_ra_handler[func];
30698e93258fSBjoern A. Zeeb 		break;
3070*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_LOG:
3071*6d67aabdSBjoern A. Zeeb 		if (func < ARRAY_SIZE(rtw89_phy_c2h_rfk_log_handler))
3072*6d67aabdSBjoern A. Zeeb 			handler = rtw89_phy_c2h_rfk_log_handler[func];
3073*6d67aabdSBjoern A. Zeeb 		break;
3074*6d67aabdSBjoern A. Zeeb 	case RTW89_PHY_C2H_RFK_REPORT:
3075*6d67aabdSBjoern A. Zeeb 		if (func < ARRAY_SIZE(rtw89_phy_c2h_rfk_report_handler))
3076*6d67aabdSBjoern A. Zeeb 			handler = rtw89_phy_c2h_rfk_report_handler[func];
3077*6d67aabdSBjoern A. Zeeb 		break;
3078e2340276SBjoern A. Zeeb 	case RTW89_PHY_C2H_CLASS_DM:
3079e2340276SBjoern A. Zeeb 		if (func == RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY)
3080e2340276SBjoern A. Zeeb 			return;
3081e2340276SBjoern A. Zeeb 		fallthrough;
30828e93258fSBjoern A. Zeeb 	default:
30838e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "c2h class %d not support\n", class);
30848e93258fSBjoern A. Zeeb 		return;
30858e93258fSBjoern A. Zeeb 	}
30868e93258fSBjoern A. Zeeb 	if (!handler) {
30878e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "c2h class %d func %d not support\n", class,
30888e93258fSBjoern A. Zeeb 			   func);
30898e93258fSBjoern A. Zeeb 		return;
30908e93258fSBjoern A. Zeeb 	}
30918e93258fSBjoern A. Zeeb 	handler(rtwdev, skb, len);
30928e93258fSBjoern A. Zeeb }
30938e93258fSBjoern A. Zeeb 
3094*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev,
3095*6d67aabdSBjoern A. Zeeb 				    enum rtw89_phy_idx phy_idx,
3096*6d67aabdSBjoern A. Zeeb 				    unsigned int ms)
3097*6d67aabdSBjoern A. Zeeb {
3098*6d67aabdSBjoern A. Zeeb 	int ret;
3099*6d67aabdSBjoern A. Zeeb 
3100*6d67aabdSBjoern A. Zeeb 	rtw89_phy_rfk_report_prep(rtwdev);
3101*6d67aabdSBjoern A. Zeeb 
3102*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx);
3103*6d67aabdSBjoern A. Zeeb 	if (ret)
3104*6d67aabdSBjoern A. Zeeb 		return ret;
3105*6d67aabdSBjoern A. Zeeb 
3106*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_rfk_report_wait(rtwdev, "PRE_NTFY", ms);
3107*6d67aabdSBjoern A. Zeeb }
3108*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_rfk_pre_ntfy_and_wait);
3109*6d67aabdSBjoern A. Zeeb 
3110*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_tssi_and_wait(struct rtw89_dev *rtwdev,
3111*6d67aabdSBjoern A. Zeeb 				enum rtw89_phy_idx phy_idx,
3112*6d67aabdSBjoern A. Zeeb 				enum rtw89_tssi_mode tssi_mode,
3113*6d67aabdSBjoern A. Zeeb 				unsigned int ms)
3114*6d67aabdSBjoern A. Zeeb {
3115*6d67aabdSBjoern A. Zeeb 	int ret;
3116*6d67aabdSBjoern A. Zeeb 
3117*6d67aabdSBjoern A. Zeeb 	rtw89_phy_rfk_report_prep(rtwdev);
3118*6d67aabdSBjoern A. Zeeb 
3119*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_h2c_rf_tssi(rtwdev, phy_idx, tssi_mode);
3120*6d67aabdSBjoern A. Zeeb 	if (ret)
3121*6d67aabdSBjoern A. Zeeb 		return ret;
3122*6d67aabdSBjoern A. Zeeb 
3123*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_rfk_report_wait(rtwdev, "TSSI", ms);
3124*6d67aabdSBjoern A. Zeeb }
3125*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_rfk_tssi_and_wait);
3126*6d67aabdSBjoern A. Zeeb 
3127*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_iqk_and_wait(struct rtw89_dev *rtwdev,
3128*6d67aabdSBjoern A. Zeeb 			       enum rtw89_phy_idx phy_idx,
3129*6d67aabdSBjoern A. Zeeb 			       unsigned int ms)
3130*6d67aabdSBjoern A. Zeeb {
3131*6d67aabdSBjoern A. Zeeb 	int ret;
3132*6d67aabdSBjoern A. Zeeb 
3133*6d67aabdSBjoern A. Zeeb 	rtw89_phy_rfk_report_prep(rtwdev);
3134*6d67aabdSBjoern A. Zeeb 
3135*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_h2c_rf_iqk(rtwdev, phy_idx);
3136*6d67aabdSBjoern A. Zeeb 	if (ret)
3137*6d67aabdSBjoern A. Zeeb 		return ret;
3138*6d67aabdSBjoern A. Zeeb 
3139*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_rfk_report_wait(rtwdev, "IQK", ms);
3140*6d67aabdSBjoern A. Zeeb }
3141*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_rfk_iqk_and_wait);
3142*6d67aabdSBjoern A. Zeeb 
3143*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_dpk_and_wait(struct rtw89_dev *rtwdev,
3144*6d67aabdSBjoern A. Zeeb 			       enum rtw89_phy_idx phy_idx,
3145*6d67aabdSBjoern A. Zeeb 			       unsigned int ms)
3146*6d67aabdSBjoern A. Zeeb {
3147*6d67aabdSBjoern A. Zeeb 	int ret;
3148*6d67aabdSBjoern A. Zeeb 
3149*6d67aabdSBjoern A. Zeeb 	rtw89_phy_rfk_report_prep(rtwdev);
3150*6d67aabdSBjoern A. Zeeb 
3151*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_h2c_rf_dpk(rtwdev, phy_idx);
3152*6d67aabdSBjoern A. Zeeb 	if (ret)
3153*6d67aabdSBjoern A. Zeeb 		return ret;
3154*6d67aabdSBjoern A. Zeeb 
3155*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_rfk_report_wait(rtwdev, "DPK", ms);
3156*6d67aabdSBjoern A. Zeeb }
3157*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_rfk_dpk_and_wait);
3158*6d67aabdSBjoern A. Zeeb 
3159*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_txgapk_and_wait(struct rtw89_dev *rtwdev,
3160*6d67aabdSBjoern A. Zeeb 				  enum rtw89_phy_idx phy_idx,
3161*6d67aabdSBjoern A. Zeeb 				  unsigned int ms)
3162*6d67aabdSBjoern A. Zeeb {
3163*6d67aabdSBjoern A. Zeeb 	int ret;
3164*6d67aabdSBjoern A. Zeeb 
3165*6d67aabdSBjoern A. Zeeb 	rtw89_phy_rfk_report_prep(rtwdev);
3166*6d67aabdSBjoern A. Zeeb 
3167*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_h2c_rf_txgapk(rtwdev, phy_idx);
3168*6d67aabdSBjoern A. Zeeb 	if (ret)
3169*6d67aabdSBjoern A. Zeeb 		return ret;
3170*6d67aabdSBjoern A. Zeeb 
3171*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_rfk_report_wait(rtwdev, "TXGAPK", ms);
3172*6d67aabdSBjoern A. Zeeb }
3173*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_rfk_txgapk_and_wait);
3174*6d67aabdSBjoern A. Zeeb 
3175*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_dack_and_wait(struct rtw89_dev *rtwdev,
3176*6d67aabdSBjoern A. Zeeb 				enum rtw89_phy_idx phy_idx,
3177*6d67aabdSBjoern A. Zeeb 				unsigned int ms)
3178*6d67aabdSBjoern A. Zeeb {
3179*6d67aabdSBjoern A. Zeeb 	int ret;
3180*6d67aabdSBjoern A. Zeeb 
3181*6d67aabdSBjoern A. Zeeb 	rtw89_phy_rfk_report_prep(rtwdev);
3182*6d67aabdSBjoern A. Zeeb 
3183*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_h2c_rf_dack(rtwdev, phy_idx);
3184*6d67aabdSBjoern A. Zeeb 	if (ret)
3185*6d67aabdSBjoern A. Zeeb 		return ret;
3186*6d67aabdSBjoern A. Zeeb 
3187*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_rfk_report_wait(rtwdev, "DACK", ms);
3188*6d67aabdSBjoern A. Zeeb }
3189*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_rfk_dack_and_wait);
3190*6d67aabdSBjoern A. Zeeb 
3191*6d67aabdSBjoern A. Zeeb int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev,
3192*6d67aabdSBjoern A. Zeeb 				 enum rtw89_phy_idx phy_idx,
3193*6d67aabdSBjoern A. Zeeb 				 unsigned int ms)
3194*6d67aabdSBjoern A. Zeeb {
3195*6d67aabdSBjoern A. Zeeb 	int ret;
3196*6d67aabdSBjoern A. Zeeb 
3197*6d67aabdSBjoern A. Zeeb 	rtw89_phy_rfk_report_prep(rtwdev);
3198*6d67aabdSBjoern A. Zeeb 
3199*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx);
3200*6d67aabdSBjoern A. Zeeb 	if (ret)
3201*6d67aabdSBjoern A. Zeeb 		return ret;
3202*6d67aabdSBjoern A. Zeeb 
3203*6d67aabdSBjoern A. Zeeb 	return rtw89_phy_rfk_report_wait(rtwdev, "RX_DCK", ms);
3204*6d67aabdSBjoern A. Zeeb }
3205*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_rfk_rxdck_and_wait);
3206*6d67aabdSBjoern A. Zeeb 
3207*6d67aabdSBjoern A. Zeeb static u32 phy_tssi_get_cck_group(u8 ch)
3208*6d67aabdSBjoern A. Zeeb {
3209*6d67aabdSBjoern A. Zeeb 	switch (ch) {
3210*6d67aabdSBjoern A. Zeeb 	case 1 ... 2:
3211*6d67aabdSBjoern A. Zeeb 		return 0;
3212*6d67aabdSBjoern A. Zeeb 	case 3 ... 5:
3213*6d67aabdSBjoern A. Zeeb 		return 1;
3214*6d67aabdSBjoern A. Zeeb 	case 6 ... 8:
3215*6d67aabdSBjoern A. Zeeb 		return 2;
3216*6d67aabdSBjoern A. Zeeb 	case 9 ... 11:
3217*6d67aabdSBjoern A. Zeeb 		return 3;
3218*6d67aabdSBjoern A. Zeeb 	case 12 ... 13:
3219*6d67aabdSBjoern A. Zeeb 		return 4;
3220*6d67aabdSBjoern A. Zeeb 	case 14:
3221*6d67aabdSBjoern A. Zeeb 		return 5;
3222*6d67aabdSBjoern A. Zeeb 	}
3223*6d67aabdSBjoern A. Zeeb 
3224*6d67aabdSBjoern A. Zeeb 	return 0;
3225*6d67aabdSBjoern A. Zeeb }
3226*6d67aabdSBjoern A. Zeeb 
3227*6d67aabdSBjoern A. Zeeb #define PHY_TSSI_EXTRA_GROUP_BIT BIT(31)
3228*6d67aabdSBjoern A. Zeeb #define PHY_TSSI_EXTRA_GROUP(idx) (PHY_TSSI_EXTRA_GROUP_BIT | (idx))
3229*6d67aabdSBjoern A. Zeeb #define PHY_IS_TSSI_EXTRA_GROUP(group) ((group) & PHY_TSSI_EXTRA_GROUP_BIT)
3230*6d67aabdSBjoern A. Zeeb #define PHY_TSSI_EXTRA_GET_GROUP_IDX1(group) \
3231*6d67aabdSBjoern A. Zeeb 	((group) & ~PHY_TSSI_EXTRA_GROUP_BIT)
3232*6d67aabdSBjoern A. Zeeb #define PHY_TSSI_EXTRA_GET_GROUP_IDX2(group) \
3233*6d67aabdSBjoern A. Zeeb 	(PHY_TSSI_EXTRA_GET_GROUP_IDX1(group) + 1)
3234*6d67aabdSBjoern A. Zeeb 
3235*6d67aabdSBjoern A. Zeeb static u32 phy_tssi_get_ofdm_group(u8 ch)
3236*6d67aabdSBjoern A. Zeeb {
3237*6d67aabdSBjoern A. Zeeb 	switch (ch) {
3238*6d67aabdSBjoern A. Zeeb 	case 1 ... 2:
3239*6d67aabdSBjoern A. Zeeb 		return 0;
3240*6d67aabdSBjoern A. Zeeb 	case 3 ... 5:
3241*6d67aabdSBjoern A. Zeeb 		return 1;
3242*6d67aabdSBjoern A. Zeeb 	case 6 ... 8:
3243*6d67aabdSBjoern A. Zeeb 		return 2;
3244*6d67aabdSBjoern A. Zeeb 	case 9 ... 11:
3245*6d67aabdSBjoern A. Zeeb 		return 3;
3246*6d67aabdSBjoern A. Zeeb 	case 12 ... 14:
3247*6d67aabdSBjoern A. Zeeb 		return 4;
3248*6d67aabdSBjoern A. Zeeb 	case 36 ... 40:
3249*6d67aabdSBjoern A. Zeeb 		return 5;
3250*6d67aabdSBjoern A. Zeeb 	case 41 ... 43:
3251*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(5);
3252*6d67aabdSBjoern A. Zeeb 	case 44 ... 48:
3253*6d67aabdSBjoern A. Zeeb 		return 6;
3254*6d67aabdSBjoern A. Zeeb 	case 49 ... 51:
3255*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(6);
3256*6d67aabdSBjoern A. Zeeb 	case 52 ... 56:
3257*6d67aabdSBjoern A. Zeeb 		return 7;
3258*6d67aabdSBjoern A. Zeeb 	case 57 ... 59:
3259*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(7);
3260*6d67aabdSBjoern A. Zeeb 	case 60 ... 64:
3261*6d67aabdSBjoern A. Zeeb 		return 8;
3262*6d67aabdSBjoern A. Zeeb 	case 100 ... 104:
3263*6d67aabdSBjoern A. Zeeb 		return 9;
3264*6d67aabdSBjoern A. Zeeb 	case 105 ... 107:
3265*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(9);
3266*6d67aabdSBjoern A. Zeeb 	case 108 ... 112:
3267*6d67aabdSBjoern A. Zeeb 		return 10;
3268*6d67aabdSBjoern A. Zeeb 	case 113 ... 115:
3269*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(10);
3270*6d67aabdSBjoern A. Zeeb 	case 116 ... 120:
3271*6d67aabdSBjoern A. Zeeb 		return 11;
3272*6d67aabdSBjoern A. Zeeb 	case 121 ... 123:
3273*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(11);
3274*6d67aabdSBjoern A. Zeeb 	case 124 ... 128:
3275*6d67aabdSBjoern A. Zeeb 		return 12;
3276*6d67aabdSBjoern A. Zeeb 	case 129 ... 131:
3277*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(12);
3278*6d67aabdSBjoern A. Zeeb 	case 132 ... 136:
3279*6d67aabdSBjoern A. Zeeb 		return 13;
3280*6d67aabdSBjoern A. Zeeb 	case 137 ... 139:
3281*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(13);
3282*6d67aabdSBjoern A. Zeeb 	case 140 ... 144:
3283*6d67aabdSBjoern A. Zeeb 		return 14;
3284*6d67aabdSBjoern A. Zeeb 	case 149 ... 153:
3285*6d67aabdSBjoern A. Zeeb 		return 15;
3286*6d67aabdSBjoern A. Zeeb 	case 154 ... 156:
3287*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(15);
3288*6d67aabdSBjoern A. Zeeb 	case 157 ... 161:
3289*6d67aabdSBjoern A. Zeeb 		return 16;
3290*6d67aabdSBjoern A. Zeeb 	case 162 ... 164:
3291*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(16);
3292*6d67aabdSBjoern A. Zeeb 	case 165 ... 169:
3293*6d67aabdSBjoern A. Zeeb 		return 17;
3294*6d67aabdSBjoern A. Zeeb 	case 170 ... 172:
3295*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(17);
3296*6d67aabdSBjoern A. Zeeb 	case 173 ... 177:
3297*6d67aabdSBjoern A. Zeeb 		return 18;
3298*6d67aabdSBjoern A. Zeeb 	}
3299*6d67aabdSBjoern A. Zeeb 
3300*6d67aabdSBjoern A. Zeeb 	return 0;
3301*6d67aabdSBjoern A. Zeeb }
3302*6d67aabdSBjoern A. Zeeb 
3303*6d67aabdSBjoern A. Zeeb static u32 phy_tssi_get_6g_ofdm_group(u8 ch)
3304*6d67aabdSBjoern A. Zeeb {
3305*6d67aabdSBjoern A. Zeeb 	switch (ch) {
3306*6d67aabdSBjoern A. Zeeb 	case 1 ... 5:
3307*6d67aabdSBjoern A. Zeeb 		return 0;
3308*6d67aabdSBjoern A. Zeeb 	case 6 ... 8:
3309*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(0);
3310*6d67aabdSBjoern A. Zeeb 	case 9 ... 13:
3311*6d67aabdSBjoern A. Zeeb 		return 1;
3312*6d67aabdSBjoern A. Zeeb 	case 14 ... 16:
3313*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(1);
3314*6d67aabdSBjoern A. Zeeb 	case 17 ... 21:
3315*6d67aabdSBjoern A. Zeeb 		return 2;
3316*6d67aabdSBjoern A. Zeeb 	case 22 ... 24:
3317*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(2);
3318*6d67aabdSBjoern A. Zeeb 	case 25 ... 29:
3319*6d67aabdSBjoern A. Zeeb 		return 3;
3320*6d67aabdSBjoern A. Zeeb 	case 33 ... 37:
3321*6d67aabdSBjoern A. Zeeb 		return 4;
3322*6d67aabdSBjoern A. Zeeb 	case 38 ... 40:
3323*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(4);
3324*6d67aabdSBjoern A. Zeeb 	case 41 ... 45:
3325*6d67aabdSBjoern A. Zeeb 		return 5;
3326*6d67aabdSBjoern A. Zeeb 	case 46 ... 48:
3327*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(5);
3328*6d67aabdSBjoern A. Zeeb 	case 49 ... 53:
3329*6d67aabdSBjoern A. Zeeb 		return 6;
3330*6d67aabdSBjoern A. Zeeb 	case 54 ... 56:
3331*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(6);
3332*6d67aabdSBjoern A. Zeeb 	case 57 ... 61:
3333*6d67aabdSBjoern A. Zeeb 		return 7;
3334*6d67aabdSBjoern A. Zeeb 	case 65 ... 69:
3335*6d67aabdSBjoern A. Zeeb 		return 8;
3336*6d67aabdSBjoern A. Zeeb 	case 70 ... 72:
3337*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(8);
3338*6d67aabdSBjoern A. Zeeb 	case 73 ... 77:
3339*6d67aabdSBjoern A. Zeeb 		return 9;
3340*6d67aabdSBjoern A. Zeeb 	case 78 ... 80:
3341*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(9);
3342*6d67aabdSBjoern A. Zeeb 	case 81 ... 85:
3343*6d67aabdSBjoern A. Zeeb 		return 10;
3344*6d67aabdSBjoern A. Zeeb 	case 86 ... 88:
3345*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(10);
3346*6d67aabdSBjoern A. Zeeb 	case 89 ... 93:
3347*6d67aabdSBjoern A. Zeeb 		return 11;
3348*6d67aabdSBjoern A. Zeeb 	case 97 ... 101:
3349*6d67aabdSBjoern A. Zeeb 		return 12;
3350*6d67aabdSBjoern A. Zeeb 	case 102 ... 104:
3351*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(12);
3352*6d67aabdSBjoern A. Zeeb 	case 105 ... 109:
3353*6d67aabdSBjoern A. Zeeb 		return 13;
3354*6d67aabdSBjoern A. Zeeb 	case 110 ... 112:
3355*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(13);
3356*6d67aabdSBjoern A. Zeeb 	case 113 ... 117:
3357*6d67aabdSBjoern A. Zeeb 		return 14;
3358*6d67aabdSBjoern A. Zeeb 	case 118 ... 120:
3359*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(14);
3360*6d67aabdSBjoern A. Zeeb 	case 121 ... 125:
3361*6d67aabdSBjoern A. Zeeb 		return 15;
3362*6d67aabdSBjoern A. Zeeb 	case 129 ... 133:
3363*6d67aabdSBjoern A. Zeeb 		return 16;
3364*6d67aabdSBjoern A. Zeeb 	case 134 ... 136:
3365*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(16);
3366*6d67aabdSBjoern A. Zeeb 	case 137 ... 141:
3367*6d67aabdSBjoern A. Zeeb 		return 17;
3368*6d67aabdSBjoern A. Zeeb 	case 142 ... 144:
3369*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(17);
3370*6d67aabdSBjoern A. Zeeb 	case 145 ... 149:
3371*6d67aabdSBjoern A. Zeeb 		return 18;
3372*6d67aabdSBjoern A. Zeeb 	case 150 ... 152:
3373*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(18);
3374*6d67aabdSBjoern A. Zeeb 	case 153 ... 157:
3375*6d67aabdSBjoern A. Zeeb 		return 19;
3376*6d67aabdSBjoern A. Zeeb 	case 161 ... 165:
3377*6d67aabdSBjoern A. Zeeb 		return 20;
3378*6d67aabdSBjoern A. Zeeb 	case 166 ... 168:
3379*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(20);
3380*6d67aabdSBjoern A. Zeeb 	case 169 ... 173:
3381*6d67aabdSBjoern A. Zeeb 		return 21;
3382*6d67aabdSBjoern A. Zeeb 	case 174 ... 176:
3383*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(21);
3384*6d67aabdSBjoern A. Zeeb 	case 177 ... 181:
3385*6d67aabdSBjoern A. Zeeb 		return 22;
3386*6d67aabdSBjoern A. Zeeb 	case 182 ... 184:
3387*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(22);
3388*6d67aabdSBjoern A. Zeeb 	case 185 ... 189:
3389*6d67aabdSBjoern A. Zeeb 		return 23;
3390*6d67aabdSBjoern A. Zeeb 	case 193 ... 197:
3391*6d67aabdSBjoern A. Zeeb 		return 24;
3392*6d67aabdSBjoern A. Zeeb 	case 198 ... 200:
3393*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(24);
3394*6d67aabdSBjoern A. Zeeb 	case 201 ... 205:
3395*6d67aabdSBjoern A. Zeeb 		return 25;
3396*6d67aabdSBjoern A. Zeeb 	case 206 ... 208:
3397*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(25);
3398*6d67aabdSBjoern A. Zeeb 	case 209 ... 213:
3399*6d67aabdSBjoern A. Zeeb 		return 26;
3400*6d67aabdSBjoern A. Zeeb 	case 214 ... 216:
3401*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(26);
3402*6d67aabdSBjoern A. Zeeb 	case 217 ... 221:
3403*6d67aabdSBjoern A. Zeeb 		return 27;
3404*6d67aabdSBjoern A. Zeeb 	case 225 ... 229:
3405*6d67aabdSBjoern A. Zeeb 		return 28;
3406*6d67aabdSBjoern A. Zeeb 	case 230 ... 232:
3407*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(28);
3408*6d67aabdSBjoern A. Zeeb 	case 233 ... 237:
3409*6d67aabdSBjoern A. Zeeb 		return 29;
3410*6d67aabdSBjoern A. Zeeb 	case 238 ... 240:
3411*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(29);
3412*6d67aabdSBjoern A. Zeeb 	case 241 ... 245:
3413*6d67aabdSBjoern A. Zeeb 		return 30;
3414*6d67aabdSBjoern A. Zeeb 	case 246 ... 248:
3415*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(30);
3416*6d67aabdSBjoern A. Zeeb 	case 249 ... 253:
3417*6d67aabdSBjoern A. Zeeb 		return 31;
3418*6d67aabdSBjoern A. Zeeb 	}
3419*6d67aabdSBjoern A. Zeeb 
3420*6d67aabdSBjoern A. Zeeb 	return 0;
3421*6d67aabdSBjoern A. Zeeb }
3422*6d67aabdSBjoern A. Zeeb 
3423*6d67aabdSBjoern A. Zeeb static u32 phy_tssi_get_trim_group(u8 ch)
3424*6d67aabdSBjoern A. Zeeb {
3425*6d67aabdSBjoern A. Zeeb 	switch (ch) {
3426*6d67aabdSBjoern A. Zeeb 	case 1 ... 8:
3427*6d67aabdSBjoern A. Zeeb 		return 0;
3428*6d67aabdSBjoern A. Zeeb 	case 9 ... 14:
3429*6d67aabdSBjoern A. Zeeb 		return 1;
3430*6d67aabdSBjoern A. Zeeb 	case 36 ... 48:
3431*6d67aabdSBjoern A. Zeeb 		return 2;
3432*6d67aabdSBjoern A. Zeeb 	case 49 ... 51:
3433*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(2);
3434*6d67aabdSBjoern A. Zeeb 	case 52 ... 64:
3435*6d67aabdSBjoern A. Zeeb 		return 3;
3436*6d67aabdSBjoern A. Zeeb 	case 100 ... 112:
3437*6d67aabdSBjoern A. Zeeb 		return 4;
3438*6d67aabdSBjoern A. Zeeb 	case 113 ... 115:
3439*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(4);
3440*6d67aabdSBjoern A. Zeeb 	case 116 ... 128:
3441*6d67aabdSBjoern A. Zeeb 		return 5;
3442*6d67aabdSBjoern A. Zeeb 	case 132 ... 144:
3443*6d67aabdSBjoern A. Zeeb 		return 6;
3444*6d67aabdSBjoern A. Zeeb 	case 149 ... 177:
3445*6d67aabdSBjoern A. Zeeb 		return 7;
3446*6d67aabdSBjoern A. Zeeb 	}
3447*6d67aabdSBjoern A. Zeeb 
3448*6d67aabdSBjoern A. Zeeb 	return 0;
3449*6d67aabdSBjoern A. Zeeb }
3450*6d67aabdSBjoern A. Zeeb 
3451*6d67aabdSBjoern A. Zeeb static u32 phy_tssi_get_6g_trim_group(u8 ch)
3452*6d67aabdSBjoern A. Zeeb {
3453*6d67aabdSBjoern A. Zeeb 	switch (ch) {
3454*6d67aabdSBjoern A. Zeeb 	case 1 ... 13:
3455*6d67aabdSBjoern A. Zeeb 		return 0;
3456*6d67aabdSBjoern A. Zeeb 	case 14 ... 16:
3457*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(0);
3458*6d67aabdSBjoern A. Zeeb 	case 17 ... 29:
3459*6d67aabdSBjoern A. Zeeb 		return 1;
3460*6d67aabdSBjoern A. Zeeb 	case 33 ... 45:
3461*6d67aabdSBjoern A. Zeeb 		return 2;
3462*6d67aabdSBjoern A. Zeeb 	case 46 ... 48:
3463*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(2);
3464*6d67aabdSBjoern A. Zeeb 	case 49 ... 61:
3465*6d67aabdSBjoern A. Zeeb 		return 3;
3466*6d67aabdSBjoern A. Zeeb 	case 65 ... 77:
3467*6d67aabdSBjoern A. Zeeb 		return 4;
3468*6d67aabdSBjoern A. Zeeb 	case 78 ... 80:
3469*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(4);
3470*6d67aabdSBjoern A. Zeeb 	case 81 ... 93:
3471*6d67aabdSBjoern A. Zeeb 		return 5;
3472*6d67aabdSBjoern A. Zeeb 	case 97 ... 109:
3473*6d67aabdSBjoern A. Zeeb 		return 6;
3474*6d67aabdSBjoern A. Zeeb 	case 110 ... 112:
3475*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(6);
3476*6d67aabdSBjoern A. Zeeb 	case 113 ... 125:
3477*6d67aabdSBjoern A. Zeeb 		return 7;
3478*6d67aabdSBjoern A. Zeeb 	case 129 ... 141:
3479*6d67aabdSBjoern A. Zeeb 		return 8;
3480*6d67aabdSBjoern A. Zeeb 	case 142 ... 144:
3481*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(8);
3482*6d67aabdSBjoern A. Zeeb 	case 145 ... 157:
3483*6d67aabdSBjoern A. Zeeb 		return 9;
3484*6d67aabdSBjoern A. Zeeb 	case 161 ... 173:
3485*6d67aabdSBjoern A. Zeeb 		return 10;
3486*6d67aabdSBjoern A. Zeeb 	case 174 ... 176:
3487*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(10);
3488*6d67aabdSBjoern A. Zeeb 	case 177 ... 189:
3489*6d67aabdSBjoern A. Zeeb 		return 11;
3490*6d67aabdSBjoern A. Zeeb 	case 193 ... 205:
3491*6d67aabdSBjoern A. Zeeb 		return 12;
3492*6d67aabdSBjoern A. Zeeb 	case 206 ... 208:
3493*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(12);
3494*6d67aabdSBjoern A. Zeeb 	case 209 ... 221:
3495*6d67aabdSBjoern A. Zeeb 		return 13;
3496*6d67aabdSBjoern A. Zeeb 	case 225 ... 237:
3497*6d67aabdSBjoern A. Zeeb 		return 14;
3498*6d67aabdSBjoern A. Zeeb 	case 238 ... 240:
3499*6d67aabdSBjoern A. Zeeb 		return PHY_TSSI_EXTRA_GROUP(14);
3500*6d67aabdSBjoern A. Zeeb 	case 241 ... 253:
3501*6d67aabdSBjoern A. Zeeb 		return 15;
3502*6d67aabdSBjoern A. Zeeb 	}
3503*6d67aabdSBjoern A. Zeeb 
3504*6d67aabdSBjoern A. Zeeb 	return 0;
3505*6d67aabdSBjoern A. Zeeb }
3506*6d67aabdSBjoern A. Zeeb 
3507*6d67aabdSBjoern A. Zeeb static s8 phy_tssi_get_ofdm_de(struct rtw89_dev *rtwdev,
3508*6d67aabdSBjoern A. Zeeb 			       enum rtw89_phy_idx phy,
3509*6d67aabdSBjoern A. Zeeb 			       const struct rtw89_chan *chan,
3510*6d67aabdSBjoern A. Zeeb 			       enum rtw89_rf_path path)
3511*6d67aabdSBjoern A. Zeeb {
3512*6d67aabdSBjoern A. Zeeb 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
3513*6d67aabdSBjoern A. Zeeb 	enum rtw89_band band = chan->band_type;
3514*6d67aabdSBjoern A. Zeeb 	u8 ch = chan->channel;
3515*6d67aabdSBjoern A. Zeeb 	u32 gidx_1st;
3516*6d67aabdSBjoern A. Zeeb 	u32 gidx_2nd;
3517*6d67aabdSBjoern A. Zeeb 	s8 de_1st;
3518*6d67aabdSBjoern A. Zeeb 	s8 de_2nd;
3519*6d67aabdSBjoern A. Zeeb 	u32 gidx;
3520*6d67aabdSBjoern A. Zeeb 	s8 val;
3521*6d67aabdSBjoern A. Zeeb 
3522*6d67aabdSBjoern A. Zeeb 	if (band == RTW89_BAND_6G)
3523*6d67aabdSBjoern A. Zeeb 		goto calc_6g;
3524*6d67aabdSBjoern A. Zeeb 
3525*6d67aabdSBjoern A. Zeeb 	gidx = phy_tssi_get_ofdm_group(ch);
3526*6d67aabdSBjoern A. Zeeb 
3527*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3528*6d67aabdSBjoern A. Zeeb 		    "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n",
3529*6d67aabdSBjoern A. Zeeb 		    path, gidx);
3530*6d67aabdSBjoern A. Zeeb 
3531*6d67aabdSBjoern A. Zeeb 	if (PHY_IS_TSSI_EXTRA_GROUP(gidx)) {
3532*6d67aabdSBjoern A. Zeeb 		gidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(gidx);
3533*6d67aabdSBjoern A. Zeeb 		gidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(gidx);
3534*6d67aabdSBjoern A. Zeeb 		de_1st = tssi_info->tssi_mcs[path][gidx_1st];
3535*6d67aabdSBjoern A. Zeeb 		de_2nd = tssi_info->tssi_mcs[path][gidx_2nd];
3536*6d67aabdSBjoern A. Zeeb 		val = (de_1st + de_2nd) / 2;
3537*6d67aabdSBjoern A. Zeeb 
3538*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3539*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n",
3540*6d67aabdSBjoern A. Zeeb 			    path, val, de_1st, de_2nd);
3541*6d67aabdSBjoern A. Zeeb 	} else {
3542*6d67aabdSBjoern A. Zeeb 		val = tssi_info->tssi_mcs[path][gidx];
3543*6d67aabdSBjoern A. Zeeb 
3544*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3545*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val);
3546*6d67aabdSBjoern A. Zeeb 	}
3547*6d67aabdSBjoern A. Zeeb 
3548*6d67aabdSBjoern A. Zeeb 	return val;
3549*6d67aabdSBjoern A. Zeeb 
3550*6d67aabdSBjoern A. Zeeb calc_6g:
3551*6d67aabdSBjoern A. Zeeb 	gidx = phy_tssi_get_6g_ofdm_group(ch);
3552*6d67aabdSBjoern A. Zeeb 
3553*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3554*6d67aabdSBjoern A. Zeeb 		    "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n",
3555*6d67aabdSBjoern A. Zeeb 		    path, gidx);
3556*6d67aabdSBjoern A. Zeeb 
3557*6d67aabdSBjoern A. Zeeb 	if (PHY_IS_TSSI_EXTRA_GROUP(gidx)) {
3558*6d67aabdSBjoern A. Zeeb 		gidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(gidx);
3559*6d67aabdSBjoern A. Zeeb 		gidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(gidx);
3560*6d67aabdSBjoern A. Zeeb 		de_1st = tssi_info->tssi_6g_mcs[path][gidx_1st];
3561*6d67aabdSBjoern A. Zeeb 		de_2nd = tssi_info->tssi_6g_mcs[path][gidx_2nd];
3562*6d67aabdSBjoern A. Zeeb 		val = (de_1st + de_2nd) / 2;
3563*6d67aabdSBjoern A. Zeeb 
3564*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3565*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n",
3566*6d67aabdSBjoern A. Zeeb 			    path, val, de_1st, de_2nd);
3567*6d67aabdSBjoern A. Zeeb 	} else {
3568*6d67aabdSBjoern A. Zeeb 		val = tssi_info->tssi_6g_mcs[path][gidx];
3569*6d67aabdSBjoern A. Zeeb 
3570*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3571*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val);
3572*6d67aabdSBjoern A. Zeeb 	}
3573*6d67aabdSBjoern A. Zeeb 
3574*6d67aabdSBjoern A. Zeeb 	return val;
3575*6d67aabdSBjoern A. Zeeb }
3576*6d67aabdSBjoern A. Zeeb 
3577*6d67aabdSBjoern A. Zeeb static s8 phy_tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev,
3578*6d67aabdSBjoern A. Zeeb 				    enum rtw89_phy_idx phy,
3579*6d67aabdSBjoern A. Zeeb 				    const struct rtw89_chan *chan,
3580*6d67aabdSBjoern A. Zeeb 				    enum rtw89_rf_path path)
3581*6d67aabdSBjoern A. Zeeb {
3582*6d67aabdSBjoern A. Zeeb 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
3583*6d67aabdSBjoern A. Zeeb 	enum rtw89_band band = chan->band_type;
3584*6d67aabdSBjoern A. Zeeb 	u8 ch = chan->channel;
3585*6d67aabdSBjoern A. Zeeb 	u32 tgidx_1st;
3586*6d67aabdSBjoern A. Zeeb 	u32 tgidx_2nd;
3587*6d67aabdSBjoern A. Zeeb 	s8 tde_1st;
3588*6d67aabdSBjoern A. Zeeb 	s8 tde_2nd;
3589*6d67aabdSBjoern A. Zeeb 	u32 tgidx;
3590*6d67aabdSBjoern A. Zeeb 	s8 val;
3591*6d67aabdSBjoern A. Zeeb 
3592*6d67aabdSBjoern A. Zeeb 	if (band == RTW89_BAND_6G)
3593*6d67aabdSBjoern A. Zeeb 		goto calc_6g;
3594*6d67aabdSBjoern A. Zeeb 
3595*6d67aabdSBjoern A. Zeeb 	tgidx = phy_tssi_get_trim_group(ch);
3596*6d67aabdSBjoern A. Zeeb 
3597*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3598*6d67aabdSBjoern A. Zeeb 		    "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n",
3599*6d67aabdSBjoern A. Zeeb 		    path, tgidx);
3600*6d67aabdSBjoern A. Zeeb 
3601*6d67aabdSBjoern A. Zeeb 	if (PHY_IS_TSSI_EXTRA_GROUP(tgidx)) {
3602*6d67aabdSBjoern A. Zeeb 		tgidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(tgidx);
3603*6d67aabdSBjoern A. Zeeb 		tgidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(tgidx);
3604*6d67aabdSBjoern A. Zeeb 		tde_1st = tssi_info->tssi_trim[path][tgidx_1st];
3605*6d67aabdSBjoern A. Zeeb 		tde_2nd = tssi_info->tssi_trim[path][tgidx_2nd];
3606*6d67aabdSBjoern A. Zeeb 		val = (tde_1st + tde_2nd) / 2;
3607*6d67aabdSBjoern A. Zeeb 
3608*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3609*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n",
3610*6d67aabdSBjoern A. Zeeb 			    path, val, tde_1st, tde_2nd);
3611*6d67aabdSBjoern A. Zeeb 	} else {
3612*6d67aabdSBjoern A. Zeeb 		val = tssi_info->tssi_trim[path][tgidx];
3613*6d67aabdSBjoern A. Zeeb 
3614*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3615*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d\n",
3616*6d67aabdSBjoern A. Zeeb 			    path, val);
3617*6d67aabdSBjoern A. Zeeb 	}
3618*6d67aabdSBjoern A. Zeeb 
3619*6d67aabdSBjoern A. Zeeb 	return val;
3620*6d67aabdSBjoern A. Zeeb 
3621*6d67aabdSBjoern A. Zeeb calc_6g:
3622*6d67aabdSBjoern A. Zeeb 	tgidx = phy_tssi_get_6g_trim_group(ch);
3623*6d67aabdSBjoern A. Zeeb 
3624*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3625*6d67aabdSBjoern A. Zeeb 		    "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n",
3626*6d67aabdSBjoern A. Zeeb 		    path, tgidx);
3627*6d67aabdSBjoern A. Zeeb 
3628*6d67aabdSBjoern A. Zeeb 	if (PHY_IS_TSSI_EXTRA_GROUP(tgidx)) {
3629*6d67aabdSBjoern A. Zeeb 		tgidx_1st = PHY_TSSI_EXTRA_GET_GROUP_IDX1(tgidx);
3630*6d67aabdSBjoern A. Zeeb 		tgidx_2nd = PHY_TSSI_EXTRA_GET_GROUP_IDX2(tgidx);
3631*6d67aabdSBjoern A. Zeeb 		tde_1st = tssi_info->tssi_trim_6g[path][tgidx_1st];
3632*6d67aabdSBjoern A. Zeeb 		tde_2nd = tssi_info->tssi_trim_6g[path][tgidx_2nd];
3633*6d67aabdSBjoern A. Zeeb 		val = (tde_1st + tde_2nd) / 2;
3634*6d67aabdSBjoern A. Zeeb 
3635*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3636*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n",
3637*6d67aabdSBjoern A. Zeeb 			    path, val, tde_1st, tde_2nd);
3638*6d67aabdSBjoern A. Zeeb 	} else {
3639*6d67aabdSBjoern A. Zeeb 		val = tssi_info->tssi_trim_6g[path][tgidx];
3640*6d67aabdSBjoern A. Zeeb 
3641*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3642*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d mcs trim_de=%d\n",
3643*6d67aabdSBjoern A. Zeeb 			    path, val);
3644*6d67aabdSBjoern A. Zeeb 	}
3645*6d67aabdSBjoern A. Zeeb 
3646*6d67aabdSBjoern A. Zeeb 	return val;
3647*6d67aabdSBjoern A. Zeeb }
3648*6d67aabdSBjoern A. Zeeb 
3649*6d67aabdSBjoern A. Zeeb void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev,
3650*6d67aabdSBjoern A. Zeeb 					       enum rtw89_phy_idx phy,
3651*6d67aabdSBjoern A. Zeeb 					       const struct rtw89_chan *chan,
3652*6d67aabdSBjoern A. Zeeb 					       struct rtw89_h2c_rf_tssi *h2c)
3653*6d67aabdSBjoern A. Zeeb {
3654*6d67aabdSBjoern A. Zeeb 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
3655*6d67aabdSBjoern A. Zeeb 	u8 ch = chan->channel;
3656*6d67aabdSBjoern A. Zeeb 	s8 trim_de;
3657*6d67aabdSBjoern A. Zeeb 	s8 ofdm_de;
3658*6d67aabdSBjoern A. Zeeb 	s8 cck_de;
3659*6d67aabdSBjoern A. Zeeb 	u8 gidx;
3660*6d67aabdSBjoern A. Zeeb 	s8 val;
3661*6d67aabdSBjoern A. Zeeb 	int i;
3662*6d67aabdSBjoern A. Zeeb 
3663*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI][TRIM]: phy=%d ch=%d\n",
3664*6d67aabdSBjoern A. Zeeb 		    phy, ch);
3665*6d67aabdSBjoern A. Zeeb 
3666*6d67aabdSBjoern A. Zeeb 	for (i = RF_PATH_A; i <= RF_PATH_B; i++) {
3667*6d67aabdSBjoern A. Zeeb 		trim_de = phy_tssi_get_ofdm_trim_de(rtwdev, phy, chan, i);
3668*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_trim_de[i] = trim_de;
3669*6d67aabdSBjoern A. Zeeb 
3670*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3671*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d trim_de=0x%x\n", i, trim_de);
3672*6d67aabdSBjoern A. Zeeb 
3673*6d67aabdSBjoern A. Zeeb 		gidx = phy_tssi_get_cck_group(ch);
3674*6d67aabdSBjoern A. Zeeb 		cck_de = tssi_info->tssi_cck[i][gidx];
3675*6d67aabdSBjoern A. Zeeb 		val = u32_get_bits(cck_de + trim_de, 0xff);
3676*6d67aabdSBjoern A. Zeeb 
3677*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_cck_de[i] = 0x0;
3678*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_cck_de_20m[i] = val;
3679*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_cck_de_40m[i] = val;
3680*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_efuse_cck_de[i] = cck_de;
3681*6d67aabdSBjoern A. Zeeb 
3682*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3683*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d cck_de=0x%x\n", i, cck_de);
3684*6d67aabdSBjoern A. Zeeb 
3685*6d67aabdSBjoern A. Zeeb 		ofdm_de = phy_tssi_get_ofdm_de(rtwdev, phy, chan, i);
3686*6d67aabdSBjoern A. Zeeb 		val = u32_get_bits(ofdm_de + trim_de, 0xff);
3687*6d67aabdSBjoern A. Zeeb 
3688*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_ofdm_de[i] = 0x0;
3689*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_ofdm_de_20m[i] = val;
3690*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_ofdm_de_40m[i] = val;
3691*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_ofdm_de_80m[i] = val;
3692*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_ofdm_de_160m[i] = val;
3693*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_ofdm_de_320m[i] = val;
3694*6d67aabdSBjoern A. Zeeb 		h2c->curr_tssi_efuse_ofdm_de[i] = ofdm_de;
3695*6d67aabdSBjoern A. Zeeb 
3696*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3697*6d67aabdSBjoern A. Zeeb 			    "[TSSI][TRIM]: path=%d ofdm_de=0x%x\n", i, ofdm_de);
3698*6d67aabdSBjoern A. Zeeb 	}
3699*6d67aabdSBjoern A. Zeeb }
3700*6d67aabdSBjoern A. Zeeb 
3701*6d67aabdSBjoern A. Zeeb void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev,
3702*6d67aabdSBjoern A. Zeeb 					      enum rtw89_phy_idx phy,
3703*6d67aabdSBjoern A. Zeeb 					      const struct rtw89_chan *chan,
3704*6d67aabdSBjoern A. Zeeb 					      struct rtw89_h2c_rf_tssi *h2c)
3705*6d67aabdSBjoern A. Zeeb {
3706*6d67aabdSBjoern A. Zeeb 	struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
3707*6d67aabdSBjoern A. Zeeb 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
3708*6d67aabdSBjoern A. Zeeb 	const s8 *thm_up[RF_PATH_B + 1] = {};
3709*6d67aabdSBjoern A. Zeeb 	const s8 *thm_down[RF_PATH_B + 1] = {};
3710*6d67aabdSBjoern A. Zeeb 	u8 subband = chan->subband_type;
3711*6d67aabdSBjoern A. Zeeb 	s8 thm_ofst[128] = {0};
3712*6d67aabdSBjoern A. Zeeb 	u8 thermal;
3713*6d67aabdSBjoern A. Zeeb 	u8 path;
3714*6d67aabdSBjoern A. Zeeb 	u8 i, j;
3715*6d67aabdSBjoern A. Zeeb 
3716*6d67aabdSBjoern A. Zeeb 	switch (subband) {
3717*6d67aabdSBjoern A. Zeeb 	default:
3718*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_2G:
3719*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P][0];
3720*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N][0];
3721*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P][0];
3722*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N][0];
3723*6d67aabdSBjoern A. Zeeb 		break;
3724*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_5G_BAND_1:
3725*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][0];
3726*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][0];
3727*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][0];
3728*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][0];
3729*6d67aabdSBjoern A. Zeeb 		break;
3730*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_5G_BAND_3:
3731*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][1];
3732*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][1];
3733*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][1];
3734*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][1];
3735*6d67aabdSBjoern A. Zeeb 		break;
3736*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_5G_BAND_4:
3737*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][2];
3738*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][2];
3739*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][2];
3740*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][2];
3741*6d67aabdSBjoern A. Zeeb 		break;
3742*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX0:
3743*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX1:
3744*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][0];
3745*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][0];
3746*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][0];
3747*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][0];
3748*6d67aabdSBjoern A. Zeeb 		break;
3749*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX2:
3750*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX3:
3751*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][1];
3752*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][1];
3753*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][1];
3754*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][1];
3755*6d67aabdSBjoern A. Zeeb 		break;
3756*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX4:
3757*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX5:
3758*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][2];
3759*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][2];
3760*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][2];
3761*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][2];
3762*6d67aabdSBjoern A. Zeeb 		break;
3763*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX6:
3764*6d67aabdSBjoern A. Zeeb 	case RTW89_CH_6G_BAND_IDX7:
3765*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][3];
3766*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_A] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][3];
3767*6d67aabdSBjoern A. Zeeb 		thm_up[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][3];
3768*6d67aabdSBjoern A. Zeeb 		thm_down[RF_PATH_B] = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][3];
3769*6d67aabdSBjoern A. Zeeb 		break;
3770*6d67aabdSBjoern A. Zeeb 	}
3771*6d67aabdSBjoern A. Zeeb 
3772*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3773*6d67aabdSBjoern A. Zeeb 		    "[TSSI] tmeter tbl on subband: %u\n", subband);
3774*6d67aabdSBjoern A. Zeeb 
3775*6d67aabdSBjoern A. Zeeb 	for (path = RF_PATH_A; path <= RF_PATH_B; path++) {
3776*6d67aabdSBjoern A. Zeeb 		thermal = tssi_info->thermal[path];
3777*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3778*6d67aabdSBjoern A. Zeeb 			    "path: %u, pg thermal: 0x%x\n", path, thermal);
3779*6d67aabdSBjoern A. Zeeb 
3780*6d67aabdSBjoern A. Zeeb 		if (thermal == 0xff) {
3781*6d67aabdSBjoern A. Zeeb 			h2c->pg_thermal[path] = 0x38;
3782*6d67aabdSBjoern A. Zeeb 			memset(h2c->ftable[path], 0, sizeof(h2c->ftable[path]));
3783*6d67aabdSBjoern A. Zeeb 			continue;
3784*6d67aabdSBjoern A. Zeeb 		}
3785*6d67aabdSBjoern A. Zeeb 
3786*6d67aabdSBjoern A. Zeeb 		h2c->pg_thermal[path] = thermal;
3787*6d67aabdSBjoern A. Zeeb 
3788*6d67aabdSBjoern A. Zeeb 		i = 0;
3789*6d67aabdSBjoern A. Zeeb 		for (j = 0; j < 64; j++)
3790*6d67aabdSBjoern A. Zeeb 			thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
3791*6d67aabdSBjoern A. Zeeb 				      thm_up[path][i++] :
3792*6d67aabdSBjoern A. Zeeb 				      thm_up[path][DELTA_SWINGIDX_SIZE - 1];
3793*6d67aabdSBjoern A. Zeeb 
3794*6d67aabdSBjoern A. Zeeb 		i = 1;
3795*6d67aabdSBjoern A. Zeeb 		for (j = 127; j >= 64; j--)
3796*6d67aabdSBjoern A. Zeeb 			thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ?
3797*6d67aabdSBjoern A. Zeeb 				      -thm_down[path][i++] :
3798*6d67aabdSBjoern A. Zeeb 				      -thm_down[path][DELTA_SWINGIDX_SIZE - 1];
3799*6d67aabdSBjoern A. Zeeb 
3800*6d67aabdSBjoern A. Zeeb 		for (i = 0; i < 128; i += 4) {
3801*6d67aabdSBjoern A. Zeeb 			h2c->ftable[path][i + 0] = thm_ofst[i + 3];
3802*6d67aabdSBjoern A. Zeeb 			h2c->ftable[path][i + 1] = thm_ofst[i + 2];
3803*6d67aabdSBjoern A. Zeeb 			h2c->ftable[path][i + 2] = thm_ofst[i + 1];
3804*6d67aabdSBjoern A. Zeeb 			h2c->ftable[path][i + 3] = thm_ofst[i + 0];
3805*6d67aabdSBjoern A. Zeeb 
3806*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_TSSI,
3807*6d67aabdSBjoern A. Zeeb 				    "thm ofst [%x]: %02x %02x %02x %02x\n",
3808*6d67aabdSBjoern A. Zeeb 				    i, thm_ofst[i], thm_ofst[i + 1],
3809*6d67aabdSBjoern A. Zeeb 				    thm_ofst[i + 2], thm_ofst[i + 3]);
3810*6d67aabdSBjoern A. Zeeb 		}
3811*6d67aabdSBjoern A. Zeeb 	}
3812*6d67aabdSBjoern A. Zeeb }
3813*6d67aabdSBjoern A. Zeeb 
38148e93258fSBjoern A. Zeeb static u8 rtw89_phy_cfo_get_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo)
38158e93258fSBjoern A. Zeeb {
3816e2340276SBjoern A. Zeeb 	const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
38178e93258fSBjoern A. Zeeb 	u32 reg_mask;
38188e93258fSBjoern A. Zeeb 
38198e93258fSBjoern A. Zeeb 	if (sc_xo)
3820e2340276SBjoern A. Zeeb 		reg_mask = xtal->sc_xo_mask;
38218e93258fSBjoern A. Zeeb 	else
3822e2340276SBjoern A. Zeeb 		reg_mask = xtal->sc_xi_mask;
38238e93258fSBjoern A. Zeeb 
3824e2340276SBjoern A. Zeeb 	return (u8)rtw89_read32_mask(rtwdev, xtal->xcap_reg, reg_mask);
38258e93258fSBjoern A. Zeeb }
38268e93258fSBjoern A. Zeeb 
38278e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_set_xcap_reg(struct rtw89_dev *rtwdev, bool sc_xo,
38288e93258fSBjoern A. Zeeb 				       u8 val)
38298e93258fSBjoern A. Zeeb {
3830e2340276SBjoern A. Zeeb 	const struct rtw89_xtal_info *xtal = rtwdev->chip->xtal_info;
38318e93258fSBjoern A. Zeeb 	u32 reg_mask;
38328e93258fSBjoern A. Zeeb 
38338e93258fSBjoern A. Zeeb 	if (sc_xo)
3834e2340276SBjoern A. Zeeb 		reg_mask = xtal->sc_xo_mask;
38358e93258fSBjoern A. Zeeb 	else
3836e2340276SBjoern A. Zeeb 		reg_mask = xtal->sc_xi_mask;
38378e93258fSBjoern A. Zeeb 
3838e2340276SBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, xtal->xcap_reg, reg_mask, val);
38398e93258fSBjoern A. Zeeb }
38408e93258fSBjoern A. Zeeb 
38418e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
38428e93258fSBjoern A. Zeeb 					  u8 crystal_cap, bool force)
38438e93258fSBjoern A. Zeeb {
38448e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
38458e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
38468e93258fSBjoern A. Zeeb 	u8 sc_xi_val, sc_xo_val;
38478e93258fSBjoern A. Zeeb 
38488e93258fSBjoern A. Zeeb 	if (!force && cfo->crystal_cap == crystal_cap)
38498e93258fSBjoern A. Zeeb 		return;
38508e93258fSBjoern A. Zeeb 	crystal_cap = clamp_t(u8, crystal_cap, 0, 127);
3851e2340276SBjoern A. Zeeb 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8851B) {
38528e93258fSBjoern A. Zeeb 		rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap);
38538e93258fSBjoern A. Zeeb 		rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap);
38548e93258fSBjoern A. Zeeb 		sc_xo_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, true);
38558e93258fSBjoern A. Zeeb 		sc_xi_val = rtw89_phy_cfo_get_xcap_reg(rtwdev, false);
38568e93258fSBjoern A. Zeeb 	} else {
38578e93258fSBjoern A. Zeeb 		rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XO,
38588e93258fSBjoern A. Zeeb 					crystal_cap, XTAL_SC_XO_MASK);
38598e93258fSBjoern A. Zeeb 		rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XI,
38608e93258fSBjoern A. Zeeb 					crystal_cap, XTAL_SC_XI_MASK);
38618e93258fSBjoern A. Zeeb 		rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XO, &sc_xo_val);
38628e93258fSBjoern A. Zeeb 		rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_XTAL_SC_XI, &sc_xi_val);
38638e93258fSBjoern A. Zeeb 	}
38648e93258fSBjoern A. Zeeb 	cfo->crystal_cap = sc_xi_val;
38658e93258fSBjoern A. Zeeb 	cfo->x_cap_ofst = (s8)((int)cfo->crystal_cap - cfo->def_x_cap);
38668e93258fSBjoern A. Zeeb 
38678e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Set sc_xi=0x%x\n", sc_xi_val);
38688e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Set sc_xo=0x%x\n", sc_xo_val);
38698e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Get xcap_ofst=%d\n",
38708e93258fSBjoern A. Zeeb 		    cfo->x_cap_ofst);
38718e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Set xcap OK\n");
38728e93258fSBjoern A. Zeeb }
38738e93258fSBjoern A. Zeeb 
38748e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_reset(struct rtw89_dev *rtwdev)
38758e93258fSBjoern A. Zeeb {
38768e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
38778e93258fSBjoern A. Zeeb 	u8 cap;
38788e93258fSBjoern A. Zeeb 
38798e93258fSBjoern A. Zeeb 	cfo->def_x_cap = cfo->crystal_cap_default & B_AX_XTAL_SC_MASK;
38808e93258fSBjoern A. Zeeb 	cfo->is_adjust = false;
38818e93258fSBjoern A. Zeeb 	if (cfo->crystal_cap == cfo->def_x_cap)
38828e93258fSBjoern A. Zeeb 		return;
38838e93258fSBjoern A. Zeeb 	cap = cfo->crystal_cap;
38848e93258fSBjoern A. Zeeb 	cap += (cap > cfo->def_x_cap ? -1 : 1);
38858e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_set_crystal_cap(rtwdev, cap, false);
38868e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
38878e93258fSBjoern A. Zeeb 		    "(0x%x) approach to dflt_val=(0x%x)\n", cfo->crystal_cap,
38888e93258fSBjoern A. Zeeb 		    cfo->def_x_cap);
38898e93258fSBjoern A. Zeeb }
38908e93258fSBjoern A. Zeeb 
38918e93258fSBjoern A. Zeeb static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo)
38928e93258fSBjoern A. Zeeb {
38938e93258fSBjoern A. Zeeb 	const struct rtw89_reg_def *dcfo_comp = rtwdev->chip->dcfo_comp;
38948e93258fSBjoern A. Zeeb 	bool is_linked = rtwdev->total_sta_assoc > 0;
38958e93258fSBjoern A. Zeeb 	s32 cfo_avg_312;
38968e93258fSBjoern A. Zeeb 	s32 dcfo_comp_val;
38978e93258fSBjoern A. Zeeb 	int sign;
38988e93258fSBjoern A. Zeeb 
3899*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8922A)
3900*6d67aabdSBjoern A. Zeeb 		return;
3901*6d67aabdSBjoern A. Zeeb 
39028e93258fSBjoern A. Zeeb 	if (!is_linked) {
39038e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "DCFO: is_linked=%d\n",
39048e93258fSBjoern A. Zeeb 			    is_linked);
39058e93258fSBjoern A. Zeeb 		return;
39068e93258fSBjoern A. Zeeb 	}
39078e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "DCFO: curr_cfo=%d\n", curr_cfo);
39088e93258fSBjoern A. Zeeb 	if (curr_cfo == 0)
39098e93258fSBjoern A. Zeeb 		return;
39108e93258fSBjoern A. Zeeb 	dcfo_comp_val = rtw89_phy_read32_mask(rtwdev, R_DCFO, B_DCFO);
39118e93258fSBjoern A. Zeeb 	sign = curr_cfo > 0 ? 1 : -1;
3912e2340276SBjoern A. Zeeb 	cfo_avg_312 = curr_cfo / 625 + sign * dcfo_comp_val;
3913e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "avg_cfo_312=%d step\n", cfo_avg_312);
39148e93258fSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8852A && rtwdev->hal.cv == CHIP_CBV)
39158e93258fSBjoern A. Zeeb 		cfo_avg_312 = -cfo_avg_312;
39168e93258fSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, dcfo_comp->addr, dcfo_comp->mask,
39178e93258fSBjoern A. Zeeb 			       cfo_avg_312);
39188e93258fSBjoern A. Zeeb }
39198e93258fSBjoern A. Zeeb 
39208e93258fSBjoern A. Zeeb static void rtw89_dcfo_comp_init(struct rtw89_dev *rtwdev)
39218e93258fSBjoern A. Zeeb {
3922*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
3923e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
3924*6d67aabdSBjoern A. Zeeb 	const struct rtw89_cfo_regs *cfo = phy->cfo;
3925e2340276SBjoern A. Zeeb 
3926*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, cfo->comp_seg0, cfo->valid_0_mask, 1);
3927*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, cfo->comp, cfo->weighting_mask, 8);
3928e2340276SBjoern A. Zeeb 
3929*6d67aabdSBjoern A. Zeeb 	if (chip->chip_gen == RTW89_CHIP_AX) {
3930*6d67aabdSBjoern A. Zeeb 		if (chip->cfo_hw_comp) {
3931e2340276SBjoern A. Zeeb 			rtw89_write32_mask(rtwdev, R_AX_PWR_UL_CTRL2,
3932e2340276SBjoern A. Zeeb 					   B_AX_PWR_UL_CFO_MASK, 0x6);
3933*6d67aabdSBjoern A. Zeeb 		} else {
3934*6d67aabdSBjoern A. Zeeb 			rtw89_phy_set_phy_regs(rtwdev, R_DCFO, B_DCFO, 1);
3935*6d67aabdSBjoern A. Zeeb 			rtw89_write32_clr(rtwdev, R_AX_PWR_UL_CTRL2,
3936*6d67aabdSBjoern A. Zeeb 					  B_AX_PWR_UL_CFO_MASK);
3937*6d67aabdSBjoern A. Zeeb 		}
3938*6d67aabdSBjoern A. Zeeb 	}
39398e93258fSBjoern A. Zeeb }
39408e93258fSBjoern A. Zeeb 
39418e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_init(struct rtw89_dev *rtwdev)
39428e93258fSBjoern A. Zeeb {
39438e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
39448e93258fSBjoern A. Zeeb 	struct rtw89_efuse *efuse = &rtwdev->efuse;
39458e93258fSBjoern A. Zeeb 
39468e93258fSBjoern A. Zeeb 	cfo->crystal_cap_default = efuse->xtal_cap & B_AX_XTAL_SC_MASK;
39478e93258fSBjoern A. Zeeb 	cfo->crystal_cap = cfo->crystal_cap_default;
39488e93258fSBjoern A. Zeeb 	cfo->def_x_cap = cfo->crystal_cap;
39498e93258fSBjoern A. Zeeb 	cfo->x_cap_ub = min_t(int, cfo->def_x_cap + CFO_BOUND, 0x7f);
39508e93258fSBjoern A. Zeeb 	cfo->x_cap_lb = max_t(int, cfo->def_x_cap - CFO_BOUND, 0x1);
39518e93258fSBjoern A. Zeeb 	cfo->is_adjust = false;
39528e93258fSBjoern A. Zeeb 	cfo->divergence_lock_en = false;
39538e93258fSBjoern A. Zeeb 	cfo->x_cap_ofst = 0;
39548e93258fSBjoern A. Zeeb 	cfo->lock_cnt = 0;
39558e93258fSBjoern A. Zeeb 	cfo->rtw89_multi_cfo_mode = RTW89_TP_BASED_AVG_MODE;
39568e93258fSBjoern A. Zeeb 	cfo->apply_compensation = false;
39578e93258fSBjoern A. Zeeb 	cfo->residual_cfo_acc = 0;
39588e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Default xcap=%0x\n",
39598e93258fSBjoern A. Zeeb 		    cfo->crystal_cap_default);
39608e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_set_crystal_cap(rtwdev, cfo->crystal_cap_default, true);
39618e93258fSBjoern A. Zeeb 	rtw89_dcfo_comp_init(rtwdev);
39628e93258fSBjoern A. Zeeb 	cfo->cfo_timer_ms = 2000;
39638e93258fSBjoern A. Zeeb 	cfo->cfo_trig_by_timer_en = false;
39648e93258fSBjoern A. Zeeb 	cfo->phy_cfo_trk_cnt = 0;
39658e93258fSBjoern A. Zeeb 	cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
39668e93258fSBjoern A. Zeeb 	cfo->cfo_ul_ofdma_acc_mode = RTW89_CFO_UL_OFDMA_ACC_ENABLE;
39678e93258fSBjoern A. Zeeb }
39688e93258fSBjoern A. Zeeb 
39698e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev,
39708e93258fSBjoern A. Zeeb 					     s32 curr_cfo)
39718e93258fSBjoern A. Zeeb {
39728e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
39738e93258fSBjoern A. Zeeb 	s8 crystal_cap = cfo->crystal_cap;
39748e93258fSBjoern A. Zeeb 	s32 cfo_abs = abs(curr_cfo);
39758e93258fSBjoern A. Zeeb 	int sign;
39768e93258fSBjoern A. Zeeb 
3977*6d67aabdSBjoern A. Zeeb 	if (curr_cfo == 0) {
3978*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "curr_cfo=0\n");
3979*6d67aabdSBjoern A. Zeeb 		return;
3980*6d67aabdSBjoern A. Zeeb 	}
39818e93258fSBjoern A. Zeeb 	if (!cfo->is_adjust) {
39828e93258fSBjoern A. Zeeb 		if (cfo_abs > CFO_TRK_ENABLE_TH)
39838e93258fSBjoern A. Zeeb 			cfo->is_adjust = true;
39848e93258fSBjoern A. Zeeb 	} else {
3985*6d67aabdSBjoern A. Zeeb 		if (cfo_abs <= CFO_TRK_STOP_TH)
39868e93258fSBjoern A. Zeeb 			cfo->is_adjust = false;
39878e93258fSBjoern A. Zeeb 	}
39888e93258fSBjoern A. Zeeb 	if (!cfo->is_adjust) {
39898e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Stop CFO tracking\n");
39908e93258fSBjoern A. Zeeb 		return;
39918e93258fSBjoern A. Zeeb 	}
39928e93258fSBjoern A. Zeeb 	sign = curr_cfo > 0 ? 1 : -1;
39938e93258fSBjoern A. Zeeb 	if (cfo_abs > CFO_TRK_STOP_TH_4)
39948e93258fSBjoern A. Zeeb 		crystal_cap += 7 * sign;
39958e93258fSBjoern A. Zeeb 	else if (cfo_abs > CFO_TRK_STOP_TH_3)
39968e93258fSBjoern A. Zeeb 		crystal_cap += 5 * sign;
39978e93258fSBjoern A. Zeeb 	else if (cfo_abs > CFO_TRK_STOP_TH_2)
39988e93258fSBjoern A. Zeeb 		crystal_cap += 3 * sign;
39998e93258fSBjoern A. Zeeb 	else if (cfo_abs > CFO_TRK_STOP_TH_1)
40008e93258fSBjoern A. Zeeb 		crystal_cap += 1 * sign;
40018e93258fSBjoern A. Zeeb 	else
40028e93258fSBjoern A. Zeeb 		return;
40038e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_set_crystal_cap(rtwdev, (u8)crystal_cap, false);
40048e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
40058e93258fSBjoern A. Zeeb 		    "X_cap{Curr,Default}={0x%x,0x%x}\n",
40068e93258fSBjoern A. Zeeb 		    cfo->crystal_cap, cfo->def_x_cap);
40078e93258fSBjoern A. Zeeb }
40088e93258fSBjoern A. Zeeb 
40098e93258fSBjoern A. Zeeb static s32 rtw89_phy_average_cfo_calc(struct rtw89_dev *rtwdev)
40108e93258fSBjoern A. Zeeb {
4011e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
40128e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
40138e93258fSBjoern A. Zeeb 	s32 cfo_khz_all = 0;
40148e93258fSBjoern A. Zeeb 	s32 cfo_cnt_all = 0;
40158e93258fSBjoern A. Zeeb 	s32 cfo_all_avg = 0;
40168e93258fSBjoern A. Zeeb 	u8 i;
40178e93258fSBjoern A. Zeeb 
40188e93258fSBjoern A. Zeeb 	if (rtwdev->total_sta_assoc != 1)
40198e93258fSBjoern A. Zeeb 		return 0;
40208e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "one_entry_only\n");
40218e93258fSBjoern A. Zeeb 	for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
40228e93258fSBjoern A. Zeeb 		if (cfo->cfo_cnt[i] == 0)
40238e93258fSBjoern A. Zeeb 			continue;
40248e93258fSBjoern A. Zeeb 		cfo_khz_all += cfo->cfo_tail[i];
40258e93258fSBjoern A. Zeeb 		cfo_cnt_all += cfo->cfo_cnt[i];
40268e93258fSBjoern A. Zeeb 		cfo_all_avg = phy_div(cfo_khz_all, cfo_cnt_all);
40278e93258fSBjoern A. Zeeb 		cfo->pre_cfo_avg[i] = cfo->cfo_avg[i];
4028e2340276SBjoern A. Zeeb 		cfo->dcfo_avg = phy_div(cfo_khz_all << chip->dcfo_comp_sft,
4029e2340276SBjoern A. Zeeb 					cfo_cnt_all);
40308e93258fSBjoern A. Zeeb 	}
40318e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
40328e93258fSBjoern A. Zeeb 		    "CFO track for macid = %d\n", i);
40338e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
40348e93258fSBjoern A. Zeeb 		    "Total cfo=%dK, pkt_cnt=%d, avg_cfo=%dK\n",
40358e93258fSBjoern A. Zeeb 		    cfo_khz_all, cfo_cnt_all, cfo_all_avg);
40368e93258fSBjoern A. Zeeb 	return cfo_all_avg;
40378e93258fSBjoern A. Zeeb }
40388e93258fSBjoern A. Zeeb 
40398e93258fSBjoern A. Zeeb static s32 rtw89_phy_multi_sta_cfo_calc(struct rtw89_dev *rtwdev)
40408e93258fSBjoern A. Zeeb {
40418e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
40428e93258fSBjoern A. Zeeb 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
40438e93258fSBjoern A. Zeeb 	s32 target_cfo = 0;
40448e93258fSBjoern A. Zeeb 	s32 cfo_khz_all = 0;
40458e93258fSBjoern A. Zeeb 	s32 cfo_khz_all_tp_wgt = 0;
40468e93258fSBjoern A. Zeeb 	s32 cfo_avg = 0;
40478e93258fSBjoern A. Zeeb 	s32 max_cfo_lb = BIT(31);
40488e93258fSBjoern A. Zeeb 	s32 min_cfo_ub = GENMASK(30, 0);
40498e93258fSBjoern A. Zeeb 	u16 cfo_cnt_all = 0;
40508e93258fSBjoern A. Zeeb 	u8 active_entry_cnt = 0;
40518e93258fSBjoern A. Zeeb 	u8 sta_cnt = 0;
40528e93258fSBjoern A. Zeeb 	u32 tp_all = 0;
40538e93258fSBjoern A. Zeeb 	u8 i;
40548e93258fSBjoern A. Zeeb 	u8 cfo_tol = 0;
40558e93258fSBjoern A. Zeeb 
40568e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Multi entry cfo_trk\n");
40578e93258fSBjoern A. Zeeb 	if (cfo->rtw89_multi_cfo_mode == RTW89_PKT_BASED_AVG_MODE) {
40588e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Pkt based avg mode\n");
40598e93258fSBjoern A. Zeeb 		for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
40608e93258fSBjoern A. Zeeb 			if (cfo->cfo_cnt[i] == 0)
40618e93258fSBjoern A. Zeeb 				continue;
40628e93258fSBjoern A. Zeeb 			cfo_khz_all += cfo->cfo_tail[i];
40638e93258fSBjoern A. Zeeb 			cfo_cnt_all += cfo->cfo_cnt[i];
40648e93258fSBjoern A. Zeeb 			cfo_avg = phy_div(cfo_khz_all, (s32)cfo_cnt_all);
40658e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
40668e93258fSBjoern A. Zeeb 				    "Msta cfo=%d, pkt_cnt=%d, avg_cfo=%d\n",
40678e93258fSBjoern A. Zeeb 				    cfo_khz_all, cfo_cnt_all, cfo_avg);
40688e93258fSBjoern A. Zeeb 			target_cfo = cfo_avg;
40698e93258fSBjoern A. Zeeb 		}
40708e93258fSBjoern A. Zeeb 	} else if (cfo->rtw89_multi_cfo_mode == RTW89_ENTRY_BASED_AVG_MODE) {
40718e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Entry based avg mode\n");
40728e93258fSBjoern A. Zeeb 		for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
40738e93258fSBjoern A. Zeeb 			if (cfo->cfo_cnt[i] == 0)
40748e93258fSBjoern A. Zeeb 				continue;
40758e93258fSBjoern A. Zeeb 			cfo->cfo_avg[i] = phy_div(cfo->cfo_tail[i],
40768e93258fSBjoern A. Zeeb 						  (s32)cfo->cfo_cnt[i]);
40778e93258fSBjoern A. Zeeb 			cfo_khz_all += cfo->cfo_avg[i];
40788e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
40798e93258fSBjoern A. Zeeb 				    "Macid=%d, cfo_avg=%d\n", i,
40808e93258fSBjoern A. Zeeb 				    cfo->cfo_avg[i]);
40818e93258fSBjoern A. Zeeb 		}
40828e93258fSBjoern A. Zeeb 		sta_cnt = rtwdev->total_sta_assoc;
40838e93258fSBjoern A. Zeeb 		cfo_avg = phy_div(cfo_khz_all, (s32)sta_cnt);
40848e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO,
40858e93258fSBjoern A. Zeeb 			    "Msta cfo_acc=%d, ent_cnt=%d, avg_cfo=%d\n",
40868e93258fSBjoern A. Zeeb 			    cfo_khz_all, sta_cnt, cfo_avg);
40878e93258fSBjoern A. Zeeb 		target_cfo = cfo_avg;
40888e93258fSBjoern A. Zeeb 	} else if (cfo->rtw89_multi_cfo_mode == RTW89_TP_BASED_AVG_MODE) {
40898e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "TP based avg mode\n");
40908e93258fSBjoern A. Zeeb 		cfo_tol = cfo->sta_cfo_tolerance;
40918e93258fSBjoern A. Zeeb 		for (i = 0; i < CFO_TRACK_MAX_USER; i++) {
40928e93258fSBjoern A. Zeeb 			sta_cnt++;
40938e93258fSBjoern A. Zeeb 			if (cfo->cfo_cnt[i] != 0) {
40948e93258fSBjoern A. Zeeb 				cfo->cfo_avg[i] = phy_div(cfo->cfo_tail[i],
40958e93258fSBjoern A. Zeeb 							  (s32)cfo->cfo_cnt[i]);
40968e93258fSBjoern A. Zeeb 				active_entry_cnt++;
40978e93258fSBjoern A. Zeeb 			} else {
40988e93258fSBjoern A. Zeeb 				cfo->cfo_avg[i] = cfo->pre_cfo_avg[i];
40998e93258fSBjoern A. Zeeb 			}
41008e93258fSBjoern A. Zeeb 			max_cfo_lb = max(cfo->cfo_avg[i] - cfo_tol, max_cfo_lb);
41018e93258fSBjoern A. Zeeb 			min_cfo_ub = min(cfo->cfo_avg[i] + cfo_tol, min_cfo_ub);
41028e93258fSBjoern A. Zeeb 			cfo_khz_all += cfo->cfo_avg[i];
41038e93258fSBjoern A. Zeeb 			/* need tp for each entry */
41048e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
41058e93258fSBjoern A. Zeeb 				    "[%d] cfo_avg=%d, tp=tbd\n",
41068e93258fSBjoern A. Zeeb 				    i, cfo->cfo_avg[i]);
41078e93258fSBjoern A. Zeeb 			if (sta_cnt >= rtwdev->total_sta_assoc)
41088e93258fSBjoern A. Zeeb 				break;
41098e93258fSBjoern A. Zeeb 		}
41108e93258fSBjoern A. Zeeb 		tp_all = stats->rx_throughput; /* need tp for each entry */
41118e93258fSBjoern A. Zeeb 		cfo_avg =  phy_div(cfo_khz_all_tp_wgt, (s32)tp_all);
41128e93258fSBjoern A. Zeeb 
41138e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Assoc sta cnt=%d\n",
41148e93258fSBjoern A. Zeeb 			    sta_cnt);
41158e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Active sta cnt=%d\n",
41168e93258fSBjoern A. Zeeb 			    active_entry_cnt);
41178e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO,
41188e93258fSBjoern A. Zeeb 			    "Msta cfo with tp_wgt=%d, avg_cfo=%d\n",
41198e93258fSBjoern A. Zeeb 			    cfo_khz_all_tp_wgt, cfo_avg);
41208e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "cfo_lb=%d,cfo_ub=%d\n",
41218e93258fSBjoern A. Zeeb 			    max_cfo_lb, min_cfo_ub);
41228e93258fSBjoern A. Zeeb 		if (max_cfo_lb <= min_cfo_ub) {
41238e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
41248e93258fSBjoern A. Zeeb 				    "cfo win_size=%d\n",
41258e93258fSBjoern A. Zeeb 				    min_cfo_ub - max_cfo_lb);
41268e93258fSBjoern A. Zeeb 			target_cfo = clamp(cfo_avg, max_cfo_lb, min_cfo_ub);
41278e93258fSBjoern A. Zeeb 		} else {
41288e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_CFO,
41298e93258fSBjoern A. Zeeb 				    "No intersection of cfo tolerance windows\n");
41308e93258fSBjoern A. Zeeb 			target_cfo = phy_div(cfo_khz_all, (s32)sta_cnt);
41318e93258fSBjoern A. Zeeb 		}
41328e93258fSBjoern A. Zeeb 		for (i = 0; i < CFO_TRACK_MAX_USER; i++)
41338e93258fSBjoern A. Zeeb 			cfo->pre_cfo_avg[i] = cfo->cfo_avg[i];
41348e93258fSBjoern A. Zeeb 	}
41358e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Target cfo=%d\n", target_cfo);
41368e93258fSBjoern A. Zeeb 	return target_cfo;
41378e93258fSBjoern A. Zeeb }
41388e93258fSBjoern A. Zeeb 
41398e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_statistics_reset(struct rtw89_dev *rtwdev)
41408e93258fSBjoern A. Zeeb {
41418e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
41428e93258fSBjoern A. Zeeb 
41438e93258fSBjoern A. Zeeb 	memset(&cfo->cfo_tail, 0, sizeof(cfo->cfo_tail));
41448e93258fSBjoern A. Zeeb 	memset(&cfo->cfo_cnt, 0, sizeof(cfo->cfo_cnt));
41458e93258fSBjoern A. Zeeb 	cfo->packet_count = 0;
41468e93258fSBjoern A. Zeeb 	cfo->packet_count_pre = 0;
41478e93258fSBjoern A. Zeeb 	cfo->cfo_avg_pre = 0;
41488e93258fSBjoern A. Zeeb }
41498e93258fSBjoern A. Zeeb 
41508e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_dm(struct rtw89_dev *rtwdev)
41518e93258fSBjoern A. Zeeb {
41528e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
41538e93258fSBjoern A. Zeeb 	s32 new_cfo = 0;
41548e93258fSBjoern A. Zeeb 	bool x_cap_update = false;
41558e93258fSBjoern A. Zeeb 	u8 pre_x_cap = cfo->crystal_cap;
4156e2340276SBjoern A. Zeeb 	u8 dcfo_comp_sft = rtwdev->chip->dcfo_comp_sft;
41578e93258fSBjoern A. Zeeb 
4158e2340276SBjoern A. Zeeb 	cfo->dcfo_avg = 0;
41598e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "CFO:total_sta_assoc=%d\n",
41608e93258fSBjoern A. Zeeb 		    rtwdev->total_sta_assoc);
41618e93258fSBjoern A. Zeeb 	if (rtwdev->total_sta_assoc == 0) {
41628e93258fSBjoern A. Zeeb 		rtw89_phy_cfo_reset(rtwdev);
41638e93258fSBjoern A. Zeeb 		return;
41648e93258fSBjoern A. Zeeb 	}
41658e93258fSBjoern A. Zeeb 	if (cfo->packet_count == 0) {
41668e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Pkt cnt = 0\n");
41678e93258fSBjoern A. Zeeb 		return;
41688e93258fSBjoern A. Zeeb 	}
41698e93258fSBjoern A. Zeeb 	if (cfo->packet_count == cfo->packet_count_pre) {
41708e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CFO, "Pkt cnt doesn't change\n");
41718e93258fSBjoern A. Zeeb 		return;
41728e93258fSBjoern A. Zeeb 	}
41738e93258fSBjoern A. Zeeb 	if (rtwdev->total_sta_assoc == 1)
41748e93258fSBjoern A. Zeeb 		new_cfo = rtw89_phy_average_cfo_calc(rtwdev);
41758e93258fSBjoern A. Zeeb 	else
41768e93258fSBjoern A. Zeeb 		new_cfo = rtw89_phy_multi_sta_cfo_calc(rtwdev);
41778e93258fSBjoern A. Zeeb 	if (cfo->divergence_lock_en) {
41788e93258fSBjoern A. Zeeb 		cfo->lock_cnt++;
41798e93258fSBjoern A. Zeeb 		if (cfo->lock_cnt > CFO_PERIOD_CNT) {
41808e93258fSBjoern A. Zeeb 			cfo->divergence_lock_en = false;
41818e93258fSBjoern A. Zeeb 			cfo->lock_cnt = 0;
41828e93258fSBjoern A. Zeeb 		} else {
41838e93258fSBjoern A. Zeeb 			rtw89_phy_cfo_reset(rtwdev);
41848e93258fSBjoern A. Zeeb 		}
41858e93258fSBjoern A. Zeeb 		return;
41868e93258fSBjoern A. Zeeb 	}
41878e93258fSBjoern A. Zeeb 	if (cfo->crystal_cap >= cfo->x_cap_ub ||
41888e93258fSBjoern A. Zeeb 	    cfo->crystal_cap <= cfo->x_cap_lb) {
41898e93258fSBjoern A. Zeeb 		cfo->divergence_lock_en = true;
41908e93258fSBjoern A. Zeeb 		rtw89_phy_cfo_reset(rtwdev);
41918e93258fSBjoern A. Zeeb 		return;
41928e93258fSBjoern A. Zeeb 	}
41938e93258fSBjoern A. Zeeb 
41948e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_crystal_cap_adjust(rtwdev, new_cfo);
41958e93258fSBjoern A. Zeeb 	cfo->cfo_avg_pre = new_cfo;
4196e2340276SBjoern A. Zeeb 	cfo->dcfo_avg_pre = cfo->dcfo_avg;
41978e93258fSBjoern A. Zeeb 	x_cap_update =  cfo->crystal_cap != pre_x_cap;
41988e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Xcap_up=%d\n", x_cap_update);
41998e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO, "Xcap: D:%x C:%x->%x, ofst=%d\n",
42008e93258fSBjoern A. Zeeb 		    cfo->def_x_cap, pre_x_cap, cfo->crystal_cap,
42018e93258fSBjoern A. Zeeb 		    cfo->x_cap_ofst);
42028e93258fSBjoern A. Zeeb 	if (x_cap_update) {
4203e2340276SBjoern A. Zeeb 		if (cfo->dcfo_avg > 0)
4204e2340276SBjoern A. Zeeb 			cfo->dcfo_avg -= CFO_SW_COMP_FINE_TUNE << dcfo_comp_sft;
42058e93258fSBjoern A. Zeeb 		else
4206e2340276SBjoern A. Zeeb 			cfo->dcfo_avg += CFO_SW_COMP_FINE_TUNE << dcfo_comp_sft;
42078e93258fSBjoern A. Zeeb 	}
4208e2340276SBjoern A. Zeeb 	rtw89_dcfo_comp(rtwdev, cfo->dcfo_avg);
42098e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_statistics_reset(rtwdev);
42108e93258fSBjoern A. Zeeb }
42118e93258fSBjoern A. Zeeb 
42128e93258fSBjoern A. Zeeb void rtw89_phy_cfo_track_work(struct work_struct *work)
42138e93258fSBjoern A. Zeeb {
42148e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
42158e93258fSBjoern A. Zeeb 						cfo_track_work.work);
42168e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
42178e93258fSBjoern A. Zeeb 
42188e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
42198e93258fSBjoern A. Zeeb 	if (!cfo->cfo_trig_by_timer_en)
42208e93258fSBjoern A. Zeeb 		goto out;
42218e93258fSBjoern A. Zeeb 	rtw89_leave_ps_mode(rtwdev);
42228e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_dm(rtwdev);
42238e93258fSBjoern A. Zeeb 	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->cfo_track_work,
42248e93258fSBjoern A. Zeeb 				     msecs_to_jiffies(cfo->cfo_timer_ms));
42258e93258fSBjoern A. Zeeb out:
42268e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
42278e93258fSBjoern A. Zeeb }
42288e93258fSBjoern A. Zeeb 
42298e93258fSBjoern A. Zeeb static void rtw89_phy_cfo_start_work(struct rtw89_dev *rtwdev)
42308e93258fSBjoern A. Zeeb {
42318e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
42328e93258fSBjoern A. Zeeb 
42338e93258fSBjoern A. Zeeb 	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->cfo_track_work,
42348e93258fSBjoern A. Zeeb 				     msecs_to_jiffies(cfo->cfo_timer_ms));
42358e93258fSBjoern A. Zeeb }
42368e93258fSBjoern A. Zeeb 
42378e93258fSBjoern A. Zeeb void rtw89_phy_cfo_track(struct rtw89_dev *rtwdev)
42388e93258fSBjoern A. Zeeb {
42398e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
42408e93258fSBjoern A. Zeeb 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
42418e93258fSBjoern A. Zeeb 	bool is_ul_ofdma = false, ofdma_acc_en = false;
42428e93258fSBjoern A. Zeeb 
42438e93258fSBjoern A. Zeeb 	if (stats->rx_tf_periodic > CFO_TF_CNT_TH)
42448e93258fSBjoern A. Zeeb 		is_ul_ofdma = true;
42458e93258fSBjoern A. Zeeb 	if (cfo->cfo_ul_ofdma_acc_mode == RTW89_CFO_UL_OFDMA_ACC_ENABLE &&
42468e93258fSBjoern A. Zeeb 	    is_ul_ofdma)
42478e93258fSBjoern A. Zeeb 		ofdma_acc_en = true;
42488e93258fSBjoern A. Zeeb 
42498e93258fSBjoern A. Zeeb 	switch (cfo->phy_cfo_status) {
42508e93258fSBjoern A. Zeeb 	case RTW89_PHY_DCFO_STATE_NORMAL:
42518e93258fSBjoern A. Zeeb 		if (stats->tx_throughput >= CFO_TP_UPPER) {
42528e93258fSBjoern A. Zeeb 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_ENHANCE;
42538e93258fSBjoern A. Zeeb 			cfo->cfo_trig_by_timer_en = true;
42548e93258fSBjoern A. Zeeb 			cfo->cfo_timer_ms = CFO_COMP_PERIOD;
42558e93258fSBjoern A. Zeeb 			rtw89_phy_cfo_start_work(rtwdev);
42568e93258fSBjoern A. Zeeb 		}
42578e93258fSBjoern A. Zeeb 		break;
42588e93258fSBjoern A. Zeeb 	case RTW89_PHY_DCFO_STATE_ENHANCE:
42598e93258fSBjoern A. Zeeb 		if (stats->tx_throughput <= CFO_TP_LOWER)
42608e93258fSBjoern A. Zeeb 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
42618e93258fSBjoern A. Zeeb 		else if (ofdma_acc_en &&
42628e93258fSBjoern A. Zeeb 			 cfo->phy_cfo_trk_cnt >= CFO_PERIOD_CNT)
42638e93258fSBjoern A. Zeeb 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_HOLD;
42648e93258fSBjoern A. Zeeb 		else
42658e93258fSBjoern A. Zeeb 			cfo->phy_cfo_trk_cnt++;
42668e93258fSBjoern A. Zeeb 
42678e93258fSBjoern A. Zeeb 		if (cfo->phy_cfo_status == RTW89_PHY_DCFO_STATE_NORMAL) {
42688e93258fSBjoern A. Zeeb 			cfo->phy_cfo_trk_cnt = 0;
42698e93258fSBjoern A. Zeeb 			cfo->cfo_trig_by_timer_en = false;
42708e93258fSBjoern A. Zeeb 		}
42718e93258fSBjoern A. Zeeb 		break;
42728e93258fSBjoern A. Zeeb 	case RTW89_PHY_DCFO_STATE_HOLD:
42738e93258fSBjoern A. Zeeb 		if (stats->tx_throughput <= CFO_TP_LOWER) {
42748e93258fSBjoern A. Zeeb 			cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
42758e93258fSBjoern A. Zeeb 			cfo->phy_cfo_trk_cnt = 0;
42768e93258fSBjoern A. Zeeb 			cfo->cfo_trig_by_timer_en = false;
42778e93258fSBjoern A. Zeeb 		} else {
42788e93258fSBjoern A. Zeeb 			cfo->phy_cfo_trk_cnt++;
42798e93258fSBjoern A. Zeeb 		}
42808e93258fSBjoern A. Zeeb 		break;
42818e93258fSBjoern A. Zeeb 	default:
42828e93258fSBjoern A. Zeeb 		cfo->phy_cfo_status = RTW89_PHY_DCFO_STATE_NORMAL;
42838e93258fSBjoern A. Zeeb 		cfo->phy_cfo_trk_cnt = 0;
42848e93258fSBjoern A. Zeeb 		break;
42858e93258fSBjoern A. Zeeb 	}
42868e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CFO,
42878e93258fSBjoern A. Zeeb 		    "[CFO]WatchDog tp=%d,state=%d,timer_en=%d,trk_cnt=%d,thermal=%ld\n",
42888e93258fSBjoern A. Zeeb 		    stats->tx_throughput, cfo->phy_cfo_status,
42898e93258fSBjoern A. Zeeb 		    cfo->cfo_trig_by_timer_en, cfo->phy_cfo_trk_cnt,
42908e93258fSBjoern A. Zeeb 		    ewma_thermal_read(&rtwdev->phystat.avg_thermal[0]));
42918e93258fSBjoern A. Zeeb 	if (cfo->cfo_trig_by_timer_en)
42928e93258fSBjoern A. Zeeb 		return;
42938e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_dm(rtwdev);
42948e93258fSBjoern A. Zeeb }
42958e93258fSBjoern A. Zeeb 
42968e93258fSBjoern A. Zeeb void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val,
42978e93258fSBjoern A. Zeeb 			 struct rtw89_rx_phy_ppdu *phy_ppdu)
42988e93258fSBjoern A. Zeeb {
42998e93258fSBjoern A. Zeeb 	struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
43008e93258fSBjoern A. Zeeb 	u8 macid = phy_ppdu->mac_id;
43018e93258fSBjoern A. Zeeb 
43028e93258fSBjoern A. Zeeb 	if (macid >= CFO_TRACK_MAX_USER) {
43038e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "mac_id %d is out of range\n", macid);
43048e93258fSBjoern A. Zeeb 		return;
43058e93258fSBjoern A. Zeeb 	}
43068e93258fSBjoern A. Zeeb 
43078e93258fSBjoern A. Zeeb 	cfo->cfo_tail[macid] += cfo_val;
43088e93258fSBjoern A. Zeeb 	cfo->cfo_cnt[macid]++;
43098e93258fSBjoern A. Zeeb 	cfo->packet_count++;
43108e93258fSBjoern A. Zeeb }
43118e93258fSBjoern A. Zeeb 
4312e2340276SBjoern A. Zeeb void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
4313e2340276SBjoern A. Zeeb {
4314e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
4315*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
4316*6d67aabdSBjoern A. Zeeb 						       rtwvif->sub_entity_idx);
4317e2340276SBjoern A. Zeeb 	struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;
4318e2340276SBjoern A. Zeeb 
4319*6d67aabdSBjoern A. Zeeb 	if (!chip->ul_tb_waveform_ctrl)
4320e2340276SBjoern A. Zeeb 		return;
4321e2340276SBjoern A. Zeeb 
4322e2340276SBjoern A. Zeeb 	rtwvif->def_tri_idx =
4323e2340276SBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG);
4324e2340276SBjoern A. Zeeb 
4325e2340276SBjoern A. Zeeb 	if (chip->chip_id == RTL8852B && rtwdev->hal.cv > CHIP_CBV)
4326e2340276SBjoern A. Zeeb 		rtwvif->dyn_tb_bedge_en = false;
4327e2340276SBjoern A. Zeeb 	else if (chan->band_type >= RTW89_BAND_5G &&
4328e2340276SBjoern A. Zeeb 		 chan->band_width >= RTW89_CHANNEL_WIDTH_40)
4329e2340276SBjoern A. Zeeb 		rtwvif->dyn_tb_bedge_en = true;
4330e2340276SBjoern A. Zeeb 	else
4331e2340276SBjoern A. Zeeb 		rtwvif->dyn_tb_bedge_en = false;
4332e2340276SBjoern A. Zeeb 
4333e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
4334e2340276SBjoern A. Zeeb 		    "[ULTB] def_if_bandedge=%d, def_tri_idx=%d\n",
4335e2340276SBjoern A. Zeeb 		    ul_tb_info->def_if_bandedge, rtwvif->def_tri_idx);
4336e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
4337e2340276SBjoern A. Zeeb 		    "[ULTB] dyn_tb_begde_en=%d, dyn_tb_tri_en=%d\n",
4338e2340276SBjoern A. Zeeb 		    rtwvif->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en);
4339e2340276SBjoern A. Zeeb }
4340e2340276SBjoern A. Zeeb 
4341e2340276SBjoern A. Zeeb struct rtw89_phy_ul_tb_check_data {
4342e2340276SBjoern A. Zeeb 	bool valid;
4343e2340276SBjoern A. Zeeb 	bool high_tf_client;
4344e2340276SBjoern A. Zeeb 	bool low_tf_client;
4345e2340276SBjoern A. Zeeb 	bool dyn_tb_bedge_en;
4346e2340276SBjoern A. Zeeb 	u8 def_tri_idx;
4347e2340276SBjoern A. Zeeb };
4348e2340276SBjoern A. Zeeb 
4349*6d67aabdSBjoern A. Zeeb struct rtw89_phy_power_diff {
4350*6d67aabdSBjoern A. Zeeb 	u32 q_00;
4351*6d67aabdSBjoern A. Zeeb 	u32 q_11;
4352*6d67aabdSBjoern A. Zeeb 	u32 q_matrix_en;
4353*6d67aabdSBjoern A. Zeeb 	u32 ultb_1t_norm_160;
4354*6d67aabdSBjoern A. Zeeb 	u32 ultb_2t_norm_160;
4355*6d67aabdSBjoern A. Zeeb 	u32 com1_norm_1sts;
4356*6d67aabdSBjoern A. Zeeb 	u32 com2_resp_1sts_path;
4357*6d67aabdSBjoern A. Zeeb };
4358*6d67aabdSBjoern A. Zeeb 
4359*6d67aabdSBjoern A. Zeeb static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev,
4360*6d67aabdSBjoern A. Zeeb 				       struct rtw89_vif *rtwvif)
4361*6d67aabdSBjoern A. Zeeb {
4362*6d67aabdSBjoern A. Zeeb 	static const struct rtw89_phy_power_diff table[2] = {
4363*6d67aabdSBjoern A. Zeeb 		{0x0, 0x0, 0x0, 0x0, 0xf4, 0x3, 0x3},
4364*6d67aabdSBjoern A. Zeeb 		{0xb50, 0xb50, 0x1, 0xc, 0x0, 0x1, 0x1},
4365*6d67aabdSBjoern A. Zeeb 	};
4366*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_power_diff *param;
4367*6d67aabdSBjoern A. Zeeb 	u32 reg;
4368*6d67aabdSBjoern A. Zeeb 
4369*6d67aabdSBjoern A. Zeeb 	if (!rtwdev->chip->ul_tb_pwr_diff)
4370*6d67aabdSBjoern A. Zeeb 		return;
4371*6d67aabdSBjoern A. Zeeb 
4372*6d67aabdSBjoern A. Zeeb 	if (rtwvif->pwr_diff_en == rtwvif->pre_pwr_diff_en) {
4373*6d67aabdSBjoern A. Zeeb 		rtwvif->pwr_diff_en = false;
4374*6d67aabdSBjoern A. Zeeb 		return;
4375*6d67aabdSBjoern A. Zeeb 	}
4376*6d67aabdSBjoern A. Zeeb 
4377*6d67aabdSBjoern A. Zeeb 	rtwvif->pre_pwr_diff_en = rtwvif->pwr_diff_en;
4378*6d67aabdSBjoern A. Zeeb 	param = &table[rtwvif->pwr_diff_en];
4379*6d67aabdSBjoern A. Zeeb 
4380*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_00, B_Q_MATRIX_00_REAL,
4381*6d67aabdSBjoern A. Zeeb 			       param->q_00);
4382*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_11, B_Q_MATRIX_11_REAL,
4383*6d67aabdSBjoern A. Zeeb 			       param->q_11);
4384*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, R_CUSTOMIZE_Q_MATRIX,
4385*6d67aabdSBjoern A. Zeeb 			       B_CUSTOMIZE_Q_MATRIX_EN, param->q_matrix_en);
4386*6d67aabdSBjoern A. Zeeb 
4387*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif->mac_idx);
4388*6d67aabdSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_NORM_BW160,
4389*6d67aabdSBjoern A. Zeeb 			   param->ultb_1t_norm_160);
4390*6d67aabdSBjoern A. Zeeb 
4391*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif->mac_idx);
4392*6d67aabdSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_NORM_BW160,
4393*6d67aabdSBjoern A. Zeeb 			   param->ultb_2t_norm_160);
4394*6d67aabdSBjoern A. Zeeb 
4395*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif->mac_idx);
4396*6d67aabdSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM1_NORM_1STS,
4397*6d67aabdSBjoern A. Zeeb 			   param->com1_norm_1sts);
4398*6d67aabdSBjoern A. Zeeb 
4399*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif->mac_idx);
4400*6d67aabdSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM2_RESP_1STS_PATH,
4401*6d67aabdSBjoern A. Zeeb 			   param->com2_resp_1sts_path);
4402*6d67aabdSBjoern A. Zeeb }
4403*6d67aabdSBjoern A. Zeeb 
4404e2340276SBjoern A. Zeeb static
4405e2340276SBjoern A. Zeeb void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev,
4406e2340276SBjoern A. Zeeb 				struct rtw89_vif *rtwvif,
4407e2340276SBjoern A. Zeeb 				struct rtw89_phy_ul_tb_check_data *ul_tb_data)
4408e2340276SBjoern A. Zeeb {
4409e2340276SBjoern A. Zeeb 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
4410e2340276SBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
4411e2340276SBjoern A. Zeeb 
4412e2340276SBjoern A. Zeeb 	if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
4413e2340276SBjoern A. Zeeb 		return;
4414e2340276SBjoern A. Zeeb 
4415e2340276SBjoern A. Zeeb 	if (!vif->cfg.assoc)
4416e2340276SBjoern A. Zeeb 		return;
4417e2340276SBjoern A. Zeeb 
4418*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->ul_tb_waveform_ctrl) {
4419e2340276SBjoern A. Zeeb 		if (stats->rx_tf_periodic > UL_TB_TF_CNT_L2H_TH)
4420e2340276SBjoern A. Zeeb 			ul_tb_data->high_tf_client = true;
4421e2340276SBjoern A. Zeeb 		else if (stats->rx_tf_periodic < UL_TB_TF_CNT_H2L_TH)
4422e2340276SBjoern A. Zeeb 			ul_tb_data->low_tf_client = true;
4423e2340276SBjoern A. Zeeb 
4424e2340276SBjoern A. Zeeb 		ul_tb_data->valid = true;
4425e2340276SBjoern A. Zeeb 		ul_tb_data->def_tri_idx = rtwvif->def_tri_idx;
4426e2340276SBjoern A. Zeeb 		ul_tb_data->dyn_tb_bedge_en = rtwvif->dyn_tb_bedge_en;
4427e2340276SBjoern A. Zeeb 	}
4428e2340276SBjoern A. Zeeb 
4429*6d67aabdSBjoern A. Zeeb 	rtw89_phy_ofdma_power_diff(rtwdev, rtwvif);
4430*6d67aabdSBjoern A. Zeeb }
4431*6d67aabdSBjoern A. Zeeb 
4432*6d67aabdSBjoern A. Zeeb static void rtw89_phy_ul_tb_waveform_ctrl(struct rtw89_dev *rtwdev,
4433*6d67aabdSBjoern A. Zeeb 					  struct rtw89_phy_ul_tb_check_data *ul_tb_data)
4434*6d67aabdSBjoern A. Zeeb {
4435*6d67aabdSBjoern A. Zeeb 	struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;
4436*6d67aabdSBjoern A. Zeeb 
4437*6d67aabdSBjoern A. Zeeb 	if (!rtwdev->chip->ul_tb_waveform_ctrl)
4438*6d67aabdSBjoern A. Zeeb 		return;
4439*6d67aabdSBjoern A. Zeeb 
4440*6d67aabdSBjoern A. Zeeb 	if (ul_tb_data->dyn_tb_bedge_en) {
4441*6d67aabdSBjoern A. Zeeb 		if (ul_tb_data->high_tf_client) {
4442*6d67aabdSBjoern A. Zeeb 			rtw89_phy_write32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN, 0);
4443*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
4444*6d67aabdSBjoern A. Zeeb 				    "[ULTB] Turn off if_bandedge\n");
4445*6d67aabdSBjoern A. Zeeb 		} else if (ul_tb_data->low_tf_client) {
4446*6d67aabdSBjoern A. Zeeb 			rtw89_phy_write32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN,
4447*6d67aabdSBjoern A. Zeeb 					       ul_tb_info->def_if_bandedge);
4448*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
4449*6d67aabdSBjoern A. Zeeb 				    "[ULTB] Set to default if_bandedge = %d\n",
4450*6d67aabdSBjoern A. Zeeb 				    ul_tb_info->def_if_bandedge);
4451*6d67aabdSBjoern A. Zeeb 		}
4452*6d67aabdSBjoern A. Zeeb 	}
4453*6d67aabdSBjoern A. Zeeb 
4454*6d67aabdSBjoern A. Zeeb 	if (ul_tb_info->dyn_tb_tri_en) {
4455*6d67aabdSBjoern A. Zeeb 		if (ul_tb_data->high_tf_client) {
4456*6d67aabdSBjoern A. Zeeb 			rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT,
4457*6d67aabdSBjoern A. Zeeb 					       B_TXSHAPE_TRIANGULAR_CFG, 0);
4458*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
4459*6d67aabdSBjoern A. Zeeb 				    "[ULTB] Turn off Tx triangle\n");
4460*6d67aabdSBjoern A. Zeeb 		} else if (ul_tb_data->low_tf_client) {
4461*6d67aabdSBjoern A. Zeeb 			rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT,
4462*6d67aabdSBjoern A. Zeeb 					       B_TXSHAPE_TRIANGULAR_CFG,
4463*6d67aabdSBjoern A. Zeeb 					       ul_tb_data->def_tri_idx);
4464*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_UL_TB,
4465*6d67aabdSBjoern A. Zeeb 				    "[ULTB] Set to default tx_shap_idx = %d\n",
4466*6d67aabdSBjoern A. Zeeb 				    ul_tb_data->def_tri_idx);
4467*6d67aabdSBjoern A. Zeeb 		}
4468*6d67aabdSBjoern A. Zeeb 	}
4469*6d67aabdSBjoern A. Zeeb }
4470*6d67aabdSBjoern A. Zeeb 
4471e2340276SBjoern A. Zeeb void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev)
4472e2340276SBjoern A. Zeeb {
4473e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
4474e2340276SBjoern A. Zeeb 	struct rtw89_phy_ul_tb_check_data ul_tb_data = {};
4475e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif;
4476e2340276SBjoern A. Zeeb 
4477*6d67aabdSBjoern A. Zeeb 	if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff)
4478e2340276SBjoern A. Zeeb 		return;
4479e2340276SBjoern A. Zeeb 
4480e2340276SBjoern A. Zeeb 	if (rtwdev->total_sta_assoc != 1)
4481e2340276SBjoern A. Zeeb 		return;
4482e2340276SBjoern A. Zeeb 
4483e2340276SBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
4484e2340276SBjoern A. Zeeb 		rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif, &ul_tb_data);
4485e2340276SBjoern A. Zeeb 
4486e2340276SBjoern A. Zeeb 	if (!ul_tb_data.valid)
4487e2340276SBjoern A. Zeeb 		return;
4488e2340276SBjoern A. Zeeb 
4489*6d67aabdSBjoern A. Zeeb 	rtw89_phy_ul_tb_waveform_ctrl(rtwdev, &ul_tb_data);
4490e2340276SBjoern A. Zeeb }
4491e2340276SBjoern A. Zeeb 
4492e2340276SBjoern A. Zeeb static void rtw89_phy_ul_tb_info_init(struct rtw89_dev *rtwdev)
4493e2340276SBjoern A. Zeeb {
4494e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
4495e2340276SBjoern A. Zeeb 	struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info;
4496e2340276SBjoern A. Zeeb 
4497*6d67aabdSBjoern A. Zeeb 	if (!chip->ul_tb_waveform_ctrl)
4498e2340276SBjoern A. Zeeb 		return;
4499e2340276SBjoern A. Zeeb 
4500e2340276SBjoern A. Zeeb 	ul_tb_info->dyn_tb_tri_en = true;
4501e2340276SBjoern A. Zeeb 	ul_tb_info->def_if_bandedge =
4502e2340276SBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, R_BANDEDGE, B_BANDEDGE_EN);
4503e2340276SBjoern A. Zeeb }
4504e2340276SBjoern A. Zeeb 
4505e2340276SBjoern A. Zeeb static
4506e2340276SBjoern A. Zeeb void rtw89_phy_antdiv_sts_instance_reset(struct rtw89_antdiv_stats *antdiv_sts)
4507e2340276SBjoern A. Zeeb {
4508e2340276SBjoern A. Zeeb 	ewma_rssi_init(&antdiv_sts->cck_rssi_avg);
4509e2340276SBjoern A. Zeeb 	ewma_rssi_init(&antdiv_sts->ofdm_rssi_avg);
4510e2340276SBjoern A. Zeeb 	ewma_rssi_init(&antdiv_sts->non_legacy_rssi_avg);
4511e2340276SBjoern A. Zeeb 	antdiv_sts->pkt_cnt_cck = 0;
4512e2340276SBjoern A. Zeeb 	antdiv_sts->pkt_cnt_ofdm = 0;
4513e2340276SBjoern A. Zeeb 	antdiv_sts->pkt_cnt_non_legacy = 0;
4514e2340276SBjoern A. Zeeb 	antdiv_sts->evm = 0;
4515e2340276SBjoern A. Zeeb }
4516e2340276SBjoern A. Zeeb 
4517e2340276SBjoern A. Zeeb static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev,
4518e2340276SBjoern A. Zeeb 					      struct rtw89_rx_phy_ppdu *phy_ppdu,
4519e2340276SBjoern A. Zeeb 					      struct rtw89_antdiv_stats *stats)
4520e2340276SBjoern A. Zeeb {
4521e2340276SBjoern A. Zeeb 	if (rtw89_get_data_rate_mode(rtwdev, phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) {
4522e2340276SBjoern A. Zeeb 		if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) {
4523e2340276SBjoern A. Zeeb 			ewma_rssi_add(&stats->cck_rssi_avg, phy_ppdu->rssi_avg);
4524e2340276SBjoern A. Zeeb 			stats->pkt_cnt_cck++;
4525e2340276SBjoern A. Zeeb 		} else {
4526e2340276SBjoern A. Zeeb 			ewma_rssi_add(&stats->ofdm_rssi_avg, phy_ppdu->rssi_avg);
4527e2340276SBjoern A. Zeeb 			stats->pkt_cnt_ofdm++;
4528e2340276SBjoern A. Zeeb 			stats->evm += phy_ppdu->ofdm.evm_min;
4529e2340276SBjoern A. Zeeb 		}
4530e2340276SBjoern A. Zeeb 	} else {
4531e2340276SBjoern A. Zeeb 		ewma_rssi_add(&stats->non_legacy_rssi_avg, phy_ppdu->rssi_avg);
4532e2340276SBjoern A. Zeeb 		stats->pkt_cnt_non_legacy++;
4533e2340276SBjoern A. Zeeb 		stats->evm += phy_ppdu->ofdm.evm_min;
4534e2340276SBjoern A. Zeeb 	}
4535e2340276SBjoern A. Zeeb }
4536e2340276SBjoern A. Zeeb 
4537e2340276SBjoern A. Zeeb static u8 rtw89_phy_antdiv_sts_instance_get_rssi(struct rtw89_antdiv_stats *stats)
4538e2340276SBjoern A. Zeeb {
4539e2340276SBjoern A. Zeeb 	if (stats->pkt_cnt_non_legacy >= stats->pkt_cnt_cck &&
4540e2340276SBjoern A. Zeeb 	    stats->pkt_cnt_non_legacy >= stats->pkt_cnt_ofdm)
4541e2340276SBjoern A. Zeeb 		return ewma_rssi_read(&stats->non_legacy_rssi_avg);
4542e2340276SBjoern A. Zeeb 	else if (stats->pkt_cnt_ofdm >= stats->pkt_cnt_cck &&
4543e2340276SBjoern A. Zeeb 		 stats->pkt_cnt_ofdm >= stats->pkt_cnt_non_legacy)
4544e2340276SBjoern A. Zeeb 		return ewma_rssi_read(&stats->ofdm_rssi_avg);
4545e2340276SBjoern A. Zeeb 	else
4546e2340276SBjoern A. Zeeb 		return ewma_rssi_read(&stats->cck_rssi_avg);
4547e2340276SBjoern A. Zeeb }
4548e2340276SBjoern A. Zeeb 
4549e2340276SBjoern A. Zeeb static u8 rtw89_phy_antdiv_sts_instance_get_evm(struct rtw89_antdiv_stats *stats)
4550e2340276SBjoern A. Zeeb {
4551e2340276SBjoern A. Zeeb 	return phy_div(stats->evm, stats->pkt_cnt_non_legacy + stats->pkt_cnt_ofdm);
4552e2340276SBjoern A. Zeeb }
4553e2340276SBjoern A. Zeeb 
4554e2340276SBjoern A. Zeeb void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
4555e2340276SBjoern A. Zeeb 			    struct rtw89_rx_phy_ppdu *phy_ppdu)
4556e2340276SBjoern A. Zeeb {
4557e2340276SBjoern A. Zeeb 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
4558e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
4559e2340276SBjoern A. Zeeb 
4560e2340276SBjoern A. Zeeb 	if (!hal->ant_diversity || hal->ant_diversity_fixed)
4561e2340276SBjoern A. Zeeb 		return;
4562e2340276SBjoern A. Zeeb 
4563e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->target_stats);
4564e2340276SBjoern A. Zeeb 
4565e2340276SBjoern A. Zeeb 	if (!antdiv->get_stats)
4566e2340276SBjoern A. Zeeb 		return;
4567e2340276SBjoern A. Zeeb 
4568e2340276SBjoern A. Zeeb 	if (hal->antenna_rx == RF_A)
4569e2340276SBjoern A. Zeeb 		rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->main_stats);
4570e2340276SBjoern A. Zeeb 	else if (hal->antenna_rx == RF_B)
4571e2340276SBjoern A. Zeeb 		rtw89_phy_antdiv_sts_instance_add(rtwdev, phy_ppdu, &antdiv->aux_stats);
4572e2340276SBjoern A. Zeeb }
4573e2340276SBjoern A. Zeeb 
4574e2340276SBjoern A. Zeeb static void rtw89_phy_antdiv_reg_init(struct rtw89_dev *rtwdev)
4575e2340276SBjoern A. Zeeb {
4576e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_ANT_TRAIN_EN,
4577e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4578e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_TX_ANT_SEL,
4579e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4580e2340276SBjoern A. Zeeb 
4581e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_TRSW_TX_EXTEND,
4582e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4583e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANT_SW, B_P0_HW_ANTSW_DIS_BY_GNT_BT,
4584e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4585e2340276SBjoern A. Zeeb 
4586e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_TRSW, B_P0_BT_FORCE_ANTIDX_EN,
4587e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4588e2340276SBjoern A. Zeeb 
4589e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_RFSW_CTRL_ANT0_BASE, B_RFSW_CTRL_ANT_MAPPING,
4590e2340276SBjoern A. Zeeb 			      0x0100, RTW89_PHY_0);
4591e2340276SBjoern A. Zeeb 
4592e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_BTG_TRX,
4593e2340276SBjoern A. Zeeb 			      0x1, RTW89_PHY_0);
4594e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_HW_CTRL,
4595e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4596e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_2G,
4597e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4598e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_SW_5G,
4599e2340276SBjoern A. Zeeb 			      0x0, RTW89_PHY_0);
4600e2340276SBjoern A. Zeeb }
4601e2340276SBjoern A. Zeeb 
4602e2340276SBjoern A. Zeeb static void rtw89_phy_antdiv_sts_reset(struct rtw89_dev *rtwdev)
4603e2340276SBjoern A. Zeeb {
4604e2340276SBjoern A. Zeeb 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
4605e2340276SBjoern A. Zeeb 
4606e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
4607e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->main_stats);
4608e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->aux_stats);
4609e2340276SBjoern A. Zeeb }
4610e2340276SBjoern A. Zeeb 
4611e2340276SBjoern A. Zeeb static void rtw89_phy_antdiv_init(struct rtw89_dev *rtwdev)
4612e2340276SBjoern A. Zeeb {
4613e2340276SBjoern A. Zeeb 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
4614e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
4615e2340276SBjoern A. Zeeb 
4616e2340276SBjoern A. Zeeb 	if (!hal->ant_diversity)
4617e2340276SBjoern A. Zeeb 		return;
4618e2340276SBjoern A. Zeeb 
4619e2340276SBjoern A. Zeeb 	antdiv->get_stats = false;
4620e2340276SBjoern A. Zeeb 	antdiv->rssi_pre = 0;
4621e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_sts_reset(rtwdev);
4622e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_reg_init(rtwdev);
4623e2340276SBjoern A. Zeeb }
4624e2340276SBjoern A. Zeeb 
46258e93258fSBjoern A. Zeeb static void rtw89_phy_stat_thermal_update(struct rtw89_dev *rtwdev)
46268e93258fSBjoern A. Zeeb {
46278e93258fSBjoern A. Zeeb 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
46288e93258fSBjoern A. Zeeb 	int i;
46298e93258fSBjoern A. Zeeb 	u8 th;
46308e93258fSBjoern A. Zeeb 
46318e93258fSBjoern A. Zeeb 	for (i = 0; i < rtwdev->chip->rf_path_num; i++) {
46328e93258fSBjoern A. Zeeb 		th = rtw89_chip_get_thermal(rtwdev, i);
46338e93258fSBjoern A. Zeeb 		if (th)
46348e93258fSBjoern A. Zeeb 			ewma_thermal_add(&phystat->avg_thermal[i], th);
46358e93258fSBjoern A. Zeeb 
46368e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK,
46378e93258fSBjoern A. Zeeb 			    "path(%d) thermal cur=%u avg=%ld", i, th,
46388e93258fSBjoern A. Zeeb 			    ewma_thermal_read(&phystat->avg_thermal[i]));
46398e93258fSBjoern A. Zeeb 	}
46408e93258fSBjoern A. Zeeb }
46418e93258fSBjoern A. Zeeb 
46428e93258fSBjoern A. Zeeb struct rtw89_phy_iter_rssi_data {
46438e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev;
46448e93258fSBjoern A. Zeeb 	struct rtw89_phy_ch_info *ch_info;
46458e93258fSBjoern A. Zeeb 	bool rssi_changed;
46468e93258fSBjoern A. Zeeb };
46478e93258fSBjoern A. Zeeb 
46488e93258fSBjoern A. Zeeb static void rtw89_phy_stat_rssi_update_iter(void *data,
46498e93258fSBjoern A. Zeeb 					    struct ieee80211_sta *sta)
46508e93258fSBjoern A. Zeeb {
46518e93258fSBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
46528e93258fSBjoern A. Zeeb 	struct rtw89_phy_iter_rssi_data *rssi_data =
46538e93258fSBjoern A. Zeeb 					(struct rtw89_phy_iter_rssi_data *)data;
46548e93258fSBjoern A. Zeeb 	struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info;
46558e93258fSBjoern A. Zeeb 	unsigned long rssi_curr;
46568e93258fSBjoern A. Zeeb 
46578e93258fSBjoern A. Zeeb 	rssi_curr = ewma_rssi_read(&rtwsta->avg_rssi);
46588e93258fSBjoern A. Zeeb 
46598e93258fSBjoern A. Zeeb 	if (rssi_curr < ch_info->rssi_min) {
46608e93258fSBjoern A. Zeeb 		ch_info->rssi_min = rssi_curr;
46618e93258fSBjoern A. Zeeb 		ch_info->rssi_min_macid = rtwsta->mac_id;
46628e93258fSBjoern A. Zeeb 	}
46638e93258fSBjoern A. Zeeb 
46648e93258fSBjoern A. Zeeb 	if (rtwsta->prev_rssi == 0) {
46658e93258fSBjoern A. Zeeb 		rtwsta->prev_rssi = rssi_curr;
46668e93258fSBjoern A. Zeeb 	} else if (abs((int)rtwsta->prev_rssi - (int)rssi_curr) > (3 << RSSI_FACTOR)) {
46678e93258fSBjoern A. Zeeb 		rtwsta->prev_rssi = rssi_curr;
46688e93258fSBjoern A. Zeeb 		rssi_data->rssi_changed = true;
46698e93258fSBjoern A. Zeeb 	}
46708e93258fSBjoern A. Zeeb }
46718e93258fSBjoern A. Zeeb 
46728e93258fSBjoern A. Zeeb static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev)
46738e93258fSBjoern A. Zeeb {
46748e93258fSBjoern A. Zeeb 	struct rtw89_phy_iter_rssi_data rssi_data = {0};
46758e93258fSBjoern A. Zeeb 
46768e93258fSBjoern A. Zeeb 	rssi_data.rtwdev = rtwdev;
46778e93258fSBjoern A. Zeeb 	rssi_data.ch_info = &rtwdev->ch_info;
46788e93258fSBjoern A. Zeeb 	rssi_data.ch_info->rssi_min = U8_MAX;
46798e93258fSBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
46808e93258fSBjoern A. Zeeb 					  rtw89_phy_stat_rssi_update_iter,
46818e93258fSBjoern A. Zeeb 					  &rssi_data);
46828e93258fSBjoern A. Zeeb 	if (rssi_data.rssi_changed)
46838e93258fSBjoern A. Zeeb 		rtw89_btc_ntfy_wl_sta(rtwdev);
46848e93258fSBjoern A. Zeeb }
46858e93258fSBjoern A. Zeeb 
46868e93258fSBjoern A. Zeeb static void rtw89_phy_stat_init(struct rtw89_dev *rtwdev)
46878e93258fSBjoern A. Zeeb {
46888e93258fSBjoern A. Zeeb 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
46898e93258fSBjoern A. Zeeb 	int i;
46908e93258fSBjoern A. Zeeb 
46918e93258fSBjoern A. Zeeb 	for (i = 0; i < rtwdev->chip->rf_path_num; i++)
46928e93258fSBjoern A. Zeeb 		ewma_thermal_init(&phystat->avg_thermal[i]);
46938e93258fSBjoern A. Zeeb 
46948e93258fSBjoern A. Zeeb 	rtw89_phy_stat_thermal_update(rtwdev);
46958e93258fSBjoern A. Zeeb 
46968e93258fSBjoern A. Zeeb 	memset(&phystat->cur_pkt_stat, 0, sizeof(phystat->cur_pkt_stat));
46978e93258fSBjoern A. Zeeb 	memset(&phystat->last_pkt_stat, 0, sizeof(phystat->last_pkt_stat));
46988e93258fSBjoern A. Zeeb }
46998e93258fSBjoern A. Zeeb 
47008e93258fSBjoern A. Zeeb void rtw89_phy_stat_track(struct rtw89_dev *rtwdev)
47018e93258fSBjoern A. Zeeb {
47028e93258fSBjoern A. Zeeb 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
47038e93258fSBjoern A. Zeeb 
47048e93258fSBjoern A. Zeeb 	rtw89_phy_stat_thermal_update(rtwdev);
47058e93258fSBjoern A. Zeeb 	rtw89_phy_stat_rssi_update(rtwdev);
47068e93258fSBjoern A. Zeeb 
47078e93258fSBjoern A. Zeeb 	phystat->last_pkt_stat = phystat->cur_pkt_stat;
47088e93258fSBjoern A. Zeeb 	memset(&phystat->cur_pkt_stat, 0, sizeof(phystat->cur_pkt_stat));
47098e93258fSBjoern A. Zeeb }
47108e93258fSBjoern A. Zeeb 
47118e93258fSBjoern A. Zeeb static u16 rtw89_phy_ccx_us_to_idx(struct rtw89_dev *rtwdev, u32 time_us)
47128e93258fSBjoern A. Zeeb {
47138e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
47148e93258fSBjoern A. Zeeb 
47158e93258fSBjoern A. Zeeb 	return time_us >> (ilog2(CCX_US_BASE_RATIO) + env->ccx_unit_idx);
47168e93258fSBjoern A. Zeeb }
47178e93258fSBjoern A. Zeeb 
47188e93258fSBjoern A. Zeeb static u32 rtw89_phy_ccx_idx_to_us(struct rtw89_dev *rtwdev, u16 idx)
47198e93258fSBjoern A. Zeeb {
47208e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
47218e93258fSBjoern A. Zeeb 
47228e93258fSBjoern A. Zeeb 	return idx << (ilog2(CCX_US_BASE_RATIO) + env->ccx_unit_idx);
47238e93258fSBjoern A. Zeeb }
47248e93258fSBjoern A. Zeeb 
47258e93258fSBjoern A. Zeeb static void rtw89_phy_ccx_top_setting_init(struct rtw89_dev *rtwdev)
47268e93258fSBjoern A. Zeeb {
4727*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
47288e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
4729*6d67aabdSBjoern A. Zeeb 	const struct rtw89_ccx_regs *ccx = phy->ccx;
47308e93258fSBjoern A. Zeeb 
47318e93258fSBjoern A. Zeeb 	env->ccx_manual_ctrl = false;
47328e93258fSBjoern A. Zeeb 	env->ccx_ongoing = false;
47338e93258fSBjoern A. Zeeb 	env->ccx_rac_lv = RTW89_RAC_RELEASE;
47348e93258fSBjoern A. Zeeb 	env->ccx_period = 0;
47358e93258fSBjoern A. Zeeb 	env->ccx_unit_idx = RTW89_CCX_32_US;
47368e93258fSBjoern A. Zeeb 
4737*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->en_mask, 1);
4738*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->trig_opt_mask, 1);
4739*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 1);
4740*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->edcca_opt_mask,
47418e93258fSBjoern A. Zeeb 			       RTW89_CCX_EDCCA_BW20_0);
47428e93258fSBjoern A. Zeeb }
47438e93258fSBjoern A. Zeeb 
47448e93258fSBjoern A. Zeeb static u16 rtw89_phy_ccx_get_report(struct rtw89_dev *rtwdev, u16 report,
47458e93258fSBjoern A. Zeeb 				    u16 score)
47468e93258fSBjoern A. Zeeb {
47478e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
47488e93258fSBjoern A. Zeeb 	u32 numer = 0;
47498e93258fSBjoern A. Zeeb 	u16 ret = 0;
47508e93258fSBjoern A. Zeeb 
47518e93258fSBjoern A. Zeeb 	numer = report * score + (env->ccx_period >> 1);
47528e93258fSBjoern A. Zeeb 	if (env->ccx_period)
47538e93258fSBjoern A. Zeeb 		ret = numer / env->ccx_period;
47548e93258fSBjoern A. Zeeb 
47558e93258fSBjoern A. Zeeb 	return ret >= score ? score - 1 : ret;
47568e93258fSBjoern A. Zeeb }
47578e93258fSBjoern A. Zeeb 
47588e93258fSBjoern A. Zeeb static void rtw89_phy_ccx_ms_to_period_unit(struct rtw89_dev *rtwdev,
47598e93258fSBjoern A. Zeeb 					    u16 time_ms, u32 *period,
47608e93258fSBjoern A. Zeeb 					    u32 *unit_idx)
47618e93258fSBjoern A. Zeeb {
47628e93258fSBjoern A. Zeeb 	u32 idx;
47638e93258fSBjoern A. Zeeb 	u8 quotient;
47648e93258fSBjoern A. Zeeb 
47658e93258fSBjoern A. Zeeb 	if (time_ms >= CCX_MAX_PERIOD)
47668e93258fSBjoern A. Zeeb 		time_ms = CCX_MAX_PERIOD;
47678e93258fSBjoern A. Zeeb 
47688e93258fSBjoern A. Zeeb 	quotient = CCX_MAX_PERIOD_UNIT * time_ms / CCX_MAX_PERIOD;
47698e93258fSBjoern A. Zeeb 
47708e93258fSBjoern A. Zeeb 	if (quotient < 4)
47718e93258fSBjoern A. Zeeb 		idx = RTW89_CCX_4_US;
47728e93258fSBjoern A. Zeeb 	else if (quotient < 8)
47738e93258fSBjoern A. Zeeb 		idx = RTW89_CCX_8_US;
47748e93258fSBjoern A. Zeeb 	else if (quotient < 16)
47758e93258fSBjoern A. Zeeb 		idx = RTW89_CCX_16_US;
47768e93258fSBjoern A. Zeeb 	else
47778e93258fSBjoern A. Zeeb 		idx = RTW89_CCX_32_US;
47788e93258fSBjoern A. Zeeb 
47798e93258fSBjoern A. Zeeb 	*unit_idx = idx;
47808e93258fSBjoern A. Zeeb 	*period = (time_ms * MS_TO_4US_RATIO) >> idx;
47818e93258fSBjoern A. Zeeb 
47828e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
47838e93258fSBjoern A. Zeeb 		    "[Trigger Time] period:%d, unit_idx:%d\n",
47848e93258fSBjoern A. Zeeb 		    *period, *unit_idx);
47858e93258fSBjoern A. Zeeb }
47868e93258fSBjoern A. Zeeb 
47878e93258fSBjoern A. Zeeb static void rtw89_phy_ccx_racing_release(struct rtw89_dev *rtwdev)
47888e93258fSBjoern A. Zeeb {
47898e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
47908e93258fSBjoern A. Zeeb 
47918e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
47928e93258fSBjoern A. Zeeb 		    "lv:(%d)->(0)\n", env->ccx_rac_lv);
47938e93258fSBjoern A. Zeeb 
47948e93258fSBjoern A. Zeeb 	env->ccx_ongoing = false;
47958e93258fSBjoern A. Zeeb 	env->ccx_rac_lv = RTW89_RAC_RELEASE;
47968e93258fSBjoern A. Zeeb 	env->ifs_clm_app = RTW89_IFS_CLM_BACKGROUND;
47978e93258fSBjoern A. Zeeb }
47988e93258fSBjoern A. Zeeb 
47998e93258fSBjoern A. Zeeb static bool rtw89_phy_ifs_clm_th_update_check(struct rtw89_dev *rtwdev,
48008e93258fSBjoern A. Zeeb 					      struct rtw89_ccx_para_info *para)
48018e93258fSBjoern A. Zeeb {
48028e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
48038e93258fSBjoern A. Zeeb 	bool is_update = env->ifs_clm_app != para->ifs_clm_app;
48048e93258fSBjoern A. Zeeb 	u8 i = 0;
48058e93258fSBjoern A. Zeeb 	u16 *ifs_th_l = env->ifs_clm_th_l;
48068e93258fSBjoern A. Zeeb 	u16 *ifs_th_h = env->ifs_clm_th_h;
48078e93258fSBjoern A. Zeeb 	u32 ifs_th0_us = 0, ifs_th_times = 0;
48088e93258fSBjoern A. Zeeb 	u32 ifs_th_h_us[RTW89_IFS_CLM_NUM] = {0};
48098e93258fSBjoern A. Zeeb 
48108e93258fSBjoern A. Zeeb 	if (!is_update)
48118e93258fSBjoern A. Zeeb 		goto ifs_update_finished;
48128e93258fSBjoern A. Zeeb 
48138e93258fSBjoern A. Zeeb 	switch (para->ifs_clm_app) {
48148e93258fSBjoern A. Zeeb 	case RTW89_IFS_CLM_INIT:
48158e93258fSBjoern A. Zeeb 	case RTW89_IFS_CLM_BACKGROUND:
48168e93258fSBjoern A. Zeeb 	case RTW89_IFS_CLM_ACS:
48178e93258fSBjoern A. Zeeb 	case RTW89_IFS_CLM_DBG:
48188e93258fSBjoern A. Zeeb 	case RTW89_IFS_CLM_DIG:
48198e93258fSBjoern A. Zeeb 	case RTW89_IFS_CLM_TDMA_DIG:
48208e93258fSBjoern A. Zeeb 		ifs_th0_us = IFS_CLM_TH0_UPPER;
48218e93258fSBjoern A. Zeeb 		ifs_th_times = IFS_CLM_TH_MUL;
48228e93258fSBjoern A. Zeeb 		break;
48238e93258fSBjoern A. Zeeb 	case RTW89_IFS_CLM_DBG_MANUAL:
48248e93258fSBjoern A. Zeeb 		ifs_th0_us = para->ifs_clm_manual_th0;
48258e93258fSBjoern A. Zeeb 		ifs_th_times = para->ifs_clm_manual_th_times;
48268e93258fSBjoern A. Zeeb 		break;
48278e93258fSBjoern A. Zeeb 	default:
48288e93258fSBjoern A. Zeeb 		break;
48298e93258fSBjoern A. Zeeb 	}
48308e93258fSBjoern A. Zeeb 
48318e93258fSBjoern A. Zeeb 	/* Set sampling threshold for 4 different regions, unit in idx_cnt.
48328e93258fSBjoern A. Zeeb 	 * low[i] = high[i-1] + 1
48338e93258fSBjoern A. Zeeb 	 * high[i] = high[i-1] * ifs_th_times
48348e93258fSBjoern A. Zeeb 	 */
48358e93258fSBjoern A. Zeeb 	ifs_th_l[IFS_CLM_TH_START_IDX] = 0;
48368e93258fSBjoern A. Zeeb 	ifs_th_h_us[IFS_CLM_TH_START_IDX] = ifs_th0_us;
48378e93258fSBjoern A. Zeeb 	ifs_th_h[IFS_CLM_TH_START_IDX] = rtw89_phy_ccx_us_to_idx(rtwdev,
48388e93258fSBjoern A. Zeeb 								 ifs_th0_us);
48398e93258fSBjoern A. Zeeb 	for (i = 1; i < RTW89_IFS_CLM_NUM; i++) {
48408e93258fSBjoern A. Zeeb 		ifs_th_l[i] = ifs_th_h[i - 1] + 1;
48418e93258fSBjoern A. Zeeb 		ifs_th_h_us[i] = ifs_th_h_us[i - 1] * ifs_th_times;
48428e93258fSBjoern A. Zeeb 		ifs_th_h[i] = rtw89_phy_ccx_us_to_idx(rtwdev, ifs_th_h_us[i]);
48438e93258fSBjoern A. Zeeb 	}
48448e93258fSBjoern A. Zeeb 
48458e93258fSBjoern A. Zeeb ifs_update_finished:
48468e93258fSBjoern A. Zeeb 	if (!is_update)
48478e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
48488e93258fSBjoern A. Zeeb 			    "No need to update IFS_TH\n");
48498e93258fSBjoern A. Zeeb 
48508e93258fSBjoern A. Zeeb 	return is_update;
48518e93258fSBjoern A. Zeeb }
48528e93258fSBjoern A. Zeeb 
48538e93258fSBjoern A. Zeeb static void rtw89_phy_ifs_clm_set_th_reg(struct rtw89_dev *rtwdev)
48548e93258fSBjoern A. Zeeb {
4855*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
48568e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
4857*6d67aabdSBjoern A. Zeeb 	const struct rtw89_ccx_regs *ccx = phy->ccx;
48588e93258fSBjoern A. Zeeb 	u8 i = 0;
48598e93258fSBjoern A. Zeeb 
4860*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_th_l_mask,
48618e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_l[0]);
4862*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_th_l_mask,
48638e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_l[1]);
4864*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_th_l_mask,
48658e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_l[2]);
4866*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_th_l_mask,
48678e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_l[3]);
48688e93258fSBjoern A. Zeeb 
4869*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_th_h_mask,
48708e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_h[0]);
4871*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_th_h_mask,
48728e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_h[1]);
4873*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_th_h_mask,
48748e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_h[2]);
4875*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_th_h_mask,
48768e93258fSBjoern A. Zeeb 			       env->ifs_clm_th_h[3]);
48778e93258fSBjoern A. Zeeb 
48788e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++)
48798e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
48808e93258fSBjoern A. Zeeb 			    "Update IFS_T%d_th{low, high} : {%d, %d}\n",
48818e93258fSBjoern A. Zeeb 			    i + 1, env->ifs_clm_th_l[i], env->ifs_clm_th_h[i]);
48828e93258fSBjoern A. Zeeb }
48838e93258fSBjoern A. Zeeb 
48848e93258fSBjoern A. Zeeb static void rtw89_phy_ifs_clm_setting_init(struct rtw89_dev *rtwdev)
48858e93258fSBjoern A. Zeeb {
4886*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
48878e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
4888*6d67aabdSBjoern A. Zeeb 	const struct rtw89_ccx_regs *ccx = phy->ccx;
48898e93258fSBjoern A. Zeeb 	struct rtw89_ccx_para_info para = {0};
48908e93258fSBjoern A. Zeeb 
48918e93258fSBjoern A. Zeeb 	env->ifs_clm_app = RTW89_IFS_CLM_BACKGROUND;
48928e93258fSBjoern A. Zeeb 	env->ifs_clm_mntr_time = 0;
48938e93258fSBjoern A. Zeeb 
48948e93258fSBjoern A. Zeeb 	para.ifs_clm_app = RTW89_IFS_CLM_INIT;
48958e93258fSBjoern A. Zeeb 	if (rtw89_phy_ifs_clm_th_update_check(rtwdev, &para))
48968e93258fSBjoern A. Zeeb 		rtw89_phy_ifs_clm_set_th_reg(rtwdev);
48978e93258fSBjoern A. Zeeb 
4898*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_collect_en_mask, true);
4899*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t1_addr, ccx->ifs_t1_en_mask, true);
4900*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t2_addr, ccx->ifs_t2_en_mask, true);
4901*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t3_addr, ccx->ifs_t3_en_mask, true);
4902*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_t4_addr, ccx->ifs_t4_en_mask, true);
49038e93258fSBjoern A. Zeeb }
49048e93258fSBjoern A. Zeeb 
49058e93258fSBjoern A. Zeeb static int rtw89_phy_ccx_racing_ctrl(struct rtw89_dev *rtwdev,
49068e93258fSBjoern A. Zeeb 				     enum rtw89_env_racing_lv level)
49078e93258fSBjoern A. Zeeb {
49088e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
49098e93258fSBjoern A. Zeeb 	int ret = 0;
49108e93258fSBjoern A. Zeeb 
49118e93258fSBjoern A. Zeeb 	if (level >= RTW89_RAC_MAX_NUM) {
49128e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
49138e93258fSBjoern A. Zeeb 			    "[WARNING] Wrong LV=%d\n", level);
49148e93258fSBjoern A. Zeeb 		return -EINVAL;
49158e93258fSBjoern A. Zeeb 	}
49168e93258fSBjoern A. Zeeb 
49178e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
49188e93258fSBjoern A. Zeeb 		    "ccx_ongoing=%d, level:(%d)->(%d)\n", env->ccx_ongoing,
49198e93258fSBjoern A. Zeeb 		    env->ccx_rac_lv, level);
49208e93258fSBjoern A. Zeeb 
49218e93258fSBjoern A. Zeeb 	if (env->ccx_ongoing) {
49228e93258fSBjoern A. Zeeb 		if (level <= env->ccx_rac_lv)
49238e93258fSBjoern A. Zeeb 			ret = -EINVAL;
49248e93258fSBjoern A. Zeeb 		else
49258e93258fSBjoern A. Zeeb 			env->ccx_ongoing = false;
49268e93258fSBjoern A. Zeeb 	}
49278e93258fSBjoern A. Zeeb 
49288e93258fSBjoern A. Zeeb 	if (ret == 0)
49298e93258fSBjoern A. Zeeb 		env->ccx_rac_lv = level;
49308e93258fSBjoern A. Zeeb 
49318e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "ccx racing success=%d\n",
49328e93258fSBjoern A. Zeeb 		    !ret);
49338e93258fSBjoern A. Zeeb 
49348e93258fSBjoern A. Zeeb 	return ret;
49358e93258fSBjoern A. Zeeb }
49368e93258fSBjoern A. Zeeb 
49378e93258fSBjoern A. Zeeb static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev)
49388e93258fSBjoern A. Zeeb {
4939*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
49408e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
4941*6d67aabdSBjoern A. Zeeb 	const struct rtw89_ccx_regs *ccx = phy->ccx;
49428e93258fSBjoern A. Zeeb 
4943*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_clm_cnt_clear_mask, 0);
4944*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 0);
4945*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_clm_cnt_clear_mask, 1);
4946*6d67aabdSBjoern A. Zeeb 	rtw89_phy_set_phy_regs(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 1);
49478e93258fSBjoern A. Zeeb 
49488e93258fSBjoern A. Zeeb 	env->ccx_ongoing = true;
49498e93258fSBjoern A. Zeeb }
49508e93258fSBjoern A. Zeeb 
49518e93258fSBjoern A. Zeeb static void rtw89_phy_ifs_clm_get_utility(struct rtw89_dev *rtwdev)
49528e93258fSBjoern A. Zeeb {
49538e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
49548e93258fSBjoern A. Zeeb 	u8 i = 0;
49558e93258fSBjoern A. Zeeb 	u32 res = 0;
49568e93258fSBjoern A. Zeeb 
49578e93258fSBjoern A. Zeeb 	env->ifs_clm_tx_ratio =
49588e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_tx, PERCENT);
49598e93258fSBjoern A. Zeeb 	env->ifs_clm_edcca_excl_cca_ratio =
49608e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_edcca_excl_cca,
49618e93258fSBjoern A. Zeeb 					 PERCENT);
49628e93258fSBjoern A. Zeeb 	env->ifs_clm_cck_fa_ratio =
49638e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_cckfa, PERCENT);
49648e93258fSBjoern A. Zeeb 	env->ifs_clm_ofdm_fa_ratio =
49658e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_ofdmfa, PERCENT);
49668e93258fSBjoern A. Zeeb 	env->ifs_clm_cck_cca_excl_fa_ratio =
49678e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_cckcca_excl_fa,
49688e93258fSBjoern A. Zeeb 					 PERCENT);
49698e93258fSBjoern A. Zeeb 	env->ifs_clm_ofdm_cca_excl_fa_ratio =
49708e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_ofdmcca_excl_fa,
49718e93258fSBjoern A. Zeeb 					 PERCENT);
49728e93258fSBjoern A. Zeeb 	env->ifs_clm_cck_fa_permil =
49738e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_cckfa, PERMIL);
49748e93258fSBjoern A. Zeeb 	env->ifs_clm_ofdm_fa_permil =
49758e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_get_report(rtwdev, env->ifs_clm_ofdmfa, PERMIL);
49768e93258fSBjoern A. Zeeb 
49778e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++) {
49788e93258fSBjoern A. Zeeb 		if (env->ifs_clm_his[i] > ENV_MNTR_IFSCLM_HIS_MAX) {
49798e93258fSBjoern A. Zeeb 			env->ifs_clm_ifs_avg[i] = ENV_MNTR_FAIL_DWORD;
49808e93258fSBjoern A. Zeeb 		} else {
49818e93258fSBjoern A. Zeeb 			env->ifs_clm_ifs_avg[i] =
49828e93258fSBjoern A. Zeeb 				rtw89_phy_ccx_idx_to_us(rtwdev,
49838e93258fSBjoern A. Zeeb 							env->ifs_clm_avg[i]);
49848e93258fSBjoern A. Zeeb 		}
49858e93258fSBjoern A. Zeeb 
49868e93258fSBjoern A. Zeeb 		res = rtw89_phy_ccx_idx_to_us(rtwdev, env->ifs_clm_cca[i]);
49878e93258fSBjoern A. Zeeb 		res += env->ifs_clm_his[i] >> 1;
49888e93258fSBjoern A. Zeeb 		if (env->ifs_clm_his[i])
49898e93258fSBjoern A. Zeeb 			res /= env->ifs_clm_his[i];
49908e93258fSBjoern A. Zeeb 		else
49918e93258fSBjoern A. Zeeb 			res = 0;
49928e93258fSBjoern A. Zeeb 		env->ifs_clm_cca_avg[i] = res;
49938e93258fSBjoern A. Zeeb 	}
49948e93258fSBjoern A. Zeeb 
49958e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
49968e93258fSBjoern A. Zeeb 		    "IFS-CLM ratio {Tx, EDCCA_exclu_cca} = {%d, %d}\n",
49978e93258fSBjoern A. Zeeb 		    env->ifs_clm_tx_ratio, env->ifs_clm_edcca_excl_cca_ratio);
49988e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
49998e93258fSBjoern A. Zeeb 		    "IFS-CLM FA ratio {CCK, OFDM} = {%d, %d}\n",
50008e93258fSBjoern A. Zeeb 		    env->ifs_clm_cck_fa_ratio, env->ifs_clm_ofdm_fa_ratio);
50018e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
50028e93258fSBjoern A. Zeeb 		    "IFS-CLM FA permil {CCK, OFDM} = {%d, %d}\n",
50038e93258fSBjoern A. Zeeb 		    env->ifs_clm_cck_fa_permil, env->ifs_clm_ofdm_fa_permil);
50048e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
50058e93258fSBjoern A. Zeeb 		    "IFS-CLM CCA_exclu_FA ratio {CCK, OFDM} = {%d, %d}\n",
50068e93258fSBjoern A. Zeeb 		    env->ifs_clm_cck_cca_excl_fa_ratio,
50078e93258fSBjoern A. Zeeb 		    env->ifs_clm_ofdm_cca_excl_fa_ratio);
50088e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
50098e93258fSBjoern A. Zeeb 		    "Time:[his, ifs_avg(us), cca_avg(us)]\n");
50108e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++)
50118e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "T%d:[%d, %d, %d]\n",
50128e93258fSBjoern A. Zeeb 			    i + 1, env->ifs_clm_his[i], env->ifs_clm_ifs_avg[i],
50138e93258fSBjoern A. Zeeb 			    env->ifs_clm_cca_avg[i]);
50148e93258fSBjoern A. Zeeb }
50158e93258fSBjoern A. Zeeb 
50168e93258fSBjoern A. Zeeb static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev)
50178e93258fSBjoern A. Zeeb {
5018*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
50198e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
5020*6d67aabdSBjoern A. Zeeb 	const struct rtw89_ccx_regs *ccx = phy->ccx;
50218e93258fSBjoern A. Zeeb 	u8 i = 0;
50228e93258fSBjoern A. Zeeb 
5023*6d67aabdSBjoern A. Zeeb 	if (rtw89_phy_read32_mask(rtwdev, ccx->ifs_total_addr,
5024*6d67aabdSBjoern A. Zeeb 				  ccx->ifs_cnt_done_mask) == 0) {
50258e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
50268e93258fSBjoern A. Zeeb 			    "Get IFS_CLM report Fail\n");
50278e93258fSBjoern A. Zeeb 		return false;
50288e93258fSBjoern A. Zeeb 	}
50298e93258fSBjoern A. Zeeb 
50308e93258fSBjoern A. Zeeb 	env->ifs_clm_tx =
5031*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_tx_cnt_addr,
5032*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_clm_tx_cnt_msk);
50338e93258fSBjoern A. Zeeb 	env->ifs_clm_edcca_excl_cca =
5034*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_tx_cnt_addr,
5035*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_clm_edcca_excl_cca_fa_mask);
50368e93258fSBjoern A. Zeeb 	env->ifs_clm_cckcca_excl_fa =
5037*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_cca_addr,
5038*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_clm_cckcca_excl_fa_mask);
50398e93258fSBjoern A. Zeeb 	env->ifs_clm_ofdmcca_excl_fa =
5040*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_cca_addr,
5041*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_clm_ofdmcca_excl_fa_mask);
50428e93258fSBjoern A. Zeeb 	env->ifs_clm_cckfa =
5043*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_fa_addr,
5044*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_clm_cck_fa_mask);
50458e93258fSBjoern A. Zeeb 	env->ifs_clm_ofdmfa =
5046*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_clm_fa_addr,
5047*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_clm_ofdm_fa_mask);
50488e93258fSBjoern A. Zeeb 
50498e93258fSBjoern A. Zeeb 	env->ifs_clm_his[0] =
5050*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr,
5051*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t1_his_mask);
50528e93258fSBjoern A. Zeeb 	env->ifs_clm_his[1] =
5053*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr,
5054*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t2_his_mask);
50558e93258fSBjoern A. Zeeb 	env->ifs_clm_his[2] =
5056*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr,
5057*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t3_his_mask);
50588e93258fSBjoern A. Zeeb 	env->ifs_clm_his[3] =
5059*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_his_addr,
5060*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t4_his_mask);
50618e93258fSBjoern A. Zeeb 
50628e93258fSBjoern A. Zeeb 	env->ifs_clm_avg[0] =
5063*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_l_addr,
5064*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t1_avg_mask);
50658e93258fSBjoern A. Zeeb 	env->ifs_clm_avg[1] =
5066*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_l_addr,
5067*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t2_avg_mask);
50688e93258fSBjoern A. Zeeb 	env->ifs_clm_avg[2] =
5069*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_h_addr,
5070*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t3_avg_mask);
50718e93258fSBjoern A. Zeeb 	env->ifs_clm_avg[3] =
5072*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_avg_h_addr,
5073*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t4_avg_mask);
50748e93258fSBjoern A. Zeeb 
50758e93258fSBjoern A. Zeeb 	env->ifs_clm_cca[0] =
5076*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_l_addr,
5077*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t1_cca_mask);
50788e93258fSBjoern A. Zeeb 	env->ifs_clm_cca[1] =
5079*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_l_addr,
5080*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t2_cca_mask);
50818e93258fSBjoern A. Zeeb 	env->ifs_clm_cca[2] =
5082*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_h_addr,
5083*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t3_cca_mask);
50848e93258fSBjoern A. Zeeb 	env->ifs_clm_cca[3] =
5085*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_cca_h_addr,
5086*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_t4_cca_mask);
50878e93258fSBjoern A. Zeeb 
50888e93258fSBjoern A. Zeeb 	env->ifs_clm_total_ifs =
5089*6d67aabdSBjoern A. Zeeb 		rtw89_phy_read32_mask(rtwdev, ccx->ifs_total_addr,
5090*6d67aabdSBjoern A. Zeeb 				      ccx->ifs_total_mask);
50918e93258fSBjoern A. Zeeb 
50928e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "IFS-CLM total_ifs = %d\n",
50938e93258fSBjoern A. Zeeb 		    env->ifs_clm_total_ifs);
50948e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
50958e93258fSBjoern A. Zeeb 		    "{Tx, EDCCA_exclu_cca} = {%d, %d}\n",
50968e93258fSBjoern A. Zeeb 		    env->ifs_clm_tx, env->ifs_clm_edcca_excl_cca);
50978e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
50988e93258fSBjoern A. Zeeb 		    "IFS-CLM FA{CCK, OFDM} = {%d, %d}\n",
50998e93258fSBjoern A. Zeeb 		    env->ifs_clm_cckfa, env->ifs_clm_ofdmfa);
51008e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
51018e93258fSBjoern A. Zeeb 		    "IFS-CLM CCA_exclu_FA{CCK, OFDM} = {%d, %d}\n",
51028e93258fSBjoern A. Zeeb 		    env->ifs_clm_cckcca_excl_fa, env->ifs_clm_ofdmcca_excl_fa);
51038e93258fSBjoern A. Zeeb 
51048e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "Time:[his, avg, cca]\n");
51058e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_IFS_CLM_NUM; i++)
51068e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
51078e93258fSBjoern A. Zeeb 			    "T%d:[%d, %d, %d]\n", i + 1, env->ifs_clm_his[i],
51088e93258fSBjoern A. Zeeb 			    env->ifs_clm_avg[i], env->ifs_clm_cca[i]);
51098e93258fSBjoern A. Zeeb 
51108e93258fSBjoern A. Zeeb 	rtw89_phy_ifs_clm_get_utility(rtwdev);
51118e93258fSBjoern A. Zeeb 
51128e93258fSBjoern A. Zeeb 	return true;
51138e93258fSBjoern A. Zeeb }
51148e93258fSBjoern A. Zeeb 
51158e93258fSBjoern A. Zeeb static int rtw89_phy_ifs_clm_set(struct rtw89_dev *rtwdev,
51168e93258fSBjoern A. Zeeb 				 struct rtw89_ccx_para_info *para)
51178e93258fSBjoern A. Zeeb {
5118*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
51198e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
5120*6d67aabdSBjoern A. Zeeb 	const struct rtw89_ccx_regs *ccx = phy->ccx;
51218e93258fSBjoern A. Zeeb 	u32 period = 0;
51228e93258fSBjoern A. Zeeb 	u32 unit_idx = 0;
51238e93258fSBjoern A. Zeeb 
51248e93258fSBjoern A. Zeeb 	if (para->mntr_time == 0) {
51258e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
51268e93258fSBjoern A. Zeeb 			    "[WARN] MNTR_TIME is 0\n");
51278e93258fSBjoern A. Zeeb 		return -EINVAL;
51288e93258fSBjoern A. Zeeb 	}
51298e93258fSBjoern A. Zeeb 
51308e93258fSBjoern A. Zeeb 	if (rtw89_phy_ccx_racing_ctrl(rtwdev, para->rac_lv))
51318e93258fSBjoern A. Zeeb 		return -EINVAL;
51328e93258fSBjoern A. Zeeb 
51338e93258fSBjoern A. Zeeb 	if (para->mntr_time != env->ifs_clm_mntr_time) {
51348e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_ms_to_period_unit(rtwdev, para->mntr_time,
51358e93258fSBjoern A. Zeeb 						&period, &unit_idx);
5136*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr,
5137*6d67aabdSBjoern A. Zeeb 				       ccx->ifs_clm_period_mask, period);
5138*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, ccx->ifs_cnt_addr,
5139*6d67aabdSBjoern A. Zeeb 				       ccx->ifs_clm_cnt_unit_mask,
5140*6d67aabdSBjoern A. Zeeb 				       unit_idx);
51418e93258fSBjoern A. Zeeb 
51428e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
51438e93258fSBjoern A. Zeeb 			    "Update IFS-CLM time ((%d)) -> ((%d))\n",
51448e93258fSBjoern A. Zeeb 			    env->ifs_clm_mntr_time, para->mntr_time);
51458e93258fSBjoern A. Zeeb 
51468e93258fSBjoern A. Zeeb 		env->ifs_clm_mntr_time = para->mntr_time;
51478e93258fSBjoern A. Zeeb 		env->ccx_period = (u16)period;
51488e93258fSBjoern A. Zeeb 		env->ccx_unit_idx = (u8)unit_idx;
51498e93258fSBjoern A. Zeeb 	}
51508e93258fSBjoern A. Zeeb 
51518e93258fSBjoern A. Zeeb 	if (rtw89_phy_ifs_clm_th_update_check(rtwdev, para)) {
51528e93258fSBjoern A. Zeeb 		env->ifs_clm_app = para->ifs_clm_app;
51538e93258fSBjoern A. Zeeb 		rtw89_phy_ifs_clm_set_th_reg(rtwdev);
51548e93258fSBjoern A. Zeeb 	}
51558e93258fSBjoern A. Zeeb 
51568e93258fSBjoern A. Zeeb 	return 0;
51578e93258fSBjoern A. Zeeb }
51588e93258fSBjoern A. Zeeb 
51598e93258fSBjoern A. Zeeb void rtw89_phy_env_monitor_track(struct rtw89_dev *rtwdev)
51608e93258fSBjoern A. Zeeb {
51618e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
51628e93258fSBjoern A. Zeeb 	struct rtw89_ccx_para_info para = {0};
51638e93258fSBjoern A. Zeeb 	u8 chk_result = RTW89_PHY_ENV_MON_CCX_FAIL;
51648e93258fSBjoern A. Zeeb 
51658e93258fSBjoern A. Zeeb 	env->ccx_watchdog_result = RTW89_PHY_ENV_MON_CCX_FAIL;
51668e93258fSBjoern A. Zeeb 	if (env->ccx_manual_ctrl) {
51678e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
51688e93258fSBjoern A. Zeeb 			    "CCX in manual ctrl\n");
51698e93258fSBjoern A. Zeeb 		return;
51708e93258fSBjoern A. Zeeb 	}
51718e93258fSBjoern A. Zeeb 
51728e93258fSBjoern A. Zeeb 	/* only ifs_clm for now */
51738e93258fSBjoern A. Zeeb 	if (rtw89_phy_ifs_clm_get_result(rtwdev))
51748e93258fSBjoern A. Zeeb 		env->ccx_watchdog_result |= RTW89_PHY_ENV_MON_IFS_CLM;
51758e93258fSBjoern A. Zeeb 
51768e93258fSBjoern A. Zeeb 	rtw89_phy_ccx_racing_release(rtwdev);
51778e93258fSBjoern A. Zeeb 	para.mntr_time = 1900;
51788e93258fSBjoern A. Zeeb 	para.rac_lv = RTW89_RAC_LV_1;
51798e93258fSBjoern A. Zeeb 	para.ifs_clm_app = RTW89_IFS_CLM_BACKGROUND;
51808e93258fSBjoern A. Zeeb 
51818e93258fSBjoern A. Zeeb 	if (rtw89_phy_ifs_clm_set(rtwdev, &para) == 0)
51828e93258fSBjoern A. Zeeb 		chk_result |= RTW89_PHY_ENV_MON_IFS_CLM;
51838e93258fSBjoern A. Zeeb 	if (chk_result)
51848e93258fSBjoern A. Zeeb 		rtw89_phy_ccx_trigger(rtwdev);
51858e93258fSBjoern A. Zeeb 
51868e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
51878e93258fSBjoern A. Zeeb 		    "get_result=0x%x, chk_result:0x%x\n",
51888e93258fSBjoern A. Zeeb 		    env->ccx_watchdog_result, chk_result);
51898e93258fSBjoern A. Zeeb }
51908e93258fSBjoern A. Zeeb 
51918e93258fSBjoern A. Zeeb static bool rtw89_physts_ie_page_valid(enum rtw89_phy_status_bitmap *ie_page)
51928e93258fSBjoern A. Zeeb {
5193e2340276SBjoern A. Zeeb 	if (*ie_page >= RTW89_PHYSTS_BITMAP_NUM ||
51948e93258fSBjoern A. Zeeb 	    *ie_page == RTW89_RSVD_9)
51958e93258fSBjoern A. Zeeb 		return false;
51968e93258fSBjoern A. Zeeb 	else if (*ie_page > RTW89_RSVD_9)
51978e93258fSBjoern A. Zeeb 		*ie_page -= 1;
51988e93258fSBjoern A. Zeeb 
51998e93258fSBjoern A. Zeeb 	return true;
52008e93258fSBjoern A. Zeeb }
52018e93258fSBjoern A. Zeeb 
52028e93258fSBjoern A. Zeeb static u32 rtw89_phy_get_ie_bitmap_addr(enum rtw89_phy_status_bitmap ie_page)
52038e93258fSBjoern A. Zeeb {
52048e93258fSBjoern A. Zeeb 	static const u8 ie_page_shift = 2;
52058e93258fSBjoern A. Zeeb 
52068e93258fSBjoern A. Zeeb 	return R_PHY_STS_BITMAP_ADDR_START + (ie_page << ie_page_shift);
52078e93258fSBjoern A. Zeeb }
52088e93258fSBjoern A. Zeeb 
52098e93258fSBjoern A. Zeeb static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev,
52108e93258fSBjoern A. Zeeb 				      enum rtw89_phy_status_bitmap ie_page)
52118e93258fSBjoern A. Zeeb {
52128e93258fSBjoern A. Zeeb 	u32 addr;
52138e93258fSBjoern A. Zeeb 
52148e93258fSBjoern A. Zeeb 	if (!rtw89_physts_ie_page_valid(&ie_page))
52158e93258fSBjoern A. Zeeb 		return 0;
52168e93258fSBjoern A. Zeeb 
52178e93258fSBjoern A. Zeeb 	addr = rtw89_phy_get_ie_bitmap_addr(ie_page);
52188e93258fSBjoern A. Zeeb 
52198e93258fSBjoern A. Zeeb 	return rtw89_phy_read32(rtwdev, addr);
52208e93258fSBjoern A. Zeeb }
52218e93258fSBjoern A. Zeeb 
52228e93258fSBjoern A. Zeeb static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev,
52238e93258fSBjoern A. Zeeb 				       enum rtw89_phy_status_bitmap ie_page,
52248e93258fSBjoern A. Zeeb 				       u32 val)
52258e93258fSBjoern A. Zeeb {
52268e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
52278e93258fSBjoern A. Zeeb 	u32 addr;
52288e93258fSBjoern A. Zeeb 
52298e93258fSBjoern A. Zeeb 	if (!rtw89_physts_ie_page_valid(&ie_page))
52308e93258fSBjoern A. Zeeb 		return;
52318e93258fSBjoern A. Zeeb 
52328e93258fSBjoern A. Zeeb 	if (chip->chip_id == RTL8852A)
52338e93258fSBjoern A. Zeeb 		val &= B_PHY_STS_BITMAP_MSK_52A;
52348e93258fSBjoern A. Zeeb 
52358e93258fSBjoern A. Zeeb 	addr = rtw89_phy_get_ie_bitmap_addr(ie_page);
52368e93258fSBjoern A. Zeeb 	rtw89_phy_write32(rtwdev, addr, val);
52378e93258fSBjoern A. Zeeb }
52388e93258fSBjoern A. Zeeb 
52398e93258fSBjoern A. Zeeb static void rtw89_physts_enable_ie_bitmap(struct rtw89_dev *rtwdev,
52408e93258fSBjoern A. Zeeb 					  enum rtw89_phy_status_bitmap bitmap,
52418e93258fSBjoern A. Zeeb 					  enum rtw89_phy_status_ie_type ie,
52428e93258fSBjoern A. Zeeb 					  bool enable)
52438e93258fSBjoern A. Zeeb {
52448e93258fSBjoern A. Zeeb 	u32 val = rtw89_physts_get_ie_bitmap(rtwdev, bitmap);
52458e93258fSBjoern A. Zeeb 
52468e93258fSBjoern A. Zeeb 	if (enable)
52478e93258fSBjoern A. Zeeb 		val |= BIT(ie);
52488e93258fSBjoern A. Zeeb 	else
52498e93258fSBjoern A. Zeeb 		val &= ~BIT(ie);
52508e93258fSBjoern A. Zeeb 
52518e93258fSBjoern A. Zeeb 	rtw89_physts_set_ie_bitmap(rtwdev, bitmap, val);
52528e93258fSBjoern A. Zeeb }
52538e93258fSBjoern A. Zeeb 
52548e93258fSBjoern A. Zeeb static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev,
52558e93258fSBjoern A. Zeeb 					    bool enable,
52568e93258fSBjoern A. Zeeb 					    enum rtw89_phy_idx phy_idx)
52578e93258fSBjoern A. Zeeb {
5258*6d67aabdSBjoern A. Zeeb 	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
5259*6d67aabdSBjoern A. Zeeb 	const struct rtw89_physts_regs *physts = phy->physts;
5260*6d67aabdSBjoern A. Zeeb 
52618e93258fSBjoern A. Zeeb 	if (enable) {
5262*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_clr(rtwdev, physts->setting_addr,
5263*6d67aabdSBjoern A. Zeeb 				      physts->dis_trigger_fail_mask);
5264*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_clr(rtwdev, physts->setting_addr,
5265*6d67aabdSBjoern A. Zeeb 				      physts->dis_trigger_brk_mask);
52668e93258fSBjoern A. Zeeb 	} else {
5267*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_set(rtwdev, physts->setting_addr,
5268*6d67aabdSBjoern A. Zeeb 				      physts->dis_trigger_fail_mask);
5269*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_set(rtwdev, physts->setting_addr,
5270*6d67aabdSBjoern A. Zeeb 				      physts->dis_trigger_brk_mask);
52718e93258fSBjoern A. Zeeb 	}
52728e93258fSBjoern A. Zeeb }
52738e93258fSBjoern A. Zeeb 
52748e93258fSBjoern A. Zeeb static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev)
52758e93258fSBjoern A. Zeeb {
52768e93258fSBjoern A. Zeeb 	u8 i;
52778e93258fSBjoern A. Zeeb 
52788e93258fSBjoern A. Zeeb 	rtw89_physts_enable_fail_report(rtwdev, false, RTW89_PHY_0);
52798e93258fSBjoern A. Zeeb 
52808e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_PHYSTS_BITMAP_NUM; i++) {
52818e93258fSBjoern A. Zeeb 		if (i >= RTW89_CCK_PKT)
52828e93258fSBjoern A. Zeeb 			rtw89_physts_enable_ie_bitmap(rtwdev, i,
52838e93258fSBjoern A. Zeeb 						      RTW89_PHYSTS_IE09_FTR_0,
52848e93258fSBjoern A. Zeeb 						      true);
52858e93258fSBjoern A. Zeeb 		if ((i >= RTW89_CCK_BRK && i <= RTW89_VHT_MU) ||
52868e93258fSBjoern A. Zeeb 		    (i >= RTW89_RSVD_9 && i <= RTW89_CCK_PKT))
52878e93258fSBjoern A. Zeeb 			continue;
52888e93258fSBjoern A. Zeeb 		rtw89_physts_enable_ie_bitmap(rtwdev, i,
52898e93258fSBjoern A. Zeeb 					      RTW89_PHYSTS_IE24_OFDM_TD_PATH_A,
52908e93258fSBjoern A. Zeeb 					      true);
52918e93258fSBjoern A. Zeeb 	}
52928e93258fSBjoern A. Zeeb 	rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_VHT_PKT,
52938e93258fSBjoern A. Zeeb 				      RTW89_PHYSTS_IE13_DL_MU_DEF, true);
52948e93258fSBjoern A. Zeeb 	rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_HE_PKT,
52958e93258fSBjoern A. Zeeb 				      RTW89_PHYSTS_IE13_DL_MU_DEF, true);
52968e93258fSBjoern A. Zeeb 
52978e93258fSBjoern A. Zeeb 	/* force IE01 for channel index, only channel field is valid */
52988e93258fSBjoern A. Zeeb 	rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_CCK_PKT,
52998e93258fSBjoern A. Zeeb 				      RTW89_PHYSTS_IE01_CMN_OFDM, true);
53008e93258fSBjoern A. Zeeb }
53018e93258fSBjoern A. Zeeb 
53028e93258fSBjoern A. Zeeb static void rtw89_phy_dig_read_gain_table(struct rtw89_dev *rtwdev, int type)
53038e93258fSBjoern A. Zeeb {
53048e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
53058e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
53068e93258fSBjoern A. Zeeb 	const struct rtw89_phy_dig_gain_cfg *cfg;
53078e93258fSBjoern A. Zeeb 	const char *msg;
53088e93258fSBjoern A. Zeeb 	u8 i;
53098e93258fSBjoern A. Zeeb 	s8 gain_base;
53108e93258fSBjoern A. Zeeb 	s8 *gain_arr;
53118e93258fSBjoern A. Zeeb 	u32 tmp;
53128e93258fSBjoern A. Zeeb 
53138e93258fSBjoern A. Zeeb 	switch (type) {
53148e93258fSBjoern A. Zeeb 	case RTW89_DIG_GAIN_LNA_G:
53158e93258fSBjoern A. Zeeb 		gain_arr = dig->lna_gain_g;
53168e93258fSBjoern A. Zeeb 		gain_base = LNA0_GAIN;
53178e93258fSBjoern A. Zeeb 		cfg = chip->dig_table->cfg_lna_g;
53188e93258fSBjoern A. Zeeb 		msg = "lna_gain_g";
53198e93258fSBjoern A. Zeeb 		break;
53208e93258fSBjoern A. Zeeb 	case RTW89_DIG_GAIN_TIA_G:
53218e93258fSBjoern A. Zeeb 		gain_arr = dig->tia_gain_g;
53228e93258fSBjoern A. Zeeb 		gain_base = TIA0_GAIN_G;
53238e93258fSBjoern A. Zeeb 		cfg = chip->dig_table->cfg_tia_g;
53248e93258fSBjoern A. Zeeb 		msg = "tia_gain_g";
53258e93258fSBjoern A. Zeeb 		break;
53268e93258fSBjoern A. Zeeb 	case RTW89_DIG_GAIN_LNA_A:
53278e93258fSBjoern A. Zeeb 		gain_arr = dig->lna_gain_a;
53288e93258fSBjoern A. Zeeb 		gain_base = LNA0_GAIN;
53298e93258fSBjoern A. Zeeb 		cfg = chip->dig_table->cfg_lna_a;
53308e93258fSBjoern A. Zeeb 		msg = "lna_gain_a";
53318e93258fSBjoern A. Zeeb 		break;
53328e93258fSBjoern A. Zeeb 	case RTW89_DIG_GAIN_TIA_A:
53338e93258fSBjoern A. Zeeb 		gain_arr = dig->tia_gain_a;
53348e93258fSBjoern A. Zeeb 		gain_base = TIA0_GAIN_A;
53358e93258fSBjoern A. Zeeb 		cfg = chip->dig_table->cfg_tia_a;
53368e93258fSBjoern A. Zeeb 		msg = "tia_gain_a";
53378e93258fSBjoern A. Zeeb 		break;
53388e93258fSBjoern A. Zeeb 	default:
53398e93258fSBjoern A. Zeeb 		return;
53408e93258fSBjoern A. Zeeb 	}
53418e93258fSBjoern A. Zeeb 
53428e93258fSBjoern A. Zeeb 	for (i = 0; i < cfg->size; i++) {
53438e93258fSBjoern A. Zeeb 		tmp = rtw89_phy_read32_mask(rtwdev, cfg->table[i].addr,
53448e93258fSBjoern A. Zeeb 					    cfg->table[i].mask);
53458e93258fSBjoern A. Zeeb 		tmp >>= DIG_GAIN_SHIFT;
53468e93258fSBjoern A. Zeeb 		gain_arr[i] = sign_extend32(tmp, U4_MAX_BIT) + gain_base;
53478e93258fSBjoern A. Zeeb 		gain_base += DIG_GAIN;
53488e93258fSBjoern A. Zeeb 
53498e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "%s[%d]=%d\n",
53508e93258fSBjoern A. Zeeb 			    msg, i, gain_arr[i]);
53518e93258fSBjoern A. Zeeb 	}
53528e93258fSBjoern A. Zeeb }
53538e93258fSBjoern A. Zeeb 
53548e93258fSBjoern A. Zeeb static void rtw89_phy_dig_update_gain_para(struct rtw89_dev *rtwdev)
53558e93258fSBjoern A. Zeeb {
53568e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
53578e93258fSBjoern A. Zeeb 	u32 tmp;
53588e93258fSBjoern A. Zeeb 	u8 i;
53598e93258fSBjoern A. Zeeb 
53608e93258fSBjoern A. Zeeb 	if (!rtwdev->hal.support_igi)
53618e93258fSBjoern A. Zeeb 		return;
53628e93258fSBjoern A. Zeeb 
53638e93258fSBjoern A. Zeeb 	tmp = rtw89_phy_read32_mask(rtwdev, R_PATH0_IB_PKPW,
53648e93258fSBjoern A. Zeeb 				    B_PATH0_IB_PKPW_MSK);
53658e93258fSBjoern A. Zeeb 	dig->ib_pkpwr = sign_extend32(tmp >> DIG_GAIN_SHIFT, U8_MAX_BIT);
53668e93258fSBjoern A. Zeeb 	dig->ib_pbk = rtw89_phy_read32_mask(rtwdev, R_PATH0_IB_PBK,
53678e93258fSBjoern A. Zeeb 					    B_PATH0_IB_PBK_MSK);
53688e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "ib_pkpwr=%d, ib_pbk=%d\n",
53698e93258fSBjoern A. Zeeb 		    dig->ib_pkpwr, dig->ib_pbk);
53708e93258fSBjoern A. Zeeb 
53718e93258fSBjoern A. Zeeb 	for (i = RTW89_DIG_GAIN_LNA_G; i < RTW89_DIG_GAIN_MAX; i++)
53728e93258fSBjoern A. Zeeb 		rtw89_phy_dig_read_gain_table(rtwdev, i);
53738e93258fSBjoern A. Zeeb }
53748e93258fSBjoern A. Zeeb 
53758e93258fSBjoern A. Zeeb static const u8 rssi_nolink = 22;
53768e93258fSBjoern A. Zeeb static const u8 igi_rssi_th[IGI_RSSI_TH_NUM] = {68, 84, 90, 98, 104};
53778e93258fSBjoern A. Zeeb static const u16 fa_th_2g[FA_TH_NUM] = {22, 44, 66, 88};
53788e93258fSBjoern A. Zeeb static const u16 fa_th_5g[FA_TH_NUM] = {4, 8, 12, 16};
53798e93258fSBjoern A. Zeeb static const u16 fa_th_nolink[FA_TH_NUM] = {196, 352, 440, 528};
53808e93258fSBjoern A. Zeeb 
53818e93258fSBjoern A. Zeeb static void rtw89_phy_dig_update_rssi_info(struct rtw89_dev *rtwdev)
53828e93258fSBjoern A. Zeeb {
53838e93258fSBjoern A. Zeeb 	struct rtw89_phy_ch_info *ch_info = &rtwdev->ch_info;
53848e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
53858e93258fSBjoern A. Zeeb 	bool is_linked = rtwdev->total_sta_assoc > 0;
53868e93258fSBjoern A. Zeeb 
53878e93258fSBjoern A. Zeeb 	if (is_linked) {
53888e93258fSBjoern A. Zeeb 		dig->igi_rssi = ch_info->rssi_min >> 1;
53898e93258fSBjoern A. Zeeb 	} else {
53908e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "RSSI update : NO Link\n");
53918e93258fSBjoern A. Zeeb 		dig->igi_rssi = rssi_nolink;
53928e93258fSBjoern A. Zeeb 	}
53938e93258fSBjoern A. Zeeb }
53948e93258fSBjoern A. Zeeb 
53958e93258fSBjoern A. Zeeb static void rtw89_phy_dig_update_para(struct rtw89_dev *rtwdev)
53968e93258fSBjoern A. Zeeb {
53978e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
53988e93258fSBjoern A. Zeeb 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
53998e93258fSBjoern A. Zeeb 	bool is_linked = rtwdev->total_sta_assoc > 0;
54008e93258fSBjoern A. Zeeb 	const u16 *fa_th_src = NULL;
54018e93258fSBjoern A. Zeeb 
54028e93258fSBjoern A. Zeeb 	switch (chan->band_type) {
54038e93258fSBjoern A. Zeeb 	case RTW89_BAND_2G:
54048e93258fSBjoern A. Zeeb 		dig->lna_gain = dig->lna_gain_g;
54058e93258fSBjoern A. Zeeb 		dig->tia_gain = dig->tia_gain_g;
54068e93258fSBjoern A. Zeeb 		fa_th_src = is_linked ? fa_th_2g : fa_th_nolink;
54078e93258fSBjoern A. Zeeb 		dig->force_gaincode_idx_en = false;
54088e93258fSBjoern A. Zeeb 		dig->dyn_pd_th_en = true;
54098e93258fSBjoern A. Zeeb 		break;
54108e93258fSBjoern A. Zeeb 	case RTW89_BAND_5G:
54118e93258fSBjoern A. Zeeb 	default:
54128e93258fSBjoern A. Zeeb 		dig->lna_gain = dig->lna_gain_a;
54138e93258fSBjoern A. Zeeb 		dig->tia_gain = dig->tia_gain_a;
54148e93258fSBjoern A. Zeeb 		fa_th_src = is_linked ? fa_th_5g : fa_th_nolink;
54158e93258fSBjoern A. Zeeb 		dig->force_gaincode_idx_en = true;
54168e93258fSBjoern A. Zeeb 		dig->dyn_pd_th_en = true;
54178e93258fSBjoern A. Zeeb 		break;
54188e93258fSBjoern A. Zeeb 	}
54198e93258fSBjoern A. Zeeb 	memcpy(dig->fa_th, fa_th_src, sizeof(dig->fa_th));
54208e93258fSBjoern A. Zeeb 	memcpy(dig->igi_rssi_th, igi_rssi_th, sizeof(dig->igi_rssi_th));
54218e93258fSBjoern A. Zeeb }
54228e93258fSBjoern A. Zeeb 
54238e93258fSBjoern A. Zeeb static const u8 pd_low_th_offset = 20, dynamic_igi_min = 0x20;
54248e93258fSBjoern A. Zeeb static const u8 igi_max_performance_mode = 0x5a;
54258e93258fSBjoern A. Zeeb static const u8 dynamic_pd_threshold_max;
54268e93258fSBjoern A. Zeeb 
54278e93258fSBjoern A. Zeeb static void rtw89_phy_dig_para_reset(struct rtw89_dev *rtwdev)
54288e93258fSBjoern A. Zeeb {
54298e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
54308e93258fSBjoern A. Zeeb 
54318e93258fSBjoern A. Zeeb 	dig->cur_gaincode.lna_idx = LNA_IDX_MAX;
54328e93258fSBjoern A. Zeeb 	dig->cur_gaincode.tia_idx = TIA_IDX_MAX;
54338e93258fSBjoern A. Zeeb 	dig->cur_gaincode.rxb_idx = RXB_IDX_MAX;
54348e93258fSBjoern A. Zeeb 	dig->force_gaincode.lna_idx = LNA_IDX_MAX;
54358e93258fSBjoern A. Zeeb 	dig->force_gaincode.tia_idx = TIA_IDX_MAX;
54368e93258fSBjoern A. Zeeb 	dig->force_gaincode.rxb_idx = RXB_IDX_MAX;
54378e93258fSBjoern A. Zeeb 
54388e93258fSBjoern A. Zeeb 	dig->dyn_igi_max = igi_max_performance_mode;
54398e93258fSBjoern A. Zeeb 	dig->dyn_igi_min = dynamic_igi_min;
54408e93258fSBjoern A. Zeeb 	dig->dyn_pd_th_max = dynamic_pd_threshold_max;
54418e93258fSBjoern A. Zeeb 	dig->pd_low_th_ofst = pd_low_th_offset;
54428e93258fSBjoern A. Zeeb 	dig->is_linked_pre = false;
54438e93258fSBjoern A. Zeeb }
54448e93258fSBjoern A. Zeeb 
54458e93258fSBjoern A. Zeeb static void rtw89_phy_dig_init(struct rtw89_dev *rtwdev)
54468e93258fSBjoern A. Zeeb {
54478e93258fSBjoern A. Zeeb 	rtw89_phy_dig_update_gain_para(rtwdev);
54488e93258fSBjoern A. Zeeb 	rtw89_phy_dig_reset(rtwdev);
54498e93258fSBjoern A. Zeeb }
54508e93258fSBjoern A. Zeeb 
54518e93258fSBjoern A. Zeeb static u8 rtw89_phy_dig_lna_idx_by_rssi(struct rtw89_dev *rtwdev, u8 rssi)
54528e93258fSBjoern A. Zeeb {
54538e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
54548e93258fSBjoern A. Zeeb 	u8 lna_idx;
54558e93258fSBjoern A. Zeeb 
54568e93258fSBjoern A. Zeeb 	if (rssi < dig->igi_rssi_th[0])
54578e93258fSBjoern A. Zeeb 		lna_idx = RTW89_DIG_GAIN_LNA_IDX6;
54588e93258fSBjoern A. Zeeb 	else if (rssi < dig->igi_rssi_th[1])
54598e93258fSBjoern A. Zeeb 		lna_idx = RTW89_DIG_GAIN_LNA_IDX5;
54608e93258fSBjoern A. Zeeb 	else if (rssi < dig->igi_rssi_th[2])
54618e93258fSBjoern A. Zeeb 		lna_idx = RTW89_DIG_GAIN_LNA_IDX4;
54628e93258fSBjoern A. Zeeb 	else if (rssi < dig->igi_rssi_th[3])
54638e93258fSBjoern A. Zeeb 		lna_idx = RTW89_DIG_GAIN_LNA_IDX3;
54648e93258fSBjoern A. Zeeb 	else if (rssi < dig->igi_rssi_th[4])
54658e93258fSBjoern A. Zeeb 		lna_idx = RTW89_DIG_GAIN_LNA_IDX2;
54668e93258fSBjoern A. Zeeb 	else
54678e93258fSBjoern A. Zeeb 		lna_idx = RTW89_DIG_GAIN_LNA_IDX1;
54688e93258fSBjoern A. Zeeb 
54698e93258fSBjoern A. Zeeb 	return lna_idx;
54708e93258fSBjoern A. Zeeb }
54718e93258fSBjoern A. Zeeb 
54728e93258fSBjoern A. Zeeb static u8 rtw89_phy_dig_tia_idx_by_rssi(struct rtw89_dev *rtwdev, u8 rssi)
54738e93258fSBjoern A. Zeeb {
54748e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
54758e93258fSBjoern A. Zeeb 	u8 tia_idx;
54768e93258fSBjoern A. Zeeb 
54778e93258fSBjoern A. Zeeb 	if (rssi < dig->igi_rssi_th[0])
54788e93258fSBjoern A. Zeeb 		tia_idx = RTW89_DIG_GAIN_TIA_IDX1;
54798e93258fSBjoern A. Zeeb 	else
54808e93258fSBjoern A. Zeeb 		tia_idx = RTW89_DIG_GAIN_TIA_IDX0;
54818e93258fSBjoern A. Zeeb 
54828e93258fSBjoern A. Zeeb 	return tia_idx;
54838e93258fSBjoern A. Zeeb }
54848e93258fSBjoern A. Zeeb 
54858e93258fSBjoern A. Zeeb #define IB_PBK_BASE 110
54868e93258fSBjoern A. Zeeb #define WB_RSSI_BASE 10
54878e93258fSBjoern A. Zeeb static u8 rtw89_phy_dig_rxb_idx_by_rssi(struct rtw89_dev *rtwdev, u8 rssi,
54888e93258fSBjoern A. Zeeb 					struct rtw89_agc_gaincode_set *set)
54898e93258fSBjoern A. Zeeb {
54908e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
54918e93258fSBjoern A. Zeeb 	s8 lna_gain = dig->lna_gain[set->lna_idx];
54928e93258fSBjoern A. Zeeb 	s8 tia_gain = dig->tia_gain[set->tia_idx];
54938e93258fSBjoern A. Zeeb 	s32 wb_rssi = rssi + lna_gain + tia_gain;
54948e93258fSBjoern A. Zeeb 	s32 rxb_idx_tmp = IB_PBK_BASE + WB_RSSI_BASE;
54958e93258fSBjoern A. Zeeb 	u8 rxb_idx;
54968e93258fSBjoern A. Zeeb 
54978e93258fSBjoern A. Zeeb 	rxb_idx_tmp += dig->ib_pkpwr - dig->ib_pbk - wb_rssi;
54988e93258fSBjoern A. Zeeb 	rxb_idx = clamp_t(s32, rxb_idx_tmp, RXB_IDX_MIN, RXB_IDX_MAX);
54998e93258fSBjoern A. Zeeb 
55008e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "wb_rssi=%03d, rxb_idx_tmp=%03d\n",
55018e93258fSBjoern A. Zeeb 		    wb_rssi, rxb_idx_tmp);
55028e93258fSBjoern A. Zeeb 
55038e93258fSBjoern A. Zeeb 	return rxb_idx;
55048e93258fSBjoern A. Zeeb }
55058e93258fSBjoern A. Zeeb 
55068e93258fSBjoern A. Zeeb static void rtw89_phy_dig_gaincode_by_rssi(struct rtw89_dev *rtwdev, u8 rssi,
55078e93258fSBjoern A. Zeeb 					   struct rtw89_agc_gaincode_set *set)
55088e93258fSBjoern A. Zeeb {
55098e93258fSBjoern A. Zeeb 	set->lna_idx = rtw89_phy_dig_lna_idx_by_rssi(rtwdev, rssi);
55108e93258fSBjoern A. Zeeb 	set->tia_idx = rtw89_phy_dig_tia_idx_by_rssi(rtwdev, rssi);
55118e93258fSBjoern A. Zeeb 	set->rxb_idx = rtw89_phy_dig_rxb_idx_by_rssi(rtwdev, rssi, set);
55128e93258fSBjoern A. Zeeb 
55138e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
55148e93258fSBjoern A. Zeeb 		    "final_rssi=%03d, (lna,tia,rab)=(%d,%d,%02d)\n",
55158e93258fSBjoern A. Zeeb 		    rssi, set->lna_idx, set->tia_idx, set->rxb_idx);
55168e93258fSBjoern A. Zeeb }
55178e93258fSBjoern A. Zeeb 
55188e93258fSBjoern A. Zeeb #define IGI_OFFSET_MAX 25
55198e93258fSBjoern A. Zeeb #define IGI_OFFSET_MUL 2
55208e93258fSBjoern A. Zeeb static void rtw89_phy_dig_igi_offset_by_env(struct rtw89_dev *rtwdev)
55218e93258fSBjoern A. Zeeb {
55228e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
55238e93258fSBjoern A. Zeeb 	struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
55248e93258fSBjoern A. Zeeb 	enum rtw89_dig_noisy_level noisy_lv;
55258e93258fSBjoern A. Zeeb 	u8 igi_offset = dig->fa_rssi_ofst;
55268e93258fSBjoern A. Zeeb 	u16 fa_ratio = 0;
55278e93258fSBjoern A. Zeeb 
55288e93258fSBjoern A. Zeeb 	fa_ratio = env->ifs_clm_cck_fa_permil + env->ifs_clm_ofdm_fa_permil;
55298e93258fSBjoern A. Zeeb 
55308e93258fSBjoern A. Zeeb 	if (fa_ratio < dig->fa_th[0])
55318e93258fSBjoern A. Zeeb 		noisy_lv = RTW89_DIG_NOISY_LEVEL0;
55328e93258fSBjoern A. Zeeb 	else if (fa_ratio < dig->fa_th[1])
55338e93258fSBjoern A. Zeeb 		noisy_lv = RTW89_DIG_NOISY_LEVEL1;
55348e93258fSBjoern A. Zeeb 	else if (fa_ratio < dig->fa_th[2])
55358e93258fSBjoern A. Zeeb 		noisy_lv = RTW89_DIG_NOISY_LEVEL2;
55368e93258fSBjoern A. Zeeb 	else if (fa_ratio < dig->fa_th[3])
55378e93258fSBjoern A. Zeeb 		noisy_lv = RTW89_DIG_NOISY_LEVEL3;
55388e93258fSBjoern A. Zeeb 	else
55398e93258fSBjoern A. Zeeb 		noisy_lv = RTW89_DIG_NOISY_LEVEL_MAX;
55408e93258fSBjoern A. Zeeb 
55418e93258fSBjoern A. Zeeb 	if (noisy_lv == RTW89_DIG_NOISY_LEVEL0 && igi_offset < 2)
55428e93258fSBjoern A. Zeeb 		igi_offset = 0;
55438e93258fSBjoern A. Zeeb 	else
55448e93258fSBjoern A. Zeeb 		igi_offset += noisy_lv * IGI_OFFSET_MUL;
55458e93258fSBjoern A. Zeeb 
55468e93258fSBjoern A. Zeeb 	igi_offset = min_t(u8, igi_offset, IGI_OFFSET_MAX);
55478e93258fSBjoern A. Zeeb 	dig->fa_rssi_ofst = igi_offset;
55488e93258fSBjoern A. Zeeb 
55498e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
55508e93258fSBjoern A. Zeeb 		    "fa_th: [+6 (%d) +4 (%d) +2 (%d) 0 (%d) -2 ]\n",
55518e93258fSBjoern A. Zeeb 		    dig->fa_th[3], dig->fa_th[2], dig->fa_th[1], dig->fa_th[0]);
55528e93258fSBjoern A. Zeeb 
55538e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
55548e93258fSBjoern A. Zeeb 		    "fa(CCK,OFDM,ALL)=(%d,%d,%d)%%, noisy_lv=%d, ofst=%d\n",
55558e93258fSBjoern A. Zeeb 		    env->ifs_clm_cck_fa_permil, env->ifs_clm_ofdm_fa_permil,
55568e93258fSBjoern A. Zeeb 		    env->ifs_clm_cck_fa_permil + env->ifs_clm_ofdm_fa_permil,
55578e93258fSBjoern A. Zeeb 		    noisy_lv, igi_offset);
55588e93258fSBjoern A. Zeeb }
55598e93258fSBjoern A. Zeeb 
55608e93258fSBjoern A. Zeeb static void rtw89_phy_dig_set_lna_idx(struct rtw89_dev *rtwdev, u8 lna_idx)
55618e93258fSBjoern A. Zeeb {
5562e2340276SBjoern A. Zeeb 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
5563e2340276SBjoern A. Zeeb 
5564e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p0_lna_init.addr,
5565e2340276SBjoern A. Zeeb 			       dig_regs->p0_lna_init.mask, lna_idx);
5566e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p1_lna_init.addr,
5567e2340276SBjoern A. Zeeb 			       dig_regs->p1_lna_init.mask, lna_idx);
55688e93258fSBjoern A. Zeeb }
55698e93258fSBjoern A. Zeeb 
55708e93258fSBjoern A. Zeeb static void rtw89_phy_dig_set_tia_idx(struct rtw89_dev *rtwdev, u8 tia_idx)
55718e93258fSBjoern A. Zeeb {
5572e2340276SBjoern A. Zeeb 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
5573e2340276SBjoern A. Zeeb 
5574e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p0_tia_init.addr,
5575e2340276SBjoern A. Zeeb 			       dig_regs->p0_tia_init.mask, tia_idx);
5576e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p1_tia_init.addr,
5577e2340276SBjoern A. Zeeb 			       dig_regs->p1_tia_init.mask, tia_idx);
55788e93258fSBjoern A. Zeeb }
55798e93258fSBjoern A. Zeeb 
55808e93258fSBjoern A. Zeeb static void rtw89_phy_dig_set_rxb_idx(struct rtw89_dev *rtwdev, u8 rxb_idx)
55818e93258fSBjoern A. Zeeb {
5582e2340276SBjoern A. Zeeb 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
5583e2340276SBjoern A. Zeeb 
5584e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p0_rxb_init.addr,
5585e2340276SBjoern A. Zeeb 			       dig_regs->p0_rxb_init.mask, rxb_idx);
5586e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p1_rxb_init.addr,
5587e2340276SBjoern A. Zeeb 			       dig_regs->p1_rxb_init.mask, rxb_idx);
55888e93258fSBjoern A. Zeeb }
55898e93258fSBjoern A. Zeeb 
55908e93258fSBjoern A. Zeeb static void rtw89_phy_dig_set_igi_cr(struct rtw89_dev *rtwdev,
55918e93258fSBjoern A. Zeeb 				     const struct rtw89_agc_gaincode_set set)
55928e93258fSBjoern A. Zeeb {
5593*6d67aabdSBjoern A. Zeeb 	if (!rtwdev->hal.support_igi)
5594*6d67aabdSBjoern A. Zeeb 		return;
5595*6d67aabdSBjoern A. Zeeb 
55968e93258fSBjoern A. Zeeb 	rtw89_phy_dig_set_lna_idx(rtwdev, set.lna_idx);
55978e93258fSBjoern A. Zeeb 	rtw89_phy_dig_set_tia_idx(rtwdev, set.tia_idx);
55988e93258fSBjoern A. Zeeb 	rtw89_phy_dig_set_rxb_idx(rtwdev, set.rxb_idx);
55998e93258fSBjoern A. Zeeb 
56008e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "Set (lna,tia,rxb)=((%d,%d,%02d))\n",
56018e93258fSBjoern A. Zeeb 		    set.lna_idx, set.tia_idx, set.rxb_idx);
56028e93258fSBjoern A. Zeeb }
56038e93258fSBjoern A. Zeeb 
56048e93258fSBjoern A. Zeeb static void rtw89_phy_dig_sdagc_follow_pagc_config(struct rtw89_dev *rtwdev,
56058e93258fSBjoern A. Zeeb 						   bool enable)
56068e93258fSBjoern A. Zeeb {
5607e2340276SBjoern A. Zeeb 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
56088e93258fSBjoern A. Zeeb 
5609e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p0_p20_pagcugc_en.addr,
5610e2340276SBjoern A. Zeeb 			       dig_regs->p0_p20_pagcugc_en.mask, enable);
5611e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p0_s20_pagcugc_en.addr,
5612e2340276SBjoern A. Zeeb 			       dig_regs->p0_s20_pagcugc_en.mask, enable);
5613e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p1_p20_pagcugc_en.addr,
5614e2340276SBjoern A. Zeeb 			       dig_regs->p1_p20_pagcugc_en.mask, enable);
5615e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->p1_s20_pagcugc_en.addr,
5616e2340276SBjoern A. Zeeb 			       dig_regs->p1_s20_pagcugc_en.mask, enable);
56178e93258fSBjoern A. Zeeb 
56188e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG, "sdagc_follow_pagc=%d\n", enable);
56198e93258fSBjoern A. Zeeb }
56208e93258fSBjoern A. Zeeb 
56218e93258fSBjoern A. Zeeb static void rtw89_phy_dig_config_igi(struct rtw89_dev *rtwdev)
56228e93258fSBjoern A. Zeeb {
56238e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
56248e93258fSBjoern A. Zeeb 
56258e93258fSBjoern A. Zeeb 	if (!rtwdev->hal.support_igi)
56268e93258fSBjoern A. Zeeb 		return;
56278e93258fSBjoern A. Zeeb 
56288e93258fSBjoern A. Zeeb 	if (dig->force_gaincode_idx_en) {
56298e93258fSBjoern A. Zeeb 		rtw89_phy_dig_set_igi_cr(rtwdev, dig->force_gaincode);
56308e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
56318e93258fSBjoern A. Zeeb 			    "Force gaincode index enabled.\n");
56328e93258fSBjoern A. Zeeb 	} else {
56338e93258fSBjoern A. Zeeb 		rtw89_phy_dig_gaincode_by_rssi(rtwdev, dig->igi_fa_rssi,
56348e93258fSBjoern A. Zeeb 					       &dig->cur_gaincode);
56358e93258fSBjoern A. Zeeb 		rtw89_phy_dig_set_igi_cr(rtwdev, dig->cur_gaincode);
56368e93258fSBjoern A. Zeeb 	}
56378e93258fSBjoern A. Zeeb }
56388e93258fSBjoern A. Zeeb 
56398e93258fSBjoern A. Zeeb static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, u8 rssi,
56408e93258fSBjoern A. Zeeb 				    bool enable)
56418e93258fSBjoern A. Zeeb {
56428e93258fSBjoern A. Zeeb 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
5643e2340276SBjoern A. Zeeb 	const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
56448e93258fSBjoern A. Zeeb 	enum rtw89_bandwidth cbw = chan->band_width;
56458e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
56468e93258fSBjoern A. Zeeb 	u8 final_rssi = 0, under_region = dig->pd_low_th_ofst;
56478e93258fSBjoern A. Zeeb 	u8 ofdm_cca_th;
56488e93258fSBjoern A. Zeeb 	s8 cck_cca_th;
56498e93258fSBjoern A. Zeeb 	u32 pd_val = 0;
56508e93258fSBjoern A. Zeeb 
5651*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
56528e93258fSBjoern A. Zeeb 		under_region += PD_TH_SB_FLTR_CMP_VAL;
56538e93258fSBjoern A. Zeeb 
56548e93258fSBjoern A. Zeeb 	switch (cbw) {
56558e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_40:
56568e93258fSBjoern A. Zeeb 		under_region += PD_TH_BW40_CMP_VAL;
56578e93258fSBjoern A. Zeeb 		break;
56588e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_80:
56598e93258fSBjoern A. Zeeb 		under_region += PD_TH_BW80_CMP_VAL;
56608e93258fSBjoern A. Zeeb 		break;
56618e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_160:
56628e93258fSBjoern A. Zeeb 		under_region += PD_TH_BW160_CMP_VAL;
56638e93258fSBjoern A. Zeeb 		break;
56648e93258fSBjoern A. Zeeb 	case RTW89_CHANNEL_WIDTH_20:
56658e93258fSBjoern A. Zeeb 		fallthrough;
56668e93258fSBjoern A. Zeeb 	default:
56678e93258fSBjoern A. Zeeb 		under_region += PD_TH_BW20_CMP_VAL;
56688e93258fSBjoern A. Zeeb 		break;
56698e93258fSBjoern A. Zeeb 	}
56708e93258fSBjoern A. Zeeb 
56718e93258fSBjoern A. Zeeb 	dig->dyn_pd_th_max = dig->igi_rssi;
56728e93258fSBjoern A. Zeeb 
56738e93258fSBjoern A. Zeeb 	final_rssi = min_t(u8, rssi, dig->igi_rssi);
56748e93258fSBjoern A. Zeeb 	ofdm_cca_th = clamp_t(u8, final_rssi, PD_TH_MIN_RSSI + under_region,
56758e93258fSBjoern A. Zeeb 			      PD_TH_MAX_RSSI + under_region);
56768e93258fSBjoern A. Zeeb 
56778e93258fSBjoern A. Zeeb 	if (enable) {
56788e93258fSBjoern A. Zeeb 		pd_val = (ofdm_cca_th - under_region - PD_TH_MIN_RSSI) >> 1;
56798e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
56808e93258fSBjoern A. Zeeb 			    "igi=%d, ofdm_ccaTH=%d, backoff=%d, PD_low=%d\n",
56818e93258fSBjoern A. Zeeb 			    final_rssi, ofdm_cca_th, under_region, pd_val);
56828e93258fSBjoern A. Zeeb 	} else {
56838e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_DIG,
56848e93258fSBjoern A. Zeeb 			    "Dynamic PD th disabled, Set PD_low_bd=0\n");
56858e93258fSBjoern A. Zeeb 	}
56868e93258fSBjoern A. Zeeb 
5687e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->seg0_pd_reg,
5688e2340276SBjoern A. Zeeb 			       dig_regs->pd_lower_bound_mask, pd_val);
5689e2340276SBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->seg0_pd_reg,
5690e2340276SBjoern A. Zeeb 			       dig_regs->pd_spatial_reuse_en, enable);
56918e93258fSBjoern A. Zeeb 
56928e93258fSBjoern A. Zeeb 	if (!rtwdev->hal.support_cckpd)
56938e93258fSBjoern A. Zeeb 		return;
56948e93258fSBjoern A. Zeeb 
56958e93258fSBjoern A. Zeeb 	cck_cca_th = max_t(s8, final_rssi - under_region, CCKPD_TH_MIN_RSSI);
56968e93258fSBjoern A. Zeeb 	pd_val = (u32)(cck_cca_th - IGI_RSSI_MAX);
56978e93258fSBjoern A. Zeeb 
56988e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
56998e93258fSBjoern A. Zeeb 		    "igi=%d, cck_ccaTH=%d, backoff=%d, cck_PD_low=((%d))dB\n",
57008e93258fSBjoern A. Zeeb 		    final_rssi, cck_cca_th, under_region, pd_val);
57018e93258fSBjoern A. Zeeb 
5702*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->bmode_pd_reg,
5703*6d67aabdSBjoern A. Zeeb 			       dig_regs->bmode_cca_rssi_limit_en, enable);
5704*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, dig_regs->bmode_pd_lower_bound_reg,
5705*6d67aabdSBjoern A. Zeeb 			       dig_regs->bmode_rssi_nocca_low_th_mask, pd_val);
57068e93258fSBjoern A. Zeeb }
57078e93258fSBjoern A. Zeeb 
57088e93258fSBjoern A. Zeeb void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev)
57098e93258fSBjoern A. Zeeb {
57108e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
57118e93258fSBjoern A. Zeeb 
57128e93258fSBjoern A. Zeeb 	dig->bypass_dig = false;
57138e93258fSBjoern A. Zeeb 	rtw89_phy_dig_para_reset(rtwdev);
57148e93258fSBjoern A. Zeeb 	rtw89_phy_dig_set_igi_cr(rtwdev, dig->force_gaincode);
57158e93258fSBjoern A. Zeeb 	rtw89_phy_dig_dyn_pd_th(rtwdev, rssi_nolink, false);
57168e93258fSBjoern A. Zeeb 	rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false);
57178e93258fSBjoern A. Zeeb 	rtw89_phy_dig_update_para(rtwdev);
57188e93258fSBjoern A. Zeeb }
57198e93258fSBjoern A. Zeeb 
57208e93258fSBjoern A. Zeeb #define IGI_RSSI_MIN 10
57218e93258fSBjoern A. Zeeb void rtw89_phy_dig(struct rtw89_dev *rtwdev)
57228e93258fSBjoern A. Zeeb {
57238e93258fSBjoern A. Zeeb 	struct rtw89_dig_info *dig = &rtwdev->dig;
57248e93258fSBjoern A. Zeeb 	bool is_linked = rtwdev->total_sta_assoc > 0;
57258e93258fSBjoern A. Zeeb 
57268e93258fSBjoern A. Zeeb 	if (unlikely(dig->bypass_dig)) {
57278e93258fSBjoern A. Zeeb 		dig->bypass_dig = false;
57288e93258fSBjoern A. Zeeb 		return;
57298e93258fSBjoern A. Zeeb 	}
57308e93258fSBjoern A. Zeeb 
57318e93258fSBjoern A. Zeeb 	if (!dig->is_linked_pre && is_linked) {
57328e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "First connected\n");
57338e93258fSBjoern A. Zeeb 		rtw89_phy_dig_update_para(rtwdev);
57348e93258fSBjoern A. Zeeb 	} else if (dig->is_linked_pre && !is_linked) {
57358e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_DIG, "First disconnected\n");
57368e93258fSBjoern A. Zeeb 		rtw89_phy_dig_update_para(rtwdev);
57378e93258fSBjoern A. Zeeb 	}
57388e93258fSBjoern A. Zeeb 	dig->is_linked_pre = is_linked;
57398e93258fSBjoern A. Zeeb 
57408e93258fSBjoern A. Zeeb 	rtw89_phy_dig_igi_offset_by_env(rtwdev);
57418e93258fSBjoern A. Zeeb 	rtw89_phy_dig_update_rssi_info(rtwdev);
57428e93258fSBjoern A. Zeeb 
57438e93258fSBjoern A. Zeeb 	dig->dyn_igi_min = (dig->igi_rssi > IGI_RSSI_MIN) ?
57448e93258fSBjoern A. Zeeb 			    dig->igi_rssi - IGI_RSSI_MIN : 0;
57458e93258fSBjoern A. Zeeb 	dig->dyn_igi_max = dig->dyn_igi_min + IGI_OFFSET_MAX;
57468e93258fSBjoern A. Zeeb 	dig->igi_fa_rssi = dig->dyn_igi_min + dig->fa_rssi_ofst;
57478e93258fSBjoern A. Zeeb 
57488e93258fSBjoern A. Zeeb 	dig->igi_fa_rssi = clamp(dig->igi_fa_rssi, dig->dyn_igi_min,
57498e93258fSBjoern A. Zeeb 				 dig->dyn_igi_max);
57508e93258fSBjoern A. Zeeb 
57518e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_DIG,
57528e93258fSBjoern A. Zeeb 		    "rssi=%03d, dyn(max,min)=(%d,%d), final_rssi=%d\n",
57538e93258fSBjoern A. Zeeb 		    dig->igi_rssi, dig->dyn_igi_max, dig->dyn_igi_min,
57548e93258fSBjoern A. Zeeb 		    dig->igi_fa_rssi);
57558e93258fSBjoern A. Zeeb 
57568e93258fSBjoern A. Zeeb 	rtw89_phy_dig_config_igi(rtwdev);
57578e93258fSBjoern A. Zeeb 
57588e93258fSBjoern A. Zeeb 	rtw89_phy_dig_dyn_pd_th(rtwdev, dig->igi_fa_rssi, dig->dyn_pd_th_en);
57598e93258fSBjoern A. Zeeb 
57608e93258fSBjoern A. Zeeb 	if (dig->dyn_pd_th_en && dig->igi_fa_rssi > dig->dyn_pd_th_max)
57618e93258fSBjoern A. Zeeb 		rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, true);
57628e93258fSBjoern A. Zeeb 	else
57638e93258fSBjoern A. Zeeb 		rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false);
57648e93258fSBjoern A. Zeeb }
57658e93258fSBjoern A. Zeeb 
5766e2340276SBjoern A. Zeeb static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
5767e2340276SBjoern A. Zeeb {
5768e2340276SBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
5769e2340276SBjoern A. Zeeb 	struct rtw89_dev *rtwdev = rtwsta->rtwdev;
5770e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
5771e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
5772e2340276SBjoern A. Zeeb 	bool *done = data;
5773e2340276SBjoern A. Zeeb 	u8 rssi_a, rssi_b;
5774e2340276SBjoern A. Zeeb 	u32 candidate;
5775e2340276SBjoern A. Zeeb 
5776e2340276SBjoern A. Zeeb 	if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls)
5777e2340276SBjoern A. Zeeb 		return;
5778e2340276SBjoern A. Zeeb 
5779e2340276SBjoern A. Zeeb 	if (*done)
5780e2340276SBjoern A. Zeeb 		return;
5781e2340276SBjoern A. Zeeb 
5782e2340276SBjoern A. Zeeb 	*done = true;
5783e2340276SBjoern A. Zeeb 
5784e2340276SBjoern A. Zeeb 	rssi_a = ewma_rssi_read(&rtwsta->rssi[RF_PATH_A]);
5785e2340276SBjoern A. Zeeb 	rssi_b = ewma_rssi_read(&rtwsta->rssi[RF_PATH_B]);
5786e2340276SBjoern A. Zeeb 
5787e2340276SBjoern A. Zeeb 	if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH)
5788e2340276SBjoern A. Zeeb 		candidate = RF_A;
5789e2340276SBjoern A. Zeeb 	else if (rssi_b > rssi_a + RTW89_TX_DIV_RSSI_RAW_TH)
5790e2340276SBjoern A. Zeeb 		candidate = RF_B;
5791e2340276SBjoern A. Zeeb 	else
5792e2340276SBjoern A. Zeeb 		return;
5793e2340276SBjoern A. Zeeb 
5794e2340276SBjoern A. Zeeb 	if (hal->antenna_tx == candidate)
5795e2340276SBjoern A. Zeeb 		return;
5796e2340276SBjoern A. Zeeb 
5797e2340276SBjoern A. Zeeb 	hal->antenna_tx = candidate;
5798e2340276SBjoern A. Zeeb 	rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta);
5799e2340276SBjoern A. Zeeb 
5800e2340276SBjoern A. Zeeb 	if (hal->antenna_tx == RF_A) {
5801e2340276SBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12);
5802e2340276SBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x11);
5803e2340276SBjoern A. Zeeb 	} else if (hal->antenna_tx == RF_B) {
5804e2340276SBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x11);
5805e2340276SBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x12);
5806e2340276SBjoern A. Zeeb 	}
5807e2340276SBjoern A. Zeeb }
5808e2340276SBjoern A. Zeeb 
5809e2340276SBjoern A. Zeeb void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
5810e2340276SBjoern A. Zeeb {
5811e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
5812e2340276SBjoern A. Zeeb 	bool done = false;
5813e2340276SBjoern A. Zeeb 
5814e2340276SBjoern A. Zeeb 	if (!hal->tx_path_diversity)
5815e2340276SBjoern A. Zeeb 		return;
5816e2340276SBjoern A. Zeeb 
5817e2340276SBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
5818e2340276SBjoern A. Zeeb 					  rtw89_phy_tx_path_div_sta_iter,
5819e2340276SBjoern A. Zeeb 					  &done);
5820e2340276SBjoern A. Zeeb }
5821e2340276SBjoern A. Zeeb 
5822e2340276SBjoern A. Zeeb #define ANTDIV_MAIN 0
5823e2340276SBjoern A. Zeeb #define ANTDIV_AUX 1
5824e2340276SBjoern A. Zeeb 
5825e2340276SBjoern A. Zeeb static void rtw89_phy_antdiv_set_ant(struct rtw89_dev *rtwdev)
5826e2340276SBjoern A. Zeeb {
5827e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
5828e2340276SBjoern A. Zeeb 	u8 default_ant, optional_ant;
5829e2340276SBjoern A. Zeeb 
5830e2340276SBjoern A. Zeeb 	if (!hal->ant_diversity || hal->antenna_tx == 0)
5831e2340276SBjoern A. Zeeb 		return;
5832e2340276SBjoern A. Zeeb 
5833e2340276SBjoern A. Zeeb 	if (hal->antenna_tx == RF_B) {
5834e2340276SBjoern A. Zeeb 		default_ant = ANTDIV_AUX;
5835e2340276SBjoern A. Zeeb 		optional_ant = ANTDIV_MAIN;
5836e2340276SBjoern A. Zeeb 	} else {
5837e2340276SBjoern A. Zeeb 		default_ant = ANTDIV_MAIN;
5838e2340276SBjoern A. Zeeb 		optional_ant = ANTDIV_AUX;
5839e2340276SBjoern A. Zeeb 	}
5840e2340276SBjoern A. Zeeb 
5841e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_CGCS_CTRL,
5842e2340276SBjoern A. Zeeb 			      default_ant, RTW89_PHY_0);
5843e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ORI,
5844e2340276SBjoern A. Zeeb 			      default_ant, RTW89_PHY_0);
5845e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_RX_ALT,
5846e2340276SBjoern A. Zeeb 			      optional_ant, RTW89_PHY_0);
5847e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, R_P0_ANTSEL, B_P0_ANTSEL_TX_ORI,
5848e2340276SBjoern A. Zeeb 			      default_ant, RTW89_PHY_0);
5849e2340276SBjoern A. Zeeb }
5850e2340276SBjoern A. Zeeb 
5851e2340276SBjoern A. Zeeb static void rtw89_phy_swap_hal_antenna(struct rtw89_dev *rtwdev)
5852e2340276SBjoern A. Zeeb {
5853e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
5854e2340276SBjoern A. Zeeb 
5855e2340276SBjoern A. Zeeb 	hal->antenna_rx = hal->antenna_rx == RF_A ? RF_B : RF_A;
5856e2340276SBjoern A. Zeeb 	hal->antenna_tx = hal->antenna_rx;
5857e2340276SBjoern A. Zeeb }
5858e2340276SBjoern A. Zeeb 
5859e2340276SBjoern A. Zeeb static void rtw89_phy_antdiv_decision_state(struct rtw89_dev *rtwdev)
5860e2340276SBjoern A. Zeeb {
5861e2340276SBjoern A. Zeeb 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
5862e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
5863e2340276SBjoern A. Zeeb 	bool no_change = false;
5864e2340276SBjoern A. Zeeb 	u8 main_rssi, aux_rssi;
5865e2340276SBjoern A. Zeeb 	u8 main_evm, aux_evm;
5866e2340276SBjoern A. Zeeb 	u32 candidate;
5867e2340276SBjoern A. Zeeb 
5868e2340276SBjoern A. Zeeb 	antdiv->get_stats = false;
5869e2340276SBjoern A. Zeeb 	antdiv->training_count = 0;
5870e2340276SBjoern A. Zeeb 
5871e2340276SBjoern A. Zeeb 	main_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->main_stats);
5872e2340276SBjoern A. Zeeb 	main_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->main_stats);
5873e2340276SBjoern A. Zeeb 	aux_rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->aux_stats);
5874e2340276SBjoern A. Zeeb 	aux_evm = rtw89_phy_antdiv_sts_instance_get_evm(&antdiv->aux_stats);
5875e2340276SBjoern A. Zeeb 
5876e2340276SBjoern A. Zeeb 	if (main_evm > aux_evm + ANTDIV_EVM_DIFF_TH)
5877e2340276SBjoern A. Zeeb 		candidate = RF_A;
5878e2340276SBjoern A. Zeeb 	else if (aux_evm > main_evm + ANTDIV_EVM_DIFF_TH)
5879e2340276SBjoern A. Zeeb 		candidate = RF_B;
5880e2340276SBjoern A. Zeeb 	else if (main_rssi > aux_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
5881e2340276SBjoern A. Zeeb 		candidate = RF_A;
5882e2340276SBjoern A. Zeeb 	else if (aux_rssi > main_rssi + RTW89_TX_DIV_RSSI_RAW_TH)
5883e2340276SBjoern A. Zeeb 		candidate = RF_B;
5884e2340276SBjoern A. Zeeb 	else
5885e2340276SBjoern A. Zeeb 		no_change = true;
5886e2340276SBjoern A. Zeeb 
5887e2340276SBjoern A. Zeeb 	if (no_change) {
5888e2340276SBjoern A. Zeeb 		/* swap back from training antenna to original */
5889e2340276SBjoern A. Zeeb 		rtw89_phy_swap_hal_antenna(rtwdev);
5890e2340276SBjoern A. Zeeb 		return;
5891e2340276SBjoern A. Zeeb 	}
5892e2340276SBjoern A. Zeeb 
5893e2340276SBjoern A. Zeeb 	hal->antenna_tx = candidate;
5894e2340276SBjoern A. Zeeb 	hal->antenna_rx = candidate;
5895e2340276SBjoern A. Zeeb }
5896e2340276SBjoern A. Zeeb 
5897e2340276SBjoern A. Zeeb static void rtw89_phy_antdiv_training_state(struct rtw89_dev *rtwdev)
5898e2340276SBjoern A. Zeeb {
5899e2340276SBjoern A. Zeeb 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
5900e2340276SBjoern A. Zeeb 	u64 state_period;
5901e2340276SBjoern A. Zeeb 
5902e2340276SBjoern A. Zeeb 	if (antdiv->training_count % 2 == 0) {
5903e2340276SBjoern A. Zeeb 		if (antdiv->training_count == 0)
5904e2340276SBjoern A. Zeeb 			rtw89_phy_antdiv_sts_reset(rtwdev);
5905e2340276SBjoern A. Zeeb 
5906e2340276SBjoern A. Zeeb 		antdiv->get_stats = true;
5907e2340276SBjoern A. Zeeb 		state_period = msecs_to_jiffies(ANTDIV_TRAINNING_INTVL);
5908e2340276SBjoern A. Zeeb 	} else {
5909e2340276SBjoern A. Zeeb 		antdiv->get_stats = false;
5910e2340276SBjoern A. Zeeb 		state_period = msecs_to_jiffies(ANTDIV_DELAY);
5911e2340276SBjoern A. Zeeb 
5912e2340276SBjoern A. Zeeb 		rtw89_phy_swap_hal_antenna(rtwdev);
5913e2340276SBjoern A. Zeeb 		rtw89_phy_antdiv_set_ant(rtwdev);
5914e2340276SBjoern A. Zeeb 	}
5915e2340276SBjoern A. Zeeb 
5916e2340276SBjoern A. Zeeb 	antdiv->training_count++;
5917e2340276SBjoern A. Zeeb 	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work,
5918e2340276SBjoern A. Zeeb 				     state_period);
5919e2340276SBjoern A. Zeeb }
5920e2340276SBjoern A. Zeeb 
5921e2340276SBjoern A. Zeeb void rtw89_phy_antdiv_work(struct work_struct *work)
5922e2340276SBjoern A. Zeeb {
5923e2340276SBjoern A. Zeeb 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
5924e2340276SBjoern A. Zeeb 						antdiv_work.work);
5925e2340276SBjoern A. Zeeb 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
5926e2340276SBjoern A. Zeeb 
5927e2340276SBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
5928e2340276SBjoern A. Zeeb 
5929e2340276SBjoern A. Zeeb 	if (antdiv->training_count <= ANTDIV_TRAINNING_CNT) {
5930e2340276SBjoern A. Zeeb 		rtw89_phy_antdiv_training_state(rtwdev);
5931e2340276SBjoern A. Zeeb 	} else {
5932e2340276SBjoern A. Zeeb 		rtw89_phy_antdiv_decision_state(rtwdev);
5933e2340276SBjoern A. Zeeb 		rtw89_phy_antdiv_set_ant(rtwdev);
5934e2340276SBjoern A. Zeeb 	}
5935e2340276SBjoern A. Zeeb 
5936e2340276SBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
5937e2340276SBjoern A. Zeeb }
5938e2340276SBjoern A. Zeeb 
5939e2340276SBjoern A. Zeeb void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev)
5940e2340276SBjoern A. Zeeb {
5941e2340276SBjoern A. Zeeb 	struct rtw89_antdiv_info *antdiv = &rtwdev->antdiv;
5942e2340276SBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
5943e2340276SBjoern A. Zeeb 	u8 rssi, rssi_pre;
5944e2340276SBjoern A. Zeeb 
5945e2340276SBjoern A. Zeeb 	if (!hal->ant_diversity || hal->ant_diversity_fixed)
5946e2340276SBjoern A. Zeeb 		return;
5947e2340276SBjoern A. Zeeb 
5948e2340276SBjoern A. Zeeb 	rssi = rtw89_phy_antdiv_sts_instance_get_rssi(&antdiv->target_stats);
5949e2340276SBjoern A. Zeeb 	rssi_pre = antdiv->rssi_pre;
5950e2340276SBjoern A. Zeeb 	antdiv->rssi_pre = rssi;
5951e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_sts_instance_reset(&antdiv->target_stats);
5952e2340276SBjoern A. Zeeb 
5953e2340276SBjoern A. Zeeb 	if (abs((int)rssi - (int)rssi_pre) < ANTDIV_RSSI_DIFF_TH)
5954e2340276SBjoern A. Zeeb 		return;
5955e2340276SBjoern A. Zeeb 
5956e2340276SBjoern A. Zeeb 	antdiv->training_count = 0;
5957e2340276SBjoern A. Zeeb 	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->antdiv_work, 0);
5958e2340276SBjoern A. Zeeb }
5959e2340276SBjoern A. Zeeb 
59608e93258fSBjoern A. Zeeb static void rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev)
59618e93258fSBjoern A. Zeeb {
59628e93258fSBjoern A. Zeeb 	rtw89_phy_ccx_top_setting_init(rtwdev);
59638e93258fSBjoern A. Zeeb 	rtw89_phy_ifs_clm_setting_init(rtwdev);
59648e93258fSBjoern A. Zeeb }
59658e93258fSBjoern A. Zeeb 
5966*6d67aabdSBjoern A. Zeeb static void rtw89_phy_edcca_init(struct rtw89_dev *rtwdev)
5967*6d67aabdSBjoern A. Zeeb {
5968*6d67aabdSBjoern A. Zeeb 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
5969*6d67aabdSBjoern A. Zeeb 	struct rtw89_edcca_bak *edcca_bak = &rtwdev->hal.edcca_bak;
5970*6d67aabdSBjoern A. Zeeb 
5971*6d67aabdSBjoern A. Zeeb 	memset(edcca_bak, 0, sizeof(*edcca_bak));
5972*6d67aabdSBjoern A. Zeeb 
5973*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8922A && rtwdev->hal.cv == CHIP_CAV) {
5974*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_TXGATING, B_TXGATING_EN, 0);
5975*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_CTLTOP, B_CTLTOP_VAL, 2);
5976*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_CTLTOP, B_CTLTOP_ON, 1);
5977*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_SPOOF_CG, B_SPOOF_CG_EN, 0);
5978*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_DFS_FFT_CG, B_DFS_CG_EN, 0);
5979*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_DFS_FFT_CG, B_DFS_FFT_EN, 0);
5980*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_SEGSND, B_SEGSND_EN, 0);
5981*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_SEGSND, B_SEGSND_EN, 1);
5982*6d67aabdSBjoern A. Zeeb 		rtw89_phy_set_phy_regs(rtwdev, R_DFS_FFT_CG, B_DFS_FFT_EN, 1);
5983*6d67aabdSBjoern A. Zeeb 	}
5984*6d67aabdSBjoern A. Zeeb 
5985*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, edcca_regs->tx_collision_t2r_st,
5986*6d67aabdSBjoern A. Zeeb 			       edcca_regs->tx_collision_t2r_st_mask, 0x29);
5987*6d67aabdSBjoern A. Zeeb }
5988*6d67aabdSBjoern A. Zeeb 
59898e93258fSBjoern A. Zeeb void rtw89_phy_dm_init(struct rtw89_dev *rtwdev)
59908e93258fSBjoern A. Zeeb {
59918e93258fSBjoern A. Zeeb 	rtw89_phy_stat_init(rtwdev);
59928e93258fSBjoern A. Zeeb 
59938e93258fSBjoern A. Zeeb 	rtw89_chip_bb_sethw(rtwdev);
59948e93258fSBjoern A. Zeeb 
59958e93258fSBjoern A. Zeeb 	rtw89_phy_env_monitor_init(rtwdev);
59968e93258fSBjoern A. Zeeb 	rtw89_physts_parsing_init(rtwdev);
59978e93258fSBjoern A. Zeeb 	rtw89_phy_dig_init(rtwdev);
59988e93258fSBjoern A. Zeeb 	rtw89_phy_cfo_init(rtwdev);
5999*6d67aabdSBjoern A. Zeeb 	rtw89_phy_bb_wrap_init(rtwdev);
6000*6d67aabdSBjoern A. Zeeb 	rtw89_phy_edcca_init(rtwdev);
6001*6d67aabdSBjoern A. Zeeb 	rtw89_phy_ch_info_init(rtwdev);
6002e2340276SBjoern A. Zeeb 	rtw89_phy_ul_tb_info_init(rtwdev);
6003e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_init(rtwdev);
6004e2340276SBjoern A. Zeeb 	rtw89_chip_rfe_gpio(rtwdev);
6005e2340276SBjoern A. Zeeb 	rtw89_phy_antdiv_set_ant(rtwdev);
60068e93258fSBjoern A. Zeeb 
6007*6d67aabdSBjoern A. Zeeb 	rtw89_chip_rfk_hw_init(rtwdev);
60088e93258fSBjoern A. Zeeb 	rtw89_phy_init_rf_nctl(rtwdev);
60098e93258fSBjoern A. Zeeb 	rtw89_chip_rfk_init(rtwdev);
60108e93258fSBjoern A. Zeeb 	rtw89_chip_set_txpwr_ctrl(rtwdev);
60118e93258fSBjoern A. Zeeb 	rtw89_chip_power_trim(rtwdev);
60128e93258fSBjoern A. Zeeb 	rtw89_chip_cfg_txrx_path(rtwdev);
60138e93258fSBjoern A. Zeeb }
60148e93258fSBjoern A. Zeeb 
60158e93258fSBjoern A. Zeeb void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
60168e93258fSBjoern A. Zeeb {
6017e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
6018*6d67aabdSBjoern A. Zeeb 	const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld;
60198e93258fSBjoern A. Zeeb 	enum rtw89_phy_idx phy_idx = RTW89_PHY_0;
60208e93258fSBjoern A. Zeeb 	u8 bss_color;
60218e93258fSBjoern A. Zeeb 
60228e93258fSBjoern A. Zeeb 	if (!vif->bss_conf.he_support || !vif->cfg.assoc)
60238e93258fSBjoern A. Zeeb 		return;
60248e93258fSBjoern A. Zeeb 
60258e93258fSBjoern A. Zeeb 	bss_color = vif->bss_conf.he_bss_color.color;
60268e93258fSBjoern A. Zeeb 
6027*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, bss_clr_vld->addr, bss_clr_vld->mask, 0x1,
60288e93258fSBjoern A. Zeeb 			      phy_idx);
6029e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, chip->bss_clr_map_reg, B_BSS_CLR_MAP_TGT,
6030e2340276SBjoern A. Zeeb 			      bss_color, phy_idx);
6031e2340276SBjoern A. Zeeb 	rtw89_phy_write32_idx(rtwdev, chip->bss_clr_map_reg, B_BSS_CLR_MAP_STAID,
60328e93258fSBjoern A. Zeeb 			      vif->cfg.aid, phy_idx);
60338e93258fSBjoern A. Zeeb }
60348e93258fSBjoern A. Zeeb 
6035*6d67aabdSBjoern A. Zeeb static bool rfk_chan_validate_desc(const struct rtw89_rfk_chan_desc *desc)
6036*6d67aabdSBjoern A. Zeeb {
6037*6d67aabdSBjoern A. Zeeb 	return desc->ch != 0;
6038*6d67aabdSBjoern A. Zeeb }
6039*6d67aabdSBjoern A. Zeeb 
6040*6d67aabdSBjoern A. Zeeb static bool rfk_chan_is_equivalent(const struct rtw89_rfk_chan_desc *desc,
6041*6d67aabdSBjoern A. Zeeb 				   const struct rtw89_chan *chan)
6042*6d67aabdSBjoern A. Zeeb {
6043*6d67aabdSBjoern A. Zeeb 	if (!rfk_chan_validate_desc(desc))
6044*6d67aabdSBjoern A. Zeeb 		return false;
6045*6d67aabdSBjoern A. Zeeb 
6046*6d67aabdSBjoern A. Zeeb 	if (desc->ch != chan->channel)
6047*6d67aabdSBjoern A. Zeeb 		return false;
6048*6d67aabdSBjoern A. Zeeb 
6049*6d67aabdSBjoern A. Zeeb 	if (desc->has_band && desc->band != chan->band_type)
6050*6d67aabdSBjoern A. Zeeb 		return false;
6051*6d67aabdSBjoern A. Zeeb 
6052*6d67aabdSBjoern A. Zeeb 	if (desc->has_bw && desc->bw != chan->band_width)
6053*6d67aabdSBjoern A. Zeeb 		return false;
6054*6d67aabdSBjoern A. Zeeb 
6055*6d67aabdSBjoern A. Zeeb 	return true;
6056*6d67aabdSBjoern A. Zeeb }
6057*6d67aabdSBjoern A. Zeeb 
6058*6d67aabdSBjoern A. Zeeb struct rfk_chan_iter_data {
6059*6d67aabdSBjoern A. Zeeb 	const struct rtw89_rfk_chan_desc desc;
6060*6d67aabdSBjoern A. Zeeb 	unsigned int found;
6061*6d67aabdSBjoern A. Zeeb };
6062*6d67aabdSBjoern A. Zeeb 
6063*6d67aabdSBjoern A. Zeeb static int rfk_chan_iter_search(const struct rtw89_chan *chan, void *data)
6064*6d67aabdSBjoern A. Zeeb {
6065*6d67aabdSBjoern A. Zeeb 	struct rfk_chan_iter_data *iter_data = data;
6066*6d67aabdSBjoern A. Zeeb 
6067*6d67aabdSBjoern A. Zeeb 	if (rfk_chan_is_equivalent(&iter_data->desc, chan))
6068*6d67aabdSBjoern A. Zeeb 		iter_data->found++;
6069*6d67aabdSBjoern A. Zeeb 
6070*6d67aabdSBjoern A. Zeeb 	return 0;
6071*6d67aabdSBjoern A. Zeeb }
6072*6d67aabdSBjoern A. Zeeb 
6073*6d67aabdSBjoern A. Zeeb u8 rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev,
6074*6d67aabdSBjoern A. Zeeb 			 const struct rtw89_rfk_chan_desc *desc, u8 desc_nr,
6075*6d67aabdSBjoern A. Zeeb 			 const struct rtw89_chan *target_chan)
6076*6d67aabdSBjoern A. Zeeb {
6077*6d67aabdSBjoern A. Zeeb 	int sel = -1;
6078*6d67aabdSBjoern A. Zeeb 	u8 i;
6079*6d67aabdSBjoern A. Zeeb 
6080*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < desc_nr; i++) {
6081*6d67aabdSBjoern A. Zeeb 		struct rfk_chan_iter_data iter_data = {
6082*6d67aabdSBjoern A. Zeeb 			.desc = desc[i],
6083*6d67aabdSBjoern A. Zeeb 		};
6084*6d67aabdSBjoern A. Zeeb 
6085*6d67aabdSBjoern A. Zeeb 		if (rfk_chan_is_equivalent(&desc[i], target_chan))
6086*6d67aabdSBjoern A. Zeeb 			return i;
6087*6d67aabdSBjoern A. Zeeb 
6088*6d67aabdSBjoern A. Zeeb 		rtw89_iterate_entity_chan(rtwdev, rfk_chan_iter_search, &iter_data);
6089*6d67aabdSBjoern A. Zeeb 		if (!iter_data.found && sel == -1)
6090*6d67aabdSBjoern A. Zeeb 			sel = i;
6091*6d67aabdSBjoern A. Zeeb 	}
6092*6d67aabdSBjoern A. Zeeb 
6093*6d67aabdSBjoern A. Zeeb 	if (sel == -1) {
6094*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_RFK,
6095*6d67aabdSBjoern A. Zeeb 			    "no idle rfk entry; force replace the first\n");
6096*6d67aabdSBjoern A. Zeeb 		sel = 0;
6097*6d67aabdSBjoern A. Zeeb 	}
6098*6d67aabdSBjoern A. Zeeb 
6099*6d67aabdSBjoern A. Zeeb 	return sel;
6100*6d67aabdSBjoern A. Zeeb }
6101*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_rfk_chan_lookup);
6102*6d67aabdSBjoern A. Zeeb 
61038e93258fSBjoern A. Zeeb static void
61048e93258fSBjoern A. Zeeb _rfk_write_rf(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
61058e93258fSBjoern A. Zeeb {
61068e93258fSBjoern A. Zeeb 	rtw89_write_rf(rtwdev, def->path, def->addr, def->mask, def->data);
61078e93258fSBjoern A. Zeeb }
61088e93258fSBjoern A. Zeeb 
61098e93258fSBjoern A. Zeeb static void
61108e93258fSBjoern A. Zeeb _rfk_write32_mask(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
61118e93258fSBjoern A. Zeeb {
61128e93258fSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, def->addr, def->mask, def->data);
61138e93258fSBjoern A. Zeeb }
61148e93258fSBjoern A. Zeeb 
61158e93258fSBjoern A. Zeeb static void
61168e93258fSBjoern A. Zeeb _rfk_write32_set(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
61178e93258fSBjoern A. Zeeb {
61188e93258fSBjoern A. Zeeb 	rtw89_phy_write32_set(rtwdev, def->addr, def->mask);
61198e93258fSBjoern A. Zeeb }
61208e93258fSBjoern A. Zeeb 
61218e93258fSBjoern A. Zeeb static void
61228e93258fSBjoern A. Zeeb _rfk_write32_clr(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
61238e93258fSBjoern A. Zeeb {
61248e93258fSBjoern A. Zeeb 	rtw89_phy_write32_clr(rtwdev, def->addr, def->mask);
61258e93258fSBjoern A. Zeeb }
61268e93258fSBjoern A. Zeeb 
61278e93258fSBjoern A. Zeeb static void
61288e93258fSBjoern A. Zeeb _rfk_delay(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def)
61298e93258fSBjoern A. Zeeb {
61308e93258fSBjoern A. Zeeb 	udelay(def->data);
61318e93258fSBjoern A. Zeeb }
61328e93258fSBjoern A. Zeeb 
61338e93258fSBjoern A. Zeeb static void
61348e93258fSBjoern A. Zeeb (*_rfk_handler[])(struct rtw89_dev *rtwdev, const struct rtw89_reg5_def *def) = {
61358e93258fSBjoern A. Zeeb 	[RTW89_RFK_F_WRF] = _rfk_write_rf,
61368e93258fSBjoern A. Zeeb 	[RTW89_RFK_F_WM] = _rfk_write32_mask,
61378e93258fSBjoern A. Zeeb 	[RTW89_RFK_F_WS] = _rfk_write32_set,
61388e93258fSBjoern A. Zeeb 	[RTW89_RFK_F_WC] = _rfk_write32_clr,
61398e93258fSBjoern A. Zeeb 	[RTW89_RFK_F_DELAY] = _rfk_delay,
61408e93258fSBjoern A. Zeeb };
61418e93258fSBjoern A. Zeeb 
61428e93258fSBjoern A. Zeeb #if defined(__linux__)
61438e93258fSBjoern A. Zeeb static_assert(ARRAY_SIZE(_rfk_handler) == RTW89_RFK_F_NUM);
61448e93258fSBjoern A. Zeeb #elif defined(__FreeBSD__)
61458e93258fSBjoern A. Zeeb rtw89_static_assert(ARRAY_SIZE(_rfk_handler) == RTW89_RFK_F_NUM);
61468e93258fSBjoern A. Zeeb #endif
61478e93258fSBjoern A. Zeeb 
61488e93258fSBjoern A. Zeeb void
61498e93258fSBjoern A. Zeeb rtw89_rfk_parser(struct rtw89_dev *rtwdev, const struct rtw89_rfk_tbl *tbl)
61508e93258fSBjoern A. Zeeb {
61518e93258fSBjoern A. Zeeb 	const struct rtw89_reg5_def *p = tbl->defs;
61528e93258fSBjoern A. Zeeb 	const struct rtw89_reg5_def *end = tbl->defs + tbl->size;
61538e93258fSBjoern A. Zeeb 
61548e93258fSBjoern A. Zeeb 	for (; p < end; p++)
61558e93258fSBjoern A. Zeeb 		_rfk_handler[p->flag](rtwdev, p);
61568e93258fSBjoern A. Zeeb }
61578e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_rfk_parser);
61588e93258fSBjoern A. Zeeb 
61598e93258fSBjoern A. Zeeb #define RTW89_TSSI_FAST_MODE_NUM 4
61608e93258fSBjoern A. Zeeb 
61618e93258fSBjoern A. Zeeb static const struct rtw89_reg_def rtw89_tssi_fastmode_regs_flat[RTW89_TSSI_FAST_MODE_NUM] = {
61628e93258fSBjoern A. Zeeb 	{0xD934, 0xff0000},
61638e93258fSBjoern A. Zeeb 	{0xD934, 0xff000000},
61648e93258fSBjoern A. Zeeb 	{0xD938, 0xff},
61658e93258fSBjoern A. Zeeb 	{0xD934, 0xff00},
61668e93258fSBjoern A. Zeeb };
61678e93258fSBjoern A. Zeeb 
61688e93258fSBjoern A. Zeeb static const struct rtw89_reg_def rtw89_tssi_fastmode_regs_level[RTW89_TSSI_FAST_MODE_NUM] = {
61698e93258fSBjoern A. Zeeb 	{0xD930, 0xff0000},
61708e93258fSBjoern A. Zeeb 	{0xD930, 0xff000000},
61718e93258fSBjoern A. Zeeb 	{0xD934, 0xff},
61728e93258fSBjoern A. Zeeb 	{0xD930, 0xff00},
61738e93258fSBjoern A. Zeeb };
61748e93258fSBjoern A. Zeeb 
61758e93258fSBjoern A. Zeeb static
61768e93258fSBjoern A. Zeeb void rtw89_phy_tssi_ctrl_set_fast_mode_cfg(struct rtw89_dev *rtwdev,
61778e93258fSBjoern A. Zeeb 					   enum rtw89_mac_idx mac_idx,
61788e93258fSBjoern A. Zeeb 					   enum rtw89_tssi_bandedge_cfg bandedge_cfg,
61798e93258fSBjoern A. Zeeb 					   u32 val)
61808e93258fSBjoern A. Zeeb {
61818e93258fSBjoern A. Zeeb 	const struct rtw89_reg_def *regs;
61828e93258fSBjoern A. Zeeb 	u32 reg;
61838e93258fSBjoern A. Zeeb 	int i;
61848e93258fSBjoern A. Zeeb 
61858e93258fSBjoern A. Zeeb 	if (bandedge_cfg == RTW89_TSSI_BANDEDGE_FLAT)
61868e93258fSBjoern A. Zeeb 		regs = rtw89_tssi_fastmode_regs_flat;
61878e93258fSBjoern A. Zeeb 	else
61888e93258fSBjoern A. Zeeb 		regs = rtw89_tssi_fastmode_regs_level;
61898e93258fSBjoern A. Zeeb 
61908e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_TSSI_FAST_MODE_NUM; i++) {
6191*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, regs[i].addr, mac_idx);
61928e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, regs[i].mask, val);
61938e93258fSBjoern A. Zeeb 	}
61948e93258fSBjoern A. Zeeb }
61958e93258fSBjoern A. Zeeb 
61968e93258fSBjoern A. Zeeb static const struct rtw89_reg_def rtw89_tssi_bandedge_regs_flat[RTW89_TSSI_SBW_NUM] = {
61978e93258fSBjoern A. Zeeb 	{0xD91C, 0xff000000},
61988e93258fSBjoern A. Zeeb 	{0xD920, 0xff},
61998e93258fSBjoern A. Zeeb 	{0xD920, 0xff00},
62008e93258fSBjoern A. Zeeb 	{0xD920, 0xff0000},
62018e93258fSBjoern A. Zeeb 	{0xD920, 0xff000000},
62028e93258fSBjoern A. Zeeb 	{0xD924, 0xff},
62038e93258fSBjoern A. Zeeb 	{0xD924, 0xff00},
62048e93258fSBjoern A. Zeeb 	{0xD914, 0xff000000},
62058e93258fSBjoern A. Zeeb 	{0xD918, 0xff},
62068e93258fSBjoern A. Zeeb 	{0xD918, 0xff00},
62078e93258fSBjoern A. Zeeb 	{0xD918, 0xff0000},
62088e93258fSBjoern A. Zeeb 	{0xD918, 0xff000000},
62098e93258fSBjoern A. Zeeb 	{0xD91C, 0xff},
62108e93258fSBjoern A. Zeeb 	{0xD91C, 0xff00},
62118e93258fSBjoern A. Zeeb 	{0xD91C, 0xff0000},
62128e93258fSBjoern A. Zeeb };
62138e93258fSBjoern A. Zeeb 
62148e93258fSBjoern A. Zeeb static const struct rtw89_reg_def rtw89_tssi_bandedge_regs_level[RTW89_TSSI_SBW_NUM] = {
62158e93258fSBjoern A. Zeeb 	{0xD910, 0xff},
62168e93258fSBjoern A. Zeeb 	{0xD910, 0xff00},
62178e93258fSBjoern A. Zeeb 	{0xD910, 0xff0000},
62188e93258fSBjoern A. Zeeb 	{0xD910, 0xff000000},
62198e93258fSBjoern A. Zeeb 	{0xD914, 0xff},
62208e93258fSBjoern A. Zeeb 	{0xD914, 0xff00},
62218e93258fSBjoern A. Zeeb 	{0xD914, 0xff0000},
62228e93258fSBjoern A. Zeeb 	{0xD908, 0xff},
62238e93258fSBjoern A. Zeeb 	{0xD908, 0xff00},
62248e93258fSBjoern A. Zeeb 	{0xD908, 0xff0000},
62258e93258fSBjoern A. Zeeb 	{0xD908, 0xff000000},
62268e93258fSBjoern A. Zeeb 	{0xD90C, 0xff},
62278e93258fSBjoern A. Zeeb 	{0xD90C, 0xff00},
62288e93258fSBjoern A. Zeeb 	{0xD90C, 0xff0000},
62298e93258fSBjoern A. Zeeb 	{0xD90C, 0xff000000},
62308e93258fSBjoern A. Zeeb };
62318e93258fSBjoern A. Zeeb 
62328e93258fSBjoern A. Zeeb void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev,
62338e93258fSBjoern A. Zeeb 					  enum rtw89_mac_idx mac_idx,
62348e93258fSBjoern A. Zeeb 					  enum rtw89_tssi_bandedge_cfg bandedge_cfg)
62358e93258fSBjoern A. Zeeb {
62368e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
62378e93258fSBjoern A. Zeeb 	const struct rtw89_reg_def *regs;
62388e93258fSBjoern A. Zeeb 	const u32 *data;
62398e93258fSBjoern A. Zeeb 	u32 reg;
62408e93258fSBjoern A. Zeeb 	int i;
62418e93258fSBjoern A. Zeeb 
62428e93258fSBjoern A. Zeeb 	if (bandedge_cfg >= RTW89_TSSI_CFG_NUM)
62438e93258fSBjoern A. Zeeb 		return;
62448e93258fSBjoern A. Zeeb 
62458e93258fSBjoern A. Zeeb 	if (bandedge_cfg == RTW89_TSSI_BANDEDGE_FLAT)
62468e93258fSBjoern A. Zeeb 		regs = rtw89_tssi_bandedge_regs_flat;
62478e93258fSBjoern A. Zeeb 	else
62488e93258fSBjoern A. Zeeb 		regs = rtw89_tssi_bandedge_regs_level;
62498e93258fSBjoern A. Zeeb 
62508e93258fSBjoern A. Zeeb 	data = chip->tssi_dbw_table->data[bandedge_cfg];
62518e93258fSBjoern A. Zeeb 
62528e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_TSSI_SBW_NUM; i++) {
6253*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, regs[i].addr, mac_idx);
62548e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, regs[i].mask, data[i]);
62558e93258fSBjoern A. Zeeb 	}
62568e93258fSBjoern A. Zeeb 
6257*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BANDEDGE_CFG, mac_idx);
62588e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_BANDEDGE_CFG_IDX_MASK, bandedge_cfg);
62598e93258fSBjoern A. Zeeb 
62608e93258fSBjoern A. Zeeb 	rtw89_phy_tssi_ctrl_set_fast_mode_cfg(rtwdev, mac_idx, bandedge_cfg,
62618e93258fSBjoern A. Zeeb 					      data[RTW89_TSSI_SBW20]);
62628e93258fSBjoern A. Zeeb }
62638e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_tssi_ctrl_set_bandedge_cfg);
6264e2340276SBjoern A. Zeeb 
6265e2340276SBjoern A. Zeeb static
6266e2340276SBjoern A. Zeeb const u8 rtw89_ch_base_table[16] = {1, 0xff,
6267e2340276SBjoern A. Zeeb 				    36, 100, 132, 149, 0xff,
6268e2340276SBjoern A. Zeeb 				    1, 33, 65, 97, 129, 161, 193, 225, 0xff};
6269e2340276SBjoern A. Zeeb #define RTW89_CH_BASE_IDX_2G		0
6270e2340276SBjoern A. Zeeb #define RTW89_CH_BASE_IDX_5G_FIRST	2
6271e2340276SBjoern A. Zeeb #define RTW89_CH_BASE_IDX_5G_LAST	5
6272e2340276SBjoern A. Zeeb #define RTW89_CH_BASE_IDX_6G_FIRST	7
6273e2340276SBjoern A. Zeeb #define RTW89_CH_BASE_IDX_6G_LAST	14
6274e2340276SBjoern A. Zeeb 
6275e2340276SBjoern A. Zeeb #define RTW89_CH_BASE_IDX_MASK		GENMASK(7, 4)
6276e2340276SBjoern A. Zeeb #define RTW89_CH_OFFSET_MASK		GENMASK(3, 0)
6277e2340276SBjoern A. Zeeb 
6278e2340276SBjoern A. Zeeb u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band)
6279e2340276SBjoern A. Zeeb {
6280e2340276SBjoern A. Zeeb 	u8 chan_idx;
6281e2340276SBjoern A. Zeeb 	u8 last, first;
6282e2340276SBjoern A. Zeeb 	u8 idx;
6283e2340276SBjoern A. Zeeb 
6284e2340276SBjoern A. Zeeb 	switch (band) {
6285e2340276SBjoern A. Zeeb 	case RTW89_BAND_2G:
6286e2340276SBjoern A. Zeeb 		chan_idx = FIELD_PREP(RTW89_CH_BASE_IDX_MASK, RTW89_CH_BASE_IDX_2G) |
6287e2340276SBjoern A. Zeeb 			   FIELD_PREP(RTW89_CH_OFFSET_MASK, central_ch);
6288e2340276SBjoern A. Zeeb 		return chan_idx;
6289e2340276SBjoern A. Zeeb 	case RTW89_BAND_5G:
6290e2340276SBjoern A. Zeeb 		first = RTW89_CH_BASE_IDX_5G_FIRST;
6291e2340276SBjoern A. Zeeb 		last = RTW89_CH_BASE_IDX_5G_LAST;
6292e2340276SBjoern A. Zeeb 		break;
6293e2340276SBjoern A. Zeeb 	case RTW89_BAND_6G:
6294e2340276SBjoern A. Zeeb 		first = RTW89_CH_BASE_IDX_6G_FIRST;
6295e2340276SBjoern A. Zeeb 		last = RTW89_CH_BASE_IDX_6G_LAST;
6296e2340276SBjoern A. Zeeb 		break;
6297e2340276SBjoern A. Zeeb 	default:
6298e2340276SBjoern A. Zeeb 		rtw89_warn(rtwdev, "Unsupported band %d\n", band);
6299e2340276SBjoern A. Zeeb 		return 0;
6300e2340276SBjoern A. Zeeb 	}
6301e2340276SBjoern A. Zeeb 
6302e2340276SBjoern A. Zeeb 	for (idx = last; idx >= first; idx--)
6303e2340276SBjoern A. Zeeb 		if (central_ch >= rtw89_ch_base_table[idx])
6304e2340276SBjoern A. Zeeb 			break;
6305e2340276SBjoern A. Zeeb 
6306e2340276SBjoern A. Zeeb 	if (idx < first) {
6307e2340276SBjoern A. Zeeb 		rtw89_warn(rtwdev, "Unknown band %d channel %d\n", band, central_ch);
6308e2340276SBjoern A. Zeeb 		return 0;
6309e2340276SBjoern A. Zeeb 	}
6310e2340276SBjoern A. Zeeb 
6311e2340276SBjoern A. Zeeb 	chan_idx = FIELD_PREP(RTW89_CH_BASE_IDX_MASK, idx) |
6312e2340276SBjoern A. Zeeb 		   FIELD_PREP(RTW89_CH_OFFSET_MASK,
6313e2340276SBjoern A. Zeeb 			      (central_ch - rtw89_ch_base_table[idx]) >> 1);
6314e2340276SBjoern A. Zeeb 	return chan_idx;
6315e2340276SBjoern A. Zeeb }
6316e2340276SBjoern A. Zeeb EXPORT_SYMBOL(rtw89_encode_chan_idx);
6317e2340276SBjoern A. Zeeb 
6318e2340276SBjoern A. Zeeb void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
6319e2340276SBjoern A. Zeeb 			   u8 *ch, enum nl80211_band *band)
6320e2340276SBjoern A. Zeeb {
6321e2340276SBjoern A. Zeeb 	u8 idx, offset;
6322e2340276SBjoern A. Zeeb 
6323e2340276SBjoern A. Zeeb 	idx = FIELD_GET(RTW89_CH_BASE_IDX_MASK, chan_idx);
6324e2340276SBjoern A. Zeeb 	offset = FIELD_GET(RTW89_CH_OFFSET_MASK, chan_idx);
6325e2340276SBjoern A. Zeeb 
6326e2340276SBjoern A. Zeeb 	if (idx == RTW89_CH_BASE_IDX_2G) {
6327e2340276SBjoern A. Zeeb 		*band = NL80211_BAND_2GHZ;
6328e2340276SBjoern A. Zeeb 		*ch = offset;
6329e2340276SBjoern A. Zeeb 		return;
6330e2340276SBjoern A. Zeeb 	}
6331e2340276SBjoern A. Zeeb 
6332e2340276SBjoern A. Zeeb 	*band = idx <= RTW89_CH_BASE_IDX_5G_LAST ? NL80211_BAND_5GHZ : NL80211_BAND_6GHZ;
6333e2340276SBjoern A. Zeeb 	*ch = rtw89_ch_base_table[idx] + (offset << 1);
6334e2340276SBjoern A. Zeeb }
6335e2340276SBjoern A. Zeeb EXPORT_SYMBOL(rtw89_decode_chan_idx);
6336e2340276SBjoern A. Zeeb 
6337e2340276SBjoern A. Zeeb void rtw89_phy_config_edcca(struct rtw89_dev *rtwdev, bool scan)
6338e2340276SBjoern A. Zeeb {
6339*6d67aabdSBjoern A. Zeeb 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
6340*6d67aabdSBjoern A. Zeeb 	struct rtw89_edcca_bak *edcca_bak = &rtwdev->hal.edcca_bak;
6341e2340276SBjoern A. Zeeb 
6342e2340276SBjoern A. Zeeb 	if (scan) {
6343*6d67aabdSBjoern A. Zeeb 		edcca_bak->a =
6344*6d67aabdSBjoern A. Zeeb 			rtw89_phy_read32_mask(rtwdev, edcca_regs->edcca_level,
6345*6d67aabdSBjoern A. Zeeb 					      edcca_regs->edcca_mask);
6346*6d67aabdSBjoern A. Zeeb 		edcca_bak->p =
6347*6d67aabdSBjoern A. Zeeb 			rtw89_phy_read32_mask(rtwdev, edcca_regs->edcca_level,
6348*6d67aabdSBjoern A. Zeeb 					      edcca_regs->edcca_p_mask);
6349*6d67aabdSBjoern A. Zeeb 		edcca_bak->ppdu =
6350*6d67aabdSBjoern A. Zeeb 			rtw89_phy_read32_mask(rtwdev, edcca_regs->ppdu_level,
6351*6d67aabdSBjoern A. Zeeb 					      edcca_regs->ppdu_mask);
6352*6d67aabdSBjoern A. Zeeb 
6353*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->edcca_level,
6354*6d67aabdSBjoern A. Zeeb 				       edcca_regs->edcca_mask, EDCCA_MAX);
6355*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->edcca_level,
6356*6d67aabdSBjoern A. Zeeb 				       edcca_regs->edcca_p_mask, EDCCA_MAX);
6357*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->ppdu_level,
6358*6d67aabdSBjoern A. Zeeb 				       edcca_regs->ppdu_mask, EDCCA_MAX);
6359e2340276SBjoern A. Zeeb 	} else {
6360*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->edcca_level,
6361*6d67aabdSBjoern A. Zeeb 				       edcca_regs->edcca_mask,
6362*6d67aabdSBjoern A. Zeeb 				       edcca_bak->a);
6363*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->edcca_level,
6364*6d67aabdSBjoern A. Zeeb 				       edcca_regs->edcca_p_mask,
6365*6d67aabdSBjoern A. Zeeb 				       edcca_bak->p);
6366*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->ppdu_level,
6367*6d67aabdSBjoern A. Zeeb 				       edcca_regs->ppdu_mask,
6368*6d67aabdSBjoern A. Zeeb 				       edcca_bak->ppdu);
6369e2340276SBjoern A. Zeeb 	}
6370e2340276SBjoern A. Zeeb }
6371*6d67aabdSBjoern A. Zeeb 
6372*6d67aabdSBjoern A. Zeeb static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev)
6373*6d67aabdSBjoern A. Zeeb {
6374*6d67aabdSBjoern A. Zeeb 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
6375*6d67aabdSBjoern A. Zeeb 	bool flag_fb, flag_p20, flag_s20, flag_s40, flag_s80;
6376*6d67aabdSBjoern A. Zeeb 	s8 pwdb_fb, pwdb_p20, pwdb_s20, pwdb_s40, pwdb_s80;
6377*6d67aabdSBjoern A. Zeeb 	u8 path, per20_bitmap;
6378*6d67aabdSBjoern A. Zeeb 	u8 pwdb[8];
6379*6d67aabdSBjoern A. Zeeb 	u32 tmp;
6380*6d67aabdSBjoern A. Zeeb 
6381*6d67aabdSBjoern A. Zeeb 	if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_EDCCA))
6382*6d67aabdSBjoern A. Zeeb 		return;
6383*6d67aabdSBjoern A. Zeeb 
6384*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8922A)
6385*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be,
6386*6d67aabdSBjoern A. Zeeb 				       edcca_regs->rpt_sel_be_mask, 0);
6387*6d67aabdSBjoern A. Zeeb 
6388*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel,
6389*6d67aabdSBjoern A. Zeeb 			       edcca_regs->rpt_sel_mask, 0);
6390*6d67aabdSBjoern A. Zeeb 	tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_b);
6391*6d67aabdSBjoern A. Zeeb 	path = u32_get_bits(tmp, B_EDCCA_RPT_B_PATH_MASK);
6392*6d67aabdSBjoern A. Zeeb 	flag_s80 = u32_get_bits(tmp, B_EDCCA_RPT_B_S80);
6393*6d67aabdSBjoern A. Zeeb 	flag_s40 = u32_get_bits(tmp, B_EDCCA_RPT_B_S40);
6394*6d67aabdSBjoern A. Zeeb 	flag_s20 = u32_get_bits(tmp, B_EDCCA_RPT_B_S20);
6395*6d67aabdSBjoern A. Zeeb 	flag_p20 = u32_get_bits(tmp, B_EDCCA_RPT_B_P20);
6396*6d67aabdSBjoern A. Zeeb 	flag_fb = u32_get_bits(tmp, B_EDCCA_RPT_B_FB);
6397*6d67aabdSBjoern A. Zeeb 	pwdb_s20 = u32_get_bits(tmp, MASKBYTE1);
6398*6d67aabdSBjoern A. Zeeb 	pwdb_p20 = u32_get_bits(tmp, MASKBYTE2);
6399*6d67aabdSBjoern A. Zeeb 	pwdb_fb = u32_get_bits(tmp, MASKBYTE3);
6400*6d67aabdSBjoern A. Zeeb 
6401*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel,
6402*6d67aabdSBjoern A. Zeeb 			       edcca_regs->rpt_sel_mask, 4);
6403*6d67aabdSBjoern A. Zeeb 	tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_b);
6404*6d67aabdSBjoern A. Zeeb 	pwdb_s80 = u32_get_bits(tmp, MASKBYTE1);
6405*6d67aabdSBjoern A. Zeeb 	pwdb_s40 = u32_get_bits(tmp, MASKBYTE2);
6406*6d67aabdSBjoern A. Zeeb 
6407*6d67aabdSBjoern A. Zeeb 	per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_regs->rpt_a,
6408*6d67aabdSBjoern A. Zeeb 					     MASKBYTE0);
6409*6d67aabdSBjoern A. Zeeb 
6410*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8922A) {
6411*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be,
6412*6d67aabdSBjoern A. Zeeb 				       edcca_regs->rpt_sel_be_mask, 4);
6413*6d67aabdSBjoern A. Zeeb 		tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_b);
6414*6d67aabdSBjoern A. Zeeb 		pwdb[0] = u32_get_bits(tmp, MASKBYTE3);
6415*6d67aabdSBjoern A. Zeeb 		pwdb[1] = u32_get_bits(tmp, MASKBYTE2);
6416*6d67aabdSBjoern A. Zeeb 		pwdb[2] = u32_get_bits(tmp, MASKBYTE1);
6417*6d67aabdSBjoern A. Zeeb 		pwdb[3] = u32_get_bits(tmp, MASKBYTE0);
6418*6d67aabdSBjoern A. Zeeb 
6419*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be,
6420*6d67aabdSBjoern A. Zeeb 				       edcca_regs->rpt_sel_be_mask, 5);
6421*6d67aabdSBjoern A. Zeeb 		tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_b);
6422*6d67aabdSBjoern A. Zeeb 		pwdb[4] = u32_get_bits(tmp, MASKBYTE3);
6423*6d67aabdSBjoern A. Zeeb 		pwdb[5] = u32_get_bits(tmp, MASKBYTE2);
6424*6d67aabdSBjoern A. Zeeb 		pwdb[6] = u32_get_bits(tmp, MASKBYTE1);
6425*6d67aabdSBjoern A. Zeeb 		pwdb[7] = u32_get_bits(tmp, MASKBYTE0);
6426*6d67aabdSBjoern A. Zeeb 	} else {
6427*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel,
6428*6d67aabdSBjoern A. Zeeb 				       edcca_regs->rpt_sel_mask, 0);
6429*6d67aabdSBjoern A. Zeeb 		tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_a);
6430*6d67aabdSBjoern A. Zeeb 		pwdb[0] = u32_get_bits(tmp, MASKBYTE3);
6431*6d67aabdSBjoern A. Zeeb 		pwdb[1] = u32_get_bits(tmp, MASKBYTE2);
6432*6d67aabdSBjoern A. Zeeb 
6433*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel,
6434*6d67aabdSBjoern A. Zeeb 				       edcca_regs->rpt_sel_mask, 1);
6435*6d67aabdSBjoern A. Zeeb 		tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_a);
6436*6d67aabdSBjoern A. Zeeb 		pwdb[2] = u32_get_bits(tmp, MASKBYTE3);
6437*6d67aabdSBjoern A. Zeeb 		pwdb[3] = u32_get_bits(tmp, MASKBYTE2);
6438*6d67aabdSBjoern A. Zeeb 
6439*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel,
6440*6d67aabdSBjoern A. Zeeb 				       edcca_regs->rpt_sel_mask, 2);
6441*6d67aabdSBjoern A. Zeeb 		tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_a);
6442*6d67aabdSBjoern A. Zeeb 		pwdb[4] = u32_get_bits(tmp, MASKBYTE3);
6443*6d67aabdSBjoern A. Zeeb 		pwdb[5] = u32_get_bits(tmp, MASKBYTE2);
6444*6d67aabdSBjoern A. Zeeb 
6445*6d67aabdSBjoern A. Zeeb 		rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel,
6446*6d67aabdSBjoern A. Zeeb 				       edcca_regs->rpt_sel_mask, 3);
6447*6d67aabdSBjoern A. Zeeb 		tmp = rtw89_phy_read32(rtwdev, edcca_regs->rpt_a);
6448*6d67aabdSBjoern A. Zeeb 		pwdb[6] = u32_get_bits(tmp, MASKBYTE3);
6449*6d67aabdSBjoern A. Zeeb 		pwdb[7] = u32_get_bits(tmp, MASKBYTE2);
6450*6d67aabdSBjoern A. Zeeb 	}
6451*6d67aabdSBjoern A. Zeeb 
6452*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
6453*6d67aabdSBjoern A. Zeeb 		    "[EDCCA]: edcca_bitmap = %04x\n", per20_bitmap);
6454*6d67aabdSBjoern A. Zeeb 
6455*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
6456*6d67aabdSBjoern A. Zeeb 		    "[EDCCA]: pwdb per20{0,1,2,3,4,5,6,7} = {%d,%d,%d,%d,%d,%d,%d,%d}(dBm)\n",
6457*6d67aabdSBjoern A. Zeeb 		    pwdb[0], pwdb[1], pwdb[2], pwdb[3], pwdb[4], pwdb[5],
6458*6d67aabdSBjoern A. Zeeb 		    pwdb[6], pwdb[7]);
6459*6d67aabdSBjoern A. Zeeb 
6460*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
6461*6d67aabdSBjoern A. Zeeb 		    "[EDCCA]: path=%d, flag {FB,p20,s20,s40,s80} = {%d,%d,%d,%d,%d}\n",
6462*6d67aabdSBjoern A. Zeeb 		    path, flag_fb, flag_p20, flag_s20, flag_s40, flag_s80);
6463*6d67aabdSBjoern A. Zeeb 
6464*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
6465*6d67aabdSBjoern A. Zeeb 		    "[EDCCA]: pwdb {FB,p20,s20,s40,s80} = {%d,%d,%d,%d,%d}(dBm)\n",
6466*6d67aabdSBjoern A. Zeeb 		    pwdb_fb, pwdb_p20, pwdb_s20, pwdb_s40, pwdb_s80);
6467*6d67aabdSBjoern A. Zeeb }
6468*6d67aabdSBjoern A. Zeeb 
6469*6d67aabdSBjoern A. Zeeb static u8 rtw89_phy_edcca_get_thre_by_rssi(struct rtw89_dev *rtwdev)
6470*6d67aabdSBjoern A. Zeeb {
6471*6d67aabdSBjoern A. Zeeb 	struct rtw89_phy_ch_info *ch_info = &rtwdev->ch_info;
6472*6d67aabdSBjoern A. Zeeb 	bool is_linked = rtwdev->total_sta_assoc > 0;
6473*6d67aabdSBjoern A. Zeeb 	u8 rssi_min = ch_info->rssi_min >> 1;
6474*6d67aabdSBjoern A. Zeeb 	u8 edcca_thre;
6475*6d67aabdSBjoern A. Zeeb 
6476*6d67aabdSBjoern A. Zeeb 	if (!is_linked) {
6477*6d67aabdSBjoern A. Zeeb 		edcca_thre = EDCCA_MAX;
6478*6d67aabdSBjoern A. Zeeb 	} else {
6479*6d67aabdSBjoern A. Zeeb 		edcca_thre = rssi_min - RSSI_UNIT_CONVER + EDCCA_UNIT_CONVER -
6480*6d67aabdSBjoern A. Zeeb 			     EDCCA_TH_REF;
6481*6d67aabdSBjoern A. Zeeb 		edcca_thre = max_t(u8, edcca_thre, EDCCA_TH_L2H_LB);
6482*6d67aabdSBjoern A. Zeeb 	}
6483*6d67aabdSBjoern A. Zeeb 
6484*6d67aabdSBjoern A. Zeeb 	return edcca_thre;
6485*6d67aabdSBjoern A. Zeeb }
6486*6d67aabdSBjoern A. Zeeb 
6487*6d67aabdSBjoern A. Zeeb void rtw89_phy_edcca_thre_calc(struct rtw89_dev *rtwdev)
6488*6d67aabdSBjoern A. Zeeb {
6489*6d67aabdSBjoern A. Zeeb 	const struct rtw89_edcca_regs *edcca_regs = rtwdev->chip->edcca_regs;
6490*6d67aabdSBjoern A. Zeeb 	struct rtw89_edcca_bak *edcca_bak = &rtwdev->hal.edcca_bak;
6491*6d67aabdSBjoern A. Zeeb 	u8 th;
6492*6d67aabdSBjoern A. Zeeb 
6493*6d67aabdSBjoern A. Zeeb 	th = rtw89_phy_edcca_get_thre_by_rssi(rtwdev);
6494*6d67aabdSBjoern A. Zeeb 	if (th == edcca_bak->th_old)
6495*6d67aabdSBjoern A. Zeeb 		return;
6496*6d67aabdSBjoern A. Zeeb 
6497*6d67aabdSBjoern A. Zeeb 	edcca_bak->th_old = th;
6498*6d67aabdSBjoern A. Zeeb 
6499*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_EDCCA,
6500*6d67aabdSBjoern A. Zeeb 		    "[EDCCA]: Normal Mode, EDCCA_th = %d\n", th);
6501*6d67aabdSBjoern A. Zeeb 
6502*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, edcca_regs->edcca_level,
6503*6d67aabdSBjoern A. Zeeb 			       edcca_regs->edcca_mask, th);
6504*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, edcca_regs->edcca_level,
6505*6d67aabdSBjoern A. Zeeb 			       edcca_regs->edcca_p_mask, th);
6506*6d67aabdSBjoern A. Zeeb 	rtw89_phy_write32_mask(rtwdev, edcca_regs->ppdu_level,
6507*6d67aabdSBjoern A. Zeeb 			       edcca_regs->ppdu_mask, th);
6508*6d67aabdSBjoern A. Zeeb }
6509*6d67aabdSBjoern A. Zeeb 
6510*6d67aabdSBjoern A. Zeeb void rtw89_phy_edcca_track(struct rtw89_dev *rtwdev)
6511*6d67aabdSBjoern A. Zeeb {
6512*6d67aabdSBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
6513*6d67aabdSBjoern A. Zeeb 
6514*6d67aabdSBjoern A. Zeeb 	if (hal->disabled_dm_bitmap & BIT(RTW89_DM_DYNAMIC_EDCCA))
6515*6d67aabdSBjoern A. Zeeb 		return;
6516*6d67aabdSBjoern A. Zeeb 
6517*6d67aabdSBjoern A. Zeeb 	rtw89_phy_edcca_thre_calc(rtwdev);
6518*6d67aabdSBjoern A. Zeeb 	rtw89_phy_edcca_log(rtwdev);
6519*6d67aabdSBjoern A. Zeeb }
6520*6d67aabdSBjoern A. Zeeb 
6521*6d67aabdSBjoern A. Zeeb enum rtw89_rf_path_bit rtw89_phy_get_kpath(struct rtw89_dev *rtwdev,
6522*6d67aabdSBjoern A. Zeeb 					   enum rtw89_phy_idx phy_idx)
6523*6d67aabdSBjoern A. Zeeb {
6524*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
6525*6d67aabdSBjoern A. Zeeb 		    "[RFK] kpath dbcc_en: 0x%x, mode=0x%x, PHY%d\n",
6526*6d67aabdSBjoern A. Zeeb 		    rtwdev->dbcc_en, rtwdev->mlo_dbcc_mode, phy_idx);
6527*6d67aabdSBjoern A. Zeeb 
6528*6d67aabdSBjoern A. Zeeb 	switch (rtwdev->mlo_dbcc_mode) {
6529*6d67aabdSBjoern A. Zeeb 	case MLO_1_PLUS_1_1RF:
6530*6d67aabdSBjoern A. Zeeb 		if (phy_idx == RTW89_PHY_0)
6531*6d67aabdSBjoern A. Zeeb 			return RF_A;
6532*6d67aabdSBjoern A. Zeeb 		else
6533*6d67aabdSBjoern A. Zeeb 			return RF_B;
6534*6d67aabdSBjoern A. Zeeb 	case MLO_1_PLUS_1_2RF:
6535*6d67aabdSBjoern A. Zeeb 		if (phy_idx == RTW89_PHY_0)
6536*6d67aabdSBjoern A. Zeeb 			return RF_A;
6537*6d67aabdSBjoern A. Zeeb 		else
6538*6d67aabdSBjoern A. Zeeb 			return RF_D;
6539*6d67aabdSBjoern A. Zeeb 	case MLO_0_PLUS_2_1RF:
6540*6d67aabdSBjoern A. Zeeb 	case MLO_2_PLUS_0_1RF:
6541*6d67aabdSBjoern A. Zeeb 		/* for both PHY 0/1 */
6542*6d67aabdSBjoern A. Zeeb 		return RF_AB;
6543*6d67aabdSBjoern A. Zeeb 	case MLO_0_PLUS_2_2RF:
6544*6d67aabdSBjoern A. Zeeb 	case MLO_2_PLUS_0_2RF:
6545*6d67aabdSBjoern A. Zeeb 	case MLO_2_PLUS_2_2RF:
6546*6d67aabdSBjoern A. Zeeb 	default:
6547*6d67aabdSBjoern A. Zeeb 		if (phy_idx == RTW89_PHY_0)
6548*6d67aabdSBjoern A. Zeeb 			return RF_AB;
6549*6d67aabdSBjoern A. Zeeb 		else
6550*6d67aabdSBjoern A. Zeeb 			return RF_CD;
6551*6d67aabdSBjoern A. Zeeb 	}
6552*6d67aabdSBjoern A. Zeeb }
6553*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_get_kpath);
6554*6d67aabdSBjoern A. Zeeb 
6555*6d67aabdSBjoern A. Zeeb enum rtw89_rf_path rtw89_phy_get_syn_sel(struct rtw89_dev *rtwdev,
6556*6d67aabdSBjoern A. Zeeb 					 enum rtw89_phy_idx phy_idx)
6557*6d67aabdSBjoern A. Zeeb {
6558*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
6559*6d67aabdSBjoern A. Zeeb 		    "[RFK] kpath dbcc_en: 0x%x, mode=0x%x, PHY%d\n",
6560*6d67aabdSBjoern A. Zeeb 		    rtwdev->dbcc_en, rtwdev->mlo_dbcc_mode, phy_idx);
6561*6d67aabdSBjoern A. Zeeb 
6562*6d67aabdSBjoern A. Zeeb 	switch (rtwdev->mlo_dbcc_mode) {
6563*6d67aabdSBjoern A. Zeeb 	case MLO_1_PLUS_1_1RF:
6564*6d67aabdSBjoern A. Zeeb 		if (phy_idx == RTW89_PHY_0)
6565*6d67aabdSBjoern A. Zeeb 			return RF_PATH_A;
6566*6d67aabdSBjoern A. Zeeb 		else
6567*6d67aabdSBjoern A. Zeeb 			return RF_PATH_B;
6568*6d67aabdSBjoern A. Zeeb 	case MLO_1_PLUS_1_2RF:
6569*6d67aabdSBjoern A. Zeeb 		if (phy_idx == RTW89_PHY_0)
6570*6d67aabdSBjoern A. Zeeb 			return RF_PATH_A;
6571*6d67aabdSBjoern A. Zeeb 		else
6572*6d67aabdSBjoern A. Zeeb 			return RF_PATH_D;
6573*6d67aabdSBjoern A. Zeeb 	case MLO_0_PLUS_2_1RF:
6574*6d67aabdSBjoern A. Zeeb 	case MLO_2_PLUS_0_1RF:
6575*6d67aabdSBjoern A. Zeeb 		if (phy_idx == RTW89_PHY_0)
6576*6d67aabdSBjoern A. Zeeb 			return RF_PATH_A;
6577*6d67aabdSBjoern A. Zeeb 		else
6578*6d67aabdSBjoern A. Zeeb 			return RF_PATH_B;
6579*6d67aabdSBjoern A. Zeeb 	case MLO_0_PLUS_2_2RF:
6580*6d67aabdSBjoern A. Zeeb 	case MLO_2_PLUS_0_2RF:
6581*6d67aabdSBjoern A. Zeeb 	case MLO_2_PLUS_2_2RF:
6582*6d67aabdSBjoern A. Zeeb 	default:
6583*6d67aabdSBjoern A. Zeeb 		if (phy_idx == RTW89_PHY_0)
6584*6d67aabdSBjoern A. Zeeb 			return RF_PATH_A;
6585*6d67aabdSBjoern A. Zeeb 		else
6586*6d67aabdSBjoern A. Zeeb 			return RF_PATH_C;
6587*6d67aabdSBjoern A. Zeeb 	}
6588*6d67aabdSBjoern A. Zeeb }
6589*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_get_syn_sel);
6590*6d67aabdSBjoern A. Zeeb 
6591*6d67aabdSBjoern A. Zeeb static const struct rtw89_ccx_regs rtw89_ccx_regs_ax = {
6592*6d67aabdSBjoern A. Zeeb 	.setting_addr = R_CCX,
6593*6d67aabdSBjoern A. Zeeb 	.edcca_opt_mask = B_CCX_EDCCA_OPT_MSK,
6594*6d67aabdSBjoern A. Zeeb 	.measurement_trig_mask = B_MEASUREMENT_TRIG_MSK,
6595*6d67aabdSBjoern A. Zeeb 	.trig_opt_mask = B_CCX_TRIG_OPT_MSK,
6596*6d67aabdSBjoern A. Zeeb 	.en_mask = B_CCX_EN_MSK,
6597*6d67aabdSBjoern A. Zeeb 	.ifs_cnt_addr = R_IFS_COUNTER,
6598*6d67aabdSBjoern A. Zeeb 	.ifs_clm_period_mask = B_IFS_CLM_PERIOD_MSK,
6599*6d67aabdSBjoern A. Zeeb 	.ifs_clm_cnt_unit_mask = B_IFS_CLM_COUNTER_UNIT_MSK,
6600*6d67aabdSBjoern A. Zeeb 	.ifs_clm_cnt_clear_mask = B_IFS_COUNTER_CLR_MSK,
6601*6d67aabdSBjoern A. Zeeb 	.ifs_collect_en_mask = B_IFS_COLLECT_EN,
6602*6d67aabdSBjoern A. Zeeb 	.ifs_t1_addr = R_IFS_T1,
6603*6d67aabdSBjoern A. Zeeb 	.ifs_t1_th_h_mask = B_IFS_T1_TH_HIGH_MSK,
6604*6d67aabdSBjoern A. Zeeb 	.ifs_t1_en_mask = B_IFS_T1_EN_MSK,
6605*6d67aabdSBjoern A. Zeeb 	.ifs_t1_th_l_mask = B_IFS_T1_TH_LOW_MSK,
6606*6d67aabdSBjoern A. Zeeb 	.ifs_t2_addr = R_IFS_T2,
6607*6d67aabdSBjoern A. Zeeb 	.ifs_t2_th_h_mask = B_IFS_T2_TH_HIGH_MSK,
6608*6d67aabdSBjoern A. Zeeb 	.ifs_t2_en_mask = B_IFS_T2_EN_MSK,
6609*6d67aabdSBjoern A. Zeeb 	.ifs_t2_th_l_mask = B_IFS_T2_TH_LOW_MSK,
6610*6d67aabdSBjoern A. Zeeb 	.ifs_t3_addr = R_IFS_T3,
6611*6d67aabdSBjoern A. Zeeb 	.ifs_t3_th_h_mask = B_IFS_T3_TH_HIGH_MSK,
6612*6d67aabdSBjoern A. Zeeb 	.ifs_t3_en_mask = B_IFS_T3_EN_MSK,
6613*6d67aabdSBjoern A. Zeeb 	.ifs_t3_th_l_mask = B_IFS_T3_TH_LOW_MSK,
6614*6d67aabdSBjoern A. Zeeb 	.ifs_t4_addr = R_IFS_T4,
6615*6d67aabdSBjoern A. Zeeb 	.ifs_t4_th_h_mask = B_IFS_T4_TH_HIGH_MSK,
6616*6d67aabdSBjoern A. Zeeb 	.ifs_t4_en_mask = B_IFS_T4_EN_MSK,
6617*6d67aabdSBjoern A. Zeeb 	.ifs_t4_th_l_mask = B_IFS_T4_TH_LOW_MSK,
6618*6d67aabdSBjoern A. Zeeb 	.ifs_clm_tx_cnt_addr = R_IFS_CLM_TX_CNT,
6619*6d67aabdSBjoern A. Zeeb 	.ifs_clm_edcca_excl_cca_fa_mask = B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK,
6620*6d67aabdSBjoern A. Zeeb 	.ifs_clm_tx_cnt_msk = B_IFS_CLM_TX_CNT_MSK,
6621*6d67aabdSBjoern A. Zeeb 	.ifs_clm_cca_addr = R_IFS_CLM_CCA,
6622*6d67aabdSBjoern A. Zeeb 	.ifs_clm_ofdmcca_excl_fa_mask = B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK,
6623*6d67aabdSBjoern A. Zeeb 	.ifs_clm_cckcca_excl_fa_mask = B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK,
6624*6d67aabdSBjoern A. Zeeb 	.ifs_clm_fa_addr = R_IFS_CLM_FA,
6625*6d67aabdSBjoern A. Zeeb 	.ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK,
6626*6d67aabdSBjoern A. Zeeb 	.ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK,
6627*6d67aabdSBjoern A. Zeeb 	.ifs_his_addr = R_IFS_HIS,
6628*6d67aabdSBjoern A. Zeeb 	.ifs_t4_his_mask = B_IFS_T4_HIS_MSK,
6629*6d67aabdSBjoern A. Zeeb 	.ifs_t3_his_mask = B_IFS_T3_HIS_MSK,
6630*6d67aabdSBjoern A. Zeeb 	.ifs_t2_his_mask = B_IFS_T2_HIS_MSK,
6631*6d67aabdSBjoern A. Zeeb 	.ifs_t1_his_mask = B_IFS_T1_HIS_MSK,
6632*6d67aabdSBjoern A. Zeeb 	.ifs_avg_l_addr = R_IFS_AVG_L,
6633*6d67aabdSBjoern A. Zeeb 	.ifs_t2_avg_mask = B_IFS_T2_AVG_MSK,
6634*6d67aabdSBjoern A. Zeeb 	.ifs_t1_avg_mask = B_IFS_T1_AVG_MSK,
6635*6d67aabdSBjoern A. Zeeb 	.ifs_avg_h_addr = R_IFS_AVG_H,
6636*6d67aabdSBjoern A. Zeeb 	.ifs_t4_avg_mask = B_IFS_T4_AVG_MSK,
6637*6d67aabdSBjoern A. Zeeb 	.ifs_t3_avg_mask = B_IFS_T3_AVG_MSK,
6638*6d67aabdSBjoern A. Zeeb 	.ifs_cca_l_addr = R_IFS_CCA_L,
6639*6d67aabdSBjoern A. Zeeb 	.ifs_t2_cca_mask = B_IFS_T2_CCA_MSK,
6640*6d67aabdSBjoern A. Zeeb 	.ifs_t1_cca_mask = B_IFS_T1_CCA_MSK,
6641*6d67aabdSBjoern A. Zeeb 	.ifs_cca_h_addr = R_IFS_CCA_H,
6642*6d67aabdSBjoern A. Zeeb 	.ifs_t4_cca_mask = B_IFS_T4_CCA_MSK,
6643*6d67aabdSBjoern A. Zeeb 	.ifs_t3_cca_mask = B_IFS_T3_CCA_MSK,
6644*6d67aabdSBjoern A. Zeeb 	.ifs_total_addr = R_IFSCNT,
6645*6d67aabdSBjoern A. Zeeb 	.ifs_cnt_done_mask = B_IFSCNT_DONE_MSK,
6646*6d67aabdSBjoern A. Zeeb 	.ifs_total_mask = B_IFSCNT_TOTAL_CNT_MSK,
6647*6d67aabdSBjoern A. Zeeb };
6648*6d67aabdSBjoern A. Zeeb 
6649*6d67aabdSBjoern A. Zeeb static const struct rtw89_physts_regs rtw89_physts_regs_ax = {
6650*6d67aabdSBjoern A. Zeeb 	.setting_addr = R_PLCP_HISTOGRAM,
6651*6d67aabdSBjoern A. Zeeb 	.dis_trigger_fail_mask = B_STS_DIS_TRIG_BY_FAIL,
6652*6d67aabdSBjoern A. Zeeb 	.dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK,
6653*6d67aabdSBjoern A. Zeeb };
6654*6d67aabdSBjoern A. Zeeb 
6655*6d67aabdSBjoern A. Zeeb static const struct rtw89_cfo_regs rtw89_cfo_regs_ax = {
6656*6d67aabdSBjoern A. Zeeb 	.comp = R_DCFO_WEIGHT,
6657*6d67aabdSBjoern A. Zeeb 	.weighting_mask = B_DCFO_WEIGHT_MSK,
6658*6d67aabdSBjoern A. Zeeb 	.comp_seg0 = R_DCFO_OPT,
6659*6d67aabdSBjoern A. Zeeb 	.valid_0_mask = B_DCFO_OPT_EN,
6660*6d67aabdSBjoern A. Zeeb };
6661*6d67aabdSBjoern A. Zeeb 
6662*6d67aabdSBjoern A. Zeeb const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
6663*6d67aabdSBjoern A. Zeeb 	.cr_base = 0x10000,
6664*6d67aabdSBjoern A. Zeeb 	.ccx = &rtw89_ccx_regs_ax,
6665*6d67aabdSBjoern A. Zeeb 	.physts = &rtw89_physts_regs_ax,
6666*6d67aabdSBjoern A. Zeeb 	.cfo = &rtw89_cfo_regs_ax,
6667*6d67aabdSBjoern A. Zeeb 	.phy0_phy1_offset = rtw89_phy0_phy1_offset_ax,
6668*6d67aabdSBjoern A. Zeeb 	.config_bb_gain = rtw89_phy_config_bb_gain_ax,
6669*6d67aabdSBjoern A. Zeeb 	.preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_ax,
6670*6d67aabdSBjoern A. Zeeb 	.bb_wrap_init = NULL,
6671*6d67aabdSBjoern A. Zeeb 	.ch_info_init = NULL,
6672*6d67aabdSBjoern A. Zeeb 
6673*6d67aabdSBjoern A. Zeeb 	.set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_ax,
6674*6d67aabdSBjoern A. Zeeb 	.set_txpwr_offset = rtw89_phy_set_txpwr_offset_ax,
6675*6d67aabdSBjoern A. Zeeb 	.set_txpwr_limit = rtw89_phy_set_txpwr_limit_ax,
6676*6d67aabdSBjoern A. Zeeb 	.set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_ax,
6677*6d67aabdSBjoern A. Zeeb };
6678*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_phy_gen_ax);
6679